[pypy-commit] pypy py3.6-exc-info: revert some parts, fix the rest
arigo
pypy.commits at gmail.com
Thu Nov 7 07:32:01 EST 2019
Author: Armin Rigo <arigo at tunes.org>
Branch: py3.6-exc-info
Changeset: r97974:2857fcf6b913
Date: 2019-11-07 13:30 +0100
http://bitbucket.org/pypy/pypy/changeset/2857fcf6b913/
Log: revert some parts, fix the rest
diff --git a/pypy/interpreter/executioncontext.py b/pypy/interpreter/executioncontext.py
--- a/pypy/interpreter/executioncontext.py
+++ b/pypy/interpreter/executioncontext.py
@@ -32,9 +32,9 @@
self.topframeref = jit.vref_None
# this is exposed to app-level as 'sys.exc_info()'. At any point in
# time it is the exception caught by the topmost 'except ... as e:'
- # app-level block. (This is the *last* item in the list; previous
- # items form a stack of older operrors.)
- self.sys_exc_operrors = [None]
+ # app-level block.
+ self.sys_exc_operror = None
+ self.previous_operror_stack = []
self.w_tracefunc = None
self.is_tracing = 0
self.compiler = space.createcompiler()
@@ -243,17 +243,23 @@
def sys_exc_info(self):
"""Implements sys.exc_info().
Return an OperationError instance or None.
+ Returns the "top-most" exception in the stack.
# NOTE: the result is not the wrapped sys.exc_info() !!!
"""
- i = len(self.sys_exc_operror) - 1
- while i > 0 and self.sys_exc_operrors[i] is None:
- i -= 1
- return self.sys_exc_operrors[i]
+ result = self.sys_exc_operror
+ if result is None:
+ i = len(self.previous_operror_stack) - 1
+ while i >= 0:
+ result = self.previous_operror_stack[i]
+ if result is not None:
+ break
+ i -= 1
+ return result
def set_sys_exc_info(self, operror):
- self.sys_exc_operrors[-1] = operror
+ self.sys_exc_operror = operror
def set_sys_exc_info3(self, w_type, w_value, w_traceback):
space = self.space
@@ -269,6 +275,21 @@
operror = OperationError(w_type, w_value, tb)
self.set_sys_exc_info(operror)
+ def enter_error_stack_item(self, saved_operr):
+ self.previous_operror_stack.append(saved_operr)
+
+ def leave_error_stack_item(self):
+ return self.previous_operror_stack.pop()
+
+ def fetch_and_clear_error_stack_state(self):
+ result = self.sys_exc_operror, self.previous_operror_stack
+ self.sys_exc_operror = None
+ self.previous_operror_stack = []
+ return result
+
+ def restore_error_stack_state(self, saved):
+ self.sys_exc_operror, self.previous_operror_stack = saved
+
@jit.dont_look_inside
def settrace(self, w_func):
"""Set the global trace function."""
diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py
--- a/pypy/interpreter/generator.py
+++ b/pypy/interpreter/generator.py
@@ -105,11 +105,6 @@
frame = self.frame
if self.running:
raise oefmt(space.w_ValueError, "%s already executing", self.KIND)
- ec = space.getexecutioncontext()
- current_exc_info = ec.sys_exc_info()
- if self.saved_operr is not None:
- ec.set_sys_exc_info(self.saved_operr)
- self.saved_operr = None
#
# Optimization only: after we've started a Coroutine without
# CO_YIELD_INSIDE_TRY, then Coroutine._finalize_() will be a no-op
@@ -123,6 +118,8 @@
raise oefmt(space.w_TypeError,
"can't send non-None value to a just-started %s",
self.KIND)
+ ec = space.getexecutioncontext()
+ ec.enter_error_stack_item(self.saved_operr)
self.running = True
try:
w_result = frame.execute_frame(w_arg_or_err)
@@ -142,10 +139,8 @@
self.running = False
# note: this is not perfectly correct: see
# test_exc_info_in_generator_4. But it's simpler and
- # bug-to-bug compatible with CPython 3.5.
- if frame._any_except_or_finally_handler():
- self.saved_operr = ec.sys_exc_info()
- ec.set_sys_exc_info(current_exc_info)
+ # bug-to-bug compatible with CPython 3.5 and 3.6.
+ self.saved_operr = ec.leave_error_stack_item()
return w_result
def get_delegate(self):
diff --git a/pypy/module/__pypy__/test/test_magic.py b/pypy/module/__pypy__/test/test_magic.py
--- a/pypy/module/__pypy__/test/test_magic.py
+++ b/pypy/module/__pypy__/test/test_magic.py
@@ -60,8 +60,7 @@
try:
raise ValueError
except ValueError as e:
- pass
- assert e.__context__ is terr
+ assert e.__context__ is terr
def test_set_exc_info_issue3096(self):
from __pypy__ import set_exc_info
diff --git a/pypy/module/_continuation/interp_continuation.py b/pypy/module/_continuation/interp_continuation.py
--- a/pypy/module/_continuation/interp_continuation.py
+++ b/pypy/module/_continuation/interp_continuation.py
@@ -46,9 +46,9 @@
#
global_state.origin = self
self.sthread = sthread
- saved_exception = pre_switch(sthread)
+ saved_error_state = pre_switch(sthread)
h = sthread.new(new_stacklet_callback)
- post_switch(sthread, h, saved_exception)
+ post_switch(sthread, h, saved_error_state)
def switch(self, w_to):
sthread = self.sthread
@@ -84,9 +84,9 @@
# double switch: the final destination is to.h
global_state.destination = to
#
- saved_exception = pre_switch(sthread)
+ saved_error_state = pre_switch(sthread)
h = sthread.switch(global_state.destination.h)
- return post_switch(sthread, h, saved_exception)
+ return post_switch(sthread, h, saved_error_state)
@unwrap_spec(w_value = WrappedDefault(None),
w_to = WrappedDefault(None))
@@ -257,11 +257,9 @@
return self.h
def pre_switch(sthread):
- saved_exception = sthread.ec.sys_exc_info()
- sthread.ec.set_sys_exc_info(None)
- return saved_exception
+ return sthread.ec.fetch_and_clear_error_stack_state()
-def post_switch(sthread, h, saved_exception):
+def post_switch(sthread, h, saved_error_state):
origin = global_state.origin
self = global_state.destination
global_state.origin = None
@@ -270,7 +268,7 @@
#
current = sthread.ec.topframeref
sthread.ec.topframeref = self.bottomframe.f_backref
- sthread.ec.set_sys_exc_info(saved_exception)
+ sthread.ec.restore_error_stack_state(saved_error_state)
self.bottomframe.f_backref = origin.bottomframe.f_backref
origin.bottomframe.f_backref = current
#
diff --git a/pypy/module/sys/moduledef.py b/pypy/module/sys/moduledef.py
--- a/pypy/module/sys/moduledef.py
+++ b/pypy/module/sys/moduledef.py
@@ -209,31 +209,6 @@
w_modules = self.get('modules')
self.space.setitem(w_modules, w_name, w_module)
- def getdictvalue(self, space, attr):
- """ specialize access to dynamic exc_* attributes. """
- value = MixedModule.getdictvalue(self, space, attr)
- if value is not None:
- return value
- if attr == 'exc_type':
- operror = space.getexecutioncontext().sys_exc_info()
- if operror is None:
- return space.w_None
- else:
- return operror.w_type
- elif attr == 'exc_value':
- operror = space.getexecutioncontext().sys_exc_info()
- if operror is None:
- return space.w_None
- else:
- return operror.get_w_value(space)
- elif attr == 'exc_traceback':
- operror = space.getexecutioncontext().sys_exc_info()
- if operror is None:
- return space.w_None
- else:
- return operror.get_w_traceback(space)
- return None
-
def get_flag(self, name):
space = self.space
return space.int_w(space.getattr(self.get('flags'), space.newtext(name)))
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
@@ -187,13 +187,6 @@
else:
return exc_info_without_tb(space, operror)
-def exc_clear(space):
- """Clear global information on the current exception. Subsequent calls
-to exc_info() will return (None,None,None) until another exception is
-raised and caught in the current thread or the execution stack returns to a
-frame where another exception is being handled."""
- space.getexecutioncontext().clear_sys_exc_info()
-
def settrace(space, w_func):
"""Set the global debug tracing function. It will be called on each
function call. See the debugger chapter in the library manual."""
More information about the pypy-commit
mailing list