blob: f5441ed54eebfbaa4f190b9da3fecaf5552aae93 [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
Pablo Galindoc5fc1562020-04-22 23:29:27 +01009import sys
Mark Dickinsonae100052010-06-28 19:44:20 +000010
Zachary Ware2b0a6102014-07-16 14:26:09 -050011
Mark Dickinsond751c2e2010-06-29 14:08:23 +000012def read_pyfile(filename):
13 """Read and return the contents of a Python source file (as a
14 string), taking into account the file encoding."""
Hakan Çelik6a5bf152020-04-16 13:11:55 +030015 with tokenize.open(filename) as stream:
16 return stream.read()
Mark Dickinsond751c2e2010-06-29 14:08:23 +000017
Pablo Galindo27fc3b62019-11-24 23:02:40 +000018
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +000019for_else = """\
Mark Dickinsonae100052010-06-28 19:44:20 +000020def f():
21 for x in range(10):
22 break
23 else:
24 y = 2
25 z = 3
26"""
27
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +000028while_else = """\
Mark Dickinsonae100052010-06-28 19:44:20 +000029def g():
30 while True:
31 break
32 else:
33 y = 2
34 z = 3
35"""
36
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +000037relative_import = """\
38from . import fred
39from .. import barney
40from .australia import shrimp as prawns
41"""
42
43nonlocal_ex = """\
44def f():
45 x = 1
46 def g():
47 nonlocal x
48 x = 2
49 y = 7
50 def h():
51 nonlocal x, y
52"""
53
54# also acts as test for 'except ... as ...'
55raise_from = """\
56try:
57 1 / 0
58except ZeroDivisionError as e:
59 raise ArithmeticError from e
60"""
61
62class_decorator = """\
63@f1(arg)
64@f2
65class Foo: pass
66"""
67
Mark Dickinson8d6d7602010-06-30 08:32:11 +000068elif1 = """\
69if cond1:
70 suite1
71elif cond2:
72 suite2
73else:
74 suite3
75"""
76
77elif2 = """\
78if cond1:
79 suite1
80elif cond2:
81 suite2
82"""
83
Mark Dickinson81ad8cc2010-06-30 08:46:53 +000084try_except_finally = """\
85try:
86 suite1
87except ex1:
88 suite2
89except ex2:
90 suite3
91else:
92 suite4
93finally:
94 suite5
95"""
Mark Dickinson8d6d7602010-06-30 08:32:11 +000096
Mark Dickinsonfe8440a2012-05-06 17:35:19 +010097with_simple = """\
98with f():
99 suite1
100"""
101
102with_as = """\
103with f() as x:
104 suite1
105"""
106
107with_two_items = """\
108with f() as x, g() as y:
109 suite1
110"""
111
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300112docstring_prefixes = [
113 "",
114 "class foo():\n ",
115 "def foo():\n ",
116 "async def foo():\n ",
117]
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000118
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000119class ASTTestCase(unittest.TestCase):
120 def assertASTEqual(self, ast1, ast2):
121 self.assertEqual(ast.dump(ast1), ast.dump(ast2))
Mark Dickinsonae100052010-06-28 19:44:20 +0000122
Batuhan Taşkaya5b66ec12020-03-15 22:56:57 +0300123 def check_ast_roundtrip(self, code1, **kwargs):
124 ast1 = ast.parse(code1, **kwargs)
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000125 code2 = ast.unparse(ast1)
Batuhan Taşkaya5b66ec12020-03-15 22:56:57 +0300126 ast2 = ast.parse(code2, **kwargs)
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000127 self.assertASTEqual(ast1, ast2)
128
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000129 def check_invalid(self, node, raises=ValueError):
130 self.assertRaises(raises, ast.unparse, node)
131
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300132 def get_source(self, code1, code2=None, strip=True):
Batuhan Taşkaya397b96f2020-03-01 23:12:17 +0300133 code2 = code2 or code1
134 code1 = ast.unparse(ast.parse(code1))
135 if strip:
136 code1 = code1.strip()
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300137 return code1, code2
138
139 def check_src_roundtrip(self, code1, code2=None, strip=True):
140 code1, code2 = self.get_source(code1, code2, strip)
Batuhan Taşkaya397b96f2020-03-01 23:12:17 +0300141 self.assertEqual(code2, code1)
142
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300143 def check_src_dont_roundtrip(self, code1, code2=None, strip=True):
144 code1, code2 = self.get_source(code1, code2, strip)
145 self.assertNotEqual(code2, code1)
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000146
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000147class UnparseTestCase(ASTTestCase):
148 # Tests for specific bugs found in earlier versions of unparse
Mark Dickinsonae100052010-06-28 19:44:20 +0000149
Eric V. Smith608adf92015-09-20 15:09:15 -0400150 def test_fstrings(self):
151 # See issue 25180
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300152 self.check_ast_roundtrip(r"""f'{f"{0}"*3}'""")
153 self.check_ast_roundtrip(r"""f'{f"{y}"*3}'""")
Eric V. Smith608adf92015-09-20 15:09:15 -0400154
Chih-Hsuan Yenaaf47ca2019-05-27 01:08:20 +0800155 def test_strings(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300156 self.check_ast_roundtrip("u'foo'")
157 self.check_ast_roundtrip("r'foo'")
158 self.check_ast_roundtrip("b'foo'")
Chih-Hsuan Yenaaf47ca2019-05-27 01:08:20 +0800159
Mark Dickinsonae100052010-06-28 19:44:20 +0000160 def test_del_statement(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300161 self.check_ast_roundtrip("del x, y, z")
Mark Dickinsonae100052010-06-28 19:44:20 +0000162
163 def test_shifts(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300164 self.check_ast_roundtrip("45 << 2")
165 self.check_ast_roundtrip("13 >> 7")
Mark Dickinsonae100052010-06-28 19:44:20 +0000166
167 def test_for_else(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300168 self.check_ast_roundtrip(for_else)
Mark Dickinsonae100052010-06-28 19:44:20 +0000169
170 def test_while_else(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300171 self.check_ast_roundtrip(while_else)
Mark Dickinsonae100052010-06-28 19:44:20 +0000172
173 def test_unary_parens(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300174 self.check_ast_roundtrip("(-1)**7")
175 self.check_ast_roundtrip("(-1.)**8")
176 self.check_ast_roundtrip("(-1j)**6")
177 self.check_ast_roundtrip("not True or False")
178 self.check_ast_roundtrip("True or not False")
Mark Dickinsonae100052010-06-28 19:44:20 +0000179
Mark Dickinson3eb02902010-06-29 08:52:36 +0000180 def test_integer_parens(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300181 self.check_ast_roundtrip("3 .__abs__()")
Mark Dickinson3eb02902010-06-29 08:52:36 +0000182
Mark Dickinson8042e282010-06-29 10:01:48 +0000183 def test_huge_float(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300184 self.check_ast_roundtrip("1e1000")
185 self.check_ast_roundtrip("-1e1000")
186 self.check_ast_roundtrip("1e1000j")
187 self.check_ast_roundtrip("-1e1000j")
Mark Dickinsoncba8c102010-06-30 11:45:53 +0000188
189 def test_min_int(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300190 self.check_ast_roundtrip(str(-(2 ** 31)))
191 self.check_ast_roundtrip(str(-(2 ** 63)))
Mark Dickinsoncba8c102010-06-30 11:45:53 +0000192
193 def test_imaginary_literals(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300194 self.check_ast_roundtrip("7j")
195 self.check_ast_roundtrip("-7j")
196 self.check_ast_roundtrip("0j")
197 self.check_ast_roundtrip("-0j")
Mark Dickinson8042e282010-06-29 10:01:48 +0000198
199 def test_lambda_parentheses(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300200 self.check_ast_roundtrip("(lambda: int)()")
Mark Dickinson8042e282010-06-29 10:01:48 +0000201
Mark Dickinsonf5451e52010-06-28 20:09:18 +0000202 def test_chained_comparisons(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300203 self.check_ast_roundtrip("1 < 4 <= 5")
204 self.check_ast_roundtrip("a is b is c is not d")
Mark Dickinsonf5451e52010-06-28 20:09:18 +0000205
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000206 def test_function_arguments(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300207 self.check_ast_roundtrip("def f(): pass")
208 self.check_ast_roundtrip("def f(a): pass")
209 self.check_ast_roundtrip("def f(b = 2): pass")
210 self.check_ast_roundtrip("def f(a, b): pass")
211 self.check_ast_roundtrip("def f(a, b = 2): pass")
212 self.check_ast_roundtrip("def f(a = 5, b = 2): pass")
213 self.check_ast_roundtrip("def f(*, a = 1, b = 2): pass")
214 self.check_ast_roundtrip("def f(*, a = 1, b): pass")
215 self.check_ast_roundtrip("def f(*, a, b = 2): pass")
216 self.check_ast_roundtrip("def f(a, b = None, *, c, **kwds): pass")
217 self.check_ast_roundtrip("def f(a=2, *args, c=5, d, **kwds): pass")
218 self.check_ast_roundtrip("def f(*args, **kwargs): pass")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000219
220 def test_relative_import(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300221 self.check_ast_roundtrip(relative_import)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000222
223 def test_nonlocal(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300224 self.check_ast_roundtrip(nonlocal_ex)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000225
226 def test_raise_from(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300227 self.check_ast_roundtrip(raise_from)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000228
229 def test_bytes(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300230 self.check_ast_roundtrip("b'123'")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000231
232 def test_annotations(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300233 self.check_ast_roundtrip("def f(a : int): pass")
234 self.check_ast_roundtrip("def f(a: int = 5): pass")
235 self.check_ast_roundtrip("def f(*args: [int]): pass")
236 self.check_ast_roundtrip("def f(**kwargs: dict): pass")
237 self.check_ast_roundtrip("def f() -> None: pass")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000238
239 def test_set_literal(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300240 self.check_ast_roundtrip("{'a', 'b', 'c'}")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000241
242 def test_set_comprehension(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300243 self.check_ast_roundtrip("{x for x in range(5)}")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000244
245 def test_dict_comprehension(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300246 self.check_ast_roundtrip("{x: x*x for x in range(10)}")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000247
248 def test_class_decorators(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300249 self.check_ast_roundtrip(class_decorator)
Mark Dickinsonae100052010-06-28 19:44:20 +0000250
Mark Dickinson578aa562010-06-29 18:38:59 +0000251 def test_class_definition(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300252 self.check_ast_roundtrip("class A(metaclass=type, *[], **{}): pass")
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000253
Mark Dickinson8d6d7602010-06-30 08:32:11 +0000254 def test_elifs(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300255 self.check_ast_roundtrip(elif1)
256 self.check_ast_roundtrip(elif2)
Mark Dickinson8d6d7602010-06-30 08:32:11 +0000257
Mark Dickinson81ad8cc2010-06-30 08:46:53 +0000258 def test_try_except_finally(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300259 self.check_ast_roundtrip(try_except_finally)
Mark Dickinson81ad8cc2010-06-30 08:46:53 +0000260
Mark Dickinson1b2e9442012-05-06 17:27:39 +0100261 def test_starred_assignment(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300262 self.check_ast_roundtrip("a, *b, c = seq")
263 self.check_ast_roundtrip("a, (*b, c) = seq")
264 self.check_ast_roundtrip("a, *b[0], c = seq")
265 self.check_ast_roundtrip("a, *(b, c) = seq")
Mark Dickinson1b2e9442012-05-06 17:27:39 +0100266
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100267 def test_with_simple(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300268 self.check_ast_roundtrip(with_simple)
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100269
270 def test_with_as(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300271 self.check_ast_roundtrip(with_as)
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100272
273 def test_with_two_items(self):
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300274 self.check_ast_roundtrip(with_two_items)
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100275
Berker Peksagd66dd5c2016-03-06 16:50:15 +0200276 def test_dict_unpacking_in_dict(self):
277 # See issue 26489
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300278 self.check_ast_roundtrip(r"""{**{'y': 2}, 'x': 1}""")
279 self.check_ast_roundtrip(r"""{**{'y': 2}, **{'x': 1}}""")
Berker Peksagd66dd5c2016-03-06 16:50:15 +0200280
Batuhan Taşkayae7cab7f2020-03-09 23:27:03 +0300281 def test_ext_slices(self):
282 self.check_ast_roundtrip("a[i]")
283 self.check_ast_roundtrip("a[i,]")
284 self.check_ast_roundtrip("a[i, j]")
285 self.check_ast_roundtrip("a[()]")
286 self.check_ast_roundtrip("a[i:j]")
287 self.check_ast_roundtrip("a[:j]")
288 self.check_ast_roundtrip("a[i:]")
289 self.check_ast_roundtrip("a[i:j:k]")
290 self.check_ast_roundtrip("a[:j:k]")
291 self.check_ast_roundtrip("a[i::k]")
292 self.check_ast_roundtrip("a[i:j,]")
293 self.check_ast_roundtrip("a[i:j, k]")
294
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000295 def test_invalid_raise(self):
296 self.check_invalid(ast.Raise(exc=None, cause=ast.Name(id="X")))
297
298 def test_invalid_fstring_constant(self):
299 self.check_invalid(ast.JoinedStr(values=[ast.Constant(value=100)]))
300
301 def test_invalid_fstring_conversion(self):
302 self.check_invalid(
303 ast.FormattedValue(
304 value=ast.Constant(value="a", kind=None),
305 conversion=ord("Y"), # random character
306 format_spec=None,
307 )
308 )
309
310 def test_invalid_set(self):
311 self.check_invalid(ast.Set(elts=[]))
312
Batuhan Taşkaya7b35bef2020-01-02 21:20:04 +0300313 def test_invalid_yield_from(self):
314 self.check_invalid(ast.YieldFrom(value=None))
Mark Dickinson1b2e9442012-05-06 17:27:39 +0100315
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300316 def test_docstrings(self):
317 docstrings = (
318 'this ends with double quote"',
319 'this includes a """triple quote"""'
320 )
321 for docstring in docstrings:
322 # check as Module docstrings for easy testing
323 self.check_ast_roundtrip(f"'{docstring}'")
324
Batuhan Taşkayae7cab7f2020-03-09 23:27:03 +0300325 def test_constant_tuples(self):
326 self.check_src_roundtrip(ast.Constant(value=(1,), kind=None), "(1,)")
327 self.check_src_roundtrip(
328 ast.Constant(value=(1, 2, 3), kind=None), "(1, 2, 3)"
329 )
330
Pablo Galindoc5fc1562020-04-22 23:29:27 +0100331 @unittest.skipIf(sys.flags.use_peg, "Pegen does not support type annotation yet")
Batuhan Taşkaya5b66ec12020-03-15 22:56:57 +0300332 def test_function_type(self):
333 for function_type in (
334 "() -> int",
335 "(int, int) -> int",
336 "(Callable[complex], More[Complex(call.to_typevar())]) -> None"
337 ):
338 self.check_ast_roundtrip(function_type, mode="func_type")
339
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300340
Batuhan Taşkaya397b96f2020-03-01 23:12:17 +0300341class CosmeticTestCase(ASTTestCase):
342 """Test if there are cosmetic issues caused by unnecesary additions"""
343
344 def test_simple_expressions_parens(self):
345 self.check_src_roundtrip("(a := b)")
346 self.check_src_roundtrip("await x")
347 self.check_src_roundtrip("x if x else y")
348 self.check_src_roundtrip("lambda x: x")
349 self.check_src_roundtrip("1 + 1")
350 self.check_src_roundtrip("1 + 2 / 3")
351 self.check_src_roundtrip("(1 + 2) / 3")
352 self.check_src_roundtrip("(1 + 2) * 3 + 4 * (5 + 2)")
353 self.check_src_roundtrip("(1 + 2) * 3 + 4 * (5 + 2) ** 2")
354 self.check_src_roundtrip("~ x")
355 self.check_src_roundtrip("x and y")
356 self.check_src_roundtrip("x and y and z")
357 self.check_src_roundtrip("x and (y and x)")
358 self.check_src_roundtrip("(x and y) and z")
359 self.check_src_roundtrip("(x ** y) ** z ** q")
360 self.check_src_roundtrip("x >> y")
361 self.check_src_roundtrip("x << y")
362 self.check_src_roundtrip("x >> y and x >> z")
363 self.check_src_roundtrip("x + y - z * q ^ t ** k")
364 self.check_src_roundtrip("P * V if P and V else n * R * T")
365 self.check_src_roundtrip("lambda P, V, n: P * V == n * R * T")
366 self.check_src_roundtrip("flag & (other | foo)")
367 self.check_src_roundtrip("not x == y")
368 self.check_src_roundtrip("x == (not y)")
369 self.check_src_roundtrip("yield x")
370 self.check_src_roundtrip("yield from x")
371 self.check_src_roundtrip("call((yield x))")
372 self.check_src_roundtrip("return x + (yield x)")
373
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300374 def test_docstrings(self):
375 docstrings = (
376 '"""simple doc string"""',
377 '''"""A more complex one
378 with some newlines"""''',
379 '''"""Foo bar baz
380
381 empty newline"""''',
382 '"""With some \t"""',
383 '"""Foo "bar" baz """',
384 )
385
386 for prefix in docstring_prefixes:
387 for docstring in docstrings:
388 self.check_src_roundtrip(f"{prefix}{docstring}")
389
390 def test_docstrings_negative_cases(self):
391 # Test some cases that involve strings in the children of the
392 # first node but aren't docstrings to make sure we don't have
393 # False positives.
394 docstrings_negative = (
395 'a = """false"""',
396 '"""false""" + """unless its optimized"""',
397 '1 + 1\n"""false"""',
398 'f"""no, top level but f-fstring"""'
399 )
400 for prefix in docstring_prefixes:
401 for negative in docstrings_negative:
402 # this cases should be result with single quote
403 # rather then triple quoted docstring
404 src = f"{prefix}{negative}"
405 self.check_ast_roundtrip(src)
406 self.check_src_dont_roundtrip(src)
Batuhan Taşkaya397b96f2020-03-01 23:12:17 +0300407
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000408class DirectoryTestCase(ASTTestCase):
409 """Test roundtrip behaviour on all files in Lib and Lib/test."""
410
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000411 lib_dir = pathlib.Path(__file__).parent / ".."
412 test_directories = (lib_dir, lib_dir / "test")
413 skip_files = {"test_fstring.py"}
Pablo Galindo23a226b2019-12-29 19:20:55 +0000414 run_always_files = {"test_grammar.py", "test_syntax.py", "test_compile.py",
415 "test_ast.py", "test_asdl_parser.py"}
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000416
Pablo Galindoac229112019-12-09 17:57:50 +0000417 _files_to_test = None
418
419 @classmethod
420 def files_to_test(cls):
421
422 if cls._files_to_test is not None:
423 return cls._files_to_test
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000424
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000425 items = [
426 item.resolve()
Pablo Galindoac229112019-12-09 17:57:50 +0000427 for directory in cls.test_directories
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000428 for item in directory.glob("*.py")
429 if not item.name.startswith("bad")
430 ]
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000431
Mark Dickinsonbe4fb692012-06-23 09:27:47 +0100432 # Test limited subset of files unless the 'cpu' resource is specified.
433 if not test.support.is_resource_enabled("cpu"):
Pablo Galindobe287c32019-12-29 20:18:36 +0000434
435 tests_to_run_always = {item for item in items if
436 item.name in cls.run_always_files}
437
Pablo Galindo23a226b2019-12-29 19:20:55 +0000438 items = set(random.sample(items, 10))
439
Pablo Galindobe287c32019-12-29 20:18:36 +0000440 # Make sure that at least tests that heavily use grammar features are
441 # always considered in order to reduce the chance of missing something.
442 items = list(items | tests_to_run_always)
Pablo Galindoac229112019-12-09 17:57:50 +0000443
444 # bpo-31174: Store the names sample to always test the same files.
445 # It prevents false alarms when hunting reference leaks.
446 cls._files_to_test = items
447
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000448 return items
Victor Stinner8e482be2017-10-24 03:33:36 -0700449
450 def test_files(self):
Pablo Galindoac229112019-12-09 17:57:50 +0000451 for item in self.files_to_test():
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000452 if test.support.verbose:
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000453 print(f"Testing {item.absolute()}")
Eric V. Smith06cf6012016-09-03 12:33:38 -0400454
Eric V. Smith451d0e32016-09-09 21:56:20 -0400455 # Some f-strings are not correctly round-tripped by
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000456 # Tools/parser/unparse.py. See issue 28002 for details.
457 # We need to skip files that contain such f-strings.
458 if item.name in self.skip_files:
Eric V. Smith06cf6012016-09-03 12:33:38 -0400459 if test.support.verbose:
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000460 print(f"Skipping {item.absolute()}: see issue 28002")
Eric V. Smith06cf6012016-09-03 12:33:38 -0400461 continue
462
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000463 with self.subTest(filename=item):
464 source = read_pyfile(item)
Batuhan Taşkaya89aa4692020-03-02 21:59:01 +0300465 self.check_ast_roundtrip(source)
Mark Dickinsond751c2e2010-06-29 14:08:23 +0000466
467
Pablo Galindo27fc3b62019-11-24 23:02:40 +0000468if __name__ == "__main__":
Zachary Ware2b0a6102014-07-16 14:26:09 -0500469 unittest.main()