1
|
|
|
from itertools import chain |
2
|
|
|
from typing import TypeVar, Type, Optional, Set, Tuple, Collection, Sequence |
3
|
|
|
|
4
|
|
|
from .container import Container |
5
|
|
|
from .interfaces import DefinitionsSource, SpecialDepDefinition |
6
|
|
|
|
7
|
|
|
X = TypeVar("X") |
8
|
|
|
|
9
|
|
|
|
10
|
|
|
def compose(*args: DefinitionsSource) -> Container: |
11
|
|
|
combined_sources = _SourceList(*args) |
12
|
|
|
_assert_unique_dependencies(args) |
13
|
|
|
|
14
|
|
|
return Container(container=combined_sources) |
15
|
|
|
|
16
|
|
|
|
17
|
|
|
class _SourceList(DefinitionsSource): |
18
|
|
|
""" |
19
|
|
|
Combines multiple `DefinitionsSource`s which are accessed in order |
20
|
|
|
""" |
21
|
|
|
|
22
|
|
|
sources: Collection[DefinitionsSource] |
23
|
|
|
|
24
|
|
|
def __init__(self, *args: DefinitionsSource): |
25
|
|
|
self.sources = args |
26
|
|
|
|
27
|
|
|
def get_definition(self, dep_type: Type[X]) -> Optional[SpecialDepDefinition[X]]: |
28
|
|
|
""" |
29
|
|
|
For a supplied type returns the definition of how to build that type. |
30
|
|
|
If unknown None is returned |
31
|
|
|
:param dep_type: |
32
|
|
|
""" |
33
|
|
|
for source in self.sources: |
34
|
|
|
definition = source.get_definition(dep_type) |
35
|
|
|
if definition is not None: |
36
|
|
|
return definition |
37
|
|
|
return None |
38
|
|
|
|
39
|
|
|
@property |
40
|
|
|
def defined_types(self) -> Set[Type]: |
41
|
|
|
""" |
42
|
|
|
The list of types that have been explicitly defined |
43
|
|
|
:return: |
44
|
|
|
""" |
45
|
|
|
return set(chain.from_iterable(s.defined_types for s in self.sources)) |
46
|
|
|
|
47
|
|
|
|
48
|
|
|
def _assert_unique_dependencies(definition_sources: Sequence[DefinitionsSource]): |
49
|
|
|
for first in range(0, len(definition_sources)): |
50
|
|
|
for second in range(first + 1, len(definition_sources)): |
51
|
|
|
for dep in definition_sources[first].defined_types: |
52
|
|
|
if ( |
53
|
|
|
dep.__name__ != "ContainerDebugInfo" |
54
|
|
|
and dep in definition_sources[second].defined_types |
55
|
|
|
): |
56
|
|
|
raise ValueError(f"Dep {dep} defined in {first} and {second}") |
57
|
|
|
|