Implement wiring of config invariant

This commit is contained in:
Roman Mogylatov 2020-09-27 17:40:06 -04:00
parent 7570e7056c
commit a02f9c6981
4 changed files with 2683 additions and 3125 deletions

File diff suppressed because it is too large Load Diff

View File

@ -127,12 +127,11 @@ class ConfigurationOption(Provider):
def __init__(self, name: Tuple[str], root: Configuration) -> None: ...
def __call__(self, *args: Injection, **kwargs: Injection) -> Any: ...
def __getattr__(self, item: str) -> ConfigurationOption: ...
def __getitem__(self, item: str) -> ConfigurationOption: ...
def __getitem__(self, item: Union[str, Provider]) -> ConfigurationOption: ...
@property
def root(self) -> Configuration: ...
def get_name(self) -> str: ...
def get_relative_name(self) -> str: ...
def get_option_provider(self, selector: str) -> ConfigurationOption: ...
def get_name_segments(self) -> Tuple[Union[str, Provider]]: ...
def as_int(self) -> TypedConfigurationOption[int]: ...
def as_float(self) -> TypedConfigurationOption[float]: ...
def as_(self, callback: _Callable[..., T], *args: Injection, **kwargs: Injection) -> TypedConfigurationOption[T]: ...
@ -152,10 +151,9 @@ class Configuration(Object):
DEFAULT_NAME: str = 'config'
def __init__(self, name: str = DEFAULT_NAME, default: Optional[Any] = None) -> None: ...
def __getattr__(self, item: str) -> ConfigurationOption: ...
def __getitem__(self, item: str) -> ConfigurationOption: ...
def __getitem__(self, item: Union[str, Provider]) -> ConfigurationOption: ...
def get_name(self) -> str: ...
def get(self, selector: str) -> Any: ...
def get_option_provider(self, selector: str) -> ConfigurationOption: ...
def set(self, selector: str, value: Any) -> OverridingContext: ...
def reset_cache(self) -> None: ...
def update(self, value: Any) -> None: ...

View File

@ -1152,25 +1152,8 @@ cdef class ConfigurationOption(Provider):
root = self.__root_ref()
return '.'.join((root.get_name(), self._get_self_name()))
def get_relative_name(self):
return self._get_self_name()
def get_option_provider(self, selector):
"""Return configuration option provider.
:param selector: Selector string, e.g. "option1.option2"
:type selector: str
:return: Option provider.
:rtype: :py:class:`ConfigurationOption`
"""
key, *other_keys = selector.split('.')
child = getattr(self, key)
if other_keys:
child = child.get_option_provider('.'.join(other_keys))
return child
def get_name_segments(self):
return self.__name
def as_int(self):
return TypedConfigurationOption(int, self)
@ -1393,23 +1376,6 @@ cdef class Configuration(Object):
return value
def get_option_provider(self, selector):
"""Return configuration option provider.
:param selector: Selector string, e.g. "option1.option2"
:type selector: str
:return: Option provider.
:rtype: :py:class:`ConfigurationOption`
"""
key, *other_keys = selector.split('.')
child = getattr(self, key)
if other_keys:
child = child.get_option_provider('.'.join(other_keys))
return child
def set(self, selector, value):
"""Override configuration option.

View File

@ -80,13 +80,21 @@ class ProvidersMap:
original: providers.ConfigurationOption,
as_: Any = None,
) -> providers.Provider:
# TODO: Take care about invariant injections
original_root = original.root
new_root: providers.Configuration = cast(providers.Configuration, self._resolve_provider(original_root))
new_option = new_root.get_option_provider(original.get_relative_name())
new = self._resolve_provider(original_root)
new = cast(providers.Configuration, new)
for segment in original.get_name_segments():
if providers.is_provider(segment):
segment = self.resolve_provider(segment)
new = new[segment]
else:
new = getattr(new, segment)
if as_:
new_option = new_option.as_(as_)
return new_option
new = new.as_(as_)
return new
def _resolve_provider(self, original: providers.Provider) -> providers.Provider:
try: