[pypy-dev] [issue15] exec statement doesn't work
Rocco Moretti
pypy-issues at codespeak.net
Sat Apr 12 23:46:59 MEST 2003
New submission from Rocco Moretti <roccomoretti at netscape.net>:
Using the exec statement in application space code fails, as
there is a function missing from opcode_app.py. The
assocated subversion diff should fix the problem.
----------
files: exec_diff.txt
messages: 31
nosy: rocco
priority: bug
status: testing
title: exec statement doesn't work
__________________________________________________
PyPython issue tracker <pypy-issues at codespeak.net>
http://codespeak.net/issues/pypy/issue15
__________________________________________________
-------------- next part --------------
Index: interpreter/opcode_app.py
===================================================================
--- interpreter/opcode_app.py (revision 364)
+++ interpreter/opcode_app.py (working copy)
@@ -57,7 +57,7 @@
stream.write(str(x))
# add a softspace unless we just printed a string which ends in a '\t'
# or '\n' -- or more generally any whitespace character but ' '
- if isinstance(x, str) and x[-1].isspace() and x[-1]!=' ':
+ if isinstance(x, str) and len(x) and x[-1].isspace() and x[-1]!=' ':
return
# XXX add unicode handling
file_softspace(stream, True)
@@ -144,3 +144,45 @@
"for keyword argument '%s'" % key)
result[key] = value
return result
+
+def exec_statement(prog, globals, locals,
+ builtins, caller_globals, caller_locals):
+ """Manipulate parameters to exec statement to (codeobject, dict, dict).
+ """
+ import types
+ if (globals is None and locals is None and
+ isinstance(prog, builtins.tuple) and
+ (len(prog) == 2 or len(prog) == 3)):
+ globals = prog[1]
+ if len(prog) == 3:
+ locals = prog[2]
+ prog = prog[0]
+ if globals is None:
+ globals = caller_globals
+ if locals is None:
+ locals = caller_locals
+ if locals is None:
+ locals = globals
+ if not isinstance(globals, types.DictType):
+ raise TypeError("exec: arg 2 must be a dictionary or None")
+ elif not globals.has_key('__builtins__'):
+ globals['__builtins__'] = builtins
+ if not isinstance(locals, types.DictType):
+ raise TypeError("exec: arg 3 must be a dictionary or None")
+ #HACK to check for code object
+ co = compile('1','<string>','eval')
+ if isinstance(prog, type(co)):
+ return (prog, globals, locals)
+ if not (isinstance(prog, types.StringTypes) or
+ isinstance(prog, types.FileType)):
+ raise TypeError("exec: arg 1 must be a string, file, or code object")
+ if isinstance(prog, types.FileType):
+ flags = 0
+ ## XXX add in parent flag merging
+ co = compile(prog.read(),prog.name,'exec',flags,1)
+ return (co,globals,locals)
+ else: # prog is a string
+ flags = 0
+ ## XXX add in parent flag merging
+ co = compile(prog,'<string>','exec',flags,1)
+ return (co,globals,locals)
Index: interpreter/opcode.py
===================================================================
--- interpreter/opcode.py (revision 364)
+++ interpreter/opcode.py (working copy)
@@ -283,10 +283,16 @@
w_locals = f.valuestack.pop()
w_globals = f.valuestack.pop()
w_prog = f.valuestack.pop()
- f.space.gethelper(appfile).call("exec_statement",
+ w_tuple = f.space.gethelper(appfile).call("exec_statement",
[w_prog, w_globals, w_locals,
f.w_builtins, f.w_globals, f.w_locals])
-
+ w_prog = f.space.getitem(w_tuple,f.space.wrap(0))
+ w_globals = f.space.getitem(w_tuple,f.space.wrap(1))
+ w_locals = f.space.getitem(w_tuple,f.space.wrap(2))
+ newframe = pyframe.PyFrame(f.space,f.space.unwrap(w_prog),w_globals,w_locals)
+ ec = f.space.getexecutioncontext()
+ ec.eval_frame(newframe) #discard return value
+
def POP_BLOCK(f):
block = f.blockstack.pop()
block.cleanup(f) # the block knows how to clean up the value stack
Index: appspace/test/test_exec.py
===================================================================
--- appspace/test/test_exec.py (working copy)
+++ appspace/test/test_exec.py (working copy)
@@ -0,0 +1,67 @@
+"""Test the exec statement functionality.
+
+New for PyPy - Could be incorporated into CPython regression tests.
+"""
+
+import unittest
+
+class TestExecStmt(unittest.TestCase):
+
+ def test_string(self):
+ g = {}
+ l = {}
+ exec "a = 3" in g, l
+ self.failUnlessEqual(l['a'], 3)
+
+ def test_localfill(self):
+ g = {}
+ exec "a = 3" in g
+ self.failUnlessEqual(g['a'], 3)
+
+ def test_builtinsupply(self):
+ g = {}
+ exec "pass" in g
+ self.failUnless(g.has_key('__builtins__'))
+
+ def test_invalidglobal(self):
+ self.failUnlessRaises(TypeError,"exec 'pass' in 1")
+
+ def test_invalidlocal(self):
+ self.failUnlessRaises(TypeError,"exec 'pass' in {}, 2")
+
+ def test_codeobject(self):
+ co = compile("a = 3", '<string>', 'exec')
+ g = {}
+ l = {}
+ exec co in g, l
+ self.failUnlessEqual(l['a'], 3)
+
+## # Commented out as PyPy give errors using open()
+## # ["Not availible in restricted mode"]
+## def test_file(self):
+## fo = open("test_exec.py", 'r')
+## g = {}
+## exec fo in g
+## self.failUnless(g.has_key('TestExecStmt'))
+
+ def test_implicit(self):
+ a = 4
+ exec "a = 3"
+ self.failUnlessEqual(a,3)
+
+ def test_tuplelocals(self):
+ g = {}
+ l = {}
+ exec ("a = 3", g, l)
+ self.failUnlessEqual(l['a'], 3)
+
+ def test_tupleglobals(self):
+ g = {}
+ exec ("a = 3", g)
+ self.failUnlessEqual(g['a'], 3)
+
+ def test_exceptionfallthrough(self):
+ self.failUnlessRaises(TypeError,"exec 'raise TypeError' in {}")
+
+if __name__ == "__main__":
+ unittest.main()
More information about the pypy-dev
mailing list