class AbstractPersister(ABC):
    def __init__(self):
        self.handler = ErrorHandler(module="AbstractPersister",
                                    method="__init__")

    @abc.abstractmethod
    def load(self, key=None):
        save_module_name = self.handler.module
        self.handler.module = "Base Persister"
        self.handler.method = "load"
        self.handler.log(message="Validating key: {}".format(key))
        if key is None:
            raise ValueError("Key must be present to load a persisted game.")
        self.handler.module = save_module_name

    @abc.abstractmethod
    def save(self, key=None, jsonstr=None):
        save_module_name = self.handler.module
        self.handler.module = "Base Persister"
        self.handler.method = "save"

        self.handler.log(message="Base persistence processing")

        self.handler.log(message="Validating key: {}".format(key))
        if key is None:
            raise ValueError("Key must be present to persist game.")

        self.handler.log(message="Validating json: {}".format(jsonstr))
        if jsonstr is None:
            raise ValueError("JSON is badly formed or not present")

        self.handler.log(
            message="Saving key {} with {} to persister".format(key, jsonstr))

        self.handler.module = save_module_name
 def test_he_check_error(self):
     eh = ErrorHandler(module="TEST",
                       method="TEST-METHOD",
                       level=logging.INFO)
     message = "Message for testing purposes only"
     exception = "IGNORE Testing"
     r = eh.error(status=404, message=message, exception=exception)
     r_data = json.loads(r.get_data())
     self.assertEqual(r_data["status"], 404)
     self.assertEqual(r_data["message"], message)
     self.assertEqual(r_data["exception"], exception)
    def execute_load(self, app):
        if app is None:
            raise ValueError(
                "The Flask app must be passed to the Configurator")
        if not isinstance(app, Flask):
            raise TypeError("Expected a Flask object, received {0}".format(
                type(app)))

        self.app = app
        self.app.config["PYTHON_VERSION_MAJOR"] = sys.version_info[0]

        self.app.config["LOGGING_FORMAT"] = os.getenv(
            "logging_format",
            os.getenv("LOGGING_FORMAT",
                      "%(asctime)s %(levelname)s: %(message)s"))
        self.app.config["LOGGING_LEVEL"] = os.getenv(
            "logging_level", os.getenv("LOGGING_LEVEL", logging.INFO))

        self.error_handler = ErrorHandler(
            module="Configurator",
            method="__init__",
            level=self.app.config["LOGGING_LEVEL"],
            format=self.app.config["LOGGING_FORMAT"])

        self.error_handler.log(
            message="Initialized logging (level: {}, format: {})".format(
                self.app.config["LOGGING_LEVEL"],
                self.app.config["LOGGING_FORMAT"]),
            logger=logging.info)

        self.error_handler.log(message="Configuring environment variables.",
                               logger=logging.info)

        self.configuration = {}

        config_file = self._set_config(source=os.getenv, name="COWBULL_CONFIG")
        self.app.config["COWBULL_CONFIG"] = config_file

        self.error_handler.log(message="Loading configuration from: {}".format(
            config_file if config_file else "environment variables"))

        source = {}
        if config_file:
            _file = open(config_file, 'r')
            try:
                source = json.load(_file)
            except:
                raise
            finally:
                _file.close()

        self.load_variables(source=source)
Пример #4
0
 def setUpClass(cls):
     error_handler = ErrorHandler()
     v1 = V1(error_handler=error_handler, app=app)
     v1.game(controller=GameServerController)
     v1.modes(controller=GameModes)
     v1.health(controller=HealthCheck)
     v1.readiness(controller=Readiness)
Пример #5
0
 def setUp(self):
     self.eh = ErrorHandler(module="TestFlaskControllers", )
     self.app = app.test_client()
     self.application = self.app.application
     c = Configurator()
     if self.application.config["PYTHON_VERSION_MAJOR"] < 3:
         self.json_raises = ValueError
     else:
         self.json_raises = json.JSONDecodeError
    def setUp(self):
        self.error_handler = ErrorHandler(module="TestErrorHandler",
                                          method="setUp")
        self.app = app.test_client()
        if app.config["PYTHON_VERSION_MAJOR"] < 3:
            self.logging_type = io.BytesIO
        else:
            self.logging_type = io.StringIO

        self.logger = self.error_handler.logger
        self.lhStdout = self.logger.handlers[0]

        self.current_log_level = self.logger.getEffectiveLevel()
        self.log_capture = self.logging_type()
        self.sh = logging.StreamHandler(stream=self.log_capture)

        self.logger.setLevel(logging.INFO)
        self.logger.addHandler(hdlr=self.sh)
        self.logger.removeHandler(self.lhStdout)
 def test_eh_instantiation(self):
     eh = ErrorHandler(module="test_module", method="test_method")
     self.assertIsInstance(eh, ErrorHandler)
     self.assertEqual(eh.module, "test_module")
     self.assertEqual(eh.method, "test_method")
 def test_he_eh_init(self):
     eh = ErrorHandler(module="test_he",
                       method="test_he_eh_init",
                       level=logging.ERROR)
     self.assertIsInstance(eh, ErrorHandler)
 def test_he_check_warn(self):
     eh = ErrorHandler(module="TEST",
                       method="TEST-METHOD",
                       level=logging.ERROR)
     message = "Message for testing purposes only"
     eh.log(status=404, message=message, logger=logging.warning)
 def test_he_bad_module(self):
     with self.assertRaises(TypeError):
         ErrorHandler(module=-2, method="test_he_eh_init", level=10)
Пример #11
0
 def __init__(self):
     self.handler = ErrorHandler(
         module="AbstractPersister",
         method="__init__",
     )
