blob: 410df7dbb75818d4cd7e8750f25ccc595d2a6ad5 [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."""
Hakan Çelik6a5bf152020-04-16 13:11:55 +030014 with tokenize.open(filename) as stream:
15 return stream.read()
Mark Dickinsond751c2e2010-06-29 14:08:23 +000016
Pablo Galindo27fc3b62019-11-24 23:02:40 +000017
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +000018for_else = """\
Mark Dickinsonae100052010-06-28 19:44:20 +000019def f():
20 for x in range(10):
21 break
22 else:
23 y = 2
24 z = 3
25"""
26
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +000027while_else = """\
Mark Dickinsonae100052010-06-28 19:44:20 +000028def g():
29 while True:
30 break
31 else:
32 y = 2
33 z = 3
34"""
35
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +000036relative_import = """\
37from . import fred
38from .. import barney
39from .australia import shrimp as prawns
40"""
41
42nonlocal_ex = """\
43def f():
44 x = 1
45 def g():
46 nonlocal x
47 x = 2
48 y = 7
49 def h():
50 nonlocal x, y
51"""
52
53# also acts as test for 'except ... as ...'
54raise_from = """\
55try:
56 1 / 0
57except ZeroDivisionError as e:
58 raise ArithmeticError from e
59"""
60
61class_decorator = """\
62@f1(arg)
63@f2
64class Foo: pass
65"""
66
Mark Dickinson8d6d7602010-06-30 08:32:11 +000067elif1 = """\
68if cond1:
69 suite1
70elif cond2:
71 suite2
72else:
73 suite3
74"""
75
76elif2 = """\
77if cond1:
78 suite1
79elif cond2:
80 suite2
81"""
82
Mark Dickinson81ad8cc2010-06-30 08:46:53 +000083try_except_finally = """\
84try:
85 suite1
86except ex1:
87 suite2
88except ex2:
89 suite3
90else:
91 suite4
92finally:
93 suite5
94"""
Mark Dickinson8d6d7602010-06-30 08:32:11 +000095
Mark Dickinsonfe8440a2012-05-06 17:35:19 +010096with_simple = """\
97with f():
98 suite1
99"""
100
101with_as = """\
102with f() as x:
103 suite1
104"""
105
106with_two_items = """\
107with f() as x, g() as y:
108 suite1
109"""
110
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300111docstring_prefixes = [
112 "",
Batuhan Taskaya25160cd2020-05-17 00:53:25 +0300113 "class foo:\n ",
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300114 "def foo():\n ",
115 "async def foo():\n ",
116]
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000117
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000118class ASTTestCase(unittest.TestCase):
119 def assertASTEqual(self, ast1, ast2):
120 self.assertEqual(ast.dump(ast1), ast.dump(ast2))
Mark Dickinsonae100052010-06-28 19:44:20 +0000121
Batuhan Taşkaya5b66ec12020-03-15 22:56:57 +0300122 def check_ast_roundtrip(self, code1, **kwargs):
123 ast1 = ast.parse(code1, **kwargs)
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000124 code2 = ast.unparse(ast1)
Batuhan Taşkaya5b66ec12020-03-15 22:56:57 +0300125 ast2 = ast.parse(code2, **kwargs)
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000126 self.assertASTEqual(ast1, ast2)
127
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000128 def check_invalid(self, node, raises=ValueError):
129 self.assertRaises(raises, ast.unparse, node)
130
Batuhan Taskaya493bf1c2020-05-03 20:11:51 +0300131 def get_source(self, code1, code2=None):
Batuhan Taşkaya397b96f2020-03-01 23:12:17 +0300132 code2 = code2 or code1
133 code1 = ast.unparse(ast.parse(code1))
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300134 return code1, code2
135
Batuhan Taskaya493bf1c2020-05-03 20:11:51 +0300136 def check_src_roundtrip(self, code1, code2=None):
137 code1, code2 = self.get_source(code1, code2)
Batuhan Taşkaya397b96f2020-03-01 23:12:17 +0300138 self.assertEqual(code2, code1)
139
Batuhan Taskaya493bf1c2020-05-03 20:11:51 +0300140 def check_src_dont_roundtrip(self, code1, code2=None):
141 code1, code2 = self.get_source(code1, code2)
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300142 self.assertNotEqual(code2, code1)
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000143
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000144class UnparseTestCase(ASTTestCase):
145 # Tests for specific bugs found in earlier versions of unparse
Mark Dickinsonae100052010-06-28 19:44:20 +0000146
Eric V. Smith608adf92015-09-20 15:09:15 -0400147 def test_fstrings(self):
148 # See issue 25180
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300149 self.check_ast_roundtrip(r"""f'{f"{0}"*3}'""")
150 self.check_ast_roundtrip(r"""f'{f"{y}"*3}'""")
Eric V. Smith608adf92015-09-20 15:09:15 -0400151
Chih-Hsuan Yenaaf47ca2019-05-27 01:08:20 +0800152 def test_strings(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300153 self.check_ast_roundtrip("u'foo'")
154 self.check_ast_roundtrip("r'foo'")
155 self.check_ast_roundtrip("b'foo'")
Chih-Hsuan Yenaaf47ca2019-05-27 01:08:20 +0800156
Mark Dickinsonae100052010-06-28 19:44:20 +0000157 def test_del_statement(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300158 self.check_ast_roundtrip("del x, y, z")
Mark Dickinsonae100052010-06-28 19:44:20 +0000159
160 def test_shifts(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300161 self.check_ast_roundtrip("45 << 2")
162 self.check_ast_roundtrip("13 >> 7")
Mark Dickinsonae100052010-06-28 19:44:20 +0000163
164 def test_for_else(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300165 self.check_ast_roundtrip(for_else)
Mark Dickinsonae100052010-06-28 19:44:20 +0000166
167 def test_while_else(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300168 self.check_ast_roundtrip(while_else)
Mark Dickinsonae100052010-06-28 19:44:20 +0000169
170 def test_unary_parens(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300171 self.check_ast_roundtrip("(-1)**7")
172 self.check_ast_roundtrip("(-1.)**8")
173 self.check_ast_roundtrip("(-1j)**6")
174 self.check_ast_roundtrip("not True or False")
175 self.check_ast_roundtrip("True or not False")
Mark Dickinsonae100052010-06-28 19:44:20 +0000176
Mark Dickinson3eb02902010-06-29 08:52:36 +0000177 def test_integer_parens(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300178 self.check_ast_roundtrip("3 .__abs__()")
Mark Dickinson3eb02902010-06-29 08:52:36 +0000179
Mark Dickinson8042e282010-06-29 10:01:48 +0000180 def test_huge_float(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300181 self.check_ast_roundtrip("1e1000")
182 self.check_ast_roundtrip("-1e1000")
183 self.check_ast_roundtrip("1e1000j")
184 self.check_ast_roundtrip("-1e1000j")
Mark Dickinsoncba8c102010-06-30 11:45:53 +0000185
186 def test_min_int(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300187 self.check_ast_roundtrip(str(-(2 ** 31)))
188 self.check_ast_roundtrip(str(-(2 ** 63)))
Mark Dickinsoncba8c102010-06-30 11:45:53 +0000189
190 def test_imaginary_literals(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300191 self.check_ast_roundtrip("7j")
192 self.check_ast_roundtrip("-7j")
193 self.check_ast_roundtrip("0j")
194 self.check_ast_roundtrip("-0j")
Mark Dickinson8042e282010-06-29 10:01:48 +0000195
196 def test_lambda_parentheses(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300197 self.check_ast_roundtrip("(lambda: int)()")
Mark Dickinson8042e282010-06-29 10:01:48 +0000198
Mark Dickinsonf5451e52010-06-28 20:09:18 +0000199 def test_chained_comparisons(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300200 self.check_ast_roundtrip("1 < 4 <= 5")
201 self.check_ast_roundtrip("a is b is c is not d")
Mark Dickinsonf5451e52010-06-28 20:09:18 +0000202
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000203 def test_function_arguments(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300204 self.check_ast_roundtrip("def f(): pass")
205 self.check_ast_roundtrip("def f(a): pass")
206 self.check_ast_roundtrip("def f(b = 2): pass")
207 self.check_ast_roundtrip("def f(a, b): pass")
208 self.check_ast_roundtrip("def f(a, b = 2): pass")
209 self.check_ast_roundtrip("def f(a = 5, b = 2): pass")
210 self.check_ast_roundtrip("def f(*, a = 1, b = 2): pass")
211 self.check_ast_roundtrip("def f(*, a = 1, b): pass")
212 self.check_ast_roundtrip("def f(*, a, b = 2): pass")
213 self.check_ast_roundtrip("def f(a, b = None, *, c, **kwds): pass")
214 self.check_ast_roundtrip("def f(a=2, *args, c=5, d, **kwds): pass")
215 self.check_ast_roundtrip("def f(*args, **kwargs): pass")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000216
217 def test_relative_import(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300218 self.check_ast_roundtrip(relative_import)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000219
220 def test_nonlocal(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300221 self.check_ast_roundtrip(nonlocal_ex)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000222
223 def test_raise_from(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300224 self.check_ast_roundtrip(raise_from)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000225
226 def test_bytes(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300227 self.check_ast_roundtrip("b'123'")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000228
229 def test_annotations(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300230 self.check_ast_roundtrip("def f(a : int): pass")
231 self.check_ast_roundtrip("def f(a: int = 5): pass")
232 self.check_ast_roundtrip("def f(*args: [int]): pass")
233 self.check_ast_roundtrip("def f(**kwargs: dict): pass")
234 self.check_ast_roundtrip("def f() -> None: pass")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000235
236 def test_set_literal(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300237 self.check_ast_roundtrip("{'a', 'b', 'c'}")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000238
239 def test_set_comprehension(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300240 self.check_ast_roundtrip("{x for x in range(5)}")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000241
242 def test_dict_comprehension(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300243 self.check_ast_roundtrip("{x: x*x for x in range(10)}")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000244
245 def test_class_decorators(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300246 self.check_ast_roundtrip(class_decorator)
Mark Dickinsonae100052010-06-28 19:44:20 +0000247
Mark Dickinson578aa562010-06-29 18:38:59 +0000248 def test_class_definition(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300249 self.check_ast_roundtrip("class A(metaclass=type, *[], **{}): pass")
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000250
Mark Dickinson8d6d7602010-06-30 08:32:11 +0000251 def test_elifs(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300252 self.check_ast_roundtrip(elif1)
253 self.check_ast_roundtrip(elif2)
Mark Dickinson8d6d7602010-06-30 08:32:11 +0000254
Mark Dickinson81ad8cc2010-06-30 08:46:53 +0000255 def test_try_except_finally(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300256 self.check_ast_roundtrip(try_except_finally)
Mark Dickinson81ad8cc2010-06-30 08:46:53 +0000257
Mark Dickinson1b2e9442012-05-06 17:27:39 +0100258 def test_starred_assignment(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300259 self.check_ast_roundtrip("a, *b, c = seq")
260 self.check_ast_roundtrip("a, (*b, c) = seq")
261 self.check_ast_roundtrip("a, *b[0], c = seq")
262 self.check_ast_roundtrip("a, *(b, c) = seq")
Mark Dickinson1b2e9442012-05-06 17:27:39 +0100263
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100264 def test_with_simple(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300265 self.check_ast_roundtrip(with_simple)
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100266
267 def test_with_as(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300268 self.check_ast_roundtrip(with_as)
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100269
270 def test_with_two_items(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300271 self.check_ast_roundtrip(with_two_items)
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100272
Berker Peksagd66dd5c2016-03-06 16:50:15 +0200273 def test_dict_unpacking_in_dict(self):
274 # See issue 26489
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300275 self.check_ast_roundtrip(r"""{**{'y': 2}, 'x': 1}""")
276 self.check_ast_roundtrip(r"""{**{'y': 2}, **{'x': 1}}""")
Berker Peksagd66dd5c2016-03-06 16:50:15 +0200277
Batuhan Taşkayae7cab7f2020-03-09 23:27:03 +0300278 def test_ext_slices(self):
279 self.check_ast_roundtrip("a[i]")
280 self.check_ast_roundtrip("a[i,]")
281 self.check_ast_roundtrip("a[i, j]")
282 self.check_ast_roundtrip("a[()]")
283 self.check_ast_roundtrip("a[i:j]")
284 self.check_ast_roundtrip("a[:j]")
285 self.check_ast_roundtrip("a[i:]")
286 self.check_ast_roundtrip("a[i:j:k]")
287 self.check_ast_roundtrip("a[:j:k]")
288 self.check_ast_roundtrip("a[i::k]")
289 self.check_ast_roundtrip("a[i:j,]")
290 self.check_ast_roundtrip("a[i:j, k]")
291
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000292 def test_invalid_raise(self):
293 self.check_invalid(ast.Raise(exc=None, cause=ast.Name(id="X")))
294
295 def test_invalid_fstring_constant(self):
296 self.check_invalid(ast.JoinedStr(values=[ast.Constant(value=100)]))
297
298 def test_invalid_fstring_conversion(self):
299 self.check_invalid(
300 ast.FormattedValue(
301 value=ast.Constant(value="a", kind=None),
302 conversion=ord("Y"), # random character
303 format_spec=None,
304 )
305 )
306
307 def test_invalid_set(self):
308 self.check_invalid(ast.Set(elts=[]))
309
Batuhan Taşkaya7b35bef2020-01-02 21:20:04 +0300310 def test_invalid_yield_from(self):
311 self.check_invalid(ast.YieldFrom(value=None))
Mark Dickinson1b2e9442012-05-06 17:27:39 +0100312
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300313 def test_docstrings(self):
314 docstrings = (
315 'this ends with double quote"',
316 'this includes a """triple quote"""'
317 )
318 for docstring in docstrings:
319 # check as Module docstrings for easy testing
320 self.check_ast_roundtrip(f"'{docstring}'")
321
Batuhan Taşkayae7cab7f2020-03-09 23:27:03 +0300322 def test_constant_tuples(self):
323 self.check_src_roundtrip(ast.Constant(value=(1,), kind=None), "(1,)")
324 self.check_src_roundtrip(
325 ast.Constant(value=(1, 2, 3), kind=None), "(1, 2, 3)"
326 )
327
Batuhan Taşkaya5b66ec12020-03-15 22:56:57 +0300328 def test_function_type(self):
329 for function_type in (
330 "() -> int",
331 "(int, int) -> int",
332 "(Callable[complex], More[Complex(call.to_typevar())]) -> None"
333 ):
334 self.check_ast_roundtrip(function_type, mode="func_type")
335
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300336
Batuhan Taşkaya397b96f2020-03-01 23:12:17 +0300337class CosmeticTestCase(ASTTestCase):
338 """Test if there are cosmetic issues caused by unnecesary additions"""
339
340 def test_simple_expressions_parens(self):
341 self.check_src_roundtrip("(a := b)")
342 self.check_src_roundtrip("await x")
343 self.check_src_roundtrip("x if x else y")
344 self.check_src_roundtrip("lambda x: x")
345 self.check_src_roundtrip("1 + 1")
346 self.check_src_roundtrip("1 + 2 / 3")
347 self.check_src_roundtrip("(1 + 2) / 3")
348 self.check_src_roundtrip("(1 + 2) * 3 + 4 * (5 + 2)")
349 self.check_src_roundtrip("(1 + 2) * 3 + 4 * (5 + 2) ** 2")
Batuhan Taskayace4a7532020-05-17 00:46:11 +0300350 self.check_src_roundtrip("~x")
Batuhan Taşkaya397b96f2020-03-01 23:12:17 +0300351 self.check_src_roundtrip("x and y")
352 self.check_src_roundtrip("x and y and z")
353 self.check_src_roundtrip("x and (y and x)")
354 self.check_src_roundtrip("(x and y) and z")
355 self.check_src_roundtrip("(x ** y) ** z ** q")
356 self.check_src_roundtrip("x >> y")
357 self.check_src_roundtrip("x << y")
358 self.check_src_roundtrip("x >> y and x >> z")
359 self.check_src_roundtrip("x + y - z * q ^ t ** k")
360 self.check_src_roundtrip("P * V if P and V else n * R * T")
361 self.check_src_roundtrip("lambda P, V, n: P * V == n * R * T")
362 self.check_src_roundtrip("flag & (other | foo)")
363 self.check_src_roundtrip("not x == y")
364 self.check_src_roundtrip("x == (not y)")
365 self.check_src_roundtrip("yield x")
366 self.check_src_roundtrip("yield from x")
367 self.check_src_roundtrip("call((yield x))")
368 self.check_src_roundtrip("return x + (yield x)")
369
Batuhan Taskaya25160cd2020-05-17 00:53:25 +0300370
371 def test_class_bases_and_keywords(self):
372 self.check_src_roundtrip("class X:\n pass")
373 self.check_src_roundtrip("class X(A):\n pass")
374 self.check_src_roundtrip("class X(A, B, C, D):\n pass")
375 self.check_src_roundtrip("class X(x=y):\n pass")
376 self.check_src_roundtrip("class X(metaclass=z):\n pass")
377 self.check_src_roundtrip("class X(x=y, z=d):\n pass")
378 self.check_src_roundtrip("class X(A, x=y):\n pass")
379 self.check_src_roundtrip("class X(A, **kw):\n pass")
380 self.check_src_roundtrip("class X(*args):\n pass")
381 self.check_src_roundtrip("class X(*args, **kwargs):\n pass")
382
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300383 def test_docstrings(self):
384 docstrings = (
385 '"""simple doc string"""',
386 '''"""A more complex one
387 with some newlines"""''',
388 '''"""Foo bar baz
389
390 empty newline"""''',
391 '"""With some \t"""',
392 '"""Foo "bar" baz """',
393 )
394
395 for prefix in docstring_prefixes:
396 for docstring in docstrings:
397 self.check_src_roundtrip(f"{prefix}{docstring}")
398
399 def test_docstrings_negative_cases(self):
400 # Test some cases that involve strings in the children of the
401 # first node but aren't docstrings to make sure we don't have
402 # False positives.
403 docstrings_negative = (
404 'a = """false"""',
405 '"""false""" + """unless its optimized"""',
406 '1 + 1\n"""false"""',
407 'f"""no, top level but f-fstring"""'
408 )
409 for prefix in docstring_prefixes:
410 for negative in docstrings_negative:
411 # this cases should be result with single quote
412 # rather then triple quoted docstring
413 src = f"{prefix}{negative}"
414 self.check_ast_roundtrip(src)
415 self.check_src_dont_roundtrip(src)
Batuhan Taşkaya397b96f2020-03-01 23:12:17 +0300416
Batuhan Taskayace4a7532020-05-17 00:46:11 +0300417 def test_unary_op_factor(self):
418 for prefix in ("+", "-", "~"):
419 self.check_src_roundtrip(f"{prefix}1")
420 for prefix in ("not",):
421 self.check_src_roundtrip(f"{prefix} 1")
422
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000423class DirectoryTestCase(ASTTestCase):
424 """Test roundtrip behaviour on all files in Lib and Lib/test."""
425
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000426 lib_dir = pathlib.Path(__file__).parent / ".."
427 test_directories = (lib_dir, lib_dir / "test")
428 skip_files = {"test_fstring.py"}
Pablo Galindo23a226b2019-12-29 19:20:55 +0000429 run_always_files = {"test_grammar.py", "test_syntax.py", "test_compile.py",
430 "test_ast.py", "test_asdl_parser.py"}
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000431
Pablo Galindoac229112019-12-09 17:57:50 +0000432 _files_to_test = None
433
434 @classmethod
435 def files_to_test(cls):
436
437 if cls._files_to_test is not None:
438 return cls._files_to_test
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000439
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000440 items = [
441 item.resolve()
Pablo Galindoac229112019-12-09 17:57:50 +0000442 for directory in cls.test_directories
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000443 for item in directory.glob("*.py")
444 if not item.name.startswith("bad")
445 ]
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000446
Mark Dickinsonbe4fb692012-06-23 09:27:47 +0100447 # Test limited subset of files unless the 'cpu' resource is specified.
448 if not test.support.is_resource_enabled("cpu"):
Pablo Galindobe287c32019-12-29 20:18:36 +0000449
450 tests_to_run_always = {item for item in items if
451 item.name in cls.run_always_files}
452
Pablo Galindo23a226b2019-12-29 19:20:55 +0000453 items = set(random.sample(items, 10))
454
Pablo Galindobe287c32019-12-29 20:18:36 +0000455 # Make sure that at least tests that heavily use grammar features are
456 # always considered in order to reduce the chance of missing something.
457 items = list(items | tests_to_run_always)
Pablo Galindoac229112019-12-09 17:57:50 +0000458
459 # bpo-31174: Store the names sample to always test the same files.
460 # It prevents false alarms when hunting reference leaks.
461 cls._files_to_test = items
462
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000463 return items
Victor Stinner8e482be2017-10-24 03:33:36 -0700464
465 def test_files(self):
Pablo Galindoac229112019-12-09 17:57:50 +0000466 for item in self.files_to_test():
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000467 if test.support.verbose:
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000468 print(f"Testing {item.absolute()}")
Eric V. Smith06cf6012016-09-03 12:33:38 -0400469
Eric V. Smith451d0e32016-09-09 21:56:20 -0400470 # Some f-strings are not correctly round-tripped by
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000471 # Tools/parser/unparse.py. See issue 28002 for details.
472 # We need to skip files that contain such f-strings.
473 if item.name in self.skip_files:
Eric V. Smith06cf6012016-09-03 12:33:38 -0400474 if test.support.verbose:
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000475 print(f"Skipping {item.absolute()}: see issue 28002")
Eric V. Smith06cf6012016-09-03 12:33:38 -0400476 continue
477
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000478 with self.subTest(filename=item):
479 source = read_pyfile(item)
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300480 self.check_ast_roundtrip(source)
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000481
482
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000483if __name__ == "__main__":
Zachary Ware2b0a6102014-07-16 14:26:09 -0500484 unittest.main()