1import unittest 2from test import test_support 3import cStringIO 4import sys 5import os 6import tokenize 7import ast 8import unparse 9 10def read_pyfile(filename): 11 """Read and return the contents of a Python source file (as a 12 string), taking into account the file encoding.""" 13 with open(filename, "r") as pyfile: 14 source = pyfile.read() 15 return source 16 17for_else = """\ 18def f(): 19 for x in range(10): 20 break 21 else: 22 y = 2 23 z = 3 24""" 25 26while_else = """\ 27def g(): 28 while True: 29 break 30 else: 31 y = 2 32 z = 3 33""" 34 35relative_import = """\ 36from . import fred 37from .. import barney 38from .australia import shrimp as prawns 39""" 40 41class_decorator = """\ 42@f1(arg) 43@f2 44class Foo: pass 45""" 46 47elif1 = """\ 48if cond1: 49 suite1 50elif cond2: 51 suite2 52else: 53 suite3 54""" 55 56elif2 = """\ 57if cond1: 58 suite1 59elif cond2: 60 suite2 61""" 62 63try_except_finally = """\ 64try: 65 suite1 66except ex1: 67 suite2 68except ex2: 69 suite3 70else: 71 suite4 72finally: 73 suite5 74""" 75 76class ASTTestCase(unittest.TestCase): 77 def assertASTEqual(self, ast1, ast2): 78 dump1 = ast.dump(ast1) 79 dump2 = ast.dump(ast2) 80 self.assertEqual(ast.dump(ast1), ast.dump(ast2)) 81 82 def check_roundtrip(self, code1, filename="internal"): 83 ast1 = compile(code1, filename, "exec", ast.PyCF_ONLY_AST) 84 unparse_buffer = cStringIO.StringIO() 85 unparse.Unparser(ast1, unparse_buffer) 86 code2 = unparse_buffer.getvalue() 87 ast2 = compile(code2, filename, "exec", ast.PyCF_ONLY_AST) 88 self.assertASTEqual(ast1, ast2) 89 90class UnparseTestCase(ASTTestCase): 91 # Tests for specific bugs found in earlier versions of unparse 92 93 def test_del_statement(self): 94 self.check_roundtrip("del x, y, z") 95 96 def test_shifts(self): 97 self.check_roundtrip("45 << 2") 98 self.check_roundtrip("13 >> 7") 99 100 def test_for_else(self): 101 self.check_roundtrip(for_else) 102 103 def test_while_else(self): 104 self.check_roundtrip(while_else) 105 106 def test_unary_parens(self): 107 self.check_roundtrip("(-1)**7") 108 self.check_roundtrip("(-1.)**8") 109 self.check_roundtrip("(-1j)**6") 110 self.check_roundtrip("not True or False") 111 self.check_roundtrip("True or not False") 112 113 def test_integer_parens(self): 114 self.check_roundtrip("3 .__abs__()") 115 116 def test_huge_float(self): 117 self.check_roundtrip("1e1000") 118 self.check_roundtrip("-1e1000") 119 self.check_roundtrip("1e1000j") 120 self.check_roundtrip("-1e1000j") 121 122 def test_min_int(self): 123 self.check_roundtrip(str(-sys.maxint-1)) 124 self.check_roundtrip("-(%s)" % (sys.maxint + 1)) 125 126 def test_imaginary_literals(self): 127 self.check_roundtrip("7j") 128 self.check_roundtrip("-7j") 129 self.check_roundtrip("-(7j)") 130 self.check_roundtrip("0j") 131 self.check_roundtrip("-0j") 132 self.check_roundtrip("-(0j)") 133 134 def test_negative_zero(self): 135 self.check_roundtrip("-0") 136 self.check_roundtrip("-(0)") 137 self.check_roundtrip("-0b0") 138 self.check_roundtrip("-(0b0)") 139 self.check_roundtrip("-0o0") 140 self.check_roundtrip("-(0o0)") 141 self.check_roundtrip("-0x0") 142 self.check_roundtrip("-(0x0)") 143 144 def test_lambda_parentheses(self): 145 self.check_roundtrip("(lambda: int)()") 146 147 def test_chained_comparisons(self): 148 self.check_roundtrip("1 < 4 <= 5") 149 self.check_roundtrip("a is b is c is not d") 150 151 def test_function_arguments(self): 152 self.check_roundtrip("def f(): pass") 153 self.check_roundtrip("def f(a): pass") 154 self.check_roundtrip("def f(b = 2): pass") 155 self.check_roundtrip("def f(a, b): pass") 156 self.check_roundtrip("def f(a, b = 2): pass") 157 self.check_roundtrip("def f(a = 5, b = 2): pass") 158 self.check_roundtrip("def f(*args, **kwargs): pass") 159 160 def test_relative_import(self): 161 self.check_roundtrip(relative_import) 162 163 def test_bytes(self): 164 self.check_roundtrip("b'123'") 165 166 def test_set_literal(self): 167 self.check_roundtrip("{'a', 'b', 'c'}") 168 169 def test_set_comprehension(self): 170 self.check_roundtrip("{x for x in range(5)}") 171 172 def test_dict_comprehension(self): 173 self.check_roundtrip("{x: x*x for x in range(10)}") 174 175 def test_class_decorators(self): 176 self.check_roundtrip(class_decorator) 177 178 def test_elifs(self): 179 self.check_roundtrip(elif1) 180 self.check_roundtrip(elif2) 181 182 def test_try_except_finally(self): 183 self.check_roundtrip(try_except_finally) 184 185class DirectoryTestCase(ASTTestCase): 186 """Test roundtrip behaviour on all files in Lib and Lib/test.""" 187 188 # test directories, relative to the root of the distribution 189 test_directories = 'Lib', os.path.join('Lib', 'test') 190 191 def test_files(self): 192 # get names of files to test 193 dist_dir = os.path.join(os.path.dirname(__file__), os.pardir, os.pardir) 194 195 names = [] 196 for d in self.test_directories: 197 test_dir = os.path.join(dist_dir, d) 198 for n in os.listdir(test_dir): 199 if n.endswith('.py') and not n.startswith('bad'): 200 names.append(os.path.join(test_dir, n)) 201 202 for filename in names: 203 if test_support.verbose: 204 print('Testing %s' % filename) 205 source = read_pyfile(filename) 206 self.check_roundtrip(source) 207 208 209def test_main(): 210 test_support.run_unittest(UnparseTestCase, DirectoryTestCase) 211 212if __name__ == '__main__': 213 test_main() 214