summaryrefslogtreecommitdiff
path: root/Python
diff options
context:
space:
mode:
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 d501a4e10a..0b8a377ee4 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 1e275390c9..4ea2ee9afe 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;
}