[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