From 731dd7a2f89bdb9165ce1681cc327fc60dc40ef5 Mon Sep 17 00:00:00 2001 From: Diego Garcia Date: Tue, 7 Mar 2017 10:07:26 -0300 Subject: [PATCH] support toml files ( fix #57 ) --- README.rst | 6 ++--- docs/index.md | 7 +++++- setup.py | 3 +++ simple_settings/strategies/__init__.py | 10 ++++++++ simple_settings/strategies/toml_file.py | 20 +++++++++++++++ tests/samples/simple_toml_file.toml | 10 ++++++++ tests/strategies/test_toml.py | 33 +++++++++++++++++++++++++ 7 files changed, 85 insertions(+), 4 deletions(-) create mode 100644 simple_settings/strategies/toml_file.py create mode 100644 tests/samples/simple_toml_file.toml create mode 100644 tests/strategies/test_toml.py diff --git a/README.rst b/README.rst index a31a769..205a646 100644 --- a/README.rst +++ b/README.rst @@ -27,7 +27,7 @@ Python Simple Settings A simple way to manage your project settings. It is inspired by Django's settings system but is generic for any python project. -With simple-settings you just need specify your settings module in ``--settings`` arg of command line (or ``SIMPLE_SETTINGS`` of environment) and all settings will be available in ``simple_settings.settings``. +With simple-settings you just need specify your settings module in ``--simple-settings`` arg of command line (or ``SIMPLE_SETTINGS`` of environment) and all settings will be available in ``simple_settings.settings``. Installation ------------ @@ -45,7 +45,7 @@ Usage .. code-block:: bash - $ python app.py --settings=my_settings + $ python app.py --simple-settings=my_settings .. code-block:: python @@ -57,7 +57,7 @@ Usage Some features ------------- -* Settings by Python modules, Cfg files, Yaml files or Json files. +* Settings by Python modules, Cfg, Yaml, Toml or Json files. * Settings inheritance (like a pipeline). * Special settings. * Dynamic settings. diff --git a/docs/index.md b/docs/index.md index 838542a..ddf3815 100644 --- a/docs/index.md +++ b/docs/index.md @@ -124,8 +124,10 @@ The simple-settings is prepared to play with the following files types: * cfg files (simple `key=value` files). * yaml files. * json files. +* toml files. -> To simple-settings load settings of yaml files is necessary install with extras require _yaml_ ex: `pip install simple-settings[yaml]` +> To simple-settings load settings of yaml files is necessary install with extras require _yaml_ ex: `pip install simple-settings[yaml]` +> For toml files is necessary install with extras require _toml_ ex: `pip install simple-settings[toml]` ## Load multiple settings modules simple-settings can load more than one setting module without use import approach, just specify yours settings modules separated by comma. @@ -335,6 +337,9 @@ assert settings.SOME_SETTING == 'bar' ``` ## Changelog +### [NEXT_RELEASE] +* Load settings of _toml_ files. + ### [0.11.0] - 2017-02-17 * Autoconfigure python logging with `CONFIGURE_LOGGING` _special setting_. diff --git a/setup.py b/setup.py index 3677a16..a87fbac 100644 --- a/setup.py +++ b/setup.py @@ -17,6 +17,7 @@ def read(fname): long_description = description YAML_REQUIRES = ['PyYAML==3.11'] +TOML_REQUIRES = ['toml==0.9.2'] DYNAMIC_SETTINGS_REQUIRES = ['jsonpickle==0.9.3'] REDIS_REQUIRES = ['redis==2.10.5', 'six==1.10.0'] + DYNAMIC_SETTINGS_REQUIRES CONSUL_REQUIRES = ['consulate==0.6.0'] + DYNAMIC_SETTINGS_REQUIRES @@ -24,6 +25,7 @@ def read(fname): ALL_REQUIRES = set( YAML_REQUIRES + + TOML_REQUIRES + REDIS_REQUIRES + CONSUL_REQUIRES + DATABASE_REQUIRES @@ -66,5 +68,6 @@ def read(fname): 'database': DATABASE_REQUIRES, 'redis': REDIS_REQUIRES, 'yaml': YAML_REQUIRES, + 'toml': TOML_REQUIRES, } ) diff --git a/simple_settings/strategies/__init__.py b/simple_settings/strategies/__init__.py index 262586a..df9ccce 100644 --- a/simple_settings/strategies/__init__.py +++ b/simple_settings/strategies/__init__.py @@ -10,6 +10,13 @@ except ImportError: # pragma: no cover pass +toml_strategy = None +try: + from .toml_file import SettingsLoadStrategyToml + toml_strategy = SettingsLoadStrategyToml +except ImportError: # pragma: no cover + pass + strategies = ( SettingsLoadStrategyPython, @@ -19,3 +26,6 @@ if yaml_strategy: strategies += (yaml_strategy,) + +if toml_strategy: + strategies += (toml_strategy,) diff --git a/simple_settings/strategies/toml_file.py b/simple_settings/strategies/toml_file.py new file mode 100644 index 0000000..ae29b7f --- /dev/null +++ b/simple_settings/strategies/toml_file.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +import codecs + +import toml + + +class SettingsLoadStrategyToml(object): + """ + This is the strategy used to read settings from toml files + """ + name = 'toml' + + @staticmethod + def is_valid_file(file_name): + return file_name.endswith('.toml') + + @staticmethod + def load_settings_file(settings_file): + with codecs.open(settings_file, 'r') as f: + return toml.loads(f.read()) diff --git a/tests/samples/simple_toml_file.toml b/tests/samples/simple_toml_file.toml new file mode 100644 index 0000000..efd3fe9 --- /dev/null +++ b/tests/samples/simple_toml_file.toml @@ -0,0 +1,10 @@ +SIMPLE_STRING = "simple" +SIMPLE_INTEGER = 1 + +SIMPLE_BOOL = true + +COMPLEX_LIST = ["foo", "bar"] + +[COMPLEX_DICT] +complex = "dict" +foo = "bar" diff --git a/tests/strategies/test_toml.py b/tests/strategies/test_toml.py new file mode 100644 index 0000000..913fcdc --- /dev/null +++ b/tests/strategies/test_toml.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +import pytest + +skip = False +try: + from simple_settings.strategies.toml_file import SettingsLoadStrategyToml +except ImportError: + skip = True + + +@pytest.mark.skipif(skip, reason='Installed without Toml') +class TestTomlStrategy(object): + + @pytest.fixture + def strategy_toml(self): + return SettingsLoadStrategyToml + + def test_should_check_a_valid_toml_file(self, strategy_toml): + assert strategy_toml.is_valid_file('foo.toml') is True + + def test_should_check_a_invalid_toml_file(self, strategy_toml): + assert strategy_toml.is_valid_file('foo.bar') is False + + def test_should_load_dict_with_settings_of_toml_file(self, strategy_toml): + settings = strategy_toml.load_settings_file( + 'tests/samples/simple_toml_file.toml' + ) + + assert settings['SIMPLE_STRING'] == 'simple' + assert settings['COMPLEX_DICT'] == {'complex': 'dict', 'foo': 'bar'} + assert settings['COMPLEX_LIST'] == ['foo', 'bar'] + assert settings['SIMPLE_INTEGER'] == 1 + assert settings['SIMPLE_BOOL'] is True