diff Python/ceval.c @ 58707:76cf60e2d005 legacy-trunk

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.
author Benjamin Peterson <benjamin@python.org>
date Fri, 05 Feb 2010 02:12:14 +0000
parents edfed0e32ced
children dd2230a8c41d
line wrap: on
line diff
--- a/Python/ceval.c	Fri Feb 05 01:53:27 2010 +0000
+++ b/Python/ceval.c	Fri Feb 05 02:12:14 2010 +0000
@@ -2555,9 +2555,11 @@
 			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 @@
 			}
 			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 @@
 					   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,