Skip to content
Snippets Groups Projects
Commit f6380c66 authored by Piotr Maślanka's avatar Piotr Maślanka
Browse files

* added some syntactic sugar for the source dict

* now unparseable "type" entries will be returned as-is
* added `ConfigurationMisconfiguredError`
, v2.16.2
parent d94128aa
No related branches found
Tags v2.16.2
No related merge requests found
...@@ -4,3 +4,6 @@ ...@@ -4,3 +4,6 @@
* added `file_contents` schema * added `file_contents` schema
* added nested configuration sources * added nested configuration sources
* added `extract_optional` * added `extract_optional`
* added some syntactic sugar for the source dict
* now unparseable "type" entries will be returned as-is
* added `ConfigurationMisconfiguredError`
...@@ -137,3 +137,18 @@ The result of this execution will be a dictionary: ...@@ -137,3 +137,18 @@ The result of this execution will be a dictionary:
"a": 5 "a": 5
} }
} }
If you have only a single argument, you can also do:
.. code-block:: json
{
"type": "DirectorySource",
"arg": "/app/config"
}
You can put any objects you like as the arguments, note however that if you pass a dictionary, that
has a key of "type" and it's value is one of recognized sources, an attempt will be made to parse
it as a child.
Note that in case you pass a dict with a type that is not recognized, a warning will be emitted.
...@@ -92,7 +92,7 @@ it's magic ...@@ -92,7 +92,7 @@ it's magic
:members: :members:
ImpossibleError ImpossibleError
--------------- ~~~~~~~~~~~~~~~
.. autoclass:: satella.exceptions.ImpossibleError .. autoclass:: satella.exceptions.ImpossibleError
:members: :members:
...@@ -101,92 +101,98 @@ Note that `ImpossibleError` inherits from `BaseException` instead of the standar ...@@ -101,92 +101,98 @@ Note that `ImpossibleError` inherits from `BaseException` instead of the standar
The thought is, since this is an anomalous exception, it should get to the top of the stack ASAP. The thought is, since this is an anomalous exception, it should get to the top of the stack ASAP.
Satella-specific exceptions Satella-specific exceptions
=========================== ---------------------------
BaseSatellaError BaseSatellaError
---------------- ~~~~~~~~~~~~~~~~
.. autoclass:: satella.exceptions.BaseSatellaError .. autoclass:: satella.exceptions.BaseSatellaError
:members: :members:
ResourceLockingError ResourceLockingError
-------------------- ~~~~~~~~~~~~~~~~~~~~
.. autoclass:: satella.exceptions.ResourceLockingError .. autoclass:: satella.exceptions.ResourceLockingError
:members: :members:
ResourceLocked ResourceLocked
-------------- ~~~~~~~~~~~~~~
.. autoclass:: satella.exceptions.ResourceLocked .. autoclass:: satella.exceptions.ResourceLocked
:members: :members:
ResourceNotLocked ResourceNotLocked
----------------- ~~~~~~~~~~~~~~~~~
.. autoclass:: satella.exceptions.ResourceNotLocked .. autoclass:: satella.exceptions.ResourceNotLocked
:members: :members:
WouldWaitMore WouldWaitMore
------------- ~~~~~~~~~~~~~
.. autoclass:: satella.exceptions.WouldWaitMore .. autoclass:: satella.exceptions.WouldWaitMore
:members: :members:
PreconditionError PreconditionError
----------------- ~~~~~~~~~~~~~~~~~
.. autoclass:: satella.exceptions.PreconditionError .. autoclass:: satella.exceptions.PreconditionError
:members: :members:
ConfigurationError ConfigurationError
------------------ ~~~~~~~~~~~~~~~~~~
.. autoclass:: satella.exceptions.ConfigurationError .. autoclass:: satella.exceptions.ConfigurationError
:members: :members:
ConfigurationSchemaError ConfigurationSchemaError
------------------------ ~~~~~~~~~~~~~~~~~~~~~~~~
.. autoclass:: satella.exceptions.ConfigurationSchemaError .. autoclass:: satella.exceptions.ConfigurationSchemaError
:members: :members:
ConfigurationMisconfiguredError
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. autoclass:: satella.exceptions.ConfigurationMisconfiguredError
:members:
ConfigurationValidationError ConfigurationValidationError
---------------------------- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. autoclass:: satella.exceptions.ConfigurationValidationError .. autoclass:: satella.exceptions.ConfigurationValidationError
:members: :members:
Empty Empty
----- ~~~~~
.. autoclass:: satella.exceptions.empty .. autoclass:: satella.exceptions.empty
:members: :members:
MetricAlreadyExists MetricAlreadyExists
------------------- ~~~~~~~~~~~~~~~~~~~
.. autoclass:: satella.exceptions.MetricAlreadyExists .. autoclass:: satella.exceptions.MetricAlreadyExists
:members: :members:
AlreadyAllocated AlreadyAllocated
---------------- ~~~~~~~~~~~~~~~~
.. autoclass:: satella.exceptions.AlreadyAllocated .. autoclass:: satella.exceptions.AlreadyAllocated
:members: :members:
ProcessFailed ProcessFailed
------------- ~~~~~~~~~~~~~
.. autoclass:: satella.exceptions.ProcessFailed .. autoclass:: satella.exceptions.ProcessFailed
:members: :members:
__version__ = '2.16.2a6' __version__ = '2.16.2'
import copy import copy
import importlib import importlib
import warnings
from satella.coding.recast_exceptions import rethrow_as from satella.coding.recast_exceptions import rethrow_as
from satella.configuration import sources from satella.configuration import sources
from satella.configuration.sources.base import BaseSource from satella.configuration.sources.base import BaseSource
from satella.configuration.sources.object_from import BuildObjectFrom from satella.exceptions import ConfigurationError, ConfigurationMisconfiguredError
from satella.exceptions import ConfigurationError
__all__ = [ __all__ = [
'load_source_from_dict', 'load_source_from_dict',
...@@ -46,7 +46,11 @@ def load_source_from_dict(dct: dict) -> BaseSource: ...@@ -46,7 +46,11 @@ def load_source_from_dict(dct: dict) -> BaseSource:
""" """
dct = copy.copy(dct) dct = copy.copy(dct)
type_ = dct.pop('type') # type: str type_ = dct.pop('type') # type: str
args = dct.pop('args', []) # type: tp.List if 'arg' in dct:
args = dct.pop('arg'),
else:
args = dct.pop('args', []) # type: tp.List
optional = dct.pop('optional', False) # type: bool optional = dct.pop('optional', False) # type: bool
def to_arg(arg): def to_arg(arg):
...@@ -57,15 +61,20 @@ def load_source_from_dict(dct: dict) -> BaseSource: ...@@ -57,15 +61,20 @@ def load_source_from_dict(dct: dict) -> BaseSource:
elif a_type in sources.__dict__: elif a_type in sources.__dict__:
return load_source_from_dict(arg) return load_source_from_dict(arg)
else: else:
raise ValueError( warnings.warn(
'unrecognized argument type %s' % (arg['type'],)) 'Caught %s attempting to parse a dict with type, returning original value' % (
e,), UserWarning)
return arg
else: else:
return arg return arg
args = map(to_arg, args) args = map(to_arg, args)
kwargs = {k: to_arg(v) for k, v in dct.items()} kwargs = {k: to_arg(v) for k, v in dct.items()}
s = sources.__dict__[type_](*args, **kwargs) try:
s = sources.__dict__[type_](*args, **kwargs)
except KeyError as e:
raise ConfigurationMisconfiguredError('unknown type %s' % (type_, ))
if optional: if optional:
s = sources.OptionalSource(s) s = sources.OptionalSource(s)
......
...@@ -6,7 +6,8 @@ __all__ = ['BaseSatellaError', 'ResourceLockingError', 'ResourceNotLocked', 'Res ...@@ -6,7 +6,8 @@ __all__ = ['BaseSatellaError', 'ResourceLockingError', 'ResourceNotLocked', 'Res
'ConfigurationValidationError', 'ConfigurationError', 'ConfigurationSchemaError', 'ConfigurationValidationError', 'ConfigurationError', 'ConfigurationSchemaError',
'PreconditionError', 'MetricAlreadyExists', 'BaseSatellaException', 'CustomException', 'PreconditionError', 'MetricAlreadyExists', 'BaseSatellaException', 'CustomException',
'CodedCustomException', 'CodedCustomExceptionMetaclass', 'WouldWaitMore', 'CodedCustomException', 'CodedCustomExceptionMetaclass', 'WouldWaitMore',
'ProcessFailed', 'AlreadyAllocated', 'Empty', 'ImpossibleError'] 'ProcessFailed', 'AlreadyAllocated', 'Empty', 'ImpossibleError',
'ConfigurationMisconfiguredError']
class CustomException(Exception): class CustomException(Exception):
...@@ -181,6 +182,10 @@ class ConfigurationSchemaError(ConfigurationError): ...@@ -181,6 +182,10 @@ class ConfigurationSchemaError(ConfigurationError):
"""Schema mismatch to what was seen""" """Schema mismatch to what was seen"""
class ConfigurationMisconfiguredError(ConfigurationError):
"""Configuration was improperly passed to Satella"""
class ConfigurationValidationError(ConfigurationSchemaError): class ConfigurationValidationError(ConfigurationSchemaError):
"""A validator failed""" """A validator failed"""
......
...@@ -17,6 +17,10 @@ INNER_DATA = [ ...@@ -17,6 +17,10 @@ INNER_DATA = [
] ]
} }
}, },
{
'type': 'JSONSource',
'arg': '{"d": 10}'
},
{ {
'type': 'JSONSource', 'type': 'JSONSource',
'args': ['{"a": 5}'] 'args': ['{"a": 5}']
...@@ -70,7 +74,7 @@ DICT_DATA = { ...@@ -70,7 +74,7 @@ DICT_DATA = {
class TestLoadSourceFromDict(SourceTestCase): class TestLoadSourceFromDict(SourceTestCase):
def test_lsf(self): def test_lsf(self):
output = {'a': 5, 'b': 5, 'c': 21, 'test': {'a': 5}} output = {'a': 5, 'b': 5, 'c': 21, 'test': {'a': 5}, 'd': 10}
self.assertSourceHas(load_source_from_dict(DICT_DATA), output) self.assertSourceHas(load_source_from_dict(DICT_DATA), output)
self.assertSourceHas(load_source_from_list(INNER_DATA), output) self.assertSourceHas(load_source_from_list(INNER_DATA), output)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment