mirror of
				https://github.com/ets-labs/python-dependency-injector.git
				synced 2025-10-31 07:57:43 +03:00 
			
		
		
		
	Merge branch 'release/4.33.0' into master
This commit is contained in:
		
						commit
						9abf34cb88
					
				|  | @ -7,6 +7,17 @@ that were made in every particular version. | |||
| From version 0.7.6 *Dependency Injector* framework strictly  | ||||
| follows `Semantic versioning`_ | ||||
| 
 | ||||
| 4.33.0 | ||||
| ------ | ||||
| - Add support of default value for environment variable in INI and YAML | ||||
|   configuration files with ``${ENV_NAME:default}`` format. | ||||
|   See issue `#459 <https://github.com/ets-labs/python-dependency-injector/issues/459>`_. | ||||
|   Thanks to `Maksym Shemet @hbmshemet <https://github.com/hbmshemet>`_ for suggesting the feature. | ||||
| - Add method ``Configuration.from_value()``. | ||||
|   See issue `#462 <https://github.com/ets-labs/python-dependency-injector/issues/462>`_. | ||||
|   Thanks to Mr. `Slack Clone <https://disqus.com/by/slackclone/>`_  for bringing it up | ||||
|   in the comments for configuration provider docs. | ||||
| 
 | ||||
| 4.32.3 | ||||
| ------ | ||||
| - This fix a typo in ``di_in_python.rst`` doc. | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ Configuration provider | |||
| 
 | ||||
| .. meta:: | ||||
|    :keywords: Python,DI,Dependency injection,IoC,Inversion of Control,Configuration,Injection, | ||||
|               Option,Ini,Json,Yaml,Pydantic,Dict,Environment Variable,Load,Read,Get | ||||
|               Option,Ini,Json,Yaml,Pydantic,Dict,Environment Variable,Default,Load,Read,Get | ||||
|    :description: Configuration provides configuration options to the other providers. This page | ||||
|                  demonstrates how to use Configuration provider to inject the dependencies, load | ||||
|                  a configuration from an ini or yaml file, a dictionary, an environment variable, | ||||
|  | @ -43,8 +43,18 @@ where ``examples/providers/configuration/config.ini`` is: | |||
|    :language: ini | ||||
| 
 | ||||
| :py:meth:`Configuration.from_ini` method supports environment variables interpolation. Use | ||||
| ``${ENV_NAME}`` format in the configuration file to substitute value of the environment | ||||
| variable ``ENV_NAME``. | ||||
| ``${ENV_NAME}`` format in the configuration file to substitute value from ``ENV_NAME`` environment | ||||
| variable. | ||||
| 
 | ||||
| You can also specify a default value using ``${ENV_NAME:default}`` format. If environment | ||||
| variable ``ENV_NAME`` is undefined, configuration provider will substitute value ``default``. | ||||
| 
 | ||||
| .. code-block:: ini | ||||
| 
 | ||||
|    [section] | ||||
|    option1 = {$ENV_VAR} | ||||
|    option2 = {$ENV_VAR}/path | ||||
|    option3 = {$ENV_VAR:default} | ||||
| 
 | ||||
| Loading from a YAML file | ||||
| ------------------------ | ||||
|  | @ -62,12 +72,22 @@ where ``examples/providers/configuration/config.yml`` is: | |||
| .. literalinclude:: ../../examples/providers/configuration/config.yml | ||||
|    :language: ini | ||||
| 
 | ||||
| :py:meth:`Configuration.from_yaml` method supports environment variables interpolation. Use | ||||
| ``${ENV_NAME}`` format in the configuration file to substitute value from ``ENV_NAME`` environment | ||||
| variable. | ||||
| 
 | ||||
| You can also specify a default value using ``${ENV_NAME:default}`` format. If environment | ||||
| variable ``ENV_NAME`` is undefined, configuration provider will substitute value ``default``. | ||||
| 
 | ||||
| .. code-block:: ini | ||||
| 
 | ||||
|    section: | ||||
|      option1: {$ENV_VAR} | ||||
|      option2: {$ENV_VAR}/path | ||||
|      option3: {$ENV_VAR:default} | ||||
| 
 | ||||
| :py:meth:`Configuration.from_yaml` method uses custom version of ``yaml.SafeLoader``. | ||||
| 
 | ||||
