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)
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)
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)
def __init__(self): self.handler = ErrorHandler( module="AbstractPersister", method="__init__", )
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)
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
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)
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)