def check_definition(self, config_definitions: Dict[str, Dict[str, Any]], name: str, **_): """ Checks for individual definitions. """ definition = config_definitions[name] if not isinstance(definition, dict): return checks.Critical( "Config definition entry is not a dict.", hint="Change definition to be a dict in settings.", obj=f"settings.{self.setting}[{name}]", ) messages = [] # Check required definitions exist for key in self.required_keys: if key not in definition: messages.append( checks.Critical( f"Config definition entry does not contain `{key}` value.", obj=f"settings.{self.setting}[{name}]", )) # Check for un-known values if self._args: for key in definition: if key not in self._args: messages.append( checks.Warn( f"Config definition entry contains unknown value `{key}`.", obj=f"settings.{self.setting}[{name}][{key}]", )) return messages
def checks(self, **kwargs): """ Run checks to ensure settings are valid, secondly run checks against individual definitions in settings. """ settings_ = kwargs['settings'] # Check settings are defined if not hasattr(settings_, self.setting): return checks.Critical( "Instance definitions missing from settings.", hint="Add a {} entry into settings.".format(self.setting), obj="settings.{}".format(self.setting)) instance_definitions = getattr(settings_, self.setting) if instance_definitions is None: return # Nothing is defined so end now. if not isinstance(instance_definitions, dict): return checks.Critical( "Instance definitions defined in settings not a dict instance.", hint="Change setting {} to be a dict in settings file.".format( self.setting), obj="settings.{}".format(self.setting)) # Take over the lock while checks are being performed with self._type_definitions_lock: # Backup definitions, replace and clear cache, this is to make it # easier to write checks for instances. instance_definitions_orig = self._instance_definitions try: self._instance_definitions = instance_definitions self._type_definitions.clear() messages = [] # Check default is defined if self.default_name not in instance_definitions: messages.append( checks.Warn( "Default definition not defined.", hint="The default instance type `{}` is not defined." .format(self.default_name), obj="settings.{}".format(self.setting))) # Check instance definitions for name in instance_definitions: message = self.check_instance(instance_definitions, name, **kwargs) if isinstance(message, checks.CheckMessage): messages.append(message) elif message: messages += message return messages finally: # Put definitions back and clear cache. self._instance_definitions = instance_definitions_orig self._type_definitions.clear()
def checks(self, **kwargs): """ Run checks to ensure settings are valid, secondly run checks against individual definitions in settings. """ settings_ = kwargs["settings"] # Check settings are defined if not hasattr(settings_, self.setting): return checks.Critical( "Config definitions missing from settings.", hint=f"Add a {self.setting} entry into settings.", obj=f"settings.{self.setting}", ) config_definitions = getattr(settings_, self.setting) if config_definitions is None: return None # Nothing is defined so end now. if not isinstance(config_definitions, dict): return checks.Critical( "Config definitions defined in settings not a dict instance.", hint= f"Change setting {self.setting} to be a dict in settings file.", obj=f"settings.{self.setting}", ) messages = [] # Check default is defined if self.default_name not in config_definitions: messages.append( checks.Warn( "Default definition not defined.", hint=f"Add a `{self.default_name}` entry.", obj=f"settings.{self.setting}", )) # Check instance definitions for name in config_definitions: message = self.check_definition(config_definitions, name, **kwargs) if isinstance(message, checks.CheckMessage): messages.append(message) elif message: messages += message return messages
def check_instance(self, idx, provider_ref, **_): """ Checks for individual providers. """ if not isinstance(provider_ref, six.string_types): return checks.Critical( "Provider definition is not a string.", hint="Change definition to be a string in settings.", obj='settings.{}[{}]'.format(self.setting, idx)) try: import_type(provider_ref) except ImportError as ex: return checks.Critical("Unable to import provider type.", hint=str(ex), obj='settings.{}[{}]'.format( self.setting, idx))
def test_checks__missing_settings(self): target = ProviderFactoryTest() with settings.modify() as ctx: del ctx.TEST_PROVIDERS actual = target.checks(settings=settings) assert actual == checks.Critical( u"Provider definitions missing from settings.", u"Add a TEST_PROVIDERS entry into settings.", u"settings.TEST_PROVIDERS")
def checks(self, **kwargs): """ Run checks to ensure settings are valid, secondly run checks against individual definitions in settings. """ settings_ = kwargs["settings"] # Check settings are defined if not hasattr(settings_, self.setting): return checks.Critical( "Provider definitions missing from settings.", hint=f"Add a {self.setting} entry into settings.", obj=f"settings.{self.setting}", ) provider_refs = getattr(settings_, self.setting) if provider_refs is None: return None # Nothing is defined so end now. if not isinstance(provider_refs, (list, tuple)): return checks.Critical( "Provider definitions defined in settings not a list/tuple instance.", hint= f"Change setting {self.setting} to be a list or tuple in settings file.", obj=f"settings.{self.setting}", ) messages = [] for idx, provider_ref in enumerate(provider_refs): message = self.check_instance(idx, provider_ref, **kwargs) if isinstance(message, checks.CheckMessage): messages.append(message) elif message: messages.extend(message) return messages
def check_instance(self, instance_definitions, name, **_): """ Checks for individual instances. """ definition = instance_definitions[name] if not isinstance(definition, (tuple, list)): return checks.Critical( "Instance definition is not a list/tuple.", hint= "Change definition to be a list/tuple (type_name, kwargs) in settings.", obj='settings.{}[{}]'.format(self.setting, name)) if len(definition) != 2: return checks.Critical( "Instance definition is not a type name, kwarg (dict) pair.", hint= "Change definition to be a list/tuple (type_name, kwargs) in settings.", obj='settings.{}[{}]'.format(self.setting, name)) type_name, kwargs = definition messages = [] try: import_type(type_name) except (ImportError, ValueError): messages.append( checks.Error("Unable to import type `{}`.".format(type_name), hint="Check the type name in definition.", obj='settings.{}[{}]'.format(self.setting, name))) if not isinstance(kwargs, dict): messages.append( checks.Critical("Instance kwargs is not a dict.", hint="Change kwargs definition to be a dict.", obj='settings.{}[{}]'.format( self.setting, name))) return messages
def check_definition(self, config_definitions, name, **_): """ Checks for individual definitions. :param config_definitions: :param name: :return: """ definition = config_definitions[name] if not isinstance(definition, dict): return checks.Critical( "Config definition entry is not a dict.", hint="Change definition to be a dict in settings.", obj='settings.{}[{}]'.format(self.setting, name) ) messages = [] # Check required definitions exist for key in self.required_keys: if key not in definition: messages.append(checks.Critical( "Config definition entry does not contain `{}` value.".format(key), obj='settings.{}[{}]'.format(self.setting, name) )) # Check for un-known values if self._args: for key in definition: if key not in self._args: messages.append(checks.Warn( "Config definition entry contains unknown value `{}`.".format(key), obj='settings.{}[{}][{}]'.format(self.setting, name, key) )) return messages
def check_instance( self, idx: int, provider_ref: str, **_ ) -> Optional[Union["checks.CheckMessage", Sequence["checks.CheckMessage"]]]: """ Checks for individual providers. """ if not isinstance(provider_ref, str): return checks.Critical( "Provider definition is not a string.", hint="Change definition to be a string in settings.", obj=f"settings.{self.setting}[{idx}]", ) try: import_type(provider_ref) except ImportError as ex: return checks.Critical( "Unable to import provider type.", hint=str(ex), obj=f"settings.{self.setting}[{idx}]", ) return None
def critical_check(**_): return checks.Critical( "Critical message, that is really really long and should be wrapped across lines. Actually across two no THREE " "lines! Now that is getting fairly full on! :)", "Remove critical messages", )
class TestProviderFactoryBase(object): def test_providers(self): target = ProviderFactoryTest() actual = target.providers assert len(actual) == 1 def test_provider_summaries(self): target = ProviderFactoryTest() actual = target.provider_summaries assert len(actual) == 1 assert actual == [ providers.ProviderSummary( 'tests.test_conf_helpers_providers.ProviderBaseTest', "Test Provider", "Description.") ] def test_get_provider(self): target = ProviderFactoryTest() actual = target.get_provider( 'tests.test_conf_helpers_providers.ProviderBaseTest') assert actual is ProviderBaseTest def test_get_provider__not_found(self): target = ProviderFactoryTest() with pytest.raises(providers.ProviderNotFound): target.get_provider('tests.wrong.ProviderBaseTest') def test_get_instance(self): target = ProviderFactoryTest( 'tests.test_conf_helpers_providers.ProviderBaseTest', {'foo': 'bar'}) actual = target() assert isinstance(actual, ProviderBaseTest) assert actual.foo == 'bar' def test_get_instance__not_found(self): target = ProviderFactoryTest('tests.wrong.ProviderBaseTest') with pytest.raises(providers.ProviderNotFound): target() @pytest.mark.parametrize('provider_settings, expected', ((None, None), ( [], [] ), ({}, checks.Critical( u"Provider definitions defined in settings not a list/tuple instance.", u"Change setting TEST_PROVIDERS to be a list or tuple in settings file.", u"settings.TEST_PROVIDERS")), ([ 'tests.test_conf_helpers_providers.ProviderBaseTest' ], []), ([123], [ checks.Critical( u"Provider definition is not a string.", u"Change definition to be a string in settings.", u"settings.TEST_PROVIDERS[0]") ]))) def test_checks(self, provider_settings, expected): target = ProviderFactoryTest() with settings.modify() as ctx: ctx.TEST_PROVIDERS = provider_settings actual = target.checks(settings=settings) assert actual == expected def test_checks__missing_settings(self): target = ProviderFactoryTest() with settings.modify() as ctx: del ctx.TEST_PROVIDERS actual = target.checks(settings=settings) assert actual == checks.Critical( u"Provider definitions missing from settings.", u"Add a TEST_PROVIDERS entry into settings.", u"settings.TEST_PROVIDERS") def test_checks__invalid_import(self): target = ProviderFactoryTest() with settings.modify() as ctx: ctx.TEST_PROVIDERS = [ 'tests.test_conf_helpers_providers.ProviderBaseTest', 'tests.wrong.ProviderBaseTest' ] actual = target.checks(settings=settings)[0] assert isinstance(actual, checks.Critical) assert actual.msg == u"Unable to import provider type." assert actual.obj == u"settings.TEST_PROVIDERS[1]"
class TestProviderFactoryBase: def test_providers(self): target = ProviderFactoryTest() actual = target.providers assert len(actual) == 1 def test_provider_summaries(self): target = ProviderFactoryTest() actual = target.provider_summaries assert len(actual) == 1 assert actual == ( providers.ProviderSummary( "tests.conf.helpers.test_providers.ProviderBaseTest", "Test Provider", "Description.", ), ) def test_get_provider(self): target = ProviderFactoryTest() actual = target.get_provider( "tests.conf.helpers.test_providers.ProviderBaseTest" ) assert actual is ProviderBaseTest def test_get_provider__not_found(self): target = ProviderFactoryTest() with pytest.raises(providers.ProviderNotFound): target.get_provider("tests.wrong.ProviderBaseTest") def test_get_instance(self): target = ProviderFactoryTest( "tests.conf.helpers.test_providers.ProviderBaseTest", {"foo": "bar"} ) actual = target.create() assert isinstance(actual, ProviderBaseTest) assert actual.foo == "bar" def test_get_instance__not_found(self): target = ProviderFactoryTest("tests.wrong.ProviderBaseTest") with pytest.raises(providers.ProviderNotFound): target.create() @pytest.mark.parametrize( "provider_settings, expected", ( (None, None), ([], []), ( {}, checks.Critical( u"Provider definitions defined in settings not a list/tuple instance.", u"Change setting TEST_PROVIDERS to be a list or tuple in settings file.", u"settings.TEST_PROVIDERS", ), ), (["tests.conf.helpers.test_providers.ProviderBaseTest"], []), ( [123], [ checks.Critical( u"Provider definition is not a string.", u"Change definition to be a string in settings.", u"settings.TEST_PROVIDERS[0]", ) ], ), ), ) def test_checks(self, provider_settings, expected): target = ProviderFactoryTest() with settings.modify() as ctx: ctx.TEST_PROVIDERS = provider_settings actual = target.checks(settings=settings) assert actual == expected def test_checks__multiple_instance_messages(self): target = ProviderFactoryTest(multi_messages=True) with settings.modify() as ctx: ctx.TEST_PROVIDERS = ("tests.conf.helpers.test_providers.ProviderBaseTest",) actual = target.checks(settings=settings) assert actual == [checks.Info("foo"), checks.Warn("bar")] def test_checks__missing_settings(self): target = ProviderFactoryTest() with settings.modify() as ctx: del ctx.TEST_PROVIDERS actual = target.checks(settings=settings) assert actual == checks.Critical( u"Provider definitions missing from settings.", u"Add a TEST_PROVIDERS entry into settings.", u"settings.TEST_PROVIDERS", ) def test_checks__invalid_import(self): target = ProviderFactoryTest() with settings.modify() as ctx: ctx.TEST_PROVIDERS = [ "tests.conf.helpers.test_providers.ProviderBaseTest", "tests.wrong.ProviderBaseTest", ] actual = target.checks(settings=settings)[0] assert isinstance(actual, checks.Critical) assert actual.msg == u"Unable to import provider type." assert actual.obj == u"settings.TEST_PROVIDERS[1]"
def check_instance(self, instance_definitions, name, **_): """ Checks for individual instances. """ definition = instance_definitions[name] if not isinstance(definition, (tuple, list)): return checks.Critical( "Instance definition is not a list/tuple.", hint= "Change definition to be a list/tuple (type_name, kwargs) in settings.", obj=f"settings.{self.setting}[{name}]", ) if len(definition) != 2: return checks.Critical( "Instance definition is not a type name, kwarg (dict) pair.", hint= "Change definition to be a list/tuple (type_name, kwargs) in settings.", obj=f"settings.{self.setting}[{name}]", ) type_name, kwargs = definition messages = [] if type_name.upper() == "ALIAS": target_name = kwargs.get("name") if not target_name: messages.append( checks.Critical( "Name of alias target not defined", hint= "An alias entry must provide a `name` value that refers to another entry.", obj=f"settings.{self.setting}[{name}]", )) elif target_name not in instance_definitions: messages.append( checks.Critical( "Alias target not defined", hint= "The target specified by the alias does not exist, check the `name` value.", obj=f"settings.{self.setting}[{name}][{target_name}]", )) if len(kwargs) > 1: messages.append( checks.Warn( "Alias contains unknown arguments", hint="An alias entry must only provide a `name` value.", obj=f"settings.{self.setting}[{name}]", )) else: try: import_type(type_name) except (ImportError, ValueError, AttributeError): messages.append( checks.Error( f"Unable to import type `{type_name}`.", hint="Check the type name in definition.", obj=f"settings.{self.setting}[{name}]", )) if not isinstance(kwargs, dict): messages.append( checks.Critical( "Instance kwargs is not a dict.", hint="Change kwargs definition to be a dict.", obj=f"settings.{self.setting}[{name}]", )) return messages