# Path: controllers/web.py
# def login():
# def logout():
# def groceries():
# def api_groceries_list():
# def api_groceries_edit(barcode, quantity):
# def products():
# def api_products_list():
# def api_products_edit(barcode, name):
# def api_products_delete(barcode):
# def api_lang():
# 
# Path: utils/database.py
# class Database:
#     """
#     This class handles :
#     - Provides a link and a cursor to the database as class attributes
#     Usage :
#     - Database.on()
#     - Database.CURSOR.execute(query, params)
#     - ... etc
#     - Database.off()
#     Available class attributes :
#     - LINK
#     - CURSOR
#     - FILE (path to the database file)
#     """
#     DATABASE_PRODUCTION = 'database.db'
#     """ Normal database filename """
#     DATABASE_TEST = 'database_test.db'
#     """ Test database filename : this database is temporary """
#     TEST_MODE = False
#     """ Does it need to use the test database ? """
# 
#     @classmethod
#     def on(cls):
#         """
#         Connect to the database
#         :rtype: bool
#         """
#         # Don't reconnect if already connected
#         if cls.is_ready():
#             return False
# 
#         # Filename
#         cls.FILE = cls.DATABASE_PRODUCTION
# 
#         if cls.TEST_MODE:
#             cls.FILE = cls.DATABASE_TEST
# 
#         # Connect
#         cls.LINK = sqlite3.connect(cls.FILE)
#         cls.LINK.row_factory = sqlite3.Row
#         cls.CURSOR = cls.LINK.cursor()
# 
#         return True
# 
#     @classmethod
#     def off(cls):
#         """
#         Ends connection with the database.
#         :rtype: bool
#         """
#         if cls.LINK:
#             cls.LINK.close()
#         cls.LINK = None
#         cls.CURSOR = None
#         return True
# 
#     @classmethod
#     def is_ready(cls):
#         """
#         Is the connection open ?
#         :rtype: bool
#         """
#         return hasattr(cls, 'LINK') and cls.LINK != None
# 
# Path: utils/lang.py
# class Lang:
#     """
#     Internationalization tool.
#     Loads messages in a given language and keeps them as object attributes.
#     Usage :
#     - lang = Lang('en')
#     - lang.message_key
#     """
#     LANG_PATH = 'assets/lang/'
#     """ Defines lang files directory """
# 
#     def __init__(self, language='en'):
#         """
#         Loads a lang file's content as class attributes.
#         Tries to find given language, falls back to english if needed.
#         :param language: language to load (default : en)
#         :type language: str
#         :rtype: bool
#         """
#         self.language = language
#         self.language = self.language.replace('..', '')
#         self.language = self.language.replace('/', '')
# 
#         # Path to the "lang" directory
#         langfile = Lang.LANG_PATH + self.language + '.json'
# 
#         # Is the wanted language available ?
#         if not os.path.isfile(langfile):
#             langfile = Lang.LANG_PATH + 'en.json' # Load default
#             self.language = 'en'
# 
#         # Load file
#         data = open(langfile, encoding='utf-8').read()
#         data = json.loads(data)
# 
#         # Load keys as attributes
#         for key, value in data.items():
#             setattr(self, key, value)
# 
#     @classmethod
#     def available(cls):
#         """
#         Returns a list of available languages
#         :rtype: list
#         """
#         available = []
#         for langfile in os.listdir(Lang.LANG_PATH):
#             if os.path.isfile(Lang.LANG_PATH + langfile):
#                 available.append(langfile.replace('.json', ''))
# 
#         return available


import os
import getpass
import hashlib
import json
import models
import controllers
import utils
from flask import session
from controllers import webapp
from utils import Database, Lang

            if phrase == lang.config_password:
                return "1234abcd"

            if phrase == lang.config_language_set:
                return 'en'

        monkeypatch.setitem(__builtins__, 'input', input_monkeypatched_valid)
        monkeypatch.setattr(getpass, 'getpass', input_monkeypatched_valid)

        # Launch
        controllers.Config.execute()

        # Test
        params = models.Params()
        assert params.buzzer_on == 1
        assert params.buzzer_port == 7
        assert params.camera_res_x == 500
        assert params.camera_res_y == 500
        assert params.user_password
        assert params.lang == 'en'

    def test_execute_invalid(self, monkeypatch):
        """
        Tests the configuration assistant with invalid parameters.
        Uses a dummy database.
        Success conditions :
        - The database has been created and contains fallback data
        """
        # Language

