Coverage for src/configuraptor/cls.py: 100%
24 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-21 15:50 +0200
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-21 15:50 +0200
1"""
2Logic for the TypedConfig inheritable class.
3"""
5import typing
7from .core import T_data, all_annotations, check_type, load_into
8from .errors import ConfigErrorExtraKey, ConfigErrorInvalidType
10C = typing.TypeVar("C", bound=typing.Any)
13class TypedConfig:
14 """
15 Can be used instead of load_into.
16 """
18 @classmethod
19 def load(
20 cls: typing.Type[C], data: T_data, key: str = None, init: dict[str, typing.Any] = None, strict: bool = True
21 ) -> C:
22 """
23 Load a class' config values from the config file.
25 SomeClass.load(data, ...) = load_into(SomeClass, data, ...).
26 """
27 return load_into(cls, data, key=key, init=init, strict=strict)
29 def _update(self, _strict: bool = True, _allow_none: bool = False, **values: typing.Any) -> None:
30 """
31 Can be used if .update is overwritten with another value in the config.
32 """
33 annotations = all_annotations(self.__class__)
35 for key, value in values.items():
36 if value is None and not _allow_none:
37 continue
39 if _strict and key not in annotations:
40 raise ConfigErrorExtraKey(cls=self.__class__, key=key, value=value)
42 if _strict and not check_type(value, annotations[key]) and not (value is None and _allow_none):
43 raise ConfigErrorInvalidType(expected_type=annotations[key], key=key, value=value)
45 setattr(self, key, value)
47 def update(self, _strict: bool = True, _allow_none: bool = False, **values: typing.Any) -> None:
48 """
49 Update values on this config.
51 Args:
52 _strict: allow wrong types?
53 _allow_none: allow None or skip those entries?
54 **values: key: value pairs in the right types to update.
55 """
56 return self._update(_strict, _allow_none, **values)
58 def _format(self, string: str) -> str:
59 """
60 Format the config data into a string template.
62 Replacement for string.format(**config), which is only possible for MutableMappings.
63 MutableMapping does not work well with our Singleton Metaclass.
64 """
65 return string.format(**self.__dict__)
68# also expose as separate function:
69def update(instance: typing.Any, _strict: bool = True, _allow_none: bool = False, **values: typing.Any) -> None:
70 """
71 Update values on a config.
73 Args:
74 instance: config instance to update
75 _strict: allow wrong types?
76 _allow_none: allow None or skip those entries?
77 **values: key: value pairs in the right types to update.
78 """
79 return TypedConfig._update(instance, _strict, _allow_none, **values)