diff -r 4fc8951488b1 Lib/doctest.py --- a/Lib/doctest.py Sat May 24 11:43:29 2008 +0200 +++ b/Lib/doctest.py Sat May 24 17:00:00 2008 +0200 @@ -1226,11 +1226,11 @@ exec(compile(example.source, filename, "single", compileflags, 1), test.globs) self.debugger.set_continue() # ==== Example Finished ==== - exception = None + exc_info = None except KeyboardInterrupt: raise except: - exception = sys.exc_info() + exc_info = sys.exc_info() self.debugger.set_continue() # ==== Example Finished ==== got = self._fakeout.getvalue() # the actual output @@ -1239,13 +1239,12 @@ # If the example executed without raising any exceptions, # verify its output. - if exception is None: + if exc_info is None: if check(example.want, got, self.optionflags): outcome = SUCCESS # The example raised an exception: check if it was expected. else: - exc_info = sys.exc_info() exc_msg = traceback.format_exception_only(*exc_info[:2])[-1] if not quiet: got += _exception_traceback(exc_info) diff -r 4fc8951488b1 Lib/test/test_exceptions.py --- a/Lib/test/test_exceptions.py Sat May 24 11:43:29 2008 +0200 +++ b/Lib/test/test_exceptions.py Sat May 24 17:00:00 2008 +0200 @@ -427,6 +427,7 @@ local_ref = obj raise MyException(obj) + # Qualified "except" with "as" obj = MyObj() wr = weakref.ref(obj) try: @@ -437,6 +438,57 @@ obj = wr() self.failUnless(obj is None, "%s" % obj) + # Qualified "except" without "as" + obj = MyObj() + wr = weakref.ref(obj) + try: + inner_raising_func() + except MyException: + pass + obj = None + obj = wr() + self.failUnless(obj is None, "%s" % obj) + + # Bare "except" + obj = MyObj() + wr = weakref.ref(obj) + try: + inner_raising_func() + except: + pass + obj = None + obj = wr() + self.failUnless(obj is None, "%s" % obj) + + # "except" with premature block leave + obj = MyObj() + wr = weakref.ref(obj) + for i in [0]: + try: + inner_raising_func() + except: + break + obj = None + obj = wr() + self.failUnless(obj is None, "%s" % obj) + + # Some complicated construct + obj = MyObj() + wr = weakref.ref(obj) + try: + inner_raising_func() + except MyException: + try: + try: + raise + finally: + raise + except MyException: + pass + obj = None + obj = wr() + self.failUnless(obj is None, "%s" % obj) + def test_main(): run_unittest(ExceptionTests) diff -r 4fc8951488b1 Python/compile.c --- a/Python/compile.c Sat May 24 11:43:29 2008 +0200 +++ b/Python/compile.c Sat May 24 17:00:00 2008 +0200 @@ -1983,6 +1983,7 @@ n = asdl_seq_LEN(s->v.TryExcept.handlers); compiler_use_next_block(c, except); for (i = 0; i < n; i++) { + basicblock *cleanup_end, *cleanup_body; excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET( s->v.TryExcept.handlers, i); if (!handler->v.ExceptHandler.type && i < n-1) @@ -2000,60 +2001,56 @@ ADDOP(c, POP_TOP); } ADDOP(c, POP_TOP); + + /* + try: + # body + except type as name: + try: + # body + finally: + name = None + del name + */ + + cleanup_end = compiler_new_block(c); + cleanup_body = compiler_new_block(c); + if(!(cleanup_end || cleanup_body)) + return 0; + + if (handler->v.ExceptHandler.name) + compiler_nameop(c, handler->v.ExceptHandler.name, Store); + else + ADDOP(c, POP_TOP); + ADDOP(c, POP_TOP); + + /* second try: */ + ADDOP_JREL(c, SETUP_FINALLY, cleanup_end); + compiler_use_next_block(c, cleanup_body); + if (!compiler_push_fblock(c, FINALLY_TRY, cleanup_body)) + return 0; + + /* second # body */ + VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body); + ADDOP(c, POP_BLOCK); + compiler_pop_fblock(c, FINALLY_TRY, cleanup_body); + + /* finally: */ + ADDOP_O(c, LOAD_CONST, Py_None, consts); + compiler_use_next_block(c, cleanup_end); + if (!compiler_push_fblock(c, FINALLY_END, cleanup_end)) + return 0; + if (handler->v.ExceptHandler.name) { - basicblock *cleanup_end, *cleanup_body; - - cleanup_end = compiler_new_block(c); - cleanup_body = compiler_new_block(c); - if(!(cleanup_end || cleanup_body)) - return 0; - - compiler_nameop(c, handler->v.ExceptHandler.name, Store); - ADDOP(c, POP_TOP); - - /* - try: - # body - except type as name: - try: - # body - finally: - name = None - del name - */ - - /* second try: */ - ADDOP_JREL(c, SETUP_FINALLY, cleanup_end); - compiler_use_next_block(c, cleanup_body); - if (!compiler_push_fblock(c, FINALLY_TRY, cleanup_body)) - return 0; - - /* second # body */ - VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body); - ADDOP(c, POP_BLOCK); - compiler_pop_fblock(c, FINALLY_TRY, cleanup_body); - - /* finally: */ - ADDOP_O(c, LOAD_CONST, Py_None, consts); - compiler_use_next_block(c, cleanup_end); - if (!compiler_push_fblock(c, FINALLY_END, cleanup_end)) - return 0; - - /* name = None */ - ADDOP_O(c, LOAD_CONST, Py_None, consts); - compiler_nameop(c, handler->v.ExceptHandler.name, Store); - - /* del name */ - compiler_nameop(c, handler->v.ExceptHandler.name, Del); - - ADDOP(c, END_FINALLY); - compiler_pop_fblock(c, FINALLY_END, cleanup_end); - } - else { - ADDOP(c, POP_TOP); - ADDOP(c, POP_TOP); - VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body); - } + /* name = None */ + ADDOP_O(c, LOAD_CONST, Py_None, consts); + compiler_nameop(c, handler->v.ExceptHandler.name, Store); + /* del name */ + compiler_nameop(c, handler->v.ExceptHandler.name, Del); + } + + ADDOP(c, END_FINALLY); + compiler_pop_fblock(c, FINALLY_END, cleanup_end); ADDOP_JREL(c, JUMP_FORWARD, end); compiler_use_next_block(c, except); if (handler->v.ExceptHandler.type) diff -r 4fc8951488b1 Python/import.c --- a/Python/import.c Sat May 24 11:43:29 2008 +0200 +++ b/Python/import.c Sat May 24 17:00:00 2008 +0200 @@ -86,8 +86,9 @@ 3100 (merge from 2.6a0, see 62151) 3102 (__file__ points to source file) Python 3.0a4: 3110 (WITH_CLEANUP optimization). + Python 3.0a5: 3120 (correct exception cleanup) */ -#define MAGIC (3110 | ((long)'\r'<<16) | ((long)'\n'<<24)) +#define MAGIC (3120 | ((long)'\r'<<16) | ((long)'\n'<<24)) /* Magic word as global; note that _PyImport_Init() can change the value of this global to accommodate for alterations of how the