Add Configuration.from_yaml method

This commit is contained in:
Roman Mogylatov 2020-06-24 16:20:03 -04:00
parent 2c43a1c426
commit a76744805a
6 changed files with 3682 additions and 2989 deletions

View File

@ -9,6 +9,7 @@ follows `Semantic versioning`_
Development version Development version
------------------- -------------------
- Add ``Configuration.from_yaml()`` method to load configuration from yaml file.
- Add ``Configuration.from_ini()`` method to load configuration from ini file. - Add ``Configuration.from_ini()`` method to load configuration from ini file.
- Add ``Configuration.from_dict()`` method to load configuration from dictionary. - Add ``Configuration.from_dict()`` method to load configuration from dictionary.
- Remove undocumented positional parameter of ``DependenciesContainer`` provider. - Remove undocumented positional parameter of ``DependenciesContainer`` provider.

View File

@ -40,9 +40,11 @@ setup(name='dependency-injector',
url='https://github.com/ets-labs/python-dependency-injector', url='https://github.com/ets-labs/python-dependency-injector',
download_url='https://pypi.python.org/pypi/dependency_injector', download_url='https://pypi.python.org/pypi/dependency_injector',
install_requires=requirements, install_requires=requirements,
packages=[ extras_require={
'dependency_injector', 'yaml': [
], 'pyyaml',
],
},
package_dir={ package_dir={
'': 'src', '': 'src',
}, },

File diff suppressed because it is too large Load Diff

View File

@ -26,6 +26,11 @@ try:
except ImportError: except ImportError:
import configparser as iniconfigparser import configparser as iniconfigparser
try:
import yaml
except ImportError:
yaml = None
from .errors import ( from .errors import (
Error, Error,
NoSuchProviderError, NoSuchProviderError,
@ -1192,6 +1197,31 @@ cdef class Configuration(Object):
current_config = {} current_config = {}
self.override(merge_dicts(current_config, config)) self.override(merge_dicts(current_config, config))
def from_yaml(self, filepath):
"""Load configuration from yaml file.
Loaded configuration is merged recursively over current configuration.
:param filepath: Path to the configuration file.
:type filepath: str
:rtype: None
"""
if yaml is None:
raise Error(
'Unable to load yaml configuration - PyYAML is not installed. '
'Install PyYAML or install Dependency Injector with yaml extras: '
'"pip install dependency-injector[yaml]"'
)
with open(filepath) as opened_file:
config = yaml.load(opened_file, yaml.Loader)
current_config = self.__call__()
if not current_config:
current_config = {}
self.override(merge_dicts(current_config, config))
def _create_children(self, value): def _create_children(self, value):
children = dict() children = dict()

View File

@ -1,11 +1,12 @@
"""Dependency injector config providers unit tests.""" """Dependency injector config providers unit tests."""
import contextlib
import os import os
import tempfile import tempfile
import unittest2 as unittest import unittest2 as unittest
from dependency_injector import containers, providers from dependency_injector import containers, providers, errors
class ConfigTests(unittest.TestCase): class ConfigTests(unittest.TestCase):
@ -376,3 +377,91 @@ class ConfigFromIniTests(unittest.TestCase):
self.assertEqual(self.config.section2.value2(), '2') self.assertEqual(self.config.section2.value2(), '2')
self.assertEqual(self.config.section3(), {'value3': '3'}) self.assertEqual(self.config.section3(), {'value3': '3'})
self.assertEqual(self.config.section3.value3(), '3') self.assertEqual(self.config.section3.value3(), '3')
class ConfigFromYamlTests(unittest.TestCase):
def setUp(self):
self.config = providers.Configuration(name='config')
_, self.config_file_1 = tempfile.mkstemp()
with open(self.config_file_1, 'w') as config_file:
config_file.write(
'section1:\n'
' value1: 1\n'
'\n'
'section2:\n'
' value2: 2\n'
)
_, self.config_file_2 = tempfile.mkstemp()
with open(self.config_file_2, 'w') as config_file:
config_file.write(
'section1:\n'
' value1: 11\n'
' value11: 11\n'
'section3:\n'
' value3: 3\n'
)
def tearDown(self):
del self.config
os.unlink(self.config_file_1)
os.unlink(self.config_file_2)
def test(self):
self.config.from_yaml(self.config_file_1)
self.assertEqual(self.config(), {'section1': {'value1': 1}, 'section2': {'value2': 2}})
self.assertEqual(self.config.section1(), {'value1': 1})
self.assertEqual(self.config.section1.value1(), 1)
self.assertEqual(self.config.section2(), {'value2': 2})
self.assertEqual(self.config.section2.value2(), 2)
def test_merge(self):
self.config.from_yaml(self.config_file_1)
self.config.from_yaml(self.config_file_2)
self.assertEqual(
self.config(),
{
'section1': {
'value1': 11,
'value11': 11,
},
'section2': {
'value2': 2,
},
'section3': {
'value3': 3,
},
},
)
self.assertEqual(self.config.section1(), {'value1': 11, 'value11': 11})
self.assertEqual(self.config.section1.value1(), 11)
self.assertEqual(self.config.section1.value11(), 11)
self.assertEqual(self.config.section2(), {'value2': 2})
self.assertEqual(self.config.section2.value2(), 2)
self.assertEqual(self.config.section3(), {'value3': 3})
self.assertEqual(self.config.section3.value3(), 3)
def test_no_yaml_installed(self):
@contextlib.contextmanager
def no_yaml_module():
yaml = providers.yaml
providers.yaml = None
yield
providers.yaml = yaml
with no_yaml_module():
with self.assertRaises(errors.Error) as error:
self.config.from_yaml(self.config_file_1)
self.assertEqual(
error.exception.args[0],
'Unable to load yaml configuration - PyYAML is not installed. '
'Install PyYAML or install Dependency Injector with yaml extras: '
'"pip install dependency-injector[yaml]"',
)

View File

@ -5,6 +5,7 @@ envlist=
[testenv] [testenv]
deps= deps=
unittest2 unittest2
extras=yaml
commands= commands=
unit2 discover -s tests/unit -p test_*_py3.py unit2 discover -s tests/unit -p test_*_py3.py