Commit 20aa477a authored by Georg Brandl's avatar Georg Brandl

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)
parent b17830e7
...@@ -851,6 +851,8 @@ class CodeGenerator: ...@@ -851,6 +851,8 @@ class CodeGenerator:
self.emit('LOAD_CONST', None) self.emit('LOAD_CONST', None)
self.nextBlock(final) self.nextBlock(final)
self.setups.push((END_FINALLY, final)) self.setups.push((END_FINALLY, final))
self._implicitNameOp('LOAD', exitvar)
self._implicitNameOp('DELETE', exitvar)
self.emit('WITH_CLEANUP') self.emit('WITH_CLEANUP')
self.emit('END_FINALLY') self.emit('END_FINALLY')
self.setups.pop() self.setups.pop()
......
...@@ -960,7 +960,7 @@ class Transformer: ...@@ -960,7 +960,7 @@ class Transformer:
if nodelist[2][0] == token.COLON: if nodelist[2][0] == token.COLON:
var = None var = None
else: 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]) return With(expr, var, body, lineno=nodelist[0][2])
def com_with_var(self, nodelist): def com_with_var(self, nodelist):
......
...@@ -7,6 +7,12 @@ from random import random ...@@ -7,6 +7,12 @@ from random import random
# How much time in seconds can pass before we print a 'Still working' message. # How much time in seconds can pass before we print a 'Still working' message.
_PRINT_WORKING_MSG_INTERVAL = 5 * 60 _PRINT_WORKING_MSG_INTERVAL = 5 * 60
class TrivialContext(object):
def __enter__(self):
return self
def __exit__(self, *exc_info):
pass
class CompilerTest(unittest.TestCase): class CompilerTest(unittest.TestCase):
def testCompileLibrary(self): def testCompileLibrary(self):
...@@ -123,6 +129,31 @@ class CompilerTest(unittest.TestCase): ...@@ -123,6 +129,31 @@ class CompilerTest(unittest.TestCase):
'eval') 'eval')
self.assertEquals(eval(c), [(0, 3), (1, 3), (2, 3)]) 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()',
'<string>',
'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()',
'<string>',
'exec' )
dct = {'TrivialContext': TrivialContext}
exec c in dct
self.assertEquals(dct.get('result'), 1)
NOLINENO = (compiler.ast.Module, compiler.ast.Stmt, compiler.ast.Discard) NOLINENO = (compiler.ast.Module, compiler.ast.Stmt, compiler.ast.Discard)
......
...@@ -154,6 +154,10 @@ Extension Modules ...@@ -154,6 +154,10 @@ Extension Modules
Library 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. - Bug #1643943: Fix %U handling for time.strptime.
- Patch #1643874: memory leak in ctypes fixed. - Patch #1643874: memory leak in ctypes fixed.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment