summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorBenjamin Peterson <benjamin@python.org>2010-02-05 02:12:14 (GMT)
committerBenjamin Peterson <benjamin@python.org>2010-02-05 02:12:14 (GMT)
commit565d78586babda2b62cbe4f89c2dd3cace79c0fa (patch)
treeaded6af69242e82a89f34df49512202d5c2ae08a /Python
parent4a7ff1d80abf841287043c5965d1c1c74a1c694a (diff)
downloadcpython-565d78586babda2b62cbe4f89c2dd3cace79c0fa.zip
cpython-565d78586babda2b62cbe4f89c2dd3cace79c0fa.tar.gz
cpython-565d78586babda2b62cbe4f89c2dd3cace79c0fa.tar.bz2
normalize exceptions passed to the __exit__ method #7853
In Python 2.x, exceptions in finally blocks are not normalized. Since with statements are implemented using finally blocks, ceval.c had to be tweaked to distinguish between with finally blocks and normal ones. A test for the finalization of generators containing with statements was also added.
Diffstat (limited to 'Python')
-rw-r--r--Python/ceval.c14
-rw-r--r--Python/compile.c3
2 files changed, 12 insertions, 5 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index d501a4e..0b8a377 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -2555,9 +2555,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
Py_DECREF(u);
if (!x)
break;
- /* Setup the finally block before pushing the result
- of __enter__ on the stack. */
- PyFrame_BlockSetup(f, SETUP_FINALLY, INSTR_OFFSET() + oparg,
+ /* Setup a finally block (SETUP_WITH as a block is
+ equivalent to SETUP_FINALLY except it normalizes
+ the exception) before pushing the result of
+ __enter__ on the stack. */
+ PyFrame_BlockSetup(f, SETUP_WITH, INSTR_OFFSET() + oparg,
STACK_LEVEL());
PUSH(x);
@@ -2898,7 +2900,8 @@ fast_block_end:
}
if (b->b_type == SETUP_FINALLY ||
(b->b_type == SETUP_EXCEPT &&
- why == WHY_EXCEPTION)) {
+ why == WHY_EXCEPTION) ||
+ b->b_type == SETUP_WITH) {
if (why == WHY_EXCEPTION) {
PyObject *exc, *val, *tb;
PyErr_Fetch(&exc, &val, &tb);
@@ -2911,7 +2914,8 @@ fast_block_end:
so a program can emulate the
Python main loop. Don't do
this for 'finally'. */
- if (b->b_type == SETUP_EXCEPT) {
+ if (b->b_type == SETUP_EXCEPT ||
+ b->b_type == SETUP_WITH) {
PyErr_NormalizeException(
&exc, &val, &tb);
set_exc_info(tstate,
diff --git a/Python/compile.c b/Python/compile.c
index 1e27539..4ea2ee9 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -2927,6 +2927,9 @@ compiler_with(struct compiler *c, stmt_ty s)
/* SETUP_WITH pushes a finally block. */
compiler_use_next_block(c, block);
+ /* Note that the block is actually called SETUP_WITH in ceval.c, but
+ functions the same as SETUP_FINALLY except that exceptions are
+ normalized. */
if (!compiler_push_fblock(c, FINALLY_TRY, block)) {
return 0;
}