# Path: controllers/web.py
# def login():
# def logout():
# def groceries():
# def api_groceries_list():
# def api_groceries_edit(barcode, quantity):
# def products():
# def api_products_list():
# def api_products_edit(barcode, name):
# def api_products_delete(barcode):
# def api_lang():
# 
# Path: utils/database.py
# class Database:
#     """
#     This class handles :
#     - Provides a link and a cursor to the database as class attributes
#     Usage :
#     - Database.on()
#     - Database.CURSOR.execute(query, params)
#     - ... etc
#     - Database.off()
#     Available class attributes :
#     - LINK
#     - CURSOR
#     - FILE (path to the database file)
#     """
#     DATABASE_PRODUCTION = 'database.db'
#     """ Normal database filename """
#     DATABASE_TEST = 'database_test.db'
#     """ Test database filename : this database is temporary """
#     TEST_MODE = False
#     """ Does it need to use the test database ? """
# 
#     @classmethod
#     def on(cls):
#         """
#         Connect to the database
#         :rtype: bool
#         """
#         # Don't reconnect if already connected
#         if cls.is_ready():
#             return False
# 
#         # Filename
#         cls.FILE = cls.DATABASE_PRODUCTION
# 
#         if cls.TEST_MODE:
#             cls.FILE = cls.DATABASE_TEST
# 
#         # Connect
#         cls.LINK = sqlite3.connect(cls.FILE)
#         cls.LINK.row_factory = sqlite3.Row
#         cls.CURSOR = cls.LINK.cursor()
# 
#         return True
# 
#     @classmethod
#     def off(cls):
#         """
#         Ends connection with the database.
#         :rtype: bool
#         """
#         if cls.LINK:
#             cls.LINK.close()
#         cls.LINK = None
#         cls.CURSOR = None
#         return True
# 
#     @classmethod
#     def is_ready(cls):
#         """
#         Is the connection open ?
#         :rtype: bool
#         """
#         return hasattr(cls, 'LINK') and cls.LINK != None
# 
# Path: utils/lang.py
# class Lang:
#     """
#     Internationalization tool.
#     Loads messages in a given language and keeps them as object attributes.
#     Usage :
#     - lang = Lang('en')
#     - lang.message_key
#     """
#     LANG_PATH = 'assets/lang/'
#     """ Defines lang files directory """
# 
#     def __init__(self, language='en'):
#         """
#         Loads a lang file's content as class attributes.
#         Tries to find given language, falls back to english if needed.
#         :param language: language to load (default : en)
#         :type language: str
#         :rtype: bool
#         """
#         self.language = language
#         self.language = self.language.replace('..', '')
#         self.language = self.language.replace('/', '')
# 
#         # Path to the "lang" directory
#         langfile = Lang.LANG_PATH + self.language + '.json'
# 
#         # Is the wanted language available ?
#         if not os.path.isfile(langfile):
#             langfile = Lang.LANG_PATH + 'en.json' # Load default
#             self.language = 'en'
# 
#         # Load file
#         data = open(langfile, encoding='utf-8').read()
#         data = json.loads(data)
# 
#         # Load keys as attributes
#         for key, value in data.items():
#             setattr(self, key, value)
# 
#     @classmethod
#     def available(cls):
#         """
#         Returns a list of available languages
#         :rtype: list
#         """
#         available = []
#         for langfile in os.listdir(Lang.LANG_PATH):
#             if os.path.isfile(Lang.LANG_PATH + langfile):
#                 available.append(langfile.replace('.json', ''))
# 
#         return available


# Path: tests/test_controllers.py
import os
import getpass
import hashlib
import json
import models
import controllers
import utils
from flask import session
from controllers import webapp
from utils import Database, Lang


            if phrase == lang.config_password:
                return "1234abcd"

            if phrase == lang.config_language_set:
                return 'en'

        monkeypatch.setitem(__builtins__, 'input', input_monkeypatched_valid)
        monkeypatch.setattr(getpass, 'getpass', input_monkeypatched_valid)

        # Launch
        controllers.Config.execute()

        # Test
        params = models.Params()
        assert params.buzzer_on == 1
        assert params.buzzer_port == 7
        assert params.camera_res_x == 500
        assert params.camera_res_y == 500
        assert params.user_password
        assert params.lang == 'en'

    def test_execute_invalid(self, monkeypatch):
        """
        Tests the configuration assistant with invalid parameters.
        Uses a dummy database.
        Success conditions :
        - The database has been created and contains fallback data
        """
        # Language

        lang = Lang()