[pypy-commit] pypy default: add __pypy__.get_hidden_tb so pypy2's app_main can grab the current traceback
pjenvey
noreply at buildbot.pypy.org
Fri Jun 19 02:46:54 CEST 2015
Author: Philip Jenvey <pjenvey at underboss.org>
Branch:
Changeset: r78200:8e8a73a3fdfa
Date: 2015-06-18 17:45 -0700
http://bitbucket.org/pypy/pypy/changeset/8e8a73a3fdfa/
Log: add __pypy__.get_hidden_tb so pypy2's app_main can grab the current
traceback from within a hidden frame (pypy3 can already get to it
via __traceback__)
diff --git a/pypy/interpreter/app_main.py b/pypy/interpreter/app_main.py
--- a/pypy/interpreter/app_main.py
+++ b/pypy/interpreter/app_main.py
@@ -41,8 +41,9 @@
"""
try:
- from __pypy__ import hidden_applevel
+ from __pypy__ import get_hidden_tb, hidden_applevel
except ImportError:
+ get_hidden_tb = lambda: sys.exc_info()[2]
hidden_applevel = lambda f: f
import sys
@@ -98,7 +99,7 @@
return True # success
def display_exception(e):
- etype, evalue, etraceback = type(e), e, e.__traceback__
+ etype, evalue, etraceback = type(e), e, get_hidden_tb()
try:
# extra debugging info in case the code below goes very wrong
if DEBUG and hasattr(sys, 'stderr'):
@@ -697,7 +698,7 @@
except SystemExit as e:
status = e.code
if inspect_requested():
- display_exception()
+ display_exception(e)
else:
status = not success
diff --git a/pypy/interpreter/executioncontext.py b/pypy/interpreter/executioncontext.py
--- a/pypy/interpreter/executioncontext.py
+++ b/pypy/interpreter/executioncontext.py
@@ -1,6 +1,7 @@
import sys
from pypy.interpreter.error import OperationError, get_cleared_operation_error
from rpython.rlib.unroll import unrolling_iterable
+from rpython.rlib.objectmodel import specialize
from rpython.rlib import jit
TICK_COUNTER_STEP = 100
@@ -214,13 +215,21 @@
self._trace(frame, 'exception', None, operationerr)
#operationerr.print_detailed_traceback(self.space)
- def sys_exc_info(self): # attn: the result is not the wrapped sys.exc_info() !!!
+ @specialize.arg(1)
+ def sys_exc_info(self, for_hidden=False):
"""Implements sys.exc_info().
- Return an OperationError instance or None."""
+ Return an OperationError instance or None.
+
+ Ignores exceptions within hidden frames unless for_hidden=True
+ is specified.
+
+ # NOTE: the result is not the wrapped sys.exc_info() !!!
+
+ """
frame = self.gettopframe()
while frame:
if frame.last_exception is not None:
- if (not frame.hide() or
+ if ((for_hidden or not frame.hide()) or
frame.last_exception is
get_cleared_operation_error(self.space)):
return frame.last_exception
diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py
--- a/pypy/module/__pypy__/__init__.py
+++ b/pypy/module/__pypy__/__init__.py
@@ -72,6 +72,7 @@
'debug_flush' : 'interp_debug.debug_flush',
'builtinify' : 'interp_magic.builtinify',
'hidden_applevel' : 'interp_magic.hidden_applevel',
+ 'get_hidden_tb' : 'interp_magic.get_hidden_tb',
'lookup_special' : 'interp_magic.lookup_special',
'do_what_I_mean' : 'interp_magic.do_what_I_mean',
'validate_fd' : 'interp_magic.validate_fd',
diff --git a/pypy/module/__pypy__/interp_magic.py b/pypy/module/__pypy__/interp_magic.py
--- a/pypy/module/__pypy__/interp_magic.py
+++ b/pypy/module/__pypy__/interp_magic.py
@@ -66,6 +66,13 @@
func.getcode().hidden_applevel = True
return w_func
+def get_hidden_tb(space):
+ """Return the traceback of the current exception being handled by a
+ frame hidden from applevel.
+ """
+ operr = space.getexecutioncontext().sys_exc_info(for_hidden=True)
+ return space.w_None if operr is None else space.wrap(operr.get_traceback())
+
@unwrap_spec(meth=str)
def lookup_special(space, w_obj, meth):
"""Lookup up a special method on an object."""
diff --git a/pypy/module/__pypy__/test/test_special.py b/pypy/module/__pypy__/test/test_special.py
--- a/pypy/module/__pypy__/test/test_special.py
+++ b/pypy/module/__pypy__/test/test_special.py
@@ -57,6 +57,22 @@
return 2
assert test_hidden() == 2
+ def test_get_hidden_tb(self):
+ import __pypy__
+ import sys
+
+ @__pypy__.hidden_applevel
+ def test_hidden_with_tb():
+ def not_hidden(): 1/0
+ try: not_hidden()
+ except ZeroDivisionError as e:
+ assert sys.exc_info() == (None, None, None)
+ tb = __pypy__.get_hidden_tb()
+ assert tb.tb_frame.f_code.co_name == 'not_hidden'
+ return True
+ else: return False
+ assert test_hidden_with_tb()
+
def test_lookup_special(self):
from __pypy__ import lookup_special
class X(object):
More information about the pypy-commit
mailing list