File tree Expand file tree Collapse file tree 3 files changed +106
-0
lines changed
Expand file tree Collapse file tree 3 files changed +106
-0
lines changed Original file line number Diff line number Diff line change 1+ #Inject python locals#
2+
3+
4+ A bit of hackery to experiment with alternative call flow in python.
5+
6+ To use:
7+
8+ def foo():
9+ print a
10+
11+ inject(a=5).into(foo)
12+ >> 5
13+
14+ @inject (cat='man')
15+ def bar():
16+ print "the cat is a", cat
17+
18+ bar()
19+ >> the cat is a man
20+
21+
22+ ** Q: Why should I use this?**
23+ A: You shouldn't
24+
25+ ** Q: Why does it exist?**
26+ A: Because it can
27+
28+ ** Q: Are you crazy?**
29+ A: ?
30+
Original file line number Diff line number Diff line change 1+
2+ import sys
3+
4+ class inject (object ):
5+ def __init__ (self , ** kwargs ):
6+ self .kwargs = kwargs
7+
8+ def __call__ (self , fn ):
9+ from functools import wraps
10+ @wraps (fn )
11+ def wrapped (* args , ** kwargs ):
12+ print "doing wrap" , args , kwargs
13+ old_trace = sys .gettrace ()
14+ def tracefn (frame , event , arg ):
15+ # define a new tracefn each time, since it needs to
16+ # call the *current* tracefn if they're in debug mode
17+ print 'updating locals with' , self .kwargs
18+ frame .f_locals .update (self .kwargs )
19+ if old_trace :
20+ return old_trace (frame , event , arg )
21+ else :
22+ return None
23+
24+ sys .settrace (tracefn )
25+ retval = fn (* args , ** kwargs )
26+ sys .settrace (old_trace )
27+ return retval
28+
29+ return wrapped
30+
31+ def into (self , fn , * args , ** kwargs ):
32+ return self (fn )(* args , ** kwargs )
33+
Original file line number Diff line number Diff line change 1+
2+ from inject import inject
3+
4+ @inject (a = 5 )
5+ def test_inject ():
6+ print locals ()
7+ assert locals () == {'a' : 5 }
8+
9+ @inject (cat = 'foo' , whatever = 15 )
10+ def test_inject2 ():
11+ print locals ()
12+ assert locals () == {'cat' : 'foo' , 'whatever' : 15 }
13+
14+ def test_inject_keeps_old_trace_behavior ():
15+ import sys
16+ events = []
17+ def tracefn (frame , event , arg ):
18+ # only grab the events for our function
19+ if frame .f_code .co_name == 'foo' :
20+ events .append (event )
21+ return tracefn
22+
23+ @inject (a = 5 )
24+ def foo ():
25+ assert locals () == {'a' : 5 }
26+
27+ # be a good citizen and reset our tracefn
28+ old_trace = sys .gettrace ()
29+ sys .settrace (tracefn )
30+ foo ()
31+ assert sys .gettrace () == tracefn
32+ sys .settrace (old_trace )
33+ assert events == ['call' , 'line' , 'return' ]
34+
35+
36+ def test_inject_apply ():
37+
38+ def foo ():
39+ return locals ()
40+
41+ assert inject (a = 5 ).into (foo ) == {'a' : 5 }
42+
43+
You can’t perform that action at this time.
0 commit comments