Пример #12
0
class Configurator(object):
    """
    Provides a configuration control to enable the Python Cowbull Server to execute_load
    configuration from a set of variables or from a configuration file.
    """
    def __init__(self):
        self.app = None
        self.configuration = {}
        self.error_handler = None
        self.env_vars = [{
            "name": "PERSISTER",
            "description": "The persistence engine object",
            "required": False,
            "default":
            '{"engine_name": "redis", "parameters": {"host": "localhost", "port": 6379, "db": 0}}',
            "caster": PersistenceEngine
        }, {
            "name": "FLASK_HOST",
            "description":
            "For debug purposes, defines the Flask host. Default is 0.0.0.0",
            "required": False,
            "default": "0.0.0.0"
        }, {
            "name": "FLASK_PORT",
            "description":
            "For debug purposes, the port Flask should serve on. Default is 5000",
            "required": False,
            "default": 5000,
            "caster": int
        }, {
            "name": "FLASK_DEBUG",
            "description": "For debug purposes, set Flask into debug mode.",
            "required": False,
            "default": True,
            "caster": bool
        }, {
            "name":
            "COWBULL_DRY_RUN",
            "description":
            "Do not run the server, simply report the configuration that would "
            "be used to run it.",
            "required":
            False,
            "default":
            False,
            "caster":
            bool
        }, {
            "name":
            "COWBULL_CUSTOM_MODES",
            "description":
            "A file which defines additional "
            "modes to be defined in addition to the default modes. The "
            "file must be a list of JSON objects containing mode "
            "definitions. Each object must contain (at a minimum): mode, digits, and "
            "priority",
            "required":
            False,
            "default":
            None,
            "caster":
            self._load_from_json
        }]

    def execute_load(self, app):
        if app is None:
            raise ValueError(
                "The Flask app must be passed to the Configurator")
        if not isinstance(app, Flask):
            raise TypeError("Expected a Flask object")

        self.app = app
        self.app.config["PYTHON_VERSION_MAJOR"] = sys.version_info[0]

        self.app.config["LOGGING_FORMAT"] = os.getenv(
            "logging_format",
            os.getenv("LOGGING_FORMAT",
                      "%(asctime)s %(levelname)s: %(message)s"))
        self.app.config["LOGGING_LEVEL"] = os.getenv(
            "logging_level", os.getenv("LOGGING_LEVEL", logging.WARNING))

        self.error_handler = ErrorHandler(
            module="Configurator",
            method="__init__",
            level=self.app.config["LOGGING_LEVEL"],
            format=self.app.config["LOGGING_FORMAT"])

        self.error_handler.log(
            message="Initialized logging (level: {}, format: {})".format(
                self.app.config["LOGGING_LEVEL"],
                self.app.config["LOGGING_FORMAT"]),
            logger=logging.info)

        self.error_handler.log(message="Configuring environment variables.",
                               logger=logging.info)

        self.configuration = {}

        config_file = self._set_config(source=os.getenv, name="COWBULL_CONFIG")
        self.app.config["COWBULL_CONFIG"] = config_file

        self.error_handler.log(message="Loading configuration from: {}".format(
            config_file if config_file else "environment variables"))

        source = {}
        if config_file:
            _file = open(config_file, 'r')
            try:
                source = json.load(_file)
            except:
                raise
            finally:
                _file.close()

        self.load_variables(source=source)

    def get_variables(self):
        return [
                   ("LOGGING_LEVEL", "An integer representing the Python "
                                     "logging level (e.g. 10 for debug, 20 for warning, etc.)"),
                   ("LOGGING_FORMAT", "The format for logs. The default is >> "
                                      "%(asctime)s %(levelname)s: %(message)s"),
                   ("COWBULL_CONFIG", "A path and filename of a configuration file "
                                      "used to set env. vars. e.g. /path/to/the/file.cfg")
               ]\
               + [(i["name"], i["description"]) for i in self.env_vars]

    def dump_variables(self):
        return [
                   ("LOGGING_LEVEL", self.app.config["LOGGING_LEVEL"]),
                   ("LOGGING_FORMAT", self.app.config["LOGGING_FORMAT"]),
                   ("COWBULL_CONFIG", self.app.config["COWBULL_CONFIG"])
               ] \
               + \
               [(i["name"], self.app.config[i["name"]]) for i in self.env_vars]

    def print_variables(self):
        print('')
        print('=' * 80)
        print('=', ' ' * 30, 'CONFIGURATION', ' ' * 31, '=')
        print('=' * 80)
        print(
            'The following environment variables may be set to dynamically configure the'
        )
        print(
            'server. Alternately, these can be defined in a file and passed using the env.'
        )
        print(
            'var. COWBULL_CONFIG. Please note, the file must be a JSON data object.'
        )
        print('')
        print(
            'Please note. Env. Var. names can be *ALL* lowercase or *ALL* uppercase.'
        )
        print('')
        print('-' * 80)
        print('| Current configuration set:')
        print('-' * 80)
        for name, val in self.dump_variables():
            outstr = "| {:20s} | {}".format(name, val)
            print(outstr)
        print('-' * 80)
        print('')

    def load_variables(self, source=None):
        if source:
            _fetch = source.get
        else:
            _fetch = os.getenv

        for item in self.env_vars:
            if isinstance(item, dict):
                self._set_config(source=_fetch, **item)
            elif isinstance(item, str):
                self._set_config(name=item, source=_fetch)
            elif isinstance(item, list):
                self.load_variables(source=item)
            else:
                raise TypeError(
                    "Unexpected item in configuration: {}, type: {}".format(
                        item, type(item)))

    def _set_config(self,
                    source=None,
                    name=None,
                    description=None,
                    required=None,
                    default=None,
                    errmsg=None,
                    caster=None,
                    choices=None):
        value = source(name.lower(), source(name.upper(), None))

        if required and value is None and default is None:
            raise ValueError(
                errmsg or "Problem fetching config item: "
                "{}. It is required and was not found or the value was None.".
                format(name))

        if value is None:
            value = default

        if caster:
            if caster == PersistenceEngine:
                if not isinstance(value, dict):
                    #
                    # Added .replace to remove single quotes being added by PyCharm
                    #
                    value = json.loads(str(value).replace("'", ""))
                value = caster(**value)
            else:
                value = caster(value)

        if choices:
            if value not in choices:
                raise ValueError(
                    errmsg or
                    "The configuration value for {}({}) is not in the list of choices: ()"
                    .format(name, value, choices))

        self.app.config[name] = value
        return value

    def _load_from_json(self, json_file_name):
        if not json_file_name:
            return None

        f = None
        return_value = None

        try:
            f = open(json_file_name, 'r')
            return_value = json.load(f)
        except Exception as e:
            self.error_handler.error(module="Configurator.py",
                                     method="_load_from_json",
                                     status=500,
                                     exception=repr(e),
                                     message="An exception occurred!")
            raise IOError(
                "A JSON file ({}) cannot be loaded. Exception: {}".format(
                    json_file_name, repr(e)))
        finally:
            if f:
                f.close()
        return return_value
