Completed
Push — appveyor ( 280314...2c0e2c )
by Konstantinos
02:09
created

PhiFunctionRegistry.get_name()   B

Complexity

Conditions 6

Size

Total Lines 11
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 11
nop 1
dl 0
loc 11
rs 8.6666
c 0
b 0
f 0
1
from abc import abstractmethod, ABC
2
from functools import wraps
3
import inspect
4
from so_magic.utils import Singleton, Transformer, ObjectRegistry, Subject
5
6
7
class PhiFunctionRegistry(Singleton, ObjectRegistry):
8
    def __new__(cls, *args, **kwargs):
9
        x = Singleton.__new__(cls, *args, **kwargs)
10
        x = ObjectRegistry(getattr(x, 'objects', {}))
11
        return x
12
13
    @staticmethod
14
    def get_instance():
15
        return PhiFunctionRegistry()
16
17
    @staticmethod
18
    def get_name(a_callable):
19
        if hasattr(a_callable, 'name'):
20
            return a_callable.name
21
        if hasattr(a_callable, '__code__') and hasattr(a_callable.__code__, 'co_name'):
22
            return a_callable.__code__.co_name
23
        if hasattr(type(a_callable), 'name'):
24
            return type(a_callable).name
25
        if hasattr(type(a_callable), '__name__'):
26
            return type(a_callable).__name__
27
        return ''
28
29
30
phi_registry = PhiFunctionRegistry()
31
32
33
class PhiFunctionMetaclass(type):
34
    def __new__(mcs, *args, **kwargs):
35
        x = super().__new__(mcs, *args, **kwargs)
36
        x.subject = Subject([])
37
        return x
38
39
40
class PhiFunctionRegistrator(metaclass=PhiFunctionMetaclass):
41
42
    @classmethod
43
    def register(cls, phi_name=''):
44
        def wrapper(a_callable):
45
            if hasattr(a_callable, '__code__'):  # it a function (def func_name ..)
46
                print(f"Registering input function {a_callable.__code__.co_name}")
47
                cls._register(a_callable, key_name=phi_name)
48
            else:
49
                if not hasattr(a_callable, '__call__'):
50
                    raise RuntimeError(f"Expected an class definition with a '__call__' instance method defined 1. Got {type(a_callable)}")
51
                members = inspect.getmembers(a_callable)
52
                if not ('__call__', a_callable.__call__) in members:
53
                    raise RuntimeError(f"Expected an class definition with a '__call__' instance method defined 2. Got {type(a_callable)}")
54
                print(f"Registering a class {type(a_callable).__name__}")
55
                instance = a_callable()
56
                cls._register(instance, key_name=phi_name)
57
            return a_callable
58
        return wrapper
59
60
    @classmethod
61
    def _register(cls, a_callable, key_name=None):
62
        key = key_name if key_name else PhiFunctionRegistry.get_name(a_callable)
63
        print(f"Registering object {a_callable} at key {key}.")
64
        phi_registry.add(key, a_callable)
65
        cls.subject.name = key
66
        cls.subject.state = a_callable
67
        cls.subject.notify()
68
69
    @classmethod
70
    def my_decorator(cls, f):
71
        print(f"Running 'my_decorator' with input type {type(f)}")
72
        @wraps(f)
73
        def wrapper(*args, **kwds):
74
            if hasattr(f, '__code__'):  # it a function (def func_name ..)
75
                print(f"Registering input function {a_callable.__code__.co_name}")
76
                cls._register(f)
77
            else:
78
                if not hasattr(f, '__call__'):
79
                    raise RuntimeError(f"Expected an class definition with a '__call__' instance method defined 1. Got {type(f)}")
80
                members = inspect.getmembers(f)
81
                if not ('__call__', f.__call__) in members:
82
                    raise RuntimeError(f"Expected an class definition with a '__call__' instance method defined 2. Got {type(f)}")
83
                print(f"Registering a class {type(a_callable).name}")
84
                instance = f()
85
                cls._register(instance)
86
            return f(*args, **kwds)
87
        return wrapper
88
89
90
if __name__ == '__main__':
91
    reg1 = PhiFunctionRegistry()
92
    reg2 = PhiFunctionRegistry()
93
    reg3 = PhiFunctionRegistry.get_instance()
94
95
    assert id(reg1) == id(reg2) == id(reg3)
96
97
    @PhiFunctionRegistrator.my_decorator
98
    def example():
99
        """Inherited Docstring"""
100
        print('Called example function')
101
102
103
    example()
104
105
    print(example.__name__)
106
    print('--')
107
    print(example.__doc__)
108