1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
|
"""
Implementation of the 'sys._current_frames()' routine.
"""
from pypy.interpreter import gateway
app = gateway.applevel('''
"NOT_RPYTHON"
import builtins
class fake_code(object):
co_name = "?"
co_filename = "?"
co_firstlineno = 0
class fake_frame(object):
f_back = None
f_builtins = builtins.__dict__
f_code = fake_code()
f_exc_traceback = None
f_exc_type = None
f_exc_value = None
f_globals = {}
f_lasti = -1
f_lineno = 0
f_locals = {}
f_restricted = False
f_trace = None
def __init__(self, f):
if f is not None:
for name in ["f_builtins", "f_code", "f_globals", "f_lasti",
"f_lineno"]:
setattr(self, name, getattr(f, name))
''')
def _current_frames(space):
"""_current_frames() -> dictionary
Return a dictionary mapping each current thread T's thread id to T's
current stack "frame". Functions in the traceback module can build the
call stack given such a frame.
Note that in PyPy this returns fake frame objects, to avoid a runtime
penalty everywhere with the JIT. (So far these fake frames can be
completely uninformative depending on the JIT state; we could return
more with more efforts.)
This function should be used for specialized purposes only."""
w_result = space.newdict()
w_fake_frame = app.wget(space, "fake_frame")
ecs = space.threadlocals.getallvalues()
for thread_ident, ec in ecs.items():
vref = ec.topframeref
frames = []
while not vref.virtual:
f = vref()
if f is None:
break
frames.append(f)
vref = f.f_backref
else:
frames.append(None)
w_topframe = space.w_None
w_prevframe = None
for f in frames:
w_nextframe = space.call_function(w_fake_frame, space.wrap_none(f))
if w_prevframe is None:
w_topframe = w_nextframe
else:
space.setattr(w_prevframe, space.newtext('f_back'), w_nextframe)
w_prevframe = w_nextframe
space.setitem(w_result,
space.newint(thread_ident),
w_topframe)
return w_result
|