class Configurator(object):
    """
    Provides a configuration control to enable the Python Cowbull Server to execute_load
    configuration from a set of variables or from a configuration file.
    """
    def __init__(self):
        self.app = None
        self.configuration = {}
        self.error_handler = None
        default_config_file = "./python_cowbull_server/defaults.config"
        self.env_vars = self._load_defaults(default_config_file)

    def execute_load(self, app):
        if app is None:
            raise ValueError(
                "The Flask app must be passed to the Configurator")
        if not isinstance(app, Flask):
            raise TypeError("Expected a Flask object, received {0}".format(
                type(app)))

        self.app = app
        self.app.config["PYTHON_VERSION_MAJOR"] = sys.version_info[0]

        self.app.config["LOGGING_FORMAT"] = os.getenv(
            "logging_format",
            os.getenv("LOGGING_FORMAT",
                      "%(asctime)s %(levelname)s: %(message)s"))
        self.app.config["LOGGING_LEVEL"] = os.getenv(
            "logging_level", os.getenv("LOGGING_LEVEL", logging.INFO))

        self.error_handler = ErrorHandler(
            module="Configurator",
            method="__init__",
            level=self.app.config["LOGGING_LEVEL"],
            format=self.app.config["LOGGING_FORMAT"])

        self.error_handler.log(
            message="Initialized logging (level: {}, format: {})".format(
                self.app.config["LOGGING_LEVEL"],
                self.app.config["LOGGING_FORMAT"]),
            logger=logging.info)

        self.error_handler.log(message="Configuring environment variables.",
                               logger=logging.info)

        self.configuration = {}

        config_file = self._set_config(source=os.getenv, name="COWBULL_CONFIG")
        self.app.config["COWBULL_CONFIG"] = config_file

        self.error_handler.log(message="Loading configuration from: {}".format(
            config_file if config_file else "environment variables"))

        source = {}
        if config_file:
            _file = open(config_file, 'r')
            try:
                source = json.load(_file)
            except:
                raise
            finally:
                _file.close()

        self.load_variables(source=source)

    def get_variables(self):
        return [
                   ("LOGGING_LEVEL", "An integer representing the Python "
                                     "logging level (e.g. 10 for debug, 20 for warning, etc.)"),
                   ("LOGGING_FORMAT", "The format for logs. The default is >> "
                                      "%(asctime)s %(levelname)s: %(message)s"),
                   ("COWBULL_CONFIG", "A path and filename of a configuration file "
                                      "used to set env. vars. e.g. /path/to/the/file.cfg")
               ]\
               + [(i["name"], i["description"]) for i in self.env_vars]

    def dump_variables(self):
        return [
                   ("LOGGING_LEVEL", self.app.config["LOGGING_LEVEL"]),
                   ("LOGGING_FORMAT", self.app.config["LOGGING_FORMAT"]),
                   ("COWBULL_CONFIG", self.app.config["COWBULL_CONFIG"])
               ] \
               + \
               [(i["name"], self.app.config[i["name"]]) for i in self.env_vars]

    def print_variables(self):
        print('')
        print('=' * 80)
        print('=', ' ' * 30, 'CONFIGURATION', ' ' * 31, '=')
        print('=' * 80)
        print(
            'The following environment variables may be set to dynamically configure the'
        )
        print(
            'server. Alternately, these can be defined in a file and passed using the env.'
        )
        print(
            'var. COWBULL_CONFIG. Please note, the file must be a JSON data object.'
        )
        print('')
        print(
            'Please note 1: Env. Var. names can be *ALL* lowercase or *ALL* uppercase.'
        )
        print(
            'Please note 2: FLASK_ env. vars. are ignored when using gUnicorn.'
        )
        print('')
        print('-' * 80)
        print('| Current configuration set:')
        print('-' * 80)
        for name, val in self.dump_variables():
            outstr = "| {:20s} | {}".format(name, val)
            print(outstr)
        print('-' * 80)
        print('')

    def load_variables(self, source=None):
        if source:
            _fetch = source.get
        else:
            _fetch = os.getenv

        for item in self.env_vars:
            self.error_handler.log(method="load_variables",
                                   message="Processing {} of type {}".format(
                                       item.get("name", "no name provided"),
                                       item.get("caster", "string")),
                                   logger=logging.debug)
            if isinstance(item, dict):
                self.error_handler.log(method="load_variables",
                                       message="Item is a dict: {}".format(
                                           item.get("name", "unknown name")),
                                       logger=logging.debug)
                self._set_config(source=_fetch, **item)
            elif isinstance(item, str):
                self.error_handler.log(method="load_variables",
                                       message="Item is a string: {}".format(
                                           item.get("name", "unknown name")),
                                       logger=logging.debug)
                self._set_config(name=item, source=_fetch)
            elif isinstance(item, list):
                self.error_handler.log(method="load_variables",
                                       message="Item is a list: {}".format(
                                           item.get("name", "unknown name")),
                                       logger=logging.debug)
                self.load_variables(source=item)
            else:
                raise TypeError(
                    "Unexpected item in configuration: {}, type: {}".format(
                        item, type(item)))

    def _load_defaults(self, source):
        if not source:
            raise ValueError("Source for _load_defaults is None!")

        f = None
        try:
            f = open(source, 'r')
            _defaults = json.load(f)
        except IOError:
            raise IOError("The source file for _load_defaults was not found!")
        finally:
            if f:
                f.close()

        _persister_default = {
            "engine_name": "redis",
            "parameters": {
                "host": "{0}".format(_defaults["redis_host"]),
                "port": _defaults["redis_port"],
                "db": 0
            }
        }
        _persister = {
            "name": "PERSISTER",
            "description": "The persistence engine object",
            "required": False,
            "default": json.dumps(_persister_default),
            "caster": PersistenceEngine
        }
        _flask_host = {
            "name": "FLASK_HOST",
            "description":
            "For debug purposes, defines the Flask host. Default is all traffic *not* localhost",
            "required": False,
            "default": "{0}".format(_defaults["flask_host"])
        }
        _flask_port = {
            "name": "FLASK_PORT",
            "description":
            "For debug purposes, the port Flask should serve on. Default is 5000",
            "required": False,
            "default": _defaults["flask_port"],
            "caster": int
        }
        _flask_debug = {
            "name": "FLASK_DEBUG",
            "description": "For debug purposes, set Flask into debug mode.",
            "required": False,
            "default": _defaults["flask_debug"],
            "caster": bool
        }
        _cowbull_dry_run = {
            "name":
            "COWBULL_DRY_RUN",
            "description":
            "Do not run the server, simply report the configuration that would "
            "be used to run it.",
            "required":
            False,
            "default":
            False,
            "caster":
            bool
        }
        _cowbull_custom_modes = {
            "name":
            "COWBULL_CUSTOM_MODES",
            "description":
            "A file which defines additional "
            "modes to be defined in addition to the default modes. The "
            "file must be a list of JSON objects containing mode "
            "definitions. Each object must contain (at a minimum): mode, digits, and "
            "priority",
            "required":
            False,
            "default":
            None,
            "caster":
            self._load_from_json
        }

        return [
            _persister, _flask_host, _flask_port, _flask_debug,
            _cowbull_dry_run, _cowbull_custom_modes
        ]

    # http://sonarqube:9000/project/issues?id=cowbull_server&issues=AWiRMKAZaAhZ-jY-ujHl&open=AWiRMKAZaAhZ-jY-ujHl
    def _set_config(self, **kwargs):
        check_kwargs(parameter_list=[
            "source", "name", "description", "required", "default", "errmsg",
            "caster", "choices"
        ],
                     caller="Configurator-_set_config",
                     **kwargs)
        source = kwargs.get("source", None)
        name = kwargs.get("name", None)
        description = kwargs.get("description", None)
        required = kwargs.get("required", None)
        default = kwargs.get("default", None)
        errmsg = kwargs.get("errmsg", None)
        caster = kwargs.get("caster", None)
        choices = kwargs.get("choices", None)

        self.error_handler.log(
            method="_set_config",
            message=
            "In _set_config -- source: {}, name: {}, description: {}, required: {}, default: {}, errmsg: {}, caster: {}, choices: {}"
            .format(source, name, description, required, default, errmsg,
                    caster, choices),
            logger=logging.debug)
        value = source(name.lower(), source(name.upper(), None))

        if required and value is None and default is None:
            raise ValueError(
                errmsg or "Problem fetching config item: "
                "{}. It is required and was not found or the value was None.".
                format(name))

        self.error_handler.log(method="_set_config",
                               message="Before casting: {}".format(value),
                               logger=logging.debug)

        if value is None:
            value = default

        if caster:
            if caster == PersistenceEngine:
                if not isinstance(value, dict):
                    value = json.loads(str(value).replace("'", ""))
                value = caster(**value)
            elif caster == bool and isinstance(value, str):
                if value.lower() == "false":
                    value = False
                else:
                    value = True
            else:
                value = caster(value)

        self.error_handler.log(method="_set_config",
                               message="After casting: {}".format(value),
                               logger=logging.debug)

        if choices and value not in choices:
            raise ValueError(
                errmsg or
                "The configuration value for {}({}) is not in the list of choices: {}"
                .format(name, value, choices))

        self.app.config[name] = value
        self.error_handler.log(
            message="In _set_config Set app.config[{}] = {}".format(
                name, value),
            logger=logging.debug)
        return value

    def _load_from_json(self, json_file_name):
        if not json_file_name:
            return None

        f = None
        return_value = None

        try:
            f = open(json_file_name, 'r')
            return_value = json.load(f)
        except Exception as e:
            self.error_handler.error(module="Configurator.py",
                                     method="_load_from_json",
                                     status=500,
                                     exception=repr(e),
                                     message="An exception occurred!")
            raise IOError(
                "A JSON file ({}) cannot be loaded. Exception: {}".format(
                    json_file_name, repr(e)))
        finally:
            if f:
                f.close()
        return return_value
 def test_he_type_error(self):
     eh = ErrorHandler(module="TEST",
                       method="TEST-METHOD",
                       level={"foobar": "logging.INFO"})
     self.assertEqual(eh.logger.level, logging.INFO)
