Passed
Push — master ( 817ef7...81ab82 )
by Steve
01:43
created

lagom.definitions.Construction.get_instance()   A

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 3
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nop 2
crap 1
1 1
import functools
2 1
import inspect
3 1
from typing import Union, Type, Optional, Callable, TypeVar, Any
4
5 1
from .exceptions import InvalidDependencyDefinition
6 1
from .interfaces import SpecialDepDefinition
7 1
from .util.functional import arity
8
9 1
X = TypeVar("X")
10
11
12 1
class Construction(SpecialDepDefinition[X]):
13 1
    constructor: Callable[[], X]
14
15 1
    def __init__(self, constructor):
16 1
        self.constructor = constructor
17
18 1
    def get_instance(self, _build_func) -> X:
19 1
        call = self.constructor  # type: ignore
20 1
        return call()
21
22
23 1
class Alias(SpecialDepDefinition[X]):
24 1
    alias_type: Type[X]
25
26 1
    def __init__(self, alias_type):
27 1
        self.alias_type = alias_type
28
29 1
    def get_instance(self, build_func) -> X:
30 1
        return build_func(self.alias_type)
31
32
33 1
class Singleton(SpecialDepDefinition[X]):
34 1
    singleton_type: Union[Type[X], Construction[X]]
35 1
    _instance: Optional[X]
36
37 1
    def __init__(self, singleton_type: Union[Type[X], Construction[X]]):
38 1
        self.singleton_type = singleton_type
39 1
        self._instance = None
40
41 1
    def get_instance(self, build_func) -> X:
42 1
        if self._has_instance:
43 1
            return self._instance  # type: ignore
44 1
        return self._set_instance(build_func(self.singleton_type))
45
46 1
    @property
47
    def _has_instance(self):
48 1
        return self._instance is not None
49
50 1
    def _set_instance(self, instance: X):
51 1
        self._instance = instance
52 1
        return instance
53
54
55 1
def normalise(resolver: Any, container) -> SpecialDepDefinition:
56 1
    if isinstance(resolver, SpecialDepDefinition):
57 1
        return resolver
58 1
    elif inspect.isfunction(resolver):
59 1
        return _build_lambda_constructor(resolver, container)
60 1
    elif not inspect.isclass(resolver):
61 1
        return Singleton(lambda: resolver)  # type: ignore
62
    else:
63 1
        return Alias(resolver)
64
65
66 1
def _build_lambda_constructor(resolver: Callable, container) -> Construction:
67 1
    artiy = arity(resolver)
68 1
    if artiy == 0:
69 1
        return Construction(resolver)
70 1
    if artiy == 1:
71 1
        return Construction(functools.partial(resolver, container))
72
    raise InvalidDependencyDefinition(f"Arity {arity} functions are not supported")
73