diff --git a/bison/__version__.py b/bison/__version__.py index 00bf193..c103b42 100644 --- a/bison/__version__.py +++ b/bison/__version__.py @@ -3,7 +3,7 @@ __title__ = 'bison' __description__ = 'Python application configuration' __url__ = 'https://github.com/edaniszewski/bison' -__version__ = '0.1.0' +__version__ = '0.1.1' __author__ = 'Erick Daniszewski' __author_email__ = 'edaniszewski@gmail.com' __license__ = 'MIT' diff --git a/bison/bison.py b/bison/bison.py index 445f61e..40fd1c3 100644 --- a/bison/bison.py +++ b/bison/bison.py @@ -75,6 +75,11 @@ class Bison(object): # the unified configuration. self._full_config = None + def __getitem__(self, item): + # Set __getitem__ so the Bison config can be accessed via subscripting, + # e.g. config['foo'] + return self.get(item) + @property def config(self): """Get the complete configuration where the default, config, diff --git a/bison/scheme.py b/bison/scheme.py index df7c77a..a07a05f 100644 --- a/bison/scheme.py +++ b/bison/scheme.py @@ -119,8 +119,9 @@ class Scheme(object): # the option does not exist in the config else: # if the option is not required, then it is fine to omit. - # otherwise, its omission constitutes a validation error. - if arg.required: + # otherwise, its omission constitutes a validation error unless + # a default value is specified for the option. + if arg.required and isinstance(arg.default, NoDefault): raise errors.SchemeValidationError( 'Option "{}" is required, but not found.'.format(arg.name) ) diff --git a/tests/test_bison.py b/tests/test_bison.py index e6e4830..526663b 100644 --- a/tests/test_bison.py +++ b/tests/test_bison.py @@ -81,6 +81,24 @@ class TestBison: value = b.get(key, default=default) assert value == expected + @pytest.mark.parametrize( + 'key,expected,config', [ + ('foo', None, None), + ('foo', None, bison.DotDict()), + ('foo', None, bison.DotDict({'foo': None})), + ('foo', 'bar', bison.DotDict({'foo': 'bar'})), + ('foo.bar', 'baz', bison.DotDict({'foo': {'bar': 'baz'}})), + ('foo.bar.baz', 1, bison.DotDict({'foo': {'bar': {'baz': 1}}})), + ] + ) + def test_get_subscriptable(self, key, expected, config): + """Get config values from Bison via subscripting.""" + b = bison.Bison() + b._full_config = config # for the test, set the config manually + + value = b[key] + assert value == expected + @pytest.mark.parametrize( 'key,value', [ ('foo', 'bar'), diff --git a/tests/test_scheme.py b/tests/test_scheme.py index 95a7630..69a13b9 100644 --- a/tests/test_scheme.py +++ b/tests/test_scheme.py @@ -760,3 +760,41 @@ class TestScheme: sch = scheme.Scheme() with pytest.raises(errors.SchemeValidationError): sch.validate(value) + + @pytest.mark.parametrize( + 'args,value', [ + ( + # option does not exist in config, has default, not required + (scheme.Option('foo', default='bar'),), + {} + ), + ( + # option does not exist in config, has default, not required + ( + scheme.DictOption('foo', scheme=scheme.Scheme( + scheme.Option('bar', default=1), + scheme.Option('baz'), + )), + ), + {'foo': {'baz': 2}} + ), + ( + # option does not exist in config, has default, not required + ( + scheme.ListOption('foo', member_scheme=scheme.Scheme( + scheme.Option('bar', default=1), + scheme.Option('baz'), + )), + ), + {'foo': [{'baz': 2}, {'bar': 3, 'baz': 2}]} + ), + ] + ) + def test_validate_has_default(self, args, value): + """Validate a Scheme where a default value is set, and the required field + may or may not be set. + + If a default value is provided, it should be assumed to not be required. + """ + sch = scheme.Scheme(*args) + sch.validate(value)