class TestErrorHandler(TestCase):
    def setUp(self):
        self.error_handler = ErrorHandler(module="TestErrorHandler",
                                          method="setUp")
        self.app = app.test_client()
        if app.config["PYTHON_VERSION_MAJOR"] < 3:
            self.logging_type = io.BytesIO
        else:
            self.logging_type = io.StringIO

        self.logger = self.error_handler.logger
        self.lhStdout = self.logger.handlers[0]

        self.current_log_level = self.logger.getEffectiveLevel()
        self.log_capture = self.logging_type()
        self.sh = logging.StreamHandler(stream=self.log_capture)

        self.logger.setLevel(logging.INFO)
        self.logger.addHandler(hdlr=self.sh)
        self.logger.removeHandler(self.lhStdout)

    def tearDown(self):
        self.logger.addHandler(self.lhStdout)
        self.logger.removeHandler(self.sh)
        self.logger.setLevel(self.current_log_level)

    def test_eh_instantiation(self):
        eh = ErrorHandler(module="test_module", method="test_method")
        self.assertIsInstance(eh, ErrorHandler)
        self.assertEqual(eh.module, "test_module")
        self.assertEqual(eh.method, "test_method")

    def test_eh_get_logger(self):
        logger = self.error_handler.logger
        self.assertIsInstance(logger, logging.RootLogger)

    def test_eh_error(self):
        self.error_handler.method = "test_eh_error"
        result = self.error_handler.error(
            status=400,
            exception="This is an exception for test purposes only",
            message="This is a message for test purposes only")
        self.assertIsInstance(result, Response)
        self.assertEqual(result.status_code, 400)

    def test_eh_logging_info(self):
        self.error_handler.method = "test_eh_logging_info"
        test_message = "This is a test message for logging"
        eval_message = "{}: {}: {}\n".format(self.error_handler.module,
                                             self.error_handler.method,
                                             test_message)
        self.error_handler.logger.setLevel(logging.INFO)
        self.error_handler.log(logger=logging.info, message=test_message)
        logged_output = self.log_capture.getvalue()
        self.assertEqual(logged_output, eval_message)

    def test_eh_logging_debug(self):
        self.error_handler.method = "test_eh_logging_debug"
        test_message = "This is a debug message for logging"
        eval_message = "{}: {}: {}\n".format(self.error_handler.module,
                                             self.error_handler.method,
                                             test_message)
        self.error_handler.logger.setLevel(logging.DEBUG)
        self.error_handler.log(logger=logging.debug, message=test_message)
        logged_output = self.log_capture.getvalue()
        self.assertEqual(logged_output, eval_message)