| The loader supports environment variables interpolation. Use ``${ENV_NAME}`` format | ||||
| in the configuration file to substitute value of the environment variable ``ENV_NAME``. | ||||
| 
 | ||||
| You can also specify a YAML loader as an argument: | ||||
| To use another loader use ``loader`` argument: | ||||
| 
 | ||||
| .. code-block:: python | ||||
| 
 | ||||
|  | @ -144,6 +164,17 @@ Loading from an environment variable | |||
|    :lines: 3- | ||||
|    :emphasize-lines: 18-20 | ||||
| 
 | ||||
| Loading a value | ||||
| --------------- | ||||
| 
 | ||||
| ``Configuration`` provider can load configuration value using the | ||||
| :py:meth:`Configuration.from_value` method: | ||||
| 
 | ||||
| .. literalinclude:: ../../examples/providers/configuration/configuration_value.py | ||||
|    :language: python | ||||
|    :lines: 3- | ||||
|    :emphasize-lines: 14-15 | ||||
| 
 | ||||
| Loading from the multiple sources | ||||
| --------------------------------- | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										24
									
								
								examples/providers/configuration/configuration_value.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								examples/providers/configuration/configuration_value.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | |||
| """`Configuration` provider values loading example.""" | ||||
| 
 | ||||
| from datetime import date | ||||
| 
 | ||||
| from dependency_injector import containers, providers | ||||
| 
 | ||||
| 
 | ||||
| class Container(containers.DeclarativeContainer): | ||||
| 
 | ||||
|     config = providers.Configuration() | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     container = Container() | ||||
| 
 | ||||
|     container.config.option1.from_value(date(2021, 6, 13)) | ||||
|     container.config.option2.from_value(date(2021, 6, 14)) | ||||
| 
 | ||||
|     assert container.config() == { | ||||
|         'option1': date(2021, 6, 13), | ||||
|         'option2': date(2021, 6, 14), | ||||
|     } | ||||
|     assert container.config.option1() == date(2021, 6, 13) | ||||
|     assert container.config.option2() == date(2021, 6, 14) | ||||
|  | @ -1,6 +1,6 @@ | |||
| """Top-level package.""" | ||||
| 
 | ||||
| __version__ = '4.32.3' | ||||
| __version__ = '4.33.0' | ||||
| """Version number. | ||||
| 
 | ||||
| :type: str | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -205,6 +205,7 @@ class ConfigurationOption(Provider[Any]): | |||
|     def from_pydantic(self, settings: PydanticSettings, required: bool = False, **kwargs: Any) -> None: ... | ||||
|     def from_dict(self, options: _Dict[str, Any], required: bool = False) -> None: ... | ||||
|     def from_env(self, name: str, default: Optional[Any] = None, required: bool = False) -> None: ... | ||||
|     def from_value(self, value: Any) -> None: ... | ||||
| 
 | ||||
| 
 | ||||
| class TypedConfigurationOption(Callable[T]): | ||||
|  | @ -241,6 +242,7 @@ class Configuration(Object[Any]): | |||
|     def from_pydantic(self, settings: PydanticSettings, required: bool = False, **kwargs: Any) -> None: ... | ||||
|     def from_dict(self, options: _Dict[str, Any], required: bool = False) -> None: ... | ||||
|     def from_env(self, name: str, default: Optional[Any] = None, required: bool = False) -> None: ... | ||||
|     def from_value(self, value: Any) -> None: ... | ||||
| 
 | ||||
| 
 | ||||
| class Factory(Provider[T]): | ||||
|  |  | |||
|  | @ -64,6 +64,25 @@ else:  # pragma: no cover | |||
|                                     copy.deepcopy(obj.im_self, memo), | ||||
|                                     obj.im_class) | ||||
| 
 | ||||
| config_env_marker_pattern = re.compile( | ||||
|     r'\${(?P<name>[^}^{:]+)(?P<separator>:?)(?P<default>.*?)}', | ||||
| ) | ||||
| 
 | ||||
| def _resolve_config_env_markers(config_value): | ||||
|     """"Replace environment variable markers with their values.""" | ||||
|     for match in reversed(list(config_env_marker_pattern.finditer(config_value))): | ||||
|         has_default = match.group('separator') == ':' | ||||
| 
 | ||||
|         value = os.getenv(match.group('name')) | ||||
|         if value is None: | ||||
|             if not has_default: | ||||
|                 continue | ||||
|             value = match.group('default') | ||||
| 
 | ||||
