|
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
|
|
|
|