Пример #16
0
    def __init__(self, **kwargs):
        self.handler = ErrorHandler(module="PersistenceEngine",
                                    method="__init__")

        self.handler.log(message="Getting persistence engine arguments")
        engine_name = kwargs.get('engine_name', None)
        parameters = kwargs.get('parameters', None)

        if not engine_name:
            raise ValueError(
                "'engine_name' must be defined for the persistence engine")
        if not isinstance(parameters, dict):
            raise TypeError("'parameters' must be a dictionary of objects")

        self._engine_name = engine_name
        self._parameters = parameters
        self._persister = None

        # Step 1 - Build path
        self.handler.log(message="Build import path")
        cwd = getcwd()
        extension_path = "{}/{}".format(cwd, "PersistenceExtensions")
        self.handler.log(
            message="Added {} to import path".format(extension_path))

        path.append(extension_path)

        # Step 2 - get the persisters and choose the right one
        self.handler.log(message="Building persisters and validators")
        persisters = [
            filefound[:-3] for filefound in listdir(extension_path)
            if filefound.endswith(".py")
        ]
        validators = [filefound.lower() for filefound in persisters]
        self.handler.log(message="Persisters: {}".format(persisters))
        self.handler.log(message="Validators: {}".format(validators))

        try:
            self.handler.log(message="Set persister")
            self._engine_name = persisters[validators.index(self._engine_name)]

            self.handler.log(message="Importing Persister from {}".format(
                self._engine_name))
            self._persister = importlib.import_module(self._engine_name)

            self.handler.log(message="Persistence engine set to {}".format(
                self._engine_name))
        except ValueError:
            if self._engine_name.lower() == 'redis':
                self.handler.log(message="Redis selected")
            else:
                self.handler.log(
                    message="Persister {} not found, defaulting to Redis".
                    format(self._engine_name))

            self._engine_name = "RedisPersist"

            self.handler.log(message="Importing RedisPersist")
            from Persistence import Redis
            self._persister = Redis
            self.handler.log(message="Persistence engine defaulted to Redis")
        except Exception:
            raise

        if not issubclass(self._persister.Persister, AbstractPersister):
            raise TypeError(
                "The persister must be a subclass of an AbstractPersister!")
        else:
            self.handler.log(
                message=
                "{} validated as a concrete implementation of an AbstractPersister"
                .format(self._engine_name))

        self.handler.log(message="Instantiating Persister")
        self._persister = self._persister.Persister(**self._parameters)
        return