|         span_min, span_max = match.span() | ||||
|         config_value = f'{config_value[:span_min]}{value}{config_value[span_max:]}' | ||||
|     return config_value | ||||
| 
 | ||||
| 
 | ||||
| if sys.version_info[0] == 3: | ||||
|     class EnvInterpolation(iniconfigparser.BasicInterpolation): | ||||
|  | @ -71,7 +90,7 @@ if sys.version_info[0] == 3: | |||
| 
 | ||||
|         def before_get(self, parser, section, option, value, defaults): | ||||
|             value = super().before_get(parser, section, option, value, defaults) | ||||
|             return os.path.expandvars(value) | ||||
|             return _resolve_config_env_markers(value) | ||||
| 
 | ||||
|     def _parse_ini_file(filepath): | ||||
|         parser = iniconfigparser.ConfigParser(interpolation=EnvInterpolation()) | ||||
|  | @ -84,19 +103,18 @@ else: | |||
|     def _parse_ini_file(filepath): | ||||
|         parser = iniconfigparser.ConfigParser() | ||||
|         with open(filepath) as config_file: | ||||
|             config_string = os.path.expandvars(config_file.read()) | ||||
|             config_string = _resolve_config_env_markers(config_file.read()) | ||||
|         parser.readfp(StringIO.StringIO(config_string)) | ||||
|         return parser | ||||
| 
 | ||||
| 
 | ||||
| if yaml: | ||||
|     # TODO: use SafeLoader without env interpolation by default in version 5.* | ||||
|     yaml_env_marker_pattern = re.compile(r'\$\{([^}^{]+)\}') | ||||
|     def yaml_env_marker_constructor(_, node): | ||||
|         """"Replace environment variable marker with its value.""" | ||||
|         return os.path.expandvars(node.value) | ||||
|         return _resolve_config_env_markers(node.value) | ||||
| 
 | ||||
|     yaml.add_implicit_resolver('!path', yaml_env_marker_pattern) | ||||
|     yaml.add_implicit_resolver('!path', config_env_marker_pattern) | ||||
|     yaml.add_constructor('!path', yaml_env_marker_constructor) | ||||
| 
 | ||||
|     class YamlLoader(yaml.SafeLoader): | ||||
|  | @ -105,7 +123,7 @@ if yaml: | |||
|         Inherits ``yaml.SafeLoader`` and add environment variables interpolation. | ||||
|         """ | ||||
| 
 | ||||
|     YamlLoader.add_implicit_resolver('!path', yaml_env_marker_pattern, None) | ||||
|     YamlLoader.add_implicit_resolver('!path', config_env_marker_pattern, None) | ||||
|     YamlLoader.add_constructor('!path', yaml_env_marker_constructor) | ||||
| else: | ||||
|     class YamlLoader: | ||||
|  | @ -1680,6 +1698,16 @@ cdef class ConfigurationOption(Provider): | |||
| 
 | ||||
|         self.override(value) | ||||
| 
 | ||||
|     def from_value(self, value): | ||||
|         """Load configuration value. | ||||
| 
 | ||||
|         :param value: Configuration value | ||||
|         :type value: object | ||||
| 
 | ||||
|         :rtype: None | ||||
|         """ | ||||
|         self.override(value) | ||||
| 
 | ||||
|     @property | ||||
|     def related(self): | ||||
|         """Return related providers generator.""" | ||||
|  | @ -2086,6 +2114,16 @@ cdef class Configuration(Object): | |||
| 
 | ||||
|         self.override(value) | ||||
| 
 | ||||
|     def from_value(self, value): | ||||
|         """Load configuration value. | ||||
| 
 | ||||
|         :param value: Configuration value | ||||
|         :type value: object | ||||
| 
 | ||||
