def test_api_products_edit(self): """ Tests the "api_products_edit" API method. Success conditions : - The API can't be accessed without being logged - Perfoms correctly ADD / EDIT operations """ with webapp.test_client() as app: # Tests access without being authenticated response = app.get('/api/products_edit/foo/bar') assert response.status_code == 401 # Authenticate data = {'password': self.password_raw} response = app.post('/', data=data, follow_redirects=True) # Test : add barcode = '1000000000001' name = 'foobar' response = app.get('/api/products_edit/' + barcode + '/' + name) entry = models.Products().get_item(barcode) assert response.status_code == 200 assert entry assert entry['barcode'] == barcode assert entry['name'] == name # Test : edit name = 'barfoo' response = app.get('/api/products_edit/' + barcode + '/' + name) entry = models.Products().get_item(barcode) assert response.status_code == 200 assert entry assert entry['barcode'] == barcode assert entry['name'] == name
def setup_method(self): """ Setup method : - Sets database to test mode and populates it - Launches Flask in test mode """ # Database Database.TEST_MODE = True Database.on() # Create test database models.Params(autoload=False).create_table() models.Products().create_table() models.Groceries().create_table() # Params : user config self.password_raw = 'abcdefg' self.password_sha1 = bytearray(self.password_raw, encoding='utf-8') self.password_sha1 = hashlib.sha1(self.password_sha1).hexdigest() params = models.Params() params.add_item('user_password', self.password_sha1) params.add_item('lang', 'en') # Products : 1 sample item self.default_barcode = '1234567890123' self.default_name = 'Lorem Ipsum' models.Products().add_item(self.default_barcode, self.default_name, True) # Groceries : 1 sample item models.Groceries().add_item(self.default_barcode, 1)
def api_products_list_key(api): """ API method : Gets all items from the products table. Outputs JSON. Returns the latest version of the grocery list. JSON format : - {"status": ..., "items" ...} Possible return status : - OK (200) """ # AJAX Auth check Database.on() # Load parameters params = models.Params() # Database : end connection # (open it only when needed because this program is meant to be shutdown harshly) Database.off() # Database access api_key = params.api_key if api_key != api: return render_template('json.html', json="{}"), 401 # Output data = {"status": "OK", "items": []} # Get info Database.on() data['items'] = models.Products().get_list() Database.off() # Render return render_template('json.html', json=json.dumps(data))
def test_api_products_list(self): """ Tests the "api_products_list" API method. Success conditions : - The API can't be accessed without being logged : HTTP 401 - Returns HTTP 200 when logged with the expected content as JSON """ with webapp.test_client() as app: # Tests access without being authenticated response = app.get('/api/products_list') assert response.status_code == 401 # Authenticate data = {'password': self.password_raw} response = app.post('/', data=data, follow_redirects=True) # Does the API returns the expected data ? # JSON "item" entry must contain the same thing as Products > get_list response = app.get('/api/products_list') expected_data = models.Products().get_list() given_data = str(response.data, encoding='utf-8') given_data = json.loads(given_data) given_data = given_data['items'].keys() assert response.status_code == 200 assert set(expected_data) == set(given_data)
def setup_method(self): """ Creates a dummy database for tests """ # Creates database Database.TEST_MODE = True Database.on() self.cursor = Database.CURSOR # Create tables self.params = models.Params(autoload=False) self.products = models.Products() self.groceries = models.Groceries() self.params.create_table() self.products.create_table() self.groceries.create_table() # Insert dummy data self.default_barcode = '123456789ABCD' self.default_name = 'Lorem Ipsum' self.default_pic = 'PIC' self.params.add_item('foo', 'bar') self.products.add_item(self.default_barcode, self.default_name, self.default_pic) self.groceries.add_item(self.default_barcode, 1)
def __init__(self): #define the cursor of pymysql to manipulate datas self.cursor = connect.cursor # creating objects that are imported from models self.cat = models.Cat() self.prods = models.Products() self.favs = models.Favorits() self.my_base = models.MyBase() #Geting the api's link of a specific categorie mentionned "creat_url method" self.req = requests.get(self.Creat_url('saucissons'))
def __init__(self): #define the cursor of pymysql to manipulate datas self.cursor = connect.cursor #Geting all classes indeed self.cat = models.Cat() self.prods = models.Products() self.app = views.MyApp() #self.app.win.mainloop() #creat a tuple of categories value to add in the comobox of the view self.cats_val = ()
def api_products_edit(barcode, name): """ API method : Add/Edit/Delete items from the products database. If an item doesn't exist, it will be created. Outputs JSON. :param barcode: An unknown product barcode :param name: The new product's name JSON format : - {"status": ..., "barcode" ..., "name": ...} Possible return status : - ADDED (200) / ADD ERROR (400) - EDITED (200) / EDIT ERROR (400) """ # AJAX Auth check if not ('is_logged' in session and session['is_logged']): return render_template('json.html', json="{}"), 401 # Remove unwanted chars to_escape = ['"', "<", ">", "&", "'"] for char in to_escape: barcode = barcode.replace(char, '') name = name.replace(char, '') # Output data = {"status": "", "barcode": barcode, "name": name} # Database access Database.on() products_db = models.Products() # Try to get the entry in the grocery list exists = products_db.get_item(barcode) status_code = 200 # If it doesn't exist : add it if not exists: try: products_db.add_item(barcode, name, False) data['status'] = 'ADDED' except Exception as trace: data['status'] = 'ADD ERROR' status_code = 400 # If it exists : edit it else: try: products_db.edit_item(barcode, name, exists['pic']) data['status'] = 'EDITED' except Exception as trace: data['status'] = 'EDIT ERROR' status_code = 400 # Database : off and outputs data Database.off() return render_template('json.html', json=json.dumps(data)), status_code
def __init__(self): # Create instances self.win = tk.Tk() self.win.geometry( "820x720" ) self.win.resizable(0,0) self.win.iconbitmap(r'C:\Users\boukr\Desktop\here\GUI-OFF-P5\logo.ico') #Attributs of the models's Classes self.cat = models.Cat() self.prods = models.Products() self.fav = models.Favorits() self.cursor = connect.cursor # Add a title self.win.title("OpenFoodFacts") #creat widgets self.createWidgets() #tuple of products combobox self.prods_val = ()
def setup_method(self): """ Setup method, creates a dummy database """ # Creates test database Database.TEST_MODE = True Database.on() self.cursor = Database.CURSOR # Create tables models.Params(autoload=False).create_table() models.Products().create_table() models.Groceries().create_table() # Defaults barcodes self.valid_barcode = '3017620424403' self.invalid_barcode = '123456789ABCD' # Deconnects database to let threads use them Database.off()
def test_api_products_delete(self): """ Tests the "api_products_delete" API method. Success conditions : - The API can't be accessed without being logged - Perfoms correctly DELETE operations """ with webapp.test_client() as app: # Tests access without being authenticated response = app.get('/api/products_edit/foo/bar') assert response.status_code == 401 # Authenticate data = {'password': self.password_raw} response = app.post('/', data=data, follow_redirects=True) # Test : Delete response = app.get('/api/products_delete/' + self.default_barcode) assert response.status_code == 200 assert not models.Products().get_item(self.default_barcode)
def groceries(): """ Shows GROCERIES template if the user is logged. """ # Auth check if 'is_logged' not in session or not session['is_logged']: return redirect(url_for('login')) # Database access + loads basic info Database.on() lang = utils.Lang(models.Params().lang) items = models.Products().get_list() Database.off() # Prepare template data data = { 'lang': lang.__dict__, 'body_class': 'groceries', 'products_list': items } # Return template return render_template('groceries.html', **data)
def api_products_delete(barcode): """ API method : Deletes an item from the products table. Outputs JSON. Returns the latest version of the grocery list. JSON format : - {"status": ...} Possible return status : - OK (200) - DELETE ERROR (400) """ # AJAX Auth check if not ('is_logged' in session and session['is_logged']): return render_template('json.html', json="{}"), 401 # Remove unwanted chars to_escape = ['"', "<", ">", "&", "'"] for char in to_escape: barcode = barcode.replace(char, '') # Output data = {"status": "OK"} # Try to delete Database.on() try: models.Products().delete_item(barcode) data['status'] = 'OK' status_code = 200 except Exception as trace: data['status'] = 'DELETE ERROR' status_code = 400 Database.off() # Render return render_template('json.html', json=json.dumps(data)), status_code
def api_products_list(): """ API method : Gets all items from the products table. Outputs JSON. Returns the latest version of the grocery list. JSON format : - {"status": ..., "items" ...} Possible return status : - OK (200) """ # AJAX Auth check if not ('is_logged' in session and session['is_logged']): return render_template('json.html', json="{}"), 401 # Output data = {"status": "OK", "items": []} # Get info Database.on() data['items'] = models.Products().get_list() Database.off() # Render return render_template('json.html', json=json.dumps(data))
def execute(cls, language='en'): """ Creates database, tables and ask for user parameters. :param language: Set language for this menu :type language: str Defined parameters : - buzzer_on - buzzer_port - camera_res_x - camera_res_y - user_password - lang """ # Language file lang = Lang(language) # Intro print("-" * 80) print(lang.config_intro) print("-" * 80) # Create / connects to the database Database.on() print(lang.config_database_created) # Create table : params params = models.Params(autoload=False) params.create_table() print(lang.config_table_params_set) # Create table : groceries groceries = models.Groceries() groceries.create_table() print(lang.config_table_groceries_set) # Create table : products products = models.Products() products.create_table() print(lang.config_table_products_set) # Set language params.delete_item('lang') language = input(lang.config_language_set) if language not in Lang.available(): language = 'en' params.add_item('lang', language) # Ask for : use buzzer / on which port ? params.delete_item('buzzer_on') params.delete_item('buzzer_port') buzzer_on = input(lang.config_buzzer_on) # Yes if buzzer_on.upper() == "Y": buzzer_port = input(lang.config_buzzer_port) if re.findall('([0-9]+)', buzzer_port): params.add_item('buzzer_on', '1') params.add_item('buzzer_port', buzzer_port) else: print(lang.config_buzzer_invalid_port) params.add_item('buzzer_on', '0') params.add_item('buzzer_port', '0') # No else: params.add_item('buzzer_on', '0') params.add_item('buzzer_port', '0') # Ask for : camera resolution params.delete_item('camera_res_x') params.delete_item('camera_res_y') for axis in ['x', 'y']: if axis == 'x': question = lang.config_camera_res_x else: question = lang.config_camera_res_y resolution = input(question) if not re.findall('([0-9]+)', resolution): resolution = 500 params.add_item('camera_res_{}'.format(axis), resolution) # Ask for : user password params.delete_item('user_password') user_password = getpass.getpass(lang.config_password) if not user_password: user_password = '******' user_password = bytearray(user_password, encoding='utf-8') user_password = hashlib.sha1(user_password).hexdigest() params.add_item('user_password', user_password) # Close connection to the database Database.off() # Bye ! print(lang.config_done)
def execute(cls, language='en'): """ Creates database, tables and ask for user parameters. :param language: Set language for this menu :type language: str Defined parameters : - buzzer_on - buzzer_port - camera_res_x - camera_res_y - user_password - lang - api_key """ # Language file lang = Lang(language) # Intro print("-" * 80) print(lang.config_intro) print("-" * 80) # Create / connects to the database Database.on() print(lang.config_database_created) # Create table : params params = models.Params(autoload=False) params.create_table() print(lang.config_table_params_set) # Create table : groceries groceries = models.Groceries() groceries.create_table() print(lang.config_table_groceries_set) # Create table : products products = models.Products() products.create_table() print(lang.config_table_products_set) # Set language params.delete_item('lang') language = input(lang.config_language_set) if language not in Lang.available(): language = 'en' params.add_item('lang', language) # Ask for : use buzzer / on which port ? params.delete_item('buzzer_on') params.delete_item('buzzer_port') buzzer_on = input(lang.config_buzzer_on) # Yes if buzzer_on.upper() == "Y": buzzer_port = input(lang.config_buzzer_port) if re.findall('([0-9]+)', buzzer_port): params.add_item('buzzer_on', '1') params.add_item('buzzer_port', buzzer_port) else: print(lang.config_buzzer_invalid_port) params.add_item('buzzer_on', '0') params.add_item('buzzer_port', '0') # No else: params.add_item('buzzer_on', '0') params.add_item('buzzer_port', '0') # Ask for : camera resolution params.delete_item('camera_res_x') params.delete_item('camera_res_y') for axis in ['x', 'y']: if axis == 'x': question = lang.config_camera_res_x else: question = lang.config_camera_res_y resolution = input(question) if not re.findall('([0-9]+)', resolution): resolution = 500 params.add_item('camera_res_{}'.format(axis), resolution) # Ask for : user password params.delete_item('user_password') user_password = getpass.getpass(lang.config_password) if not user_password: user_password = '******' user_password = bytearray(user_password, encoding='utf-8') user_password = hashlib.sha1(user_password).hexdigest() params.add_item('user_password', user_password) import random random = random.SystemRandom() def get_random_string(length=12, allowed_chars='abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'): return ''.join(random.choice(allowed_chars) for i in range(length)) def get_secret_key(): """ Create a random secret key. Taken from the Django project. """ chars = 'abcdefghijklmnopqrstuvwxyz0123456789!@#$^*(-_=+)' return get_random_string(24, chars) # Ask for : api key params.delete_item('api_key') api_key = getpass.getpass(lang.config_api) if not api_key: api_key = (get_secret_key()) params.add_item('api_key', api_key) print('Api-Key: ' + api_key) # Close connection to the database Database.off() # Bye ! print(lang.config_done)
def api_products_editt_key(api, barcode, name): """ API method : Add/Edit/Delete items from the products database. If an item doesn't exist, it will be created. Outputs JSON. :param barcode: An unknown product barcode :param name: The new product's name JSON format : - {"status": ..., "barcode" ..., "name": ...} Possible return status : - ADDED (200) / ADD ERROR (400) - EDITED (200) / EDIT ERROR (400) """ # AJAX Auth check Database.on() # Load parameters params = models.Params() # Database : end connection # (open it only when needed because this program is meant to be shutdown harshly) Database.off() # Database access api_key = params.api_key if api_key == api: session['is_logged'] = True # return redirect(url_for('groceries')) # Remove unwanted chars to_escape = ['"', "<", ">", "&", "'"] for char in to_escape: barcode = barcode.replace(char, '') name = name.replace(char, '') # Output data = {"status": "", "barcode": barcode, "name": name} # Database access Database.on() products_db = models.Products() # Try to get the entry in the grocery list exists = products_db.get_item(barcode) status_code = 200 # If it doesn't exist : add it if not exists: try: products_db.add_item(barcode, name, False) data['status'] = 'ADDED' except Exception as trace: data['status'] = 'ADD ERROR' status_code = 400 # If it exists : edit it else: try: products_db.edit_item(barcode, name, exists['pic']) data['status'] = 'EDITED' except Exception as trace: data['status'] = 'EDIT ERROR' status_code = 400 # Database : off and outputs data Database.off() return render_template('json.html', json=json.dumps(data)), status_code
def api_groceries_edit(barcode, quantity): """ API method : Add/Edit/Delete items from the grocery list. If the item doesn't exist, it will be created. Outputs JSON. :param barcode: A known product barcode :param quantity: The quantity defines the operation (quantity 0 = delete) JSON format : - {"status": ..., "barcode" ..., "quantity": ...} Possible return status : - PRODUCT NOT FOUND (404) - ADDED (200) / ADD ERROR (400) - EDITED (200) / EDIT ERROR (400) - DELETED (200) / DELETE ERROR (400) """ # AJAX Auth check if not ('is_logged' in session and session['is_logged']): return render_template('json.html', json="{}"), 401 # Remove unwanted chars to_escape = ['"', "<", ">", "&", "'"] for char in to_escape: barcode = barcode.replace(char, '') quantity = int(quantity) # Output data = {"status": "", "barcode": barcode, "quantity": quantity} # Database access Database.on() products_db = models.Products() groceries_db = models.Groceries() # Try to get the product associated with the barcode product = products_db.get_item(barcode) if not product: data['status'] = 'PRODUCT NOT FOUND' return render_template('json.html', json=json.dumps(data)), 404 # Try to get the entry in the grocery list exists = groceries_db.get_item(barcode) status_code = 200 # If it doesn't exist : add it if not exists: try: if not quantity: quantity = 1 groceries_db.add_item(barcode, quantity) data['status'] = 'ADDED' except Exception as trace: data['status'] = 'ADD ERROR' status_code = 400 # If it exists : else: # If quantity = 0 : Delete if quantity <= 0: try: groceries_db.delete_item(barcode) data['status'] = 'DELETED' except Exception as trace: data['status'] = 'DELETE ERROR' status_code = 400 # If quantity > 0 : Edit quantity else: try: groceries_db.edit_item(barcode, abs(quantity)) data['status'] = 'EDITED' except Exception as trace: data['status'] = 'EDIT ERROR' status_code = 400 # Database : off and outputs data Database.off() return render_template('json.html', json=json.dumps(data)), status_code
def run(self): """ Fetch, gathers, insert product infos and adds it to the grocery list. Threaded :rtype: bool """ with FindProduct.LOCK: # Database connection Database.on() # Marks found = False cache = False products = models.Products() groceries = models.Groceries() message = "" # Try to find the product in the local products database cache = products.get_item(self.barcode) if cache: found = True self.name = cache['name'] self.barcode = cache['barcode'] message += "{barcode} : Found {name} from local products database.\n" # If not found locally : Try to find the product in the OpenFoodFacts API if not found: # If found on OpenFoodFacts : add it to the local database if self.__fetch_openfoodfacts(): found = True products.add_item(self.barcode, self.name, self.pic) message += "{barcode} : Found {name} from OpenFoodFacts.\n" message += "{barcode} : {name} added to cache.\n" else: message += "{barcode} : Not found locally nor on OpenFoodFacts.\n" # If not found : add as unknown item (name = ???) if not found: self.name = '???' self.pic = False products.add_item(self.barcode, self.name, self.pic) message += "{barcode} : Unknown product added to the database.\n" # If the product's already present in the grocery list: increase its quantity by 1 previous = groceries.get_item(self.barcode) if previous: self.quantity = previous['quantity'] + 1 groceries.edit_item(self.barcode, self.quantity) message += "{barcode} : {quantity} {name} now in grocery list.\n" # Otherwise : add it else: groceries.add_item(self.barcode, 1) message += "{barcode} : 1 {name} added to the grocery list.\n" # Disconnect the database, allowing it to be used by another thread Database.off() # Print message message = message.format(barcode=self.barcode, name=self.name, quantity=self.quantity) print(message)