Skip to content

Commit ece2f96

Browse files
committed
initial inject repository.
0 parents  commit ece2f96

File tree

3 files changed

+106
-0
lines changed

3 files changed

+106
-0
lines changed

README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
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+

inject.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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+

test_inject.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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+

0 commit comments

Comments
 (0)