extern DL_IMPORT(PyTypeObject) PyCode_Type;
#define PyCode_Check(op) ((op)->ob_type == &PyCode_Type)
+#define PyCode_GetNumFree(op) (PyTuple_GET_SIZE((op)->co_freevars))
#define CO_MAXBLOCKS 20 /* Max static block nesting within a function */
18. verify that locals() works
19. var is bound and free in class
20. interaction with trace function
+20. eval and exec with free variables
+21. list comprehension with local variables
+22. eval with free variables
from __future__ import nested_scopes
-from test.test_support import verify, TestFailed, check_syntax
+from test_support import verify, TestFailed, check_syntax
+
+import warnings
+warnings.filterwarnings("ignore", r"(import \*|local name|unqualified)",
+ SyntaxWarning, "<string>")
print "1. simple nesting"
print "11. unoptimized namespaces"
-check_syntax("""from __future__ import nested_scopes
+check_syntax("""\
+from __future__ import nested_scopes
def unoptimized_clash1(strip):
def f(s):
from string import *
return f
""")
-check_syntax("""from __future__ import nested_scopes
+check_syntax("""\
+from __future__ import nested_scopes
def unoptimized_clash2():
from string import *
def f(s):
return f
""")
-check_syntax("""from __future__ import nested_scopes
+check_syntax("""\
+from __future__ import nested_scopes
def unoptimized_clash2():
from string import *
def g():
""")
# XXX could allow this for exec with const argument, but what's the point
-check_syntax("""from __future__ import nested_scopes
+check_syntax("""\
+from __future__ import nested_scopes
def error(y):
exec "a = 1"
def f(x):
return f
""")
-check_syntax("""from __future__ import nested_scopes
+check_syntax("""\
+from __future__ import nested_scopes
def f(x):
def g():
return x
del x # can't del name
""")
-check_syntax("""from __future__ import nested_scopes
+check_syntax("""\
+from __future__ import nested_scopes
def f():
def g():
from string import *
# and verify a few cases that should work
+exec """
def noproblem1():
from string import *
f = lambda x:x
def f(x):
global y
y = x
+"""
print "12. lambdas"
sys.settrace(tracer)
adaptgetter("foo", TestClass, (1, ""))
sys.settrace(None)
+
+##try: sys.settrace()
+##except TypeError: pass
+##else: raise TestFailed, 'sys.settrace() did not raise TypeError'
+
+print "20. eval and exec with free variables"
+
+def f(x):
+ return lambda: x + 1
+
+g = f(3)
+try:
+ eval(g.func_code)
+except TypeError:
+ pass
+else:
+ print "eval() should have failed, because code contained free vars"
+
+try:
+ exec g.func_code
+except TypeError:
+ pass
+else:
+ print "exec should have failed, because code contained free vars"
+
+print "21. list comprehension with local variables"
+
+try:
+ print bad
+except NameError:
+ pass
+else:
+ print "bad should not be defined"
+
+def x():
+ [bad for s in 'a b' for bad in s.split()]
+
+x()
+try:
+ print bad
+except NameError:
+ pass
+
+print "22. eval with free variables"
+
+def f(free):
+ def g():
+ free
+ eval("free + 1")
+ return g
+
+f(4)()
return;
}
}
- if (f->f_nlocals == 0)
- return;
map = f->f_code->co_varnames;
if (!PyDict_Check(locals) || !PyTuple_Check(map))
return;
j = PyTuple_Size(map);
if (j > f->f_nlocals)
j = f->f_nlocals;
- map_to_dict(map, j, locals, fast, 0);
+ if (f->f_nlocals)
+ map_to_dict(map, j, locals, fast, 0);
if (f->f_ncells || f->f_nfreevars) {
if (!(PyTuple_Check(f->f_code->co_cellvars)
&& PyTuple_Check(f->f_code->co_freevars))) {
return;
locals = f->f_locals;
map = f->f_code->co_varnames;
- if (locals == NULL || f->f_code->co_nlocals == 0)
+ if (locals == NULL)
return;
if (!PyDict_Check(locals) || !PyTuple_Check(map))
return;
j = PyTuple_Size(map);
if (j > f->f_nlocals)
j = f->f_nlocals;
- dict_to_map(f->f_code->co_varnames, j, locals, fast, 0, clear);
+ if (f->f_nlocals)
+ dict_to_map(f->f_code->co_varnames, j, locals, fast, 0, clear);
if (f->f_ncells || f->f_nfreevars) {
if (!(PyTuple_Check(f->f_code->co_cellvars)
&& PyTuple_Check(f->f_code->co_freevars)))
PyEval_GetBuiltins()) != 0)
return NULL;
}
- if (PyCode_Check(cmd))
+ if (PyCode_Check(cmd)) {
+ if (PyCode_GetNumFree((PyCodeObject *)cmd) > 0) {
+ PyErr_SetString(PyExc_TypeError,
+ "code object passed to eval() may not contain free variables");
+ return NULL;
+ }
return PyEval_EvalCode((PyCodeObject *) cmd, globals, locals);
+ }
if (!PyString_Check(cmd) &&
!PyUnicode_Check(cmd)) {
PyErr_SetString(PyExc_TypeError,
if (PyDict_GetItemString(globals, "__builtins__") == NULL)
PyDict_SetItemString(globals, "__builtins__", f->f_builtins);
if (PyCode_Check(prog)) {
+ if (PyCode_GetNumFree((PyCodeObject *)prog) > 0) {
+ PyErr_SetString(PyExc_TypeError,
+ "code object passed to exec may not contain free variables");
+ return -1;
+ }
v = PyEval_EvalCode((PyCodeObject *) prog, globals, locals);
}
else if (PyFile_Check(prog)) {