ClickIO.__getattr__()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1.2963

Importance

Changes 0
Metric Value
cc 1
eloc 3
nop 2
dl 0
loc 4
rs 10
c 0
b 0
f 0
ccs 1
cts 3
cp 0.3333
crap 1.2963
1
"""
2
Integration layer for Click https://click.palletsprojects.com/
3
"""
4
5 1
from typing import Optional, List, Type, Callable
6
7 1
from click import utils, decorators
8 1
from click.core import BaseCommand
9
10 1
from lagom.interfaces import ExtendableContainer, WriteableContainer
11
12
13 1
class DecoratedCommand(BaseCommand):
14
    """
15
    Virtual class which is returned by the lagom wrapped click command
16
    decorator
17
    """
18
19 1
    plain_function: Callable
20
21
22 1
class ClickIO:
23
    """
24
    Provides an injectable hint for click IO if needed.
25
    """
26
27 1
    @staticmethod
28 1
    def echo(message=None, file=None, nl=True, err=False, color=None):
29 1
        utils.echo(message, file, nl, err, color)
30
31 1
    def __getattr__(self, item):
32
        import click
33
34
        return getattr(click, item)
35
36
37 1
class ClickIntegration:
38
    """
39
    Integration between a container and click. The ClickIntegration
40
    instance provides all the same decorators and functions as click.
41
    """
42
43 1
    _container: WriteableContainer
44
45 1
    def __init__(
46
        self,
47
        container: ExtendableContainer,
48
        execution_singletons: Optional[List[Type]] = None,
49
    ):
50 1
        self._container = container.clone()
51 1
        self._container[ClickIO] = ClickIO()
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable ClickIO does not seem to be defined.
Loading history...
52 1
        self._execution_singletons = execution_singletons or []
53
54 1
    def command(
55
        self, name=None, cls=None, **attrs
56
    ) -> Callable[[Callable], DecoratedCommand]:
57
        """
58
        Proxies click.command but binds the function to lagom
59
        so that any arguments with lagom.injectable as a default will
60
        be injected by the container
61
        :param name:
62
        :param cls:
63
        :param attrs:
64
        :return:
65
        """
66
67 1
        def _decorator(f):
68 1
            bound_f = self._container.partial(f, shared=self._execution_singletons)
69 1
            command = decorators.command(name, cls, **attrs)(bound_f)
70 1
            setattr(command, "plain_function", bound_f)
71 1
            return command
72
73 1
        return _decorator
74
75 1
    @staticmethod
76 1
    def option(*param_decls, **attrs):
77
        """
78
        Proxies click.option
79
        :param param_decls:
80
        :param attrs:
81
        :return:
82
        """
83
        return decorators.option(*param_decls, **attrs)
84
85 1
    @staticmethod
86 1
    def argument(*param_decls, **attrs):
87
        """
88
        Proxies click.argument
89
        :param param_decls:
90
        :param attrs:
91
        :return:
92
        """
93 1
        return decorators.argument(*param_decls, **attrs)
94
95 1
    def __getattr__(self, item):
96
        # Any method not explicitly code just gets passed to click
97 1
        import click
98
99
        return getattr(click, item)
100