Пример #17
0
class PersistenceEngine(object):
    def __init__(self, **kwargs):
        self.handler = ErrorHandler(module="PersistenceEngine",
                                    method="__init__")

        self.handler.log(message="Getting persistence engine arguments")
        engine_name = kwargs.get('engine_name', None)
        parameters = kwargs.get('parameters', None)

        if not engine_name:
            raise ValueError(
                "'engine_name' must be defined for the persistence engine")
        if not isinstance(parameters, dict):
            raise TypeError("'parameters' must be a dictionary of objects")

        self._engine_name = engine_name
        self._parameters = parameters
        self._persister = None

        # Step 1 - Build path
        self.handler.log(message="Build import path")
        cwd = getcwd()
        extension_path = "{}/{}".format(cwd, "PersistenceExtensions")
        self.handler.log(
            message="Added {} to import path".format(extension_path))

        path.append(extension_path)

        # Step 2 - get the persisters and choose the right one
        self.handler.log(message="Building persisters and validators")
        persisters = [
            filefound[:-3] for filefound in listdir(extension_path)
            if filefound.endswith(".py")
        ]
        validators = [filefound.lower() for filefound in persisters]
        self.handler.log(message="Persisters: {}".format(persisters))
        self.handler.log(message="Validators: {}".format(validators))

        try:
            self.handler.log(message="Set persister")
            self._engine_name = persisters[validators.index(self._engine_name)]

            self.handler.log(message="Importing Persister from {}".format(
                self._engine_name))
            self._persister = importlib.import_module(self._engine_name)

            self.handler.log(message="Persistence engine set to {}".format(
                self._engine_name))
        except ValueError:
            if self._engine_name.lower() == 'redis':
                self.handler.log(message="Redis selected")
            else:
                self.handler.log(
                    message="Persister {} not found, defaulting to Redis".
                    format(self._engine_name))

            self._engine_name = "RedisPersist"

            self.handler.log(message="Importing RedisPersist")
            from Persistence import Redis
            self._persister = Redis
            self.handler.log(message="Persistence engine defaulted to Redis")
        except Exception:
            raise

        if not issubclass(self._persister.Persister, AbstractPersister):
            raise TypeError(
                "The persister must be a subclass of an AbstractPersister!")
        else:
            self.handler.log(
                message=
                "{} validated as a concrete implementation of an AbstractPersister"
                .format(self._engine_name))

        self.handler.log(message="Instantiating Persister")
        self._persister = self._persister.Persister(**self._parameters)
        return

    @property
    def engine_name(self):
        return self._engine_name

    @property
    def parameters(self):
        return self._parameters

    @property
    def persister(self):
        return self._persister

    def __repr__(self):
        return "<persister>{}".format(self._engine_name)

    #
    # 'Private' methods
    #
    def _validate_persister_functions(self):
        _key = "abc"
        _content = '{"foo":"bar"}'
        self._persister.save(_key, _content)
        _fetch_key = self._persister.load(_key)
        if str(_content) != str(_fetch_key):
            raise ValueError("Persister {} was unable to save {} ({})!".format(
                self._engine_name, _key, type(_key)))
        else:
            self.handler.log(
                message="Confirmed save and load methods work correctly.")
 def test_he_bad_method(self):
     with self.assertRaises(TypeError):
         ErrorHandler(module="test_he", method=10, level=10)
