|
@@ -7,8 +7,15 @@
|
7
|
7
|
import types
|
8
|
8
|
from .magix import MAGIX
|
9
|
9
|
|
|
10
|
+## @brief Default call catcher for wrappers
|
10
|
11
|
class DefaultCallCatcher(object):
|
11
|
|
-
|
|
12
|
+
|
|
13
|
+ ## @brief Method designed to be called when an access is done on a wrapped class
|
|
14
|
+ # @note fetch the attribute
|
|
15
|
+ # @param obj : the python object on wich the access is done
|
|
16
|
+ # @param attr_name str : the name of the accessed attribute
|
|
17
|
+ # @return the attribute
|
|
18
|
+ # @throw AttributeError if the attr does not exist
|
12
|
19
|
@classmethod
|
13
|
20
|
def attr_get(self, obj, attr_name):
|
14
|
21
|
if hasattr(obj, '__name__'):
|
|
@@ -17,6 +24,13 @@ class DefaultCallCatcher(object):
|
17
|
24
|
print("\tCatched ! Get %s.%s" % (obj, attr_name))
|
18
|
25
|
return getattr(obj, attr_name)
|
19
|
26
|
|
|
27
|
+ ## @brief Method designed to be called when a wrapped class method is called
|
|
28
|
+ # @note Do the call
|
|
29
|
+ # @param obj : the python object the method belongs to
|
|
30
|
+ # @param method : the python bound method
|
|
31
|
+ # @param args tuple : method call positional arguments
|
|
32
|
+ # @param kwargs dict : method call named arguments
|
|
33
|
+ # @return the call returned value
|
20
|
34
|
@classmethod
|
21
|
35
|
def method_call(self, obj, method, args, kwargs):
|
22
|
36
|
if obj is method:
|
|
@@ -30,8 +44,19 @@ class DefaultCallCatcher(object):
|
30
|
44
|
|
31
|
45
|
return method(*args, **kwargs)
|
32
|
46
|
|
|
47
|
+## @brief Generate a wrapper
|
|
48
|
+#
|
|
49
|
+# Returns a wrapper for a given class. The wrapper will call the call_catcher
|
|
50
|
+# for any access done on wrapped class
|
|
51
|
+#
|
|
52
|
+# @param towrap Class : Python class to wrap
|
|
53
|
+# @param call_catcher_cls : A child class of DefaultCallCatcher designed to be called by the wrapper
|
|
54
|
+# @return A class that is a wrapper for towrap
|
33
|
55
|
def get_wrap(towrap, call_catcher_cls = DefaultCallCatcher):
|
34
|
|
-
|
|
56
|
+
|
|
57
|
+ ## @brief Function wrapper
|
|
58
|
+ #
|
|
59
|
+ # In fact this class will only be a wrapper for methods
|
35
|
60
|
class funwrap(object):
|
36
|
61
|
|
37
|
62
|
def __init__(self, obj, fun):
|
|
@@ -44,6 +69,9 @@ def get_wrap(towrap, call_catcher_cls = DefaultCallCatcher):
|
44
|
69
|
def __repr__(self):
|
45
|
70
|
return '<funwrap %s>' % self._fun
|
46
|
71
|
|
|
72
|
+ ## @brief the wrapper class metaclass
|
|
73
|
+ #
|
|
74
|
+ # Handles static attributes access
|
47
|
75
|
class metawrap(type):
|
48
|
76
|
|
49
|
77
|
def __getattribute__(self, name):
|
|
@@ -55,7 +83,10 @@ def get_wrap(towrap, call_catcher_cls = DefaultCallCatcher):
|
55
|
83
|
return call_catcher_cls.attr_get(towrap, name)
|
56
|
84
|
except Exception as e:
|
57
|
85
|
raise e
|
58
|
|
-
|
|
86
|
+
|
|
87
|
+ ## @brief The class that will be the wrapper
|
|
88
|
+ #
|
|
89
|
+ # Handles instance attributes access
|
59
|
90
|
class wrap(object, metaclass=metawrap):
|
60
|
91
|
|
61
|
92
|
def __init__(self, *args, **kwargs):
|
|
@@ -99,8 +130,10 @@ def get_wrap(towrap, call_catcher_cls = DefaultCallCatcher):
|
99
|
130
|
return call_catcher_cls.method_call(towrap.__class__, method, args, kwargs)
|
100
|
131
|
return magix_class_wrap
|
101
|
132
|
|
102
|
|
- instance_ex = ['__init__', '__new__'] # exclude for instances
|
103
|
|
- class_ex = ['__new__'] # exclude for classes
|
|
133
|
+ instance_ex = ['__init__'] # exclude for instances
|
|
134
|
+ class_ex = [] # exclude for classes
|
|
135
|
+
|
|
136
|
+ # Add all magic methods to wrap and metawrap classes
|
104
|
137
|
for name in MAGIX:
|
105
|
138
|
if name not in instance_ex:
|
106
|
139
|
setattr(wrap, name, make_instance_magix(name))
|