Index: test_ast.py =================================================================== --- test_ast.py (revision 88452) +++ test_ast.py (working copy) @@ -20,10 +20,24 @@ # These tests are compiled through "exec" # There should be atleast one test per statement exec_tests = [ + # None + "None", # FunctionDef "def f(): pass", + # FunctionDef with arg + "def f(a): pass", + # FunctionDef with arg and default value + "def f(a=0): pass", + # FunctionDef with varargs + "def f(*args): pass", + # FunctionDef with kwargs + "def f(**kwargs): pass", + # FunctionDef with all kind of args + "def f(a, b=1, c=None, d=[], e={}, *args, **kwargs): pass", # ClassDef "class C:pass", + # ClassDef, new style class + "class C(object): pass", # Return "def f():return 1", # Delete @@ -68,6 +82,27 @@ "for a,b in c: pass", "[(a,b) for a,b in c]", "((a,b) for a,b in c)", + "((a,b) for (a,b) in c)", + # Multiline generator expression + """( + ( + Aa + , + Bb + ) + for + Aa + , + Bb in Cc + )""", + # dictcomp + "{a : b for w in x for m in p if g}", + # dictcomp with naked tuple + "{a : b for v,w in x}", + # setcomp + "{r for l in x if g}", + # setcomp with naked tuple + "{r for l,m in x}", ] # These are compiled through "single" @@ -80,6 +115,8 @@ # These are compiled through "eval" # It should test all expressions eval_tests = [ + # None + "None", # BoolOp "a and b", # BinOp @@ -90,6 +127,16 @@ "lambda:None", # Dict "{ 1:2 }", + # Empty dict + "{}", + # Set + "{None,}", + # Multiline dict + """{ + 1 + : + 2 + }""", # ListComp "[a for b in c if d]", # GeneratorExp @@ -114,8 +161,14 @@ "v", # List "[1,2,3]", + # Empty list + "[]", # Tuple "1,2,3", + # Tuple + "(1,2,3)", + # Empty tuple + "()", # Combination "a.b.c.d(a.b[1:2])", @@ -141,6 +194,31 @@ elif value is not None: self._assertTrueorder(value, parent_pos) + def test_AST_objects(self): + x = ast.AST() + try: + x.foobar = 21 + except AttributeError, e: + self.assertEquals(e.args[0], + "'_ast.AST' object has no attribute 'foobar'") + else: + self.assert_(False) + + try: + ast.AST(lineno=2) + except AttributeError, e: + self.assertEquals(e.args[0], + "'_ast.AST' object has no attribute 'lineno'") + else: + self.assert_(False) + try: + ast.AST(2) + except TypeError, e: + self.assertEquals(e.args[0], + "_ast.AST constructor takes 0 positional arguments") + else: + self.assert_(False) + def test_snippets(self): for input, output, kind in ((exec_tests, exec_results, "exec"), (single_tests, single_results, "single"), @@ -169,7 +247,98 @@ self.assertTrue(issubclass(ast.comprehension, ast.AST)) self.assertTrue(issubclass(ast.Gt, ast.AST)) + def test_field_attr_existence(self): + for name, item in ast.__dict__.iteritems(): + if isinstance(item, type) and name != 'AST' and name[0].isupper(): + x = item() + if isinstance(x, ast.AST): + self.assertEquals(type(x._fields), tuple) + + def test_arguments(self): + x = ast.arguments() + self.assertEquals(x._fields, ('args', 'vararg', 'kwarg', 'defaults')) + try: + x.vararg + except AttributeError, e: + self.assertEquals(e.args[0], + "'arguments' object has no attribute 'vararg'") + else: + self.assert_(False) + x = ast.arguments(1, 2, 3, 4) + self.assertEquals(x.vararg, 2) + + def test_field_attr_writable(self): + x = ast.Num() + # We can assign to _fields + x._fields = 666 + self.assertEquals(x._fields, 666) + + def test_classattrs(self): + x = ast.Num() + self.assertEquals(x._fields, ('n',)) + try: + x.n + except AttributeError, e: + self.assertEquals(e.args[0], + "'Num' object has no attribute 'n'") + else: + self.assert_(False) + + x = ast.Num(42) + self.assertEquals(x.n, 42) + try: + x.lineno + except AttributeError, e: + self.assertEquals(e.args[0], + "'Num' object has no attribute 'lineno'") + else: + self.assert_(False) + try: + x.foobar + except AttributeError, e: + self.assertEquals(e.args[0], + "'Num' object has no attribute 'foobar'") + else: + self.assert_(False) + + x = ast.Num(lineno=2) + self.assertEquals(x.lineno, 2) + + x = ast.Num(42, lineno=0) + self.assertEquals(x.lineno, 0) + self.assertEquals(x._fields, ('n',)) + self.assertEquals(x.n, 42) + + self.assertRaises(TypeError, ast.Num, 1, 2) + self.assertRaises(TypeError, ast.Num, 1, 2, lineno=0) + + def test_module(self): + body = [ast.Num(42)] + x = ast.Module(body) + self.assertEquals(x.body, body) + def test_nodeclasses(self): + # Zero arguments constructor explicitely allowed + x = ast.BinOp() + self.assertEquals(x._fields, ('left', 'op', 'right')) + + # Random attribute allowed too + x.foobarbaz = 5 + self.assertEquals(x.foobarbaz, 5) + + n1 = ast.Num(1) + n3 = ast.Num(3) + addop = ast.Add() + x = ast.BinOp(n1, addop, n3) + self.assertEquals(x.left, n1) + self.assertEquals(x.op, addop) + self.assertEquals(x.right, n3) + + x = ast.BinOp(1, 2, 3) + self.assertEquals(x.left, 1) + self.assertEquals(x.op, 2) + self.assertEquals(x.right, 3) + x = ast.BinOp(1, 2, 3, lineno=0) self.assertEqual(x.left, 1) self.assertEqual(x.op, 2) @@ -178,6 +347,12 @@ # node raises exception when not given enough arguments self.assertRaises(TypeError, ast.BinOp, 1, 2) + # node raises exception when given too many arguments + self.assertRaises(TypeError, ast.BinOp, 1, 2, 3, 4) + # node raises exception when not given enough arguments + self.assertRaises(TypeError, ast.BinOp, 1, 2, lineno=0) + # node raises exception when given too many arguments + self.assertRaises(TypeError, ast.BinOp, 1, 2, 3, 4, lineno=0) # can set attributes through kwargs too x = ast.BinOp(left=1, op=2, right=3, lineno=0) @@ -186,8 +361,14 @@ self.assertEqual(x.right, 3) self.assertEqual(x.lineno, 0) + # Random kwargs also allowed + x = ast.BinOp(1, 2, 3, foobarbaz=42) + self.assertEquals(x.foobarbaz, 42) + + def test_no_fields(self): # this used to fail because Sub._fields was None x = ast.Sub() + self.assertEquals(x._fields, ()) def test_pickling(self): import pickle @@ -330,8 +511,15 @@ #### EVERYTHING BELOW IS GENERATED ##### exec_results = [ +('Module', [('Expr', (1, 0), ('Name', (1, 0), 'None', ('Load',)))]), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, None, []), [('Pass', (1, 9))], [])]), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('Name', (1, 6), 'a', ('Param',))], None, None, []), [('Pass', (1, 10))], [])]), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('Name', (1, 6), 'a', ('Param',))], None, None, [('Num', (1, 8), 0)]), [('Pass', (1, 12))], [])]), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], 'args', None, []), [('Pass', (1, 14))], [])]), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, 'kwargs', []), [('Pass', (1, 17))], [])]), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('Name', (1, 6), 'a', ('Param',)), ('Name', (1, 9), 'b', ('Param',)), ('Name', (1, 14), 'c', ('Param',)), ('Name', (1, 22), 'd', ('Param',)), ('Name', (1, 28), 'e', ('Param',))], 'args', 'kwargs', [('Num', (1, 11), 1), ('Name', (1, 16), 'None', ('Load',)), ('List', (1, 24), [], ('Load',)), ('Dict', (1, 30), [], [])]), [('Pass', (1, 52))], [])]), ('Module', [('ClassDef', (1, 0), 'C', [], [('Pass', (1, 8))], [])]), +('Module', [('ClassDef', (1, 0), 'C', [('Name', (1, 8), 'object', ('Load',))], [('Pass', (1, 17))], [])]), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, None, []), [('Return', (1, 8), ('Num', (1, 15), 1))], [])]), ('Module', [('Delete', (1, 0), [('Name', (1, 4), 'v', ('Del',))])]), ('Module', [('Assign', (1, 0), [('Name', (1, 0), 'v', ('Store',))], ('Num', (1, 4), 1))]), @@ -355,16 +543,26 @@ ('Module', [('For', (1, 0), ('Tuple', (1, 4), [('Name', (1, 4), 'a', ('Store',)), ('Name', (1, 6), 'b', ('Store',))], ('Store',)), ('Name', (1, 11), 'c', ('Load',)), [('Pass', (1, 14))], [])]), ('Module', [('Expr', (1, 0), ('ListComp', (1, 1), ('Tuple', (1, 2), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'a', ('Store',)), ('Name', (1, 13), 'b', ('Store',))], ('Store',)), ('Name', (1, 18), 'c', ('Load',)), [])]))]), ('Module', [('Expr', (1, 0), ('GeneratorExp', (1, 1), ('Tuple', (1, 2), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'a', ('Store',)), ('Name', (1, 13), 'b', ('Store',))], ('Store',)), ('Name', (1, 18), 'c', ('Load',)), [])]))]), +('Module', [('Expr', (1, 0), ('GeneratorExp', (1, 1), ('Tuple', (1, 2), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 12), [('Name', (1, 12), 'a', ('Store',)), ('Name', (1, 14), 'b', ('Store',))], ('Store',)), ('Name', (1, 20), 'c', ('Load',)), [])]))]), +('Module', [('Expr', (1, 0), ('GeneratorExp', (2, 4), ('Tuple', (3, 4), [('Name', (3, 4), 'Aa', ('Load',)), ('Name', (5, 7), 'Bb', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (8, 4), [('Name', (8, 4), 'Aa', ('Store',)), ('Name', (10, 4), 'Bb', ('Store',))], ('Store',)), ('Name', (10, 10), 'Cc', ('Load',)), [])]))]), +('Module', [('Expr', (1, 0), ('DictComp', (1, 1), ('Name', (1, 1), 'a', ('Load',)), ('Name', (1, 5), 'b', ('Load',)), [('comprehension', ('Name', (1, 11), 'w', ('Store',)), ('Name', (1, 16), 'x', ('Load',)), []), ('comprehension', ('Name', (1, 22), 'm', ('Store',)), ('Name', (1, 27), 'p', ('Load',)), [('Name', (1, 32), 'g', ('Load',))])]))]), +('Module', [('Expr', (1, 0), ('DictComp', (1, 1), ('Name', (1, 1), 'a', ('Load',)), ('Name', (1, 5), 'b', ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'v', ('Store',)), ('Name', (1, 13), 'w', ('Store',))], ('Store',)), ('Name', (1, 18), 'x', ('Load',)), [])]))]), +('Module', [('Expr', (1, 0), ('SetComp', (1, 1), ('Name', (1, 1), 'r', ('Load',)), [('comprehension', ('Name', (1, 7), 'l', ('Store',)), ('Name', (1, 12), 'x', ('Load',)), [('Name', (1, 17), 'g', ('Load',))])]))]), +('Module', [('Expr', (1, 0), ('SetComp', (1, 1), ('Name', (1, 1), 'r', ('Load',)), [('comprehension', ('Tuple', (1, 7), [('Name', (1, 7), 'l', ('Store',)), ('Name', (1, 9), 'm', ('Store',))], ('Store',)), ('Name', (1, 14), 'x', ('Load',)), [])]))]), ] single_results = [ ('Interactive', [('Expr', (1, 0), ('BinOp', (1, 0), ('Num', (1, 0), 1), ('Add',), ('Num', (1, 2), 2)))]), ] eval_results = [ +('Expression', ('Name', (1, 0), 'None', ('Load',))), ('Expression', ('BoolOp', (1, 0), ('And',), [('Name', (1, 0), 'a', ('Load',)), ('Name', (1, 6), 'b', ('Load',))])), ('Expression', ('BinOp', (1, 0), ('Name', (1, 0), 'a', ('Load',)), ('Add',), ('Name', (1, 4), 'b', ('Load',)))), ('Expression', ('UnaryOp', (1, 0), ('Not',), ('Name', (1, 4), 'v', ('Load',)))), ('Expression', ('Lambda', (1, 0), ('arguments', [], None, None, []), ('Name', (1, 7), 'None', ('Load',)))), ('Expression', ('Dict', (1, 0), [('Num', (1, 2), 1)], [('Num', (1, 4), 2)])), +('Expression', ('Dict', (1, 0), [], [])), +('Expression', ('Set', (1, 0), [('Name', (1, 1), 'None', ('Load',))])), +('Expression', ('Dict', (1, 0), [('Num', (2, 6), 1)], [('Num', (4, 10), 2)])), ('Expression', ('ListComp', (1, 1), ('Name', (1, 1), 'a', ('Load',)), [('comprehension', ('Name', (1, 7), 'b', ('Store',)), ('Name', (1, 12), 'c', ('Load',)), [('Name', (1, 17), 'd', ('Load',))])])), ('Expression', ('GeneratorExp', (1, 1), ('Name', (1, 1), 'a', ('Load',)), [('comprehension', ('Name', (1, 7), 'b', ('Store',)), ('Name', (1, 12), 'c', ('Load',)), [('Name', (1, 17), 'd', ('Load',))])])), ('Expression', ('Compare', (1, 0), ('Num', (1, 0), 1), [('Lt',), ('Lt',)], [('Num', (1, 4), 2), ('Num', (1, 8), 3)])), @@ -376,7 +574,10 @@ ('Expression', ('Subscript', (1, 0), ('Name', (1, 0), 'a', ('Load',)), ('Slice', ('Name', (1, 2), 'b', ('Load',)), ('Name', (1, 4), 'c', ('Load',)), None), ('Load',))), ('Expression', ('Name', (1, 0), 'v', ('Load',))), ('Expression', ('List', (1, 0), [('Num', (1, 1), 1), ('Num', (1, 3), 2), ('Num', (1, 5), 3)], ('Load',))), +('Expression', ('List', (1, 0), [], ('Load',))), ('Expression', ('Tuple', (1, 0), [('Num', (1, 0), 1), ('Num', (1, 2), 2), ('Num', (1, 4), 3)], ('Load',))), +('Expression', ('Tuple', (1, 1), [('Num', (1, 1), 1), ('Num', (1, 3), 2), ('Num', (1, 5), 3)], ('Load',))), +('Expression', ('Tuple', (1, 0), [], ('Load',))), ('Expression', ('Call', (1, 0), ('Attribute', (1, 0), ('Attribute', (1, 0), ('Attribute', (1, 0), ('Name', (1, 0), 'a', ('Load',)), 'b', ('Load',)), 'c', ('Load',)), 'd', ('Load',)), [('Subscript', (1, 8), ('Attribute', (1, 8), ('Name', (1, 8), 'a', ('Load',)), 'b', ('Load',)), ('Slice', ('Num', (1, 12), 1), ('Num', (1, 14), 2), None), ('Load',))], [], None, None)), ] main()