From 5fe1ed37cbf65a659b0f7458a1a6cd4d7e290a67 Mon Sep 17 00:00:00 2001 From: Vasily Loginov Date: Tue, 6 Feb 2018 17:46:57 +0700 Subject: [PATCH] Added validator param support. --- README.rst | 19 ++++++++++++++++++- envparse.py | 10 ++++++++-- tests/test_casts.py | 9 +++++++++ 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index e154392..74e8133 100644 --- a/README.rst +++ b/README.rst @@ -167,6 +167,22 @@ An example of one might be returning a datastructure expected by a framework: 'LOCATION': '127.0.0.1:6379:0', 'OPTIONS': {'PASSWORD': 'redispass'}} +Value Validators +~~~~~~~~~~~~~~~~ +Value validators are callables that are run on the environment variable after a +preprocessor, type casting and postprocessor. If the return value of the validator +is falsy, error will be raised. + +.. code-block:: python + + import logging + + to_upper = lambda v: v.upper() + + env('LOG_LEVEL', preprocessor=to_upper, validator=lambda v: hasattr(logging, v)) + env.int('PORT', validator=lambda v: v > 0 and v < 65535) + + Environment File ~~~~~~~~~~~~~~~~ Read from a .env file (line delimited KEY=VALUE): @@ -191,6 +207,7 @@ To run the tests install tox:: pip install tox -Then run them with:: +Then run them with: make test + diff --git a/envparse.py b/envparse.py index e13b584..6905cc9 100644 --- a/envparse.py +++ b/envparse.py @@ -16,7 +16,7 @@ import urlparse -__version__ = '0.2.0' +__version__ = '0.3.0' logger = logging.getLogger(__file__) @@ -57,7 +57,8 @@ def __init__(self, **schema): self.schema = schema def __call__(self, var, default=NOTSET, cast=None, subcast=None, - force=False, preprocessor=None, postprocessor=None): + force=False, preprocessor=None, postprocessor=None, + validator=None): """ Return value for given environment variable. @@ -69,6 +70,8 @@ def __call__(self, var, default=NOTSET, cast=None, subcast=None, :param force: force to cast to type even if default is set. :param preprocessor: callable to run on pre-casted value. :param postprocessor: callable to run on casted value. + :param validator: callable which should return truthy value, otherwise + ConfigurationError will be thrown. :returns: Value from environment or default (if set). """ @@ -111,6 +114,9 @@ def __call__(self, var, default=NOTSET, cast=None, subcast=None, value = self.cast(value, cast, subcast) if postprocessor: value = postprocessor(value) + if validator and not validator(value): + raise ConfigurationError("Value '{}' is invalid for variable '{}'" + .format(value, var)) return value @classmethod diff --git a/tests/test_casts.py b/tests/test_casts.py index ecb6bd8..57a6196 100644 --- a/tests/test_casts.py +++ b/tests/test_casts.py @@ -145,6 +145,15 @@ def django_redis(url): postprocessor=django_redis)) +def test_validator(): + env.int('INT', validator=lambda v: v in [41, 42]) + env.json('JSON', validator=lambda v: 'foo' in v) + with pytest.raises(ConfigurationError): + env.int('INT', validator=lambda v: v in [1, 2]) + with pytest.raises(ConfigurationError): + env.json('JSON', validator=lambda v: 'bar' in v) + + def test_schema(): env = Env(STR=str, STR_DEFAULT=dict(cast=str, default='default'), INT=int, LIST_STR=list, LIST_INT=dict(cast=list, subcast=int))