|         :rtype: None | ||||
|         """ | ||||
|         self.override(value) | ||||
| 
 | ||||
|     @property | ||||
|     def related(self): | ||||
|         """Return related providers generator.""" | ||||
|  |  | |||
|  | @ -591,17 +591,20 @@ class ConfigFromIniWithEnvInterpolationTests(unittest.TestCase): | |||
|         self.config = providers.Configuration(name='config') | ||||
| 
 | ||||
|         os.environ['CONFIG_TEST_ENV'] = 'test-value' | ||||
|         os.environ['CONFIG_TEST_PATH'] = 'test-path' | ||||
| 
 | ||||
|         _, self.config_file = tempfile.mkstemp() | ||||
|         with open(self.config_file, 'w') as config_file: | ||||
|             config_file.write( | ||||
|                 '[section1]\n' | ||||
|                 'value1=${CONFIG_TEST_ENV}\n' | ||||
|                 'value2=${CONFIG_TEST_PATH}/path\n' | ||||
|             ) | ||||
| 
 | ||||
|     def tearDown(self): | ||||
|         del self.config | ||||
|         del os.environ['CONFIG_TEST_ENV'] | ||||
|         os.environ.pop('CONFIG_TEST_ENV', None) | ||||
|         os.environ.pop('CONFIG_TEST_PATH', None) | ||||
|         os.unlink(self.config_file) | ||||
| 
 | ||||
|     def test_env_variable_interpolation(self): | ||||
|  | @ -612,11 +615,67 @@ class ConfigFromIniWithEnvInterpolationTests(unittest.TestCase): | |||
|             { | ||||
|                 'section1': { | ||||
|                     'value1': 'test-value', | ||||
|                     'value2': 'test-path/path', | ||||
|                 }, | ||||
|             }, | ||||
|         ) | ||||
|         self.assertEqual(self.config.section1(), {'value1': 'test-value'}) | ||||
|         self.assertEqual( | ||||
|             self.config.section1(), | ||||
|             { | ||||
|                 'value1': 'test-value', | ||||
|                 'value2': 'test-path/path', | ||||
|             }, | ||||
|         ) | ||||
|         self.assertEqual(self.config.section1.value1(), 'test-value') | ||||
|         self.assertEqual(self.config.section1.value2(), 'test-path/path') | ||||
| 
 | ||||
|     def test_missing_envs(self): | ||||
|         del os.environ['CONFIG_TEST_ENV'] | ||||
|         del os.environ['CONFIG_TEST_PATH'] | ||||
| 
 | ||||
|         self.config.from_ini(self.config_file) | ||||
| 
 | ||||
|         self.assertEqual( | ||||
|             self.config(), | ||||
|             { | ||||
|                 'section1': { | ||||
|                     'value1': '${CONFIG_TEST_ENV}', | ||||
|                     'value2': '${CONFIG_TEST_PATH}/path', | ||||
|                 }, | ||||
|             }, | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             self.config.section1(), | ||||
|             { | ||||
|                 'value1': '${CONFIG_TEST_ENV}', | ||||
|                 'value2': '${CONFIG_TEST_PATH}/path', | ||||
|             }, | ||||
|         ) | ||||
|         self.assertEqual(self.config.section1.value1(), '${CONFIG_TEST_ENV}') | ||||
|         self.assertEqual(self.config.section1.value2(), '${CONFIG_TEST_PATH}/path') | ||||
| 
 | ||||
|     def test_default_values(self): | ||||
|         os.environ['DEFINED'] = 'defined' | ||||
|         self.addCleanup(os.environ.pop, 'DEFINED') | ||||
| 
 | ||||
|         with open(self.config_file, 'w') as config_file: | ||||
|             config_file.write( | ||||
|                 '[section]\n' | ||||
|                 'defined_with_default=${DEFINED:default}\n' | ||||
|                 'undefined_with_default=${UNDEFINED:default}\n' | ||||
|                 'complex=${DEFINED}/path/${DEFINED:default}/${UNDEFINED}/${UNDEFINED:default}\n' | ||||
|             ) | ||||
| 
 | ||||
|         self.config.from_ini(self.config_file) | ||||
| 
 | ||||
|         self.assertEqual( | ||||
|             self.config.section(), | ||||
|             { | ||||
|                 'defined_with_default': 'defined', | ||||
|                 'undefined_with_default': 'default', | ||||
|                 'complex': 'defined/path/defined/${UNDEFINED}/default', | ||||
|             }, | ||||
|         ) | ||||
| 
 | ||||
| 
 | ||||
| class ConfigFromYamlTests(unittest.TestCase): | ||||
|  | @ -781,17 +840,20 @@ class ConfigFromYamlWithEnvInterpolationTests(unittest.TestCase): | |||
|         self.config = providers.Configuration(name='config') | ||||
| 
 | ||||
|         os.environ['CONFIG_TEST_ENV'] = 'test-value' | ||||
|         os.environ['CONFIG_TEST_PATH'] = 'test-path' | ||||
| 
 | ||||
|         _, self.config_file = tempfile.mkstemp() | ||||
|         with open(self.config_file, 'w') as config_file: | ||||
|             config_file.write( | ||||
|                 'section1:\n' | ||||
|                 '  value1: ${CONFIG_TEST_ENV}\n' | ||||
|                 '  value2: ${CONFIG_TEST_PATH}/path\n' | ||||
|             ) | ||||
| 
 | ||||
|     def tearDown(self): | ||||
|         del self.config | ||||
|         del os.environ['CONFIG_TEST_ENV'] | ||||
|         os.environ.pop('CONFIG_TEST_ENV', None) | ||||
|         os.environ.pop('CONFIG_TEST_PATH', None) | ||||
|         os.unlink(self.config_file) | ||||
| 
 | ||||
|     @unittest.skipIf(sys.version_info[:2] == (3, 4), 'PyYAML does not support Python 3.4') | ||||
|  | @ -803,11 +865,69 @@ class ConfigFromYamlWithEnvInterpolationTests(unittest.TestCase): | |||
|             { | ||||
|                 'section1': { | ||||
|                     'value1': 'test-value', | ||||
|                     'value2': 'test-path/path', | ||||
|                 }, | ||||
|             }, | ||||
|         ) | ||||
|         self.assertEqual(self.config.section1(), {'value1': 'test-value'}) | ||||
|         self.assertEqual( | ||||
|             self.config.section1(), | ||||
|             { | ||||
|                 'value1': 'test-value', | ||||
|                 'value2': 'test-path/path', | ||||
|             }, | ||||
|         ) | ||||
|         self.assertEqual(self.config.section1.value1(), 'test-value') | ||||
|         self.assertEqual(self.config.section1.value2(), 'test-path/path') | ||||
| 
 | ||||
|     @unittest.skipIf(sys.version_info[:2] == (3, 4), 'PyYAML does not support Python 3.4') | ||||
|     def test_missing_envs(self): | ||||
|         del os.environ['CONFIG_TEST_ENV'] | ||||
|         del os.environ['CONFIG_TEST_PATH'] | ||||
| 
 | ||||
|         self.config.from_yaml(self.config_file) | ||||
| 
 | ||||
|         self.assertEqual( | ||||
|             self.config(), | ||||
|             { | ||||
|                 'section1': { | ||||
|                     'value1': '${CONFIG_TEST_ENV}', | ||||
|                     'value2': '${CONFIG_TEST_PATH}/path', | ||||
|                 }, | ||||
|             }, | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             self.config.section1(), | ||||
|             { | ||||
|                 'value1': '${CONFIG_TEST_ENV}', | ||||
|                 'value2': '${CONFIG_TEST_PATH}/path', | ||||
|             }, | ||||
|         ) | ||||
|         self.assertEqual(self.config.section1.value1(), '${CONFIG_TEST_ENV}') | ||||
|         self.assertEqual(self.config.section1.value2(), '${CONFIG_TEST_PATH}/path') | ||||
| 
 | ||||
|     @unittest.skipIf(sys.version_info[:2] == (3, 4), 'PyYAML does not support Python 3.4') | ||||
|     def test_default_values(self): | ||||
|         os.environ['DEFINED'] = 'defined' | ||||
|         self.addCleanup(os.environ.pop, 'DEFINED') | ||||
| 
 | ||||
|         with open(self.config_file, 'w') as config_file: | ||||
|             config_file.write( | ||||
|                 'section:\n' | ||||
|                 '  defined_with_default: ${DEFINED:default}\n' | ||||
|                 '  undefined_with_default: ${UNDEFINED:default}\n' | ||||
|                 '  complex: ${DEFINED}/path/${DEFINED:default}/${UNDEFINED}/${UNDEFINED:default}\n' | ||||
|             ) | ||||
| 
 | ||||
|         self.config.from_yaml(self.config_file) | ||||
| 
 | ||||
|         self.assertEqual( | ||||
|             self.config.section(), | ||||
|             { | ||||
|                 'defined_with_default': 'defined', | ||||
|                 'undefined_with_default': 'default', | ||||
|                 'complex': 'defined/path/defined/${UNDEFINED}/default', | ||||
|             }, | ||||
|         ) | ||||
| 
 | ||||
|     @unittest.skipIf(sys.version_info[:2] == (3, 4), 'PyYAML does not support Python 3.4') | ||||
|     def test_option_env_variable_interpolation(self): | ||||
|  | @ -818,41 +938,47 @@ class ConfigFromYamlWithEnvInterpolationTests(unittest.TestCase): | |||
|             { | ||||
|                 'section1': { | ||||
|                     'value1': 'test-value', | ||||
|                     'value2': 'test-path/path', | ||||
|                 }, | ||||
|             }, | ||||
|         ) | ||||
|         self.assertEqual(self.config.option.section1(), {'value1': 'test-value'}) | ||||
|         self.assertEqual( | ||||
|             self.config.option.section1(), | ||||
|             { | ||||
|                 'value1': 'test-value', | ||||
|                 'value2': 'test-path/path', | ||||
|             }, | ||||
|         ) | ||||
|         self.assertEqual(self.config.option.section1.value1(), 'test-value') | ||||
|         self.assertEqual(self.config.option.section1.value2(), 'test-path/path') | ||||
| 
 | ||||
|     @unittest.skipIf(sys.version_info[:2] == (3, 4), 'PyYAML does not support Python 3.4') | ||||
|     def test_env_variable_interpolation_custom_loader(self): | ||||
|         self.config.from_yaml(self.config_file, loader=yaml.UnsafeLoader) | ||||
| 
 | ||||
|         self.assertEqual( | ||||
|             self.config(), | ||||
|             self.config.section1(), | ||||
|             { | ||||
|                 'section1': { | ||||
|                     'value1': 'test-value', | ||||
|                 }, | ||||
|                 'value1': 'test-value', | ||||
|                 'value2': 'test-path/path', | ||||
|             }, | ||||
|         ) | ||||
|         self.assertEqual(self.config.section1(), {'value1': 'test-value'}) | ||||
|         self.assertEqual(self.config.section1.value1(), 'test-value') | ||||
|         self.assertEqual(self.config.section1.value2(), 'test-path/path') | ||||
| 
 | ||||
|     @unittest.skipIf(sys.version_info[:2] == (3, 4), 'PyYAML does not support Python 3.4') | ||||
|     def test_option_env_variable_interpolation_custom_loader(self): | ||||
|         self.config.option.from_yaml(self.config_file, loader=yaml.UnsafeLoader) | ||||
| 
 | ||||
|         self.assertEqual( | ||||
|             self.config.option(), | ||||
|             self.config.option.section1(), | ||||
|             { | ||||
|                 'section1': { | ||||
|                     'value1': 'test-value', | ||||
|                 }, | ||||
|                 'value1': 'test-value', | ||||
|                 'value2': 'test-path/path', | ||||
|             }, | ||||
|         ) | ||||
|         self.assertEqual(self.config.option.section1(), {'value1': 'test-value'}) | ||||
|         self.assertEqual(self.config.option.section1.value1(), 'test-value') | ||||
|         self.assertEqual(self.config.option.section1.value2(), 'test-path/path') | ||||
| 
 | ||||
| 
 | ||||
| class ConfigFromPydanticTests(unittest.TestCase): | ||||
|  | @ -1250,3 +1376,25 @@ class ConfigFromEnvTests(unittest.TestCase): | |||
|         self.config = providers.Configuration(strict=True) | ||||
|         self.config.option.from_env('UNDEFINED_ENV', default='default-value', required=False) | ||||
|         self.assertEqual(self.config.option(), 'default-value') | ||||
| 
 | ||||
| 
 | ||||
| class ConfigFromValueTests(unittest.TestCase): | ||||
| 
 | ||||
|     def setUp(self): | ||||
|         self.config = providers.Configuration(name='config') | ||||
| 
 | ||||
|     def test_from_value(self): | ||||
|         test_value = 123321 | ||||
|         self.config.from_value(test_value) | ||||
|         self.assertEqual(self.config(), test_value) | ||||
| 
 | ||||
|     def test_option_from_value(self): | ||||
|         test_value_1 = 123 | ||||
|         test_value_2 = 321 | ||||
| 
 | ||||
|         self.config.option1.from_value(test_value_1) | ||||
|         self.config.option2.from_value(test_value_2) | ||||
| 
 | ||||
|         self.assertEqual(self.config(), {'option1': test_value_1, 'option2': test_value_2}) | ||||
|         self.assertEqual(self.config.option1(), test_value_1) | ||||
|         self.assertEqual(self.config.option2(), test_value_2) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user