diff options
Diffstat (limited to 'Python')
-rw-r--r-- | Python/ceval.c | 14 | ||||
-rw-r--r-- | Python/compile.c | 3 |
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; } |