blob: d04db4d5f46e1ad0b83456b509812d394232902e [file] [log] [blame]
Zachary Ware2b0a6102014-07-16 14:26:09 -05001"""Tests for the unparse.py script in the Tools/parser directory."""
2
Mark Dickinsonae100052010-06-28 19:44:20 +00003import unittest
4import test.support
Pablo Galindo27fc3b62019-11-24 23:02:40 +00005import pathlib
Mark Dickinsonbe4fb692012-06-23 09:27:47 +01006import random
Mark Dickinsond751c2e2010-06-29 14:08:23 +00007import tokenize
Mark Dickinsonbe4fb692012-06-23 09:27:47 +01008import ast
Mark Dickinsonae100052010-06-28 19:44:20 +00009
Zachary Ware2b0a6102014-07-16 14:26:09 -050010
Mark Dickinsond751c2e2010-06-29 14:08:23 +000011def read_pyfile(filename):
12 """Read and return the contents of a Python source file (as a
13 string), taking into account the file encoding."""
14 with open(filename, "rb") as pyfile:
15 encoding = tokenize.detect_encoding(pyfile.readline)[0]
16 with open(filename, "r", encoding=encoding) as pyfile:
17 source = pyfile.read()
18 return source
19
Pablo Galindo27fc3b62019-11-24 23:02:40 +000020
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +000021for_else = """\
Mark Dickinsonae100052010-06-28 19:44:20 +000022def f():
23 for x in range(10):
24 break
25 else:
26 y = 2
27 z = 3
28"""
29
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +000030while_else = """\
Mark Dickinsonae100052010-06-28 19:44:20 +000031def g():
32 while True:
33 break
34 else:
35 y = 2
36 z = 3
37"""
38
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +000039relative_import = """\
40from . import fred
41from .. import barney
42from .australia import shrimp as prawns
43"""
44
45nonlocal_ex = """\
46def f():
47 x = 1
48 def g():
49 nonlocal x
50 x = 2
51 y = 7
52 def h():
53 nonlocal x, y
54"""
55
56# also acts as test for 'except ... as ...'
57raise_from = """\
58try:
59 1 / 0
60except ZeroDivisionError as e:
61 raise ArithmeticError from e
62"""
63
64class_decorator = """\
65@f1(arg)
66@f2
67class Foo: pass
68"""
69
Mark Dickinson8d6d7602010-06-30 08:32:11 +000070elif1 = """\
71if cond1:
72 suite1
73elif cond2:
74 suite2
75else:
76 suite3
77"""
78
79elif2 = """\
80if cond1:
81 suite1
82elif cond2:
83 suite2
84"""
85
Mark Dickinson81ad8cc2010-06-30 08:46:53 +000086try_except_finally = """\
87try:
88 suite1
89except ex1:
90 suite2
91except ex2:
92 suite3
93else:
94 suite4
95finally:
96 suite5
97"""
Mark Dickinson8d6d7602010-06-30 08:32:11 +000098
Mark Dickinsonfe8440a2012-05-06 17:35:19 +010099with_simple = """\
100with f():
101 suite1
102"""
103
104with_as = """\
105with f() as x:
106 suite1
107"""
108
109with_two_items = """\
110with f() as x, g() as y:
111 suite1
112"""
113
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300114docstring_prefixes = [
115 "",
116 "class foo():\n ",
117 "def foo():\n ",
118 "async def foo():\n ",
119]
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000120
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000121class ASTTestCase(unittest.TestCase):
122 def assertASTEqual(self, ast1, ast2):
123 self.assertEqual(ast.dump(ast1), ast.dump(ast2))
Mark Dickinsonae100052010-06-28 19:44:20 +0000124
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300125 def check_ast_roundtrip(self, code1):
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000126 ast1 = ast.parse(code1)
127 code2 = ast.unparse(ast1)
128 ast2 = ast.parse(code2)
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000129 self.assertASTEqual(ast1, ast2)
130
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000131 def check_invalid(self, node, raises=ValueError):
132 self.assertRaises(raises, ast.unparse, node)
133
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300134 def get_source(self, code1, code2=None, strip=True):
Batuhan Taşkaya397b96f2020-03-01 23:12:17 +0300135 code2 = code2 or code1
136 code1 = ast.unparse(ast.parse(code1))
137 if strip:
138 code1 = code1.strip()
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300139 return code1, code2
140
141 def check_src_roundtrip(self, code1, code2=None, strip=True):
142 code1, code2 = self.get_source(code1, code2, strip)
Batuhan Taşkaya397b96f2020-03-01 23:12:17 +0300143 self.assertEqual(code2, code1)
144
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300145 def check_src_dont_roundtrip(self, code1, code2=None, strip=True):
146 code1, code2 = self.get_source(code1, code2, strip)
147 self.assertNotEqual(code2, code1)
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000148
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000149class UnparseTestCase(ASTTestCase):
150 # Tests for specific bugs found in earlier versions of unparse
Mark Dickinsonae100052010-06-28 19:44:20 +0000151
Eric V. Smith608adf92015-09-20 15:09:15 -0400152 def test_fstrings(self):
153 # See issue 25180
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300154 self.check_ast_roundtrip(r"""f'{f"{0}"*3}'""")
155 self.check_ast_roundtrip(r"""f'{f"{y}"*3}'""")
Eric V. Smith608adf92015-09-20 15:09:15 -0400156
Chih-Hsuan Yenaaf47ca2019-05-27 01:08:20 +0800157 def test_strings(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300158 self.check_ast_roundtrip("u'foo'")
159 self.check_ast_roundtrip("r'foo'")
160 self.check_ast_roundtrip("b'foo'")
Chih-Hsuan Yenaaf47ca2019-05-27 01:08:20 +0800161
Mark Dickinsonae100052010-06-28 19:44:20 +0000162 def test_del_statement(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300163 self.check_ast_roundtrip("del x, y, z")
Mark Dickinsonae100052010-06-28 19:44:20 +0000164
165 def test_shifts(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300166 self.check_ast_roundtrip("45 << 2")
167 self.check_ast_roundtrip("13 >> 7")
Mark Dickinsonae100052010-06-28 19:44:20 +0000168
169 def test_for_else(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300170 self.check_ast_roundtrip(for_else)
Mark Dickinsonae100052010-06-28 19:44:20 +0000171
172 def test_while_else(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300173 self.check_ast_roundtrip(while_else)
Mark Dickinsonae100052010-06-28 19:44:20 +0000174
175 def test_unary_parens(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300176 self.check_ast_roundtrip("(-1)**7")
177 self.check_ast_roundtrip("(-1.)**8")
178 self.check_ast_roundtrip("(-1j)**6")
179 self.check_ast_roundtrip("not True or False")
180 self.check_ast_roundtrip("True or not False")
Mark Dickinsonae100052010-06-28 19:44:20 +0000181
Mark Dickinson3eb02902010-06-29 08:52:36 +0000182 def test_integer_parens(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300183 self.check_ast_roundtrip("3 .__abs__()")
Mark Dickinson3eb02902010-06-29 08:52:36 +0000184
Mark Dickinson8042e282010-06-29 10:01:48 +0000185 def test_huge_float(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300186 self.check_ast_roundtrip("1e1000")
187 self.check_ast_roundtrip("-1e1000")
188 self.check_ast_roundtrip("1e1000j")
189 self.check_ast_roundtrip("-1e1000j")
Mark Dickinsoncba8c102010-06-30 11:45:53 +0000190
191 def test_min_int(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300192 self.check_ast_roundtrip(str(-(2 ** 31)))
193 self.check_ast_roundtrip(str(-(2 ** 63)))
Mark Dickinsoncba8c102010-06-30 11:45:53 +0000194
195 def test_imaginary_literals(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300196 self.check_ast_roundtrip("7j")
197 self.check_ast_roundtrip("-7j")
198 self.check_ast_roundtrip("0j")
199 self.check_ast_roundtrip("-0j")
Mark Dickinson8042e282010-06-29 10:01:48 +0000200
201 def test_lambda_parentheses(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300202 self.check_ast_roundtrip("(lambda: int)()")
Mark Dickinson8042e282010-06-29 10:01:48 +0000203
Mark Dickinsonf5451e52010-06-28 20:09:18 +0000204 def test_chained_comparisons(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300205 self.check_ast_roundtrip("1 < 4 <= 5")
206 self.check_ast_roundtrip("a is b is c is not d")
Mark Dickinsonf5451e52010-06-28 20:09:18 +0000207
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000208 def test_function_arguments(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300209 self.check_ast_roundtrip("def f(): pass")
210 self.check_ast_roundtrip("def f(a): pass")
211 self.check_ast_roundtrip("def f(b = 2): pass")
212 self.check_ast_roundtrip("def f(a, b): pass")
213 self.check_ast_roundtrip("def f(a, b = 2): pass")
214 self.check_ast_roundtrip("def f(a = 5, b = 2): pass")
215 self.check_ast_roundtrip("def f(*, a = 1, b = 2): pass")
216 self.check_ast_roundtrip("def f(*, a = 1, b): pass")
217 self.check_ast_roundtrip("def f(*, a, b = 2): pass")
218 self.check_ast_roundtrip("def f(a, b = None, *, c, **kwds): pass")
219 self.check_ast_roundtrip("def f(a=2, *args, c=5, d, **kwds): pass")
220 self.check_ast_roundtrip("def f(*args, **kwargs): pass")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000221
222 def test_relative_import(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300223 self.check_ast_roundtrip(relative_import)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000224
225 def test_nonlocal(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300226 self.check_ast_roundtrip(nonlocal_ex)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000227
228 def test_raise_from(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300229 self.check_ast_roundtrip(raise_from)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000230
231 def test_bytes(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300232 self.check_ast_roundtrip("b'123'")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000233
234 def test_annotations(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300235 self.check_ast_roundtrip("def f(a : int): pass")
236 self.check_ast_roundtrip("def f(a: int = 5): pass")
237 self.check_ast_roundtrip("def f(*args: [int]): pass")
238 self.check_ast_roundtrip("def f(**kwargs: dict): pass")
239 self.check_ast_roundtrip("def f() -> None: pass")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000240
241 def test_set_literal(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300242 self.check_ast_roundtrip("{'a', 'b', 'c'}")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000243
244 def test_set_comprehension(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300245 self.check_ast_roundtrip("{x for x in range(5)}")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000246
247 def test_dict_comprehension(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300248 self.check_ast_roundtrip("{x: x*x for x in range(10)}")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000249
250 def test_class_decorators(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300251 self.check_ast_roundtrip(class_decorator)
Mark Dickinsonae100052010-06-28 19:44:20 +0000252
Mark Dickinson578aa562010-06-29 18:38:59 +0000253 def test_class_definition(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300254 self.check_ast_roundtrip("class A(metaclass=type, *[], **{}): pass")
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000255
Mark Dickinson8d6d7602010-06-30 08:32:11 +0000256 def test_elifs(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300257 self.check_ast_roundtrip(elif1)
258 self.check_ast_roundtrip(elif2)
Mark Dickinson8d6d7602010-06-30 08:32:11 +0000259
Mark Dickinson81ad8cc2010-06-30 08:46:53 +0000260 def test_try_except_finally(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300261 self.check_ast_roundtrip(try_except_finally)
Mark Dickinson81ad8cc2010-06-30 08:46:53 +0000262
Mark Dickinson1b2e9442012-05-06 17:27:39 +0100263 def test_starred_assignment(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300264 self.check_ast_roundtrip("a, *b, c = seq")
265 self.check_ast_roundtrip("a, (*b, c) = seq")
266 self.check_ast_roundtrip("a, *b[0], c = seq")
267 self.check_ast_roundtrip("a, *(b, c) = seq")
Mark Dickinson1b2e9442012-05-06 17:27:39 +0100268
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100269 def test_with_simple(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300270 self.check_ast_roundtrip(with_simple)
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100271
272 def test_with_as(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300273 self.check_ast_roundtrip(with_as)
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100274
275 def test_with_two_items(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300276 self.check_ast_roundtrip(with_two_items)
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100277
Berker Peksagd66dd5c2016-03-06 16:50:15 +0200278 def test_dict_unpacking_in_dict(self):
279 # See issue 26489
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300280 self.check_ast_roundtrip(r"""{**{'y': 2}, 'x': 1}""")
281 self.check_ast_roundtrip(r"""{**{'y': 2}, **{'x': 1}}""")
Berker Peksagd66dd5c2016-03-06 16:50:15 +0200282
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000283 def test_invalid_raise(self):
284 self.check_invalid(ast.Raise(exc=None, cause=ast.Name(id="X")))
285
286 def test_invalid_fstring_constant(self):
287 self.check_invalid(ast.JoinedStr(values=[ast.Constant(value=100)]))
288
289 def test_invalid_fstring_conversion(self):
290 self.check_invalid(
291 ast.FormattedValue(
292 value=ast.Constant(value="a", kind=None),
293 conversion=ord("Y"), # random character
294 format_spec=None,
295 )
296 )
297
298 def test_invalid_set(self):
299 self.check_invalid(ast.Set(elts=[]))
300
Batuhan Taşkaya7b35bef2020-01-02 21:20:04 +0300301 def test_invalid_yield_from(self):
302 self.check_invalid(ast.YieldFrom(value=None))
Mark Dickinson1b2e9442012-05-06 17:27:39 +0100303
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300304 def test_docstrings(self):
305 docstrings = (
306 'this ends with double quote"',
307 'this includes a """triple quote"""'
308 )
309 for docstring in docstrings:
310 # check as Module docstrings for easy testing
311 self.check_ast_roundtrip(f"'{docstring}'")
312
313
Batuhan Taşkaya397b96f2020-03-01 23:12:17 +0300314class CosmeticTestCase(ASTTestCase):
315 """Test if there are cosmetic issues caused by unnecesary additions"""
316
317 def test_simple_expressions_parens(self):
318 self.check_src_roundtrip("(a := b)")
319 self.check_src_roundtrip("await x")
320 self.check_src_roundtrip("x if x else y")
321 self.check_src_roundtrip("lambda x: x")
322 self.check_src_roundtrip("1 + 1")
323 self.check_src_roundtrip("1 + 2 / 3")
324 self.check_src_roundtrip("(1 + 2) / 3")
325 self.check_src_roundtrip("(1 + 2) * 3 + 4 * (5 + 2)")
326 self.check_src_roundtrip("(1 + 2) * 3 + 4 * (5 + 2) ** 2")
327 self.check_src_roundtrip("~ x")
328 self.check_src_roundtrip("x and y")
329 self.check_src_roundtrip("x and y and z")
330 self.check_src_roundtrip("x and (y and x)")
331 self.check_src_roundtrip("(x and y) and z")
332 self.check_src_roundtrip("(x ** y) ** z ** q")
333 self.check_src_roundtrip("x >> y")
334 self.check_src_roundtrip("x << y")
335 self.check_src_roundtrip("x >> y and x >> z")
336 self.check_src_roundtrip("x + y - z * q ^ t ** k")
337 self.check_src_roundtrip("P * V if P and V else n * R * T")
338 self.check_src_roundtrip("lambda P, V, n: P * V == n * R * T")
339 self.check_src_roundtrip("flag & (other | foo)")
340 self.check_src_roundtrip("not x == y")
341 self.check_src_roundtrip("x == (not y)")
342 self.check_src_roundtrip("yield x")
343 self.check_src_roundtrip("yield from x")
344 self.check_src_roundtrip("call((yield x))")
345 self.check_src_roundtrip("return x + (yield x)")
346
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300347 def test_docstrings(self):
348 docstrings = (
349 '"""simple doc string"""',
350 '''"""A more complex one
351 with some newlines"""''',
352 '''"""Foo bar baz
353
354 empty newline"""''',
355 '"""With some \t"""',
356 '"""Foo "bar" baz """',
357 )
358
359 for prefix in docstring_prefixes:
360 for docstring in docstrings:
361 self.check_src_roundtrip(f"{prefix}{docstring}")
362
363 def test_docstrings_negative_cases(self):
364 # Test some cases that involve strings in the children of the
365 # first node but aren't docstrings to make sure we don't have
366 # False positives.
367 docstrings_negative = (
368 'a = """false"""',
369 '"""false""" + """unless its optimized"""',
370 '1 + 1\n"""false"""',
371 'f"""no, top level but f-fstring"""'
372 )
373 for prefix in docstring_prefixes:
374 for negative in docstrings_negative:
375 # this cases should be result with single quote
376 # rather then triple quoted docstring
377 src = f"{prefix}{negative}"
378 self.check_ast_roundtrip(src)
379 self.check_src_dont_roundtrip(src)
Batuhan Taşkaya397b96f2020-03-01 23:12:17 +0300380
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000381class DirectoryTestCase(ASTTestCase):
382 """Test roundtrip behaviour on all files in Lib and Lib/test."""
383
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000384 lib_dir = pathlib.Path(__file__).parent / ".."
385 test_directories = (lib_dir, lib_dir / "test")
386 skip_files = {"test_fstring.py"}
Pablo Galindo23a226b2019-12-29 19:20:55 +0000387 run_always_files = {"test_grammar.py", "test_syntax.py", "test_compile.py",
388 "test_ast.py", "test_asdl_parser.py"}
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000389
Pablo Galindoac229112019-12-09 17:57:50 +0000390 _files_to_test = None
391
392 @classmethod
393 def files_to_test(cls):
394
395 if cls._files_to_test is not None:
396 return cls._files_to_test
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000397
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000398 items = [
399 item.resolve()
Pablo Galindoac229112019-12-09 17:57:50 +0000400 for directory in cls.test_directories
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000401 for item in directory.glob("*.py")
402 if not item.name.startswith("bad")
403 ]
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000404
Mark Dickinsonbe4fb692012-06-23 09:27:47 +0100405 # Test limited subset of files unless the 'cpu' resource is specified.
406 if not test.support.is_resource_enabled("cpu"):
Pablo Galindobe287c32019-12-29 20:18:36 +0000407
408 tests_to_run_always = {item for item in items if
409 item.name in cls.run_always_files}
410
Pablo Galindo23a226b2019-12-29 19:20:55 +0000411 items = set(random.sample(items, 10))
412
Pablo Galindobe287c32019-12-29 20:18:36 +0000413 # Make sure that at least tests that heavily use grammar features are
414 # always considered in order to reduce the chance of missing something.
415 items = list(items | tests_to_run_always)
Pablo Galindoac229112019-12-09 17:57:50 +0000416
417 # bpo-31174: Store the names sample to always test the same files.
418 # It prevents false alarms when hunting reference leaks.
419 cls._files_to_test = items
420
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000421 return items
Victor Stinner8e482be2017-10-24 03:33:36 -0700422
423 def test_files(self):
Pablo Galindoac229112019-12-09 17:57:50 +0000424 for item in self.files_to_test():
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000425 if test.support.verbose:
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000426 print(f"Testing {item.absolute()}")
Eric V. Smith06cf6012016-09-03 12:33:38 -0400427
Eric V. Smith451d0e32016-09-09 21:56:20 -0400428 # Some f-strings are not correctly round-tripped by
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000429 # Tools/parser/unparse.py. See issue 28002 for details.
430 # We need to skip files that contain such f-strings.
431 if item.name in self.skip_files:
Eric V. Smith06cf6012016-09-03 12:33:38 -0400432 if test.support.verbose:
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000433 print(f"Skipping {item.absolute()}: see issue 28002")
Eric V. Smith06cf6012016-09-03 12:33:38 -0400434 continue
435
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000436 with self.subTest(filename=item):
437 source = read_pyfile(item)
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300438 self.check_ast_roundtrip(source)
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000439
440
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000441if __name__ == "__main__":
Zachary Ware2b0a6102014-07-16 14:26:09 -0500442 unittest.main()