# s.sy == 'exec'
pos = s.position()
s.next()
- args = [ p_bit_expr(s) ]
+ code = p_bit_expr(s)
+ if isinstance(code, ExprNodes.TupleNode):
+ # Py3 compatibility syntax
+ tuple_variant = True
+ args = code.args
+ if len(args) not in (2, 3):
+ s.error("expected tuple of length 2 or 3, got length %d" % len(args),
+ pos=pos, fatal=False)
+ args = [code]
+ else:
+ tuple_variant = False
+ args = [code]
if s.sy == 'in':
+ if tuple_variant:
+ s.error("tuple variant of exec does not support additional 'in' arguments",
+ fatal=False)
s.next()
args.append(p_test(s))
if s.sy == ',':
s.next()
args.append(p_test(s))
- return Nodes.ExecStatNode(pos, args = args)
+ return Nodes.ExecStatNode(pos, args=args)
def p_del_statement(s):
# s.sy == 'del'
--- /dev/null
+# mode: error
+# tag: exec
+
+def test_exec_tuples():
+ exec()
+ exec(1,)
+ exec(1,2,3,4)
+
+def test_exec_tuples_with_in(d1, d2):
+ exec(1,2) in d1
+ exec(1,2,3) in d1
+ exec(1,2) in d1, d2
+ exec(1,2,3) in d1, d2
+
+
+_ERRORS = """
+ 5:4: expected tuple of length 2 or 3, got length 0
+ 6:4: expected tuple of length 2 or 3, got length 1
+ 7:4: expected tuple of length 2 or 3, got length 4
+10:14: tuple variant of exec does not support additional 'in' arguments
+11:16: tuple variant of exec does not support additional 'in' arguments
+12:14: tuple variant of exec does not support additional 'in' arguments
+13:16: tuple variant of exec does not support additional 'in' arguments
+"""
def test_dict_scope_ref(d1, d2):
exec u"b=a+c" in d1, d2
+def test_dict_scope_tuple2():
+ """
+ >>> test_dict_scope_tuple2()
+ 2
+ """
+ cdef dict d = {}
+ exec(u"b=1+1", d) # Py3 compatibility syntax
+ return d[u'b']
+
+def test_dict_scope_tuple3(d1, d2):
+ """
+ >>> d1, d2 = {}, {}
+ >>> test_dict_scope_tuple3(d1, d2)
+ >>> (d1.get('b'), d2.get('b'))
+ (None, 2)
+ """
+ exec(u"b=1+1", d1, d2)
+
def test_def(d, varref):
exec u"""
def test():