Пример #19
0
from TestGameController import TestGameController
from TestGameObject import TestGameObject
from TestHelpers import TestHelpers
from TestPersister import TestPersister
from TestPersisterMongo import TestPersisterMongo
from TestPersisterRedis import TestPersisterRedis
from TestFlaskControllers import TestFlaskControllers
from TestHealthCheck import TestHealthCheck
from TestGameMode import TestGameMode
from TestGameModes import TestGameModes
from python_cowbull_server import app
from Routes.V1 import V1
from flask_helpers.ErrorHandler import ErrorHandler
from flask_controllers import GameServerController
from flask_controllers import HealthCheck
from flask_controllers import Readiness
from flask_controllers import GameModes

logging.disable(logging.CRITICAL)
error_handler = ErrorHandler()
v1 = V1(error_handler=error_handler, app=app)
v1.game(controller=GameServerController)
v1.modes(controller=GameModes)
v1.health(controller=HealthCheck)
v1.readiness(controller=Readiness)

if __name__ == '__main__':
    import xmlrunner
    unittest.main(testRunner=xmlrunner.XMLTestRunner(
        output='unittest-reports'))
 def test_he_value_error(self):
     eh2 = ErrorHandler(module="TEST",
                        method="TEST-METHOD",
                        level="logging.INFO")
     self.assertEqual(eh2.logger.level, logging.INFO)