jacked._injectable._decorator()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 18
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 16
nop 6
dl 0
loc 18
rs 9.6
c 0
b 0
f 0
1
"""
2
PRIVATE MODULE: do not import (from) it directly.
3
4
This module contains the ``Injectable`` class and the ``injectable`` decorator.
5
"""
6
from functools import partial
7
from typing import Dict, Any
8
from jacked import _container
9
from jacked._typing import AttrDict
10
11
12
class Injectable:
13
    """
14
    Objects of this class hold stuff that can be injected.
15
    """
16
    def __init__(
17
            self,
18
            *,
19
            subject: object,
20
            priority: int,
21
            singleton: bool,
22
            meta: Dict[str, Any]):
23
        """
24
        Constructor.
25
        :param subject: the thing that is to be injected.
26
        :param priority: a number that indicates how jacked should choose
27
        between candidates.
28
        :param singleton: if ``True`` and ``subject`` is a class, then only one
29
        instance is ever injected.
30
        :param meta: any meta information.
31
        """
32
        self._subject = subject
33
        self._singleton = singleton
34
        self._meta = meta
35
        self._priority = priority
36
37
    @property
38
    def name(self) -> str:
39
        return self._meta['name']
40
41
    @property
42
    def meta(self) -> AttrDict:
43
        return AttrDict(self._meta)
44
45
    @property
46
    def subject(self) -> object:
47
        # Set the meta data 'just in time' to allow different meta objects in
48
        # different Containers.
49
        result = self._subject
50
        result.__meta__ = self.meta  # Use the property, not the field.
51
        return result
52
53
    @property
54
    def singleton(self) -> bool:
55
        return self._singleton
56
57
    @property
58
    def priority(self) -> int:
59
        return self._priority
60
61
62
def injectable(
63
        decorated: object = None,
64
        *,
65
        name: str = None,
66
        priority: int = 0,
67
        meta: Dict[str, Any] = None,
68
        singleton: bool = False,
69
        container: _container.Container = _container.DEFAULT_CONTAINER
70
):
71
    """
72
    A decorator that marks something as injectable.
73
74
    Usage example:
75
    ```
76
    @injectable
77
    class Bird(Animal):
78
        def sound(self):
79
        return 'tweet'
80
    ```
81
    :param decorated: the thing (class, function, method) that is to become
82
    injectable.
83
    :param name: the name of that thing, stored in the meta information.
84
    :param priority: a number that indicates how jacked should choose between
85
    candidates; higher priorities are more likely to get injected.
86
    :param meta: any meta information that is added to the injectable.
87
    :param singleton: if True and ``decorated`` is a class, then a singleton
88
    instance will be injected for every injection on from ``container``.
89
    :param container: the registry that stores the new injectable.
90
    :return: a decorator.
91
    """
92
    if decorated:
93
        result = _decorator(name, priority, meta, singleton,
94
                          container, decorated)
95
        return result
96
    return partial(_decorator, name, priority, meta, singleton, container)
97
98
99
def _decorator(
100
        name: str,
101
        priority: int,
102
        meta: Dict[str, Any],
103
        singleton: bool,
104
        container: _container.Container,
105
        decorated: object) -> callable:
106
    # This is the actual decorator that registers the decorated object.
107
    meta = {
108
        **(meta or {}),
109
        'name': name or decorated.__name__
110
    }
111
    injectable_inst = Injectable(subject=decorated,
112
                                 priority=priority,
113
                                 singleton=singleton,
114
                                 meta=meta)
115
    container.register(injectable_inst)
116
    return decorated
117