so_magic.data.command_factories   A
last analyzed

Complexity

Total Complexity 4

Size/Duplication

Total Lines 46
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 34
dl 0
loc 46
rs 10
c 0
b 0
f 0
wmc 4

3 Methods

Rating   Name   Duplication   Size   Complexity  
A DataManagerCommandFactoryBuilder.create_factory() 0 9 1
A DataManagerCommandFactory.__call__() 0 5 1
A DataManagerCommandFactory.build_command_prototype() 0 15 2
1
from typing import Callable
2
import attr
3
from so_magic.utils import Command, Subject, CommandFactoryInterface, CommandFactoryType
4
5
6
class DataManagerCommandFactoryBuilder(metaclass=CommandFactoryType):
7
    @classmethod
8
    def create_factory(cls, name, callback):
9
        @DataManagerCommandFactoryBuilder.register_as_subclass(name)
10
        class DataManagerRuntimeCommandFactory(CommandFactoryInterface):
11
            def construct(self, *args, **kwargs) -> Command:
12
                receiver = args[0]
13
                def command(*runtime_args):
14
                    callback(receiver, *runtime_args)
15
                return Command(command, '__call__', *args[1:])
16
17
18
@attr.s
19
class DataManagerCommandFactory:
20
    _data_manager = attr.ib(init=True)
21
    command_factory = attr.ib(init=True, default=DataManagerCommandFactoryBuilder)
22
    subject: Subject = attr.ib(init=False, default=attr.Factory(Subject))
23
    name: str = attr.ib(init=False, default='')
24
25
    def __call__(self, command_type, *args, **kwargs):
26
        self.subject.state = self.command_factory.create(command_type).construct(self._data_manager, *args, **kwargs)
27
        self.subject.name = command_type
28
        self.subject.notify()
29
        return self.subject.state
30
31
    def build_command_prototype(self):
32
        def wrapper(a_callable: Callable) -> Callable:
33
            """Build and register a new Command given a callable object that holds the important business logic.
34
35
            Args:
36
                a_callable (Callable): the Command's important underlying business logic
37
            """
38
            if hasattr(a_callable, '__code__'):  # a_callable object has been defined with the def python keyword
39
                decorated_function_name = a_callable.__code__.co_name
40
                self.command_factory.create_factory(decorated_function_name, a_callable)
41
                self(decorated_function_name)
42
            else:
43
                raise RuntimeError(f"Expected a function to be decorated; got {type(a_callable)}")
44
            return a_callable
45
        return wrapper
46