[pypy-commit] pypy default: Issue863 Implement sys._current_frames()
amauryfa
noreply at buildbot.pypy.org
Tue Sep 6 01:30:33 CEST 2011
Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch:
Changeset: r47094:411a4e22b5bc
Date: 2011-09-06 01:29 +0200
http://bitbucket.org/pypy/pypy/changeset/411a4e22b5bc/
Log: Issue863 Implement sys._current_frames() "for debugging purposes"
diff --git a/pypy/interpreter/miscutils.py b/pypy/interpreter/miscutils.py
--- a/pypy/interpreter/miscutils.py
+++ b/pypy/interpreter/miscutils.py
@@ -167,3 +167,7 @@
def getmainthreadvalue(self):
return self._value
+
+ def getallvalues(self):
+ return {0: self._value}
+
diff --git a/pypy/module/sys/__init__.py b/pypy/module/sys/__init__.py
--- a/pypy/module/sys/__init__.py
+++ b/pypy/module/sys/__init__.py
@@ -47,6 +47,7 @@
'pypy_initial_path' : 'state.pypy_initial_path',
'_getframe' : 'vm._getframe',
+ '_current_frames' : 'vm._current_frames',
'setrecursionlimit' : 'vm.setrecursionlimit',
'getrecursionlimit' : 'vm.getrecursionlimit',
'setcheckinterval' : 'vm.setcheckinterval',
diff --git a/pypy/module/sys/test/test_sysmodule.py b/pypy/module/sys/test/test_sysmodule.py
--- a/pypy/module/sys/test/test_sysmodule.py
+++ b/pypy/module/sys/test/test_sysmodule.py
@@ -1,6 +1,6 @@
# -*- coding: iso-8859-1 -*-
import autopath
-from pypy.conftest import option
+from pypy.conftest import option, gettestobjspace
from py.test import raises
from pypy.interpreter.gateway import app2interp_temp
import sys
@@ -524,3 +524,51 @@
# If this ever actually becomes a compilation option this test should
# be changed.
assert sys.float_repr_style == "short"
+
+class AppTestCurrentFrames:
+
+ def test_current_frames(self):
+ try:
+ import thread
+ except ImportError:
+ pass
+ else:
+ skip('This test requires an intepreter without threads')
+ import sys
+
+ def f():
+ return sys._current_frames()
+ frames = f()
+ assert frames.keys() == [0]
+ assert frames[0].f_code.co_name == 'f'
+
+class AppTestCurrentFramesWithThread(AppTestCurrentFrames):
+ def setup_class(cls):
+ cls.space = gettestobjspace(usemodules=('thread',))
+
+ def test_current_frames(self):
+ import sys
+ import time
+ import thread
+
+ thread_id = thread.get_ident()
+ self.ready = False
+ def other_thread():
+ self.ready = True
+ print "thread started"
+ time.sleep(5)
+ thread.start_new_thread(other_thread, ())
+
+ def f():
+ for i in range(100):
+ if self.ready: break
+ time.sleep(0.1)
+ return sys._current_frames()
+
+ frames = f()
+ thisframe = frames.pop(thread_id)
+ assert thisframe.f_code.co_name == 'f'
+
+ assert len(frames) == 1
+ _, other_frame = frames.popitem()
+ assert other_frame.f_code.co_name == 'other_thread'
diff --git a/pypy/module/sys/vm.py b/pypy/module/sys/vm.py
--- a/pypy/module/sys/vm.py
+++ b/pypy/module/sys/vm.py
@@ -43,6 +43,23 @@
f.mark_as_escaped()
return space.wrap(f)
+def _current_frames(space):
+ """_current_frames() -> dictionary
+
+ Return a dictionary mapping each current thread T's thread id to T's
+ current stack frame.
+
+ This function should be used for specialized purposes only."""
+ w_result = space.newdict()
+ ecs = space.threadlocals.getallvalues()
+ for thread_ident, ec in ecs.items():
+ f = ec.gettopframe_nohidden()
+ f.mark_as_escaped()
+ space.setitem(w_result,
+ space.wrap(thread_ident),
+ space.wrap(f))
+ return w_result
+
def setrecursionlimit(space, w_new_limit):
"""setrecursionlimit() sets the maximum number of nested calls that
can occur before a RuntimeError is raised. On PyPy the limit is
diff --git a/pypy/module/thread/threadlocals.py b/pypy/module/thread/threadlocals.py
--- a/pypy/module/thread/threadlocals.py
+++ b/pypy/module/thread/threadlocals.py
@@ -43,6 +43,9 @@
ident = self._mainthreadident
return self._valuedict.get(ident, None)
+ def getallvalues(self):
+ return self._valuedict
+
def enter_thread(self, space):
"Notification that the current thread is just starting."
ec = space.getexecutioncontext()
More information about the pypy-commit
mailing list