Author: Amaury Forgeot d'Arc <amaur...@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() _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit