From 20aa477a2d07ed85b81c4ecda74b51444f9c6b38 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sat, 27 Jan 2007 17:43:07 +0000 Subject: [PATCH] Patch #1638243: the compiler package is now able to correctly compile a with statement; previously, executing code containing a with statement compiled by the compiler package crashed the interpreter. (backport from rev. 53575) --- Lib/compiler/pycodegen.py | 2 ++ Lib/compiler/transformer.py | 2 +- Lib/test/test_compiler.py | 31 +++++++++++++++++++++++++++++++ Misc/NEWS | 4 ++++ 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/Lib/compiler/pycodegen.py b/Lib/compiler/pycodegen.py index 009438da6d8..2af03a89e22 100644 --- a/Lib/compiler/pycodegen.py +++ b/Lib/compiler/pycodegen.py @@ -851,6 +851,8 @@ class CodeGenerator: self.emit('LOAD_CONST', None) self.nextBlock(final) self.setups.push((END_FINALLY, final)) + self._implicitNameOp('LOAD', exitvar) + self._implicitNameOp('DELETE', exitvar) self.emit('WITH_CLEANUP') self.emit('END_FINALLY') self.setups.pop() diff --git a/Lib/compiler/transformer.py b/Lib/compiler/transformer.py index a16dc553c46..ac23ad18a99 100644 --- a/Lib/compiler/transformer.py +++ b/Lib/compiler/transformer.py @@ -960,7 +960,7 @@ class Transformer: if nodelist[2][0] == token.COLON: var = None else: - var = self.com_node(nodelist[2]) + var = self.com_assign(nodelist[2][2], OP_ASSIGN) return With(expr, var, body, lineno=nodelist[0][2]) def com_with_var(self, nodelist): diff --git a/Lib/test/test_compiler.py b/Lib/test/test_compiler.py index 81f2ea89250..229d8a370fd 100644 --- a/Lib/test/test_compiler.py +++ b/Lib/test/test_compiler.py @@ -7,6 +7,12 @@ from random import random # How much time in seconds can pass before we print a 'Still working' message. _PRINT_WORKING_MSG_INTERVAL = 5 * 60 +class TrivialContext(object): + def __enter__(self): + return self + def __exit__(self, *exc_info): + pass + class CompilerTest(unittest.TestCase): def testCompileLibrary(self): @@ -123,6 +129,31 @@ class CompilerTest(unittest.TestCase): 'eval') self.assertEquals(eval(c), [(0, 3), (1, 3), (2, 3)]) + def testWith(self): + # SF bug 1638243 + c = compiler.compile('from __future__ import with_statement\n' + 'def f():\n' + ' with TrivialContext():\n' + ' return 1\n' + 'result = f()', + '', + 'exec' ) + dct = {'TrivialContext': TrivialContext} + exec c in dct + self.assertEquals(dct.get('result'), 1) + + def testWithAss(self): + c = compiler.compile('from __future__ import with_statement\n' + 'def f():\n' + ' with TrivialContext() as tc:\n' + ' return 1\n' + 'result = f()', + '', + 'exec' ) + dct = {'TrivialContext': TrivialContext} + exec c in dct + self.assertEquals(dct.get('result'), 1) + NOLINENO = (compiler.ast.Module, compiler.ast.Stmt, compiler.ast.Discard) diff --git a/Misc/NEWS b/Misc/NEWS index d776f49f4eb..6036a2daadc 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -154,6 +154,10 @@ Extension Modules Library ------- +- Patch #1638243: the compiler package is now able to correctly compile + a with statement; previously, executing code containing a with statement + compiled by the compiler package crashed the interpreter. + - Bug #1643943: Fix %U handling for time.strptime. - Patch #1643874: memory leak in ctypes fixed.