Skip to content

Commit 8a3bd45

Browse files
author
Denis Navarro
committed
refactor(*): Improve ContainerBuilder code
1 parent d2078dd commit 8a3bd45

File tree

6 files changed

+93
-76
lines changed

6 files changed

+93
-76
lines changed

aiodi/builder.py

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@
55
from .container import Container
66
from .logger import logger
77
from .resolver import Resolver, ValueResolutionPostponed
8-
from .resolver.loader import LoaderResolver, prepare_loader_to_parse
8+
from .resolver.loader import LoadData, LoaderResolver, prepare_loader_to_parse
99
from .resolver.path import PathResolver, prepare_path_to_parse
10-
from .resolver.service import ServiceResolver, prepare_services_to_parse
10+
from .resolver.service import (
11+
ServiceDefaults,
12+
ServiceResolver,
13+
prepare_services_to_parse,
14+
)
1115
from .resolver.variable import VariableResolver, prepare_variables_to_parse
1216
from .toml import TOMLDecoder, lazy_toml_decoder
1317

@@ -37,7 +41,7 @@ def __init__(
3741
'./../pyproject.toml',
3842
'./../services.toml',
3943
]
40-
if len(filenames or '') == 0
44+
if filenames is None or len(filenames) == 0
4145
else filenames
4246
)
4347
self._cwd = None if len(cwd or '') == 0 else cwd
@@ -51,19 +55,23 @@ def __init__(
5155
self._decoders = {
5256
'toml': lambda path: (toml_decoder or lazy_toml_decoder())(path).get('tool', {}).get(tool_key, {}),
5357
}
54-
self._map_items = lambda items: [
55-
(key, val, {})
56-
for key, val in {
57-
str('env' if var_key is None or len(var_key) == 0 else var_key): items.get('variables'),
58-
**items.get('services'),
59-
}.items()
60-
]
58+
59+
def map_items(items: Dict[str, Dict[str, Any]]) -> List[Tuple[str, Any, Dict[str, Any]]]:
60+
return [
61+
(key, val, {})
62+
for key, val in {
63+
str('env' if var_key is None or len(var_key) == 0 else var_key): items['variables'],
64+
**items['services'],
65+
}.items()
66+
]
67+
68+
self._map_items = map_items # type: ignore
6169

6270
def load(self) -> Container:
63-
extra = {
71+
extra: Dict[str, Any] = {
6472
'path_data': {},
6573
'data': {},
66-
'_service_defaults': None,
74+
'_service_defaults': ServiceDefaults(),
6775
'resolvers': self._resolvers,
6876
'variables': {},
6977
'services': {},
@@ -89,29 +97,28 @@ def load(self) -> Container:
8997
extra=extra,
9098
),
9199
)
92-
extra['data'] = extra['data']['value']
100+
data: LoadData = extra['data']['value']
101+
extra['data'] = data
93102

94-
extra['_service_defaults'] = extra['data'].service_defaults
103+
extra['_service_defaults'] = data.service_defaults
95104

96105
self._parse_values(
97106
resolver=self._resolvers['variable'],
98107
storage=extra['variables'],
99108
extra=extra,
100-
items=prepare_variables_to_parse(
101-
resolver=self._resolvers['variable'], items=extra['data'].variables, extra=extra
102-
),
109+
items=prepare_variables_to_parse(resolver=self._resolvers['variable'], items=data.variables, extra=extra),
103110
)
104111

105112
self._parse_values(
106113
resolver=self._resolvers['service'],
107114
storage=extra['services'],
108115
extra=extra,
109-
items=prepare_services_to_parse(
110-
resolver=self._resolvers['service'], items=extra['data'].services, extra=extra
111-
),
116+
items=prepare_services_to_parse(resolver=self._resolvers['service'], items=data.services, extra=extra),
112117
)
113118

114-
return Container(items=self._map_items({'variables': extra['variables'], 'services': extra['services']}))
119+
return Container(
120+
items=self._map_items({'variables': extra['variables'], 'services': extra['services']}) # type: ignore
121+
)
115122

116123
def _parse_values(
117124
self,

aiodi/resolver/loader.py

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def decode(self) -> OutputData:
1818
if filepath.is_file() and filepath.exists():
1919
ext = filepath.suffix[1:]
2020
if ext not in self.decoders:
21-
raise NotImplemented('Missing {0} decoder to load dependencies'.format(ext.upper()))
21+
raise NotImplemented('Missing {0} decoder to load dependencies'.format(ext.upper())) # type: ignore
2222
data = self.decoders[ext](filepath)
2323

2424
data.setdefault('variables', {})
@@ -37,8 +37,8 @@ class LoadData(NamedTuple):
3737
def from_metadata(cls, metadata: LoaderMetadata, data: OutputData) -> 'LoadData':
3838
path_data = metadata.path_data
3939

40-
defaults = data.get('services').get('_defaults', ServiceDefaults()._asdict())
41-
project_dir = defaults.get('project_dir')
40+
defaults = data['services'].get('_defaults', ServiceDefaults()._asdict())
41+
project_dir = defaults['project_dir']
4242

4343
if len(project_dir or '') == 0:
4444
defaults['project_dir'] = path_data.cwd
@@ -51,29 +51,36 @@ def from_metadata(cls, metadata: LoaderMetadata, data: OutputData) -> 'LoadData'
5151

5252
defaults['project_dir'] = project_dir
5353

54-
if '_defaults' in data.get('services'):
55-
del data.get('services')['_defaults']
54+
if '_defaults' in data['services']:
55+
del data['services']['_defaults']
5656

5757
return cls(
58-
variables=data.get('variables'),
59-
services=data.get('services'),
58+
variables=data['variables'],
59+
services=data['services'],
6060
service_defaults=ServiceDefaults(**defaults),
6161
)
6262

6363

6464
class LoaderResolver(Resolver[LoaderMetadata, LoadData]):
65-
def extract_metadata(self, data: Dict[str, Any], extra: Dict[str, Any] = {}) -> LoaderMetadata:
65+
def extract_metadata(
66+
self, data: Dict[str, Any], extra: Dict[str, Any] = {} # pylint: disable=W0613
67+
) -> LoaderMetadata:
6668
return LoaderMetadata(
67-
path_data=data.get('path_data'),
68-
decoders=data.get('decoders'),
69+
path_data=data['path_data'],
70+
decoders=data['decoders'],
6971
)
7072

71-
def parse_value(self, metadata: LoaderMetadata, retries: int = -1, extra: Dict[str, Any] = {}) -> LoadData:
73+
def parse_value(
74+
self,
75+
metadata: LoaderMetadata,
76+
retries: int = -1, # pylint: disable=W0613
77+
extra: Dict[str, Any] = {}, # pylint: disable=W0613
78+
) -> LoadData:
7279
return LoadData.from_metadata(metadata=metadata, data=metadata.decode())
7380

7481

7582
def prepare_loader_to_parse(
76-
resolver: Resolver[Any, Any], items: Dict[str, Any], extra: Dict[str, Any]
83+
resolver: Resolver[Any, Any], items: Dict[str, Any], extra: Dict[str, Any] # pylint: disable=W0613
7784
) -> Dict[str, Tuple[LoaderMetadata, int]]:
7885
return {
7986
'value': (resolver.extract_metadata(data=items), 0),

aiodi/resolver/path.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,22 @@ def from_metadata(cls, metadata: PathMetadata) -> 'PathData':
4747

4848

4949
class PathResolver(Resolver[PathMetadata, PathData]):
50-
def extract_metadata(self, data: Dict[str, Any], extra: Dict[str, Any] = {}) -> PathMetadata:
50+
def extract_metadata(
51+
self, data: Dict[str, Any], extra: Dict[str, Any] = {} # pylint: disable=W0613
52+
) -> PathMetadata:
5153
return PathMetadata(cwd=data.get('cwd', None), filenames=data.get('filenames', []))
5254

53-
def parse_value(self, metadata: PathMetadata, retries: int = -1, extra: Dict[str, Any] = {}) -> PathData:
55+
def parse_value(
56+
self,
57+
metadata: PathMetadata,
58+
retries: int = -1, # pylint: disable=W0613
59+
extra: Dict[str, Any] = {}, # pylint: disable=W0613
60+
) -> PathData:
5461
return PathData.from_metadata(metadata)
5562

5663

5764
def prepare_path_to_parse(
58-
resolver: Resolver[Any, Any], items: Dict[str, Any], extra: Dict[str, Any]
65+
resolver: Resolver[Any, Any], items: Dict[str, Any], extra: Dict[str, Any] # pylint: disable=W0613
5966
) -> Dict[str, Tuple[PathMetadata, int]]:
6067
return {
6168
'value': (resolver.extract_metadata(data=items), 0),

aiodi/resolver/service.py

Lines changed: 28 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@
22
from glob import glob
33
from inspect import Parameter, signature
44
from pathlib import Path
5-
from typing import Any, Dict, List, NamedTuple, Optional, Tuple, Type
5+
from typing import Any, Dict, List, NamedTuple, Optional, Tuple, Type, cast
66

77
from ..helpers import (
88
import_module_and_get_attr,
99
import_module_and_get_attrs,
1010
is_abstract,
1111
is_primitive,
12-
raise_,
1312
re_finditer,
1413
)
1514
from . import Resolver, ValueNotFound, ValueResolutionPostponed
1615

1716
_SERVICE_AUTOREGISTRATION_EXCLUDE_REGEX = r"^([.\w/]+)?({[\w/.*,]+})?$"
17+
_SVC_DEFAULTS = ...
1818

1919

2020
class ServiceDefaults(NamedTuple):
@@ -135,10 +135,10 @@ class ServiceMetadata(NamedTuple):
135135
type: Type[Any]
136136
clazz: Type[Any]
137137
arguments: Dict[str, Any]
138-
params: List['ServiceMetadata.ParameterMetadata']
138+
params: List[Any]
139139
defaults: ServiceDefaults
140140

141-
class ParameterMetadata(NamedTuple):
141+
class ParameterMetadata(NamedTuple): # type: ignore
142142
name: str
143143
source_kind: str
144144
type: Type[Any]
@@ -186,39 +186,39 @@ class ServiceResolutionPostponed(ValueResolutionPostponed[ServiceMetadata]):
186186
class ServiceResolver(Resolver[ServiceMetadata, Any]):
187187
@staticmethod
188188
def _define_service_type(name: str, typ: str, cls: str) -> Tuple[Type[Any], Type[Any]]:
189-
if typ is ... and cls is ...:
190-
cls = typ = import_module_and_get_attr(name=name)
191-
return typ, cls
189+
if typ is _SVC_DEFAULTS and cls is _SVC_DEFAULTS: # type: ignore
190+
cls = typ = import_module_and_get_attr(name=name) # type: ignore
191+
return typ, cls # type: ignore
192192

193-
if typ is not ...:
194-
typ = import_module_and_get_attr(name=typ)
195-
if cls is not ...:
196-
cls = import_module_and_get_attr(name=cls)
193+
if typ is not _SVC_DEFAULTS: # type: ignore
194+
typ = import_module_and_get_attr(name=typ) # type: ignore
195+
if cls is not _SVC_DEFAULTS: # type: ignore
196+
cls = import_module_and_get_attr(name=cls) # type: ignore
197197

198-
if typ is ...:
198+
if typ is _SVC_DEFAULTS: # type: ignore
199199
try:
200-
typ = import_module_and_get_attr(name=name)
200+
typ = import_module_and_get_attr(name=name) # type: ignore
201201
except Exception:
202202
typ = cls
203-
if cls is ...:
203+
if cls is _SVC_DEFAULTS: # type: ignore
204204
cls = typ
205205

206-
if cls is not typ and not issubclass(signature(cls).return_annotation or cls, typ):
206+
if cls is not typ and not issubclass(signature(cls).return_annotation or cls, typ): # type: ignore
207207
raise TypeError('Class <{0}> return type must be <{1}>'.format(cls, typ))
208208

209-
return typ, cls
209+
return typ, cls # type: ignore
210210

211-
def extract_metadata(self, data: Dict[str, Any], extra: Dict[str, Any] = {}) -> ServiceMetadata:
212-
key: str = data.get('key') or raise_(KeyError('Missing key "key" to extract service metadata'))
213-
val: Any = data.get('val') or raise_(KeyError('Missing key "val" to extract service metadata'))
214-
defaults: ServiceDefaults = data.get('defaults') or raise_(
215-
KeyError('Missing key "defaults" to extract service metadata')
216-
)
211+
def extract_metadata(
212+
self, data: Dict[str, Any], extra: Dict[str, Any] = {} # pylint: disable=W0613
213+
) -> ServiceMetadata:
214+
key = cast(str, data.get('key'))
215+
val = data.get('val')
216+
defaults = cast(ServiceDefaults, data.get('defaults'))
217217

218218
typ, clazz = self._define_service_type(
219219
name=key,
220-
typ=val['type'] if isinstance(val, dict) and 'type' in val else ...,
221-
cls=val['class'] if isinstance(val, dict) and 'class' in val else ...,
220+
typ=val['type'] if isinstance(val, dict) and 'type' in val else _SVC_DEFAULTS,
221+
cls=val['class'] if isinstance(val, dict) and 'class' in val else _SVC_DEFAULTS,
222222
)
223223
kwargs = val['arguments'] if isinstance(val, dict) and 'arguments' in val else {}
224224
return ServiceMetadata(
@@ -234,15 +234,9 @@ def extract_metadata(self, data: Dict[str, Any], extra: Dict[str, Any] = {}) ->
234234
)
235235

236236
def parse_value(self, metadata: ServiceMetadata, retries: int = -1, extra: Dict[str, Any] = {}) -> Any:
237-
_variables: Dict[str, Any] = extra.get('variables')
238-
if _variables is None:
239-
raise KeyError('Missing key "variables" to parse service value')
240-
_services: Dict[str, Any] = extra.get('services')
241-
if _services is None:
242-
raise KeyError('Missing key "services" to parse service value')
243-
variable_resolver: Resolver = extra.get('resolvers', {}).get('variable') or raise_(
244-
KeyError('Missing key "resolvers.variable"')
245-
)
237+
_variables = cast(Dict[str, Any], extra.get('variables'))
238+
_services = cast(Dict[str, Any], extra.get('services'))
239+
variable_resolver = cast(Resolver, extra.get('resolvers', {}).get('variable'))
246240

247241
parameters: Dict[str, Any] = {}
248242
for param in metadata.params:
@@ -285,9 +279,7 @@ def parse_value(self, metadata: ServiceMetadata, retries: int = -1, extra: Dict[
285279
def prepare_services_to_parse(
286280
resolver: Resolver[Any, Any], items: Dict[str, Any], extra: Dict[str, Any]
287281
) -> Dict[str, Tuple['ServiceMetadata', int]]:
288-
_service_defaults: ServiceDefaults = extra.get('_service_defaults') or raise_(
289-
KeyError('Missing key "_service_defaults"')
290-
)
282+
_service_defaults = cast(ServiceDefaults, extra.get('_service_defaults'))
291283

292284
services: Dict[str, Tuple['ServiceMetadata', int]] = {}
293285
for key, val in items.items():

aiodi/resolver/variable.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ def __call__(string: Any) -> List[Match]:
4848

4949
return __call__(string=val) or __call__(string=STATIC_TEMPLATE.format(type(val).__name__, key, val))
5050

51-
def extract_metadata(self, data: Dict[str, Any], extra: Dict[str, Any] = {}) -> VariableMetadata:
51+
def extract_metadata(
52+
self, data: Dict[str, Any], extra: Dict[str, Any] = {} # pylint: disable=W0613
53+
) -> VariableMetadata:
5254
key: str = data.get('key') or raise_(KeyError('Missing key "key" to extract variable metadata')) # type: ignore
5355
val: Any = data.get('val') or raise_(KeyError('Missing key "val" to extract variable metadata'))
5456

@@ -61,7 +63,9 @@ def extract_metadata(self, data: Dict[str, Any], extra: Dict[str, Any] = {}) ->
6163
],
6264
)
6365

64-
def parse_value(self, metadata: VariableMetadata, retries: int = -1, extra: Dict[str, Any] = {}) -> Any:
66+
def parse_value(
67+
self, metadata: VariableMetadata, retries: int = -1, extra: Dict[str, Any] = {} # pylint: disable=W0613
68+
) -> Any:
6569
_variables: Dict[str, Any] = extra.get('variables') # type: ignore
6670
if _variables is None:
6771
raise KeyError('Missing key "variables" to parse variable value')
@@ -94,6 +98,6 @@ def parse_value(self, metadata: VariableMetadata, retries: int = -1, extra: Dict
9498

9599

96100
def prepare_variables_to_parse(
97-
resolver: Resolver[Any, Any], items: Dict[str, Any], extra: Dict[str, Any]
101+
resolver: Resolver[Any, Any], items: Dict[str, Any], extra: Dict[str, Any] # pylint: disable=W0613
98102
) -> Dict[str, Tuple[VariableMetadata, int]]:
99103
return dict([(key, (resolver.extract_metadata(data={'key': key, 'val': val}), 0)) for key, val in items.items()])

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ uuid = "1.30"
3232
[tool.pylint.master]
3333
jobs = "0"
3434
[tool.pylint.messages_control]
35-
disable = "C0103,C0114,C0115,C0116,C0201,C0205,C0209,C0301,C0415,E0401,E0611,E1136,R0902,R0903,R0912,R0914,R1704,R1717,R1725,W0102,W0108,W0212,W0235,W0236,W0603,W0611,W0622,W0703,W0707,W1202"
35+
disable = "C0103,C0114,C0115,C0116,C0201,C0205,C0209,C0301,C0415,E1102,E0401,E0611,E0711,E1136,R0201,R0902,R0903,R0912,R0914,R1704,R1717,R1725,W0102,W0108,W0212,W0235,W0236,W0603,W0611,W0622,W0703,W0707,W1202"
3636

3737
[tool.pytest.ini_options]
3838
cache_dir = "var/cache/.pytest_cache"

0 commit comments

Comments
 (0)