File: currentframes.py

package info (click to toggle)
pypy3 7.0.0%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 111,848 kB
  • sloc: python: 1,291,746; ansic: 74,281; asm: 5,187; cpp: 3,017; sh: 2,533; makefile: 544; xml: 243; lisp: 45; csh: 21; awk: 4
file content (77 lines) | stat: -rw-r--r-- 2,274 bytes parent folder | download
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