3
3
import inspect
4
4
5
5
class ExpressionReaction :
6
+ """An Expression Reaction object will be called when a change is detected.
7
+ Define the action with on_change(expression)."""
8
+
6
9
def __init__ (self , expression_to_monitor ):
7
10
self .expression_to_monitor = expression_to_monitor
8
11
self .old_value = expression_to_monitor ()
@@ -18,9 +21,16 @@ def call(self):
18
21
self .old_value = new_value
19
22
20
23
class UnimplementedInstructionException (Exception ):
24
+ """An UnimplementedInstructionException will be thrown when
25
+ the analysis try to process an unknown byte-code."""
26
+
21
27
pass
22
28
23
29
class ObjectWrapper :
30
+ """Wraps an object on the object stack. Can be a placeholder,
31
+ a buildin or a simple object. If it an attribute of another object,
32
+ base_obj will contains the original object."""
33
+
24
34
def __init__ (self , obj = None , base_obj = None , placeholder = False , buildin = False ):
25
35
self .obj = obj
26
36
self .base_obj = base_obj
@@ -34,6 +44,9 @@ def is_build_in(self):
34
44
return self .buildin
35
45
36
46
def placeaexpr (obj , attr_name , expression_reaction_object ):
47
+ """placeaexpr will be called by the byte-code analysis
48
+ when an instrumentable attribute is found."""
49
+
37
50
if not hasattr (obj , '__listenon__' ):
38
51
if not hasattr (type (obj ), "__aexprhandler__" ):
39
52
original = type (obj ).__setattr__
@@ -57,6 +70,11 @@ def execaexprhandler(self, name, value):
57
70
58
71
59
72
def aexpr (lambda_expression , globalvars , localvars = None ):
73
+ """aexpr performs the byte-code analysis to find all
74
+ dependencies of the given expression. It places hooks on these dependencies.
75
+ When one of these hooks is triggered, an ExpressionReaction will be executed.
76
+ The method returns the ExpressionReaction which were created during this execution."""
77
+
60
78
expression_reaction_object = ExpressionReaction (lambda_expression )
61
79
62
80
#####
0 commit comments