| 
									
										
										
										
											2023-06-16 09:31:23 -07:00
										 |  |  | """Tests for ast.unparse.""" | 
					
						
							| 
									
										
										
										
											2014-07-16 14:26:09 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-28 19:44:20 +00:00
										 |  |  | import unittest | 
					
						
							|  |  |  | import test.support | 
					
						
							| 
									
										
										
										
											2019-11-24 23:02:40 +00:00
										 |  |  | import pathlib | 
					
						
							| 
									
										
										
										
											2012-06-23 09:27:47 +01:00
										 |  |  | import random | 
					
						
							| 
									
										
										
										
											2010-06-29 14:08:23 +00:00
										 |  |  | import tokenize | 
					
						
							| 
									
										
										
										
											2012-06-23 09:27:47 +01:00
										 |  |  | import ast | 
					
						
							| 
									
										
										
										
											2023-01-22 00:44:41 +03:00
										 |  |  | from test.support.ast_helper import ASTTestMixin | 
					
						
							| 
									
										
										
										
											2010-06-28 19:44:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-16 14:26:09 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-29 14:08:23 +00:00
										 |  |  | def read_pyfile(filename): | 
					
						
							|  |  |  |     """Read and return the contents of a Python source file (as a
 | 
					
						
							|  |  |  |     string), taking into account the file encoding."""
 | 
					
						
							| 
									
										
										
										
											2020-04-16 13:11:55 +03:00
										 |  |  |     with tokenize.open(filename) as stream: | 
					
						
							|  |  |  |         return stream.read() | 
					
						
							| 
									
										
										
										
											2010-06-29 14:08:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-24 23:02:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-28 21:14:17 +00:00
										 |  |  | for_else = """\
 | 
					
						
							| 
									
										
										
										
											2010-06-28 19:44:20 +00:00
										 |  |  | def f(): | 
					
						
							|  |  |  |     for x in range(10): | 
					
						
							|  |  |  |         break | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         y = 2 | 
					
						
							|  |  |  |     z = 3 | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-28 21:14:17 +00:00
										 |  |  | while_else = """\
 | 
					
						
							| 
									
										
										
										
											2010-06-28 19:44:20 +00:00
										 |  |  | def g(): | 
					
						
							|  |  |  |     while True: | 
					
						
							|  |  |  |         break | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         y = 2 | 
					
						
							|  |  |  |     z = 3 | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-28 21:14:17 +00:00
										 |  |  | relative_import = """\
 | 
					
						
							|  |  |  | from . import fred | 
					
						
							|  |  |  | from .. import barney | 
					
						
							|  |  |  | from .australia import shrimp as prawns | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | nonlocal_ex = """\
 | 
					
						
							|  |  |  | def f(): | 
					
						
							|  |  |  |     x = 1 | 
					
						
							|  |  |  |     def g(): | 
					
						
							|  |  |  |         nonlocal x | 
					
						
							|  |  |  |         x = 2 | 
					
						
							|  |  |  |         y = 7 | 
					
						
							|  |  |  |         def h(): | 
					
						
							|  |  |  |             nonlocal x, y | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # also acts as test for 'except ... as ...' | 
					
						
							|  |  |  | raise_from = """\
 | 
					
						
							|  |  |  | try: | 
					
						
							|  |  |  |     1 / 0 | 
					
						
							|  |  |  | except ZeroDivisionError as e: | 
					
						
							|  |  |  |     raise ArithmeticError from e | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class_decorator = """\
 | 
					
						
							|  |  |  | @f1(arg) | 
					
						
							|  |  |  | @f2 | 
					
						
							|  |  |  | class Foo: pass | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-30 08:32:11 +00:00
										 |  |  | elif1 = """\
 | 
					
						
							|  |  |  | if cond1: | 
					
						
							|  |  |  |     suite1 | 
					
						
							|  |  |  | elif cond2: | 
					
						
							|  |  |  |     suite2 | 
					
						
							|  |  |  | else: | 
					
						
							|  |  |  |     suite3 | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | elif2 = """\
 | 
					
						
							|  |  |  | if cond1: | 
					
						
							|  |  |  |     suite1 | 
					
						
							|  |  |  | elif cond2: | 
					
						
							|  |  |  |     suite2 | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-30 08:46:53 +00:00
										 |  |  | try_except_finally = """\
 | 
					
						
							|  |  |  | try: | 
					
						
							|  |  |  |     suite1 | 
					
						
							|  |  |  | except ex1: | 
					
						
							|  |  |  |     suite2 | 
					
						
							|  |  |  | except ex2: | 
					
						
							|  |  |  |     suite3 | 
					
						
							|  |  |  | else: | 
					
						
							|  |  |  |     suite4 | 
					
						
							|  |  |  | finally: | 
					
						
							|  |  |  |     suite5 | 
					
						
							|  |  |  | """
 | 
					
						
							| 
									
										
										
										
											2010-06-30 08:32:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-14 16:48:15 +00:00
										 |  |  | try_except_star_finally = """\
 | 
					
						
							|  |  |  | try: | 
					
						
							|  |  |  |     suite1 | 
					
						
							|  |  |  | except* ex1: | 
					
						
							|  |  |  |     suite2 | 
					
						
							|  |  |  | except* ex2: | 
					
						
							|  |  |  |     suite3 | 
					
						
							|  |  |  | else: | 
					
						
							|  |  |  |     suite4 | 
					
						
							|  |  |  | finally: | 
					
						
							|  |  |  |     suite5 | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 17:35:19 +01:00
										 |  |  | with_simple = """\
 | 
					
						
							|  |  |  | with f(): | 
					
						
							|  |  |  |     suite1 | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | with_as = """\
 | 
					
						
							|  |  |  | with f() as x: | 
					
						
							|  |  |  |     suite1 | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | with_two_items = """\
 | 
					
						
							|  |  |  | with f() as x, g() as y: | 
					
						
							|  |  |  |     suite1 | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-17 02:04:12 +03:00
										 |  |  | docstring_prefixes = ( | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |     "", | 
					
						
							| 
									
										
										
										
											2020-05-17 00:53:25 +03:00
										 |  |  |     "class foo:\n    ", | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |     "def foo():\n    ", | 
					
						
							|  |  |  |     "async def foo():\n    ", | 
					
						
							| 
									
										
										
										
											2020-05-17 02:04:12 +03:00
										 |  |  | ) | 
					
						
							| 
									
										
										
										
											2019-11-24 23:02:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-22 00:44:41 +03:00
										 |  |  | class ASTTestCase(ASTTestMixin, unittest.TestCase): | 
					
						
							| 
									
										
										
										
											2020-03-15 22:56:57 +03:00
										 |  |  |     def check_ast_roundtrip(self, code1, **kwargs): | 
					
						
							| 
									
										
										
										
											2020-05-17 03:53:57 +01:00
										 |  |  |         with self.subTest(code1=code1, ast_parse_kwargs=kwargs): | 
					
						
							|  |  |  |             ast1 = ast.parse(code1, **kwargs) | 
					
						
							|  |  |  |             code2 = ast.unparse(ast1) | 
					
						
							|  |  |  |             ast2 = ast.parse(code2, **kwargs) | 
					
						
							|  |  |  |             self.assertASTEqual(ast1, ast2) | 
					
						
							| 
									
										
										
										
											2010-06-29 14:08:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-24 23:02:40 +00:00
										 |  |  |     def check_invalid(self, node, raises=ValueError): | 
					
						
							| 
									
										
										
										
											2020-05-17 03:53:57 +01:00
										 |  |  |         with self.subTest(node=node): | 
					
						
							|  |  |  |             self.assertRaises(raises, ast.unparse, node) | 
					
						
							| 
									
										
										
										
											2019-11-24 23:02:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-03 20:11:51 +03:00
										 |  |  |     def get_source(self, code1, code2=None): | 
					
						
							| 
									
										
										
										
											2020-03-01 23:12:17 +03:00
										 |  |  |         code2 = code2 or code1 | 
					
						
							|  |  |  |         code1 = ast.unparse(ast.parse(code1)) | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         return code1, code2 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-03 20:11:51 +03:00
										 |  |  |     def check_src_roundtrip(self, code1, code2=None): | 
					
						
							|  |  |  |         code1, code2 = self.get_source(code1, code2) | 
					
						
							| 
									
										
										
										
											2020-05-17 03:53:57 +01:00
										 |  |  |         with self.subTest(code1=code1, code2=code2): | 
					
						
							|  |  |  |             self.assertEqual(code2, code1) | 
					
						
							| 
									
										
										
										
											2020-03-01 23:12:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-03 20:11:51 +03:00
										 |  |  |     def check_src_dont_roundtrip(self, code1, code2=None): | 
					
						
							|  |  |  |         code1, code2 = self.get_source(code1, code2) | 
					
						
							| 
									
										
										
										
											2020-05-17 03:53:57 +01:00
										 |  |  |         with self.subTest(code1=code1, code2=code2): | 
					
						
							|  |  |  |             self.assertNotEqual(code2, code1) | 
					
						
							| 
									
										
										
										
											2019-11-24 23:02:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-29 14:08:23 +00:00
										 |  |  | class UnparseTestCase(ASTTestCase): | 
					
						
							|  |  |  |     # Tests for specific bugs found in earlier versions of unparse | 
					
						
							| 
									
										
										
										
											2010-06-28 19:44:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-20 15:09:15 -04:00
										 |  |  |     def test_fstrings(self): | 
					
						
							| 
									
										
										
										
											2021-05-09 02:32:04 +03:00
										 |  |  |         self.check_ast_roundtrip("f'a'") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("f'{{}}'") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("f'{{5}}'") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("f'{{5}}5'") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("f'X{{}}X'") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("f'{a}'") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("f'{ {1:2}}'") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("f'a{a}a'") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("f'a{a}{a}a'") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("f'a{a}a{a}a'") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("f'{a!r}x{a!s}12{{}}{a!a}'") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("f'{a:10}'") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("f'{a:100_000{10}}'") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("f'{a!r:10}'") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("f'{a:a{b}10}'") | 
					
						
							|  |  |  |         self.check_ast_roundtrip( | 
					
						
							|  |  |  |                 "f'a{b}{c!s}{d!r}{e!a}{f:a}{g:a{b}}{h!s:a}" | 
					
						
							|  |  |  |                 "{j!s:{a}b}{k!s:a{b}c}{l!a:{b}c{d}}{x+y=}'" | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_fstrings_special_chars(self): | 
					
						
							| 
									
										
										
										
											2015-09-20 15:09:15 -04:00
										 |  |  |         # See issue 25180 | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip(r"""f'{f"{0}"*3}'""") | 
					
						
							|  |  |  |         self.check_ast_roundtrip(r"""f'{f"{y}"*3}'""") | 
					
						
							| 
									
										
										
										
											2020-11-20 13:16:42 -08:00
										 |  |  |         self.check_ast_roundtrip("""f''""") | 
					
						
							|  |  |  |         self.check_ast_roundtrip('''f"""'end' "quote\\""""''') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_fstrings_complicated(self): | 
					
						
							|  |  |  |         # See issue 28002 | 
					
						
							|  |  |  |         self.check_ast_roundtrip("""f'''{"'"}'''""") | 
					
						
							|  |  |  |         self.check_ast_roundtrip('''f\'\'\'-{f"""*{f"+{f'.{x}.'}+"}*"""}-\'\'\'''') | 
					
						
							|  |  |  |         self.check_ast_roundtrip('''f\'\'\'-{f"""*{f"+{f'.{x}.'}+"}*"""}-'single quote\\'\'\'\'''') | 
					
						
							|  |  |  |         self.check_ast_roundtrip('f"""{\'\'\'\n\'\'\'}"""') | 
					
						
							|  |  |  |         self.check_ast_roundtrip('f"""{g(\'\'\'\n\'\'\')}"""') | 
					
						
							|  |  |  |         self.check_ast_roundtrip('''f"a\\r\\nb"''') | 
					
						
							|  |  |  |         self.check_ast_roundtrip('''f"\\u2028{'x'}"''') | 
					
						
							| 
									
										
										
										
											2015-09-20 15:09:15 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-06 06:01:23 +10:00
										 |  |  |     def test_fstrings_pep701(self): | 
					
						
							|  |  |  |         self.check_ast_roundtrip('f" something { my_dict["key"] } something else "') | 
					
						
							|  |  |  |         self.check_ast_roundtrip('f"{f"{f"{f"{f"{f"{1+1}"}"}"}"}"}"') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-27 01:08:20 +08:00
										 |  |  |     def test_strings(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip("u'foo'") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("r'foo'") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("b'foo'") | 
					
						
							| 
									
										
										
										
											2019-05-27 01:08:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-28 19:44:20 +00:00
										 |  |  |     def test_del_statement(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip("del x, y, z") | 
					
						
							| 
									
										
										
										
											2010-06-28 19:44:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_shifts(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip("45 << 2") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("13 >> 7") | 
					
						
							| 
									
										
										
										
											2010-06-28 19:44:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_for_else(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip(for_else) | 
					
						
							| 
									
										
										
										
											2010-06-28 19:44:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_while_else(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip(while_else) | 
					
						
							| 
									
										
										
										
											2010-06-28 19:44:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_unary_parens(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip("(-1)**7") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("(-1.)**8") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("(-1j)**6") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("not True or False") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("True or not False") | 
					
						
							| 
									
										
										
										
											2010-06-28 19:44:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-29 08:52:36 +00:00
										 |  |  |     def test_integer_parens(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip("3 .__abs__()") | 
					
						
							| 
									
										
										
										
											2010-06-29 08:52:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-29 10:01:48 +00:00
										 |  |  |     def test_huge_float(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip("1e1000") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("-1e1000") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("1e1000j") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("-1e1000j") | 
					
						
							| 
									
										
										
										
											2010-06-30 11:45:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-18 13:36:06 -04:00
										 |  |  |     def test_nan(self): | 
					
						
							|  |  |  |         self.assertASTEqual( | 
					
						
							|  |  |  |             ast.parse(ast.unparse(ast.Constant(value=float('nan')))), | 
					
						
							|  |  |  |             ast.parse('1e1000 - 1e1000') | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-30 11:45:53 +00:00
										 |  |  |     def test_min_int(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip(str(-(2 ** 31))) | 
					
						
							|  |  |  |         self.check_ast_roundtrip(str(-(2 ** 63))) | 
					
						
							| 
									
										
										
										
											2010-06-30 11:45:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_imaginary_literals(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip("7j") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("-7j") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("0j") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("-0j") | 
					
						
							| 
									
										
										
										
											2010-06-29 10:01:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_lambda_parentheses(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip("(lambda: int)()") | 
					
						
							| 
									
										
										
										
											2010-06-29 10:01:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-28 20:09:18 +00:00
										 |  |  |     def test_chained_comparisons(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip("1 < 4 <= 5") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("a is b is c is not d") | 
					
						
							| 
									
										
										
										
											2010-06-28 20:09:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-28 21:14:17 +00:00
										 |  |  |     def test_function_arguments(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip("def f(): pass") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("def f(a): pass") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("def f(b = 2): pass") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("def f(a, b): pass") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("def f(a, b = 2): pass") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("def f(a = 5, b = 2): pass") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("def f(*, a = 1, b = 2): pass") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("def f(*, a = 1, b): pass") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("def f(*, a, b = 2): pass") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("def f(a, b = None, *, c, **kwds): pass") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("def f(a=2, *args, c=5, d, **kwds): pass") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("def f(*args, **kwargs): pass") | 
					
						
							| 
									
										
										
										
											2010-06-28 21:14:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_relative_import(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip(relative_import) | 
					
						
							| 
									
										
										
										
											2010-06-28 21:14:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_nonlocal(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip(nonlocal_ex) | 
					
						
							| 
									
										
										
										
											2010-06-28 21:14:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_raise_from(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip(raise_from) | 
					
						
							| 
									
										
										
										
											2010-06-28 21:14:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_bytes(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip("b'123'") | 
					
						
							| 
									
										
										
										
											2010-06-28 21:14:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_annotations(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip("def f(a : int): pass") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("def f(a: int = 5): pass") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("def f(*args: [int]): pass") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("def f(**kwargs: dict): pass") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("def f() -> None: pass") | 
					
						
							| 
									
										
										
										
											2010-06-28 21:14:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_set_literal(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip("{'a', 'b', 'c'}") | 
					
						
							| 
									
										
										
										
											2010-06-28 21:14:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-18 13:36:06 -04:00
										 |  |  |     def test_empty_set(self): | 
					
						
							|  |  |  |         self.assertASTEqual( | 
					
						
							|  |  |  |             ast.parse(ast.unparse(ast.Set(elts=[]))), | 
					
						
							|  |  |  |             ast.parse('{*()}') | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-28 21:14:17 +00:00
										 |  |  |     def test_set_comprehension(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip("{x for x in range(5)}") | 
					
						
							| 
									
										
										
										
											2010-06-28 21:14:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_dict_comprehension(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip("{x: x*x for x in range(10)}") | 
					
						
							| 
									
										
										
										
											2010-06-28 21:14:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_class_decorators(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip(class_decorator) | 
					
						
							| 
									
										
										
										
											2010-06-28 19:44:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-29 18:38:59 +00:00
										 |  |  |     def test_class_definition(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip("class A(metaclass=type, *[], **{}): pass") | 
					
						
							| 
									
										
										
										
											2010-06-29 14:08:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-30 08:32:11 +00:00
										 |  |  |     def test_elifs(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip(elif1) | 
					
						
							|  |  |  |         self.check_ast_roundtrip(elif2) | 
					
						
							| 
									
										
										
										
											2010-06-30 08:32:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-30 08:46:53 +00:00
										 |  |  |     def test_try_except_finally(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip(try_except_finally) | 
					
						
							| 
									
										
										
										
											2010-06-30 08:46:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-14 16:48:15 +00:00
										 |  |  |     def test_try_except_star_finally(self): | 
					
						
							|  |  |  |         self.check_ast_roundtrip(try_except_star_finally) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 17:27:39 +01:00
										 |  |  |     def test_starred_assignment(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip("a, *b, c = seq") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("a, (*b, c) = seq") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("a, *b[0], c = seq") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("a, *(b, c) = seq") | 
					
						
							| 
									
										
										
										
											2012-05-06 17:27:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 17:35:19 +01:00
										 |  |  |     def test_with_simple(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip(with_simple) | 
					
						
							| 
									
										
										
										
											2012-05-06 17:35:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_with_as(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip(with_as) | 
					
						
							| 
									
										
										
										
											2012-05-06 17:35:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_with_two_items(self): | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip(with_two_items) | 
					
						
							| 
									
										
										
										
											2012-05-06 17:35:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 16:50:15 +02:00
										 |  |  |     def test_dict_unpacking_in_dict(self): | 
					
						
							|  |  |  |         # See issue 26489 | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         self.check_ast_roundtrip(r"""{**{'y': 2}, 'x': 1}""") | 
					
						
							|  |  |  |         self.check_ast_roundtrip(r"""{**{'y': 2}, **{'x': 1}}""") | 
					
						
							| 
									
										
										
										
											2016-03-06 16:50:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-18 23:48:49 +03:00
										 |  |  |     def test_slices(self): | 
					
						
							| 
									
										
										
										
											2020-03-09 23:27:03 +03:00
										 |  |  |         self.check_ast_roundtrip("a[i]") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("a[i,]") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("a[i, j]") | 
					
						
							| 
									
										
										
										
											2022-03-26 16:55:35 +00:00
										 |  |  |         # The AST for these next two both look like `a[(*a,)]` | 
					
						
							| 
									
										
										
										
											2020-05-18 23:48:49 +03:00
										 |  |  |         self.check_ast_roundtrip("a[(*a,)]") | 
					
						
							| 
									
										
										
										
											2022-03-26 16:55:35 +00:00
										 |  |  |         self.check_ast_roundtrip("a[*a]") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("a[b, *a]") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("a[*a, c]") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("a[b, *a, c]") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("a[*a, *a]") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("a[b, *a, *a]") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("a[*a, b, *a]") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("a[*a, *a, b]") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("a[b, *a, *a, c]") | 
					
						
							| 
									
										
										
										
											2020-05-18 23:48:49 +03:00
										 |  |  |         self.check_ast_roundtrip("a[(a:=b)]") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("a[(a:=b,c)]") | 
					
						
							| 
									
										
										
										
											2020-03-09 23:27:03 +03:00
										 |  |  |         self.check_ast_roundtrip("a[()]") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("a[i:j]") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("a[:j]") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("a[i:]") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("a[i:j:k]") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("a[:j:k]") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("a[i::k]") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("a[i:j,]") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("a[i:j, k]") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-24 23:02:40 +00:00
										 |  |  |     def test_invalid_raise(self): | 
					
						
							| 
									
										
										
										
											2024-02-28 13:04:23 +02:00
										 |  |  |         self.check_invalid(ast.Raise(exc=None, cause=ast.Name(id="X", ctx=ast.Load()))) | 
					
						
							| 
									
										
										
										
											2019-11-24 23:02:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-09 02:32:04 +03:00
										 |  |  |     def test_invalid_fstring_value(self): | 
					
						
							| 
									
										
										
										
											2019-11-24 23:02:40 +00:00
										 |  |  |         self.check_invalid( | 
					
						
							| 
									
										
										
										
											2021-05-09 02:32:04 +03:00
										 |  |  |             ast.JoinedStr( | 
					
						
							|  |  |  |                 values=[ | 
					
						
							| 
									
										
										
										
											2024-02-28 13:04:23 +02:00
										 |  |  |                     ast.Name(id="test", ctx=ast.Load()), | 
					
						
							| 
									
										
										
										
											2021-05-09 02:32:04 +03:00
										 |  |  |                     ast.Constant(value="test") | 
					
						
							|  |  |  |                 ] | 
					
						
							| 
									
										
										
										
											2019-11-24 23:02:40 +00:00
										 |  |  |             ) | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-06 06:01:23 +10:00
										 |  |  |     def test_fstring_backslash(self): | 
					
						
							|  |  |  |         # valid since Python 3.12 | 
					
						
							|  |  |  |         self.assertEqual(ast.unparse( | 
					
						
							|  |  |  |                             ast.FormattedValue( | 
					
						
							|  |  |  |                                 value=ast.Constant(value="\\\\"), | 
					
						
							|  |  |  |                                 conversion=-1, | 
					
						
							|  |  |  |                                 format_spec=None, | 
					
						
							|  |  |  |                             ) | 
					
						
							|  |  |  |                         ), "{'\\\\\\\\'}") | 
					
						
							| 
									
										
										
										
											2020-11-20 13:16:42 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-02 21:20:04 +03:00
										 |  |  |     def test_invalid_yield_from(self): | 
					
						
							|  |  |  |         self.check_invalid(ast.YieldFrom(value=None)) | 
					
						
							| 
									
										
										
										
											2012-05-06 17:27:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-05 10:14:50 -07:00
										 |  |  |     def test_import_from_level_none(self): | 
					
						
							|  |  |  |         tree = ast.ImportFrom(module='mod', names=[ast.alias(name='x')]) | 
					
						
							|  |  |  |         self.assertEqual(ast.unparse(tree), "from mod import x") | 
					
						
							|  |  |  |         tree = ast.ImportFrom(module='mod', names=[ast.alias(name='x')], level=None) | 
					
						
							|  |  |  |         self.assertEqual(ast.unparse(tree), "from mod import x") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |     def test_docstrings(self): | 
					
						
							|  |  |  |         docstrings = ( | 
					
						
							|  |  |  |             'this ends with double quote"', | 
					
						
							| 
									
										
										
										
											2020-05-17 01:49:07 +03:00
										 |  |  |             'this includes a """triple quote"""', | 
					
						
							|  |  |  |             '\r', | 
					
						
							|  |  |  |             '\\r', | 
					
						
							|  |  |  |             '\t', | 
					
						
							|  |  |  |             '\\t', | 
					
						
							|  |  |  |             '\n', | 
					
						
							|  |  |  |             '\\n', | 
					
						
							| 
									
										
										
										
											2020-05-18 21:41:35 +03:00
										 |  |  |             '\r\\r\t\\t\n\\n', | 
					
						
							|  |  |  |             '""">>> content = \"\"\"blabla\"\"\" <<<"""', | 
					
						
							|  |  |  |             r'foo\n\x00', | 
					
						
							| 
									
										
										
										
											2020-11-20 13:16:42 -08:00
										 |  |  |             "' \\'\\'\\'\"\"\" \"\"\\'\\' \\'", | 
					
						
							|  |  |  |             '🐍⛎𩸽üéş^\\\\X\\\\BB\N{LONG RIGHTWARDS SQUIGGLE ARROW}' | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         ) | 
					
						
							|  |  |  |         for docstring in docstrings: | 
					
						
							|  |  |  |             # check as Module docstrings for easy testing | 
					
						
							| 
									
										
										
										
											2020-05-17 01:49:07 +03:00
										 |  |  |             self.check_ast_roundtrip(f"'''{docstring}'''") | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-09 23:27:03 +03:00
										 |  |  |     def test_constant_tuples(self): | 
					
						
							| 
									
										
										
										
											2025-03-17 20:48:54 +00:00
										 |  |  |         locs = ast.fix_missing_locations | 
					
						
							| 
									
										
										
										
											2020-03-09 23:27:03 +03:00
										 |  |  |         self.check_src_roundtrip( | 
					
						
							| 
									
										
										
										
											2025-03-17 20:48:54 +00:00
										 |  |  |             locs(ast.Module([ast.Expr(ast.Constant(value=(1,)))])), "(1,)") | 
					
						
							|  |  |  |         self.check_src_roundtrip( | 
					
						
							|  |  |  |             locs(ast.Module([ast.Expr(ast.Constant(value=(1, 2, 3)))])), "(1, 2, 3)" | 
					
						
							| 
									
										
										
										
											2020-03-09 23:27:03 +03:00
										 |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-15 22:56:57 +03:00
										 |  |  |     def test_function_type(self): | 
					
						
							|  |  |  |         for function_type in ( | 
					
						
							|  |  |  |             "() -> int", | 
					
						
							|  |  |  |             "(int, int) -> int", | 
					
						
							|  |  |  |             "(Callable[complex], More[Complex(call.to_typevar())]) -> None" | 
					
						
							|  |  |  |         ): | 
					
						
							|  |  |  |             self.check_ast_roundtrip(function_type, mode="func_type") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-17 02:04:12 +03:00
										 |  |  |     def test_type_comments(self): | 
					
						
							|  |  |  |         for statement in ( | 
					
						
							|  |  |  |             "a = 5 # type:", | 
					
						
							|  |  |  |             "a = 5 # type: int", | 
					
						
							|  |  |  |             "a = 5 # type: int and more", | 
					
						
							|  |  |  |             "def x(): # type: () -> None\n\tpass", | 
					
						
							|  |  |  |             "def x(y): # type: (int) -> None and more\n\tpass", | 
					
						
							|  |  |  |             "async def x(): # type: () -> None\n\tpass", | 
					
						
							|  |  |  |             "async def x(y): # type: (int) -> None and more\n\tpass", | 
					
						
							|  |  |  |             "for x in y: # type: int\n\tpass", | 
					
						
							|  |  |  |             "async for x in y: # type: int\n\tpass", | 
					
						
							|  |  |  |             "with x(): # type: int\n\tpass", | 
					
						
							|  |  |  |             "async with x(): # type: int\n\tpass" | 
					
						
							|  |  |  |         ): | 
					
						
							|  |  |  |             self.check_ast_roundtrip(statement, type_comments=True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_type_ignore(self): | 
					
						
							|  |  |  |         for statement in ( | 
					
						
							|  |  |  |             "a = 5 # type: ignore", | 
					
						
							|  |  |  |             "a = 5 # type: ignore and more", | 
					
						
							|  |  |  |             "def x(): # type: ignore\n\tpass", | 
					
						
							|  |  |  |             "def x(y): # type: ignore and more\n\tpass", | 
					
						
							|  |  |  |             "async def x(): # type: ignore\n\tpass", | 
					
						
							|  |  |  |             "async def x(y): # type: ignore and more\n\tpass", | 
					
						
							|  |  |  |             "for x in y: # type: ignore\n\tpass", | 
					
						
							|  |  |  |             "async for x in y: # type: ignore\n\tpass", | 
					
						
							|  |  |  |             "with x(): # type: ignore\n\tpass", | 
					
						
							|  |  |  |             "async with x(): # type: ignore\n\tpass" | 
					
						
							|  |  |  |         ): | 
					
						
							|  |  |  |             self.check_ast_roundtrip(statement, type_comments=True) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-01 23:12:17 +03:00
										 |  |  | class CosmeticTestCase(ASTTestCase): | 
					
						
							| 
									
										
										
										
											2021-10-07 01:13:48 +02:00
										 |  |  |     """Test if there are cosmetic issues caused by unnecessary additions""" | 
					
						
							| 
									
										
										
										
											2020-03-01 23:12:17 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_simple_expressions_parens(self): | 
					
						
							|  |  |  |         self.check_src_roundtrip("(a := b)") | 
					
						
							|  |  |  |         self.check_src_roundtrip("await x") | 
					
						
							|  |  |  |         self.check_src_roundtrip("x if x else y") | 
					
						
							|  |  |  |         self.check_src_roundtrip("lambda x: x") | 
					
						
							|  |  |  |         self.check_src_roundtrip("1 + 1") | 
					
						
							|  |  |  |         self.check_src_roundtrip("1 + 2 / 3") | 
					
						
							|  |  |  |         self.check_src_roundtrip("(1 + 2) / 3") | 
					
						
							|  |  |  |         self.check_src_roundtrip("(1 + 2) * 3 + 4 * (5 + 2)") | 
					
						
							|  |  |  |         self.check_src_roundtrip("(1 + 2) * 3 + 4 * (5 + 2) ** 2") | 
					
						
							| 
									
										
										
										
											2020-05-17 00:46:11 +03:00
										 |  |  |         self.check_src_roundtrip("~x") | 
					
						
							| 
									
										
										
										
											2020-03-01 23:12:17 +03:00
										 |  |  |         self.check_src_roundtrip("x and y") | 
					
						
							|  |  |  |         self.check_src_roundtrip("x and y and z") | 
					
						
							|  |  |  |         self.check_src_roundtrip("x and (y and x)") | 
					
						
							|  |  |  |         self.check_src_roundtrip("(x and y) and z") | 
					
						
							|  |  |  |         self.check_src_roundtrip("(x ** y) ** z ** q") | 
					
						
							|  |  |  |         self.check_src_roundtrip("x >> y") | 
					
						
							|  |  |  |         self.check_src_roundtrip("x << y") | 
					
						
							|  |  |  |         self.check_src_roundtrip("x >> y and x >> z") | 
					
						
							|  |  |  |         self.check_src_roundtrip("x + y - z * q ^ t ** k") | 
					
						
							|  |  |  |         self.check_src_roundtrip("P * V if P and V else n * R * T") | 
					
						
							|  |  |  |         self.check_src_roundtrip("lambda P, V, n: P * V == n * R * T") | 
					
						
							|  |  |  |         self.check_src_roundtrip("flag & (other | foo)") | 
					
						
							|  |  |  |         self.check_src_roundtrip("not x == y") | 
					
						
							|  |  |  |         self.check_src_roundtrip("x == (not y)") | 
					
						
							|  |  |  |         self.check_src_roundtrip("yield x") | 
					
						
							|  |  |  |         self.check_src_roundtrip("yield from x") | 
					
						
							|  |  |  |         self.check_src_roundtrip("call((yield x))") | 
					
						
							|  |  |  |         self.check_src_roundtrip("return x + (yield x)") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-17 00:53:25 +03:00
										 |  |  |     def test_class_bases_and_keywords(self): | 
					
						
							|  |  |  |         self.check_src_roundtrip("class X:\n    pass") | 
					
						
							|  |  |  |         self.check_src_roundtrip("class X(A):\n    pass") | 
					
						
							|  |  |  |         self.check_src_roundtrip("class X(A, B, C, D):\n    pass") | 
					
						
							|  |  |  |         self.check_src_roundtrip("class X(x=y):\n    pass") | 
					
						
							|  |  |  |         self.check_src_roundtrip("class X(metaclass=z):\n    pass") | 
					
						
							|  |  |  |         self.check_src_roundtrip("class X(x=y, z=d):\n    pass") | 
					
						
							|  |  |  |         self.check_src_roundtrip("class X(A, x=y):\n    pass") | 
					
						
							|  |  |  |         self.check_src_roundtrip("class X(A, **kw):\n    pass") | 
					
						
							|  |  |  |         self.check_src_roundtrip("class X(*args):\n    pass") | 
					
						
							|  |  |  |         self.check_src_roundtrip("class X(*args, **kwargs):\n    pass") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-20 13:16:42 -08:00
										 |  |  |     def test_fstrings(self): | 
					
						
							| 
									
										
										
										
											2025-01-31 00:49:06 -08:00
										 |  |  |         self.check_src_roundtrip('''f\'\'\'-{f"""*{f"+{f'.{x}.'}+"}*"""}-\'\'\'''') | 
					
						
							|  |  |  |         self.check_src_roundtrip('''f\'-{f\'\'\'*{f"""+{f".{f'{x}'}."}+"""}*\'\'\'}-\'''') | 
					
						
							|  |  |  |         self.check_src_roundtrip('''f\'-{f\'*{f\'\'\'+{f""".{f"{f'{x}'}"}."""}+\'\'\'}*\'}-\'''') | 
					
						
							|  |  |  |         self.check_src_roundtrip('''f"\\u2028{'x'}"''') | 
					
						
							| 
									
										
										
										
											2020-11-20 13:16:42 -08:00
										 |  |  |         self.check_src_roundtrip(r"f'{x}\n'") | 
					
						
							| 
									
										
										
										
											2025-01-31 00:49:06 -08:00
										 |  |  |         self.check_src_roundtrip('''f"{'\\n'}\\n"''') | 
					
						
							|  |  |  |         self.check_src_roundtrip('''f"{f'{x}\\n'}\\n"''') | 
					
						
							| 
									
										
										
										
											2020-11-20 13:16:42 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |     def test_docstrings(self): | 
					
						
							|  |  |  |         docstrings = ( | 
					
						
							|  |  |  |             '"""simple doc string"""', | 
					
						
							|  |  |  |             '''"""A more complex one
 | 
					
						
							|  |  |  |             with some newlines"""''',
 | 
					
						
							|  |  |  |             '''"""Foo bar baz
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             empty newline"""''',
 | 
					
						
							|  |  |  |             '"""With some \t"""', | 
					
						
							|  |  |  |             '"""Foo "bar" baz """', | 
					
						
							| 
									
										
										
										
											2020-05-17 01:49:07 +03:00
										 |  |  |             '"""\\r"""', | 
					
						
							|  |  |  |             '""""""', | 
					
						
							|  |  |  |             '"""\'\'\'"""', | 
					
						
							|  |  |  |             '"""\'\'\'\'\'\'"""', | 
					
						
							| 
									
										
										
										
											2020-11-20 13:16:42 -08:00
										 |  |  |             '"""🐍⛎𩸽üéş^\\\\X\\\\BB⟿"""', | 
					
						
							|  |  |  |             '"""end in single \'quote\'"""', | 
					
						
							|  |  |  |             "'''end in double \"quote\"'''", | 
					
						
							|  |  |  |             '"""almost end in double "quote"."""', | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for prefix in docstring_prefixes: | 
					
						
							|  |  |  |             for docstring in docstrings: | 
					
						
							|  |  |  |                 self.check_src_roundtrip(f"{prefix}{docstring}") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_docstrings_negative_cases(self): | 
					
						
							|  |  |  |         # Test some cases that involve strings in the children of the | 
					
						
							|  |  |  |         # first node but aren't docstrings to make sure we don't have | 
					
						
							|  |  |  |         # False positives. | 
					
						
							|  |  |  |         docstrings_negative = ( | 
					
						
							|  |  |  |             'a = """false"""', | 
					
						
							|  |  |  |             '"""false""" + """unless its optimized"""', | 
					
						
							|  |  |  |             '1 + 1\n"""false"""', | 
					
						
							|  |  |  |             'f"""no, top level but f-fstring"""' | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         for prefix in docstring_prefixes: | 
					
						
							|  |  |  |             for negative in docstrings_negative: | 
					
						
							|  |  |  |                 # this cases should be result with single quote | 
					
						
							|  |  |  |                 # rather then triple quoted docstring | 
					
						
							|  |  |  |                 src = f"{prefix}{negative}" | 
					
						
							|  |  |  |                 self.check_ast_roundtrip(src) | 
					
						
							|  |  |  |                 self.check_src_dont_roundtrip(src) | 
					
						
							| 
									
										
										
										
											2020-03-01 23:12:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-17 00:46:11 +03:00
										 |  |  |     def test_unary_op_factor(self): | 
					
						
							|  |  |  |         for prefix in ("+", "-", "~"): | 
					
						
							|  |  |  |             self.check_src_roundtrip(f"{prefix}1") | 
					
						
							|  |  |  |         for prefix in ("not",): | 
					
						
							|  |  |  |             self.check_src_roundtrip(f"{prefix} 1") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-18 23:48:49 +03:00
										 |  |  |     def test_slices(self): | 
					
						
							| 
									
										
										
										
											2022-03-26 16:55:35 +00:00
										 |  |  |         self.check_src_roundtrip("a[()]") | 
					
						
							| 
									
										
										
										
											2020-05-18 23:48:49 +03:00
										 |  |  |         self.check_src_roundtrip("a[1]") | 
					
						
							|  |  |  |         self.check_src_roundtrip("a[1, 2]") | 
					
						
							| 
									
										
										
										
											2022-03-26 16:55:35 +00:00
										 |  |  |         # Note that `a[*a]`, `a[*a,]`, and `a[(*a,)]` all evaluate to the same | 
					
						
							|  |  |  |         # thing at runtime and have the same AST, but only `a[*a,]` passes | 
					
						
							|  |  |  |         # this test, because that's what `ast.unparse` produces. | 
					
						
							|  |  |  |         self.check_src_roundtrip("a[*a,]") | 
					
						
							|  |  |  |         self.check_src_roundtrip("a[1, *a]") | 
					
						
							|  |  |  |         self.check_src_roundtrip("a[*a, 2]") | 
					
						
							|  |  |  |         self.check_src_roundtrip("a[1, *a, 2]") | 
					
						
							|  |  |  |         self.check_src_roundtrip("a[*a, *a]") | 
					
						
							|  |  |  |         self.check_src_roundtrip("a[1, *a, *a]") | 
					
						
							|  |  |  |         self.check_src_roundtrip("a[*a, 1, *a]") | 
					
						
							|  |  |  |         self.check_src_roundtrip("a[*a, *a, 1]") | 
					
						
							|  |  |  |         self.check_src_roundtrip("a[1, *a, *a, 2]") | 
					
						
							|  |  |  |         self.check_src_roundtrip("a[1:2, *a]") | 
					
						
							|  |  |  |         self.check_src_roundtrip("a[*a, 1:2]") | 
					
						
							| 
									
										
										
										
											2020-05-18 23:48:49 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-15 15:55:53 +03:00
										 |  |  |     def test_lambda_parameters(self): | 
					
						
							|  |  |  |         self.check_src_roundtrip("lambda: something") | 
					
						
							|  |  |  |         self.check_src_roundtrip("four = lambda: 2 + 2") | 
					
						
							|  |  |  |         self.check_src_roundtrip("lambda x: x * 2") | 
					
						
							|  |  |  |         self.check_src_roundtrip("square = lambda n: n ** 2") | 
					
						
							|  |  |  |         self.check_src_roundtrip("lambda x, y: x + y") | 
					
						
							|  |  |  |         self.check_src_roundtrip("add = lambda x, y: x + y") | 
					
						
							|  |  |  |         self.check_src_roundtrip("lambda x, y, /, z, q, *, u: None") | 
					
						
							|  |  |  |         self.check_src_roundtrip("lambda x, *y, **z: None") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-16 16:33:22 +03:00
										 |  |  |     def test_star_expr_assign_target(self): | 
					
						
							|  |  |  |         for source_type, source in [ | 
					
						
							|  |  |  |             ("single assignment", "{target} = foo"), | 
					
						
							|  |  |  |             ("multiple assignment", "{target} = {target} = bar"), | 
					
						
							|  |  |  |             ("for loop", "for {target} in foo:\n    pass"), | 
					
						
							|  |  |  |             ("async for loop", "async for {target} in foo:\n    pass") | 
					
						
							|  |  |  |         ]: | 
					
						
							|  |  |  |             for target in [ | 
					
						
							|  |  |  |                 "a", | 
					
						
							|  |  |  |                 "a,", | 
					
						
							|  |  |  |                 "a, b", | 
					
						
							|  |  |  |                 "a, *b, c", | 
					
						
							|  |  |  |                 "a, (b, c), d", | 
					
						
							|  |  |  |                 "a, (b, c, d), *e", | 
					
						
							|  |  |  |                 "a, (b, *c, d), e", | 
					
						
							|  |  |  |                 "a, (b, *c, (d, e), f), g", | 
					
						
							|  |  |  |                 "[a]", | 
					
						
							|  |  |  |                 "[a, b]", | 
					
						
							|  |  |  |                 "[a, *b, c]", | 
					
						
							|  |  |  |                 "[a, [b, c], d]", | 
					
						
							|  |  |  |                 "[a, [b, c, d], *e]", | 
					
						
							|  |  |  |                 "[a, [b, *c, d], e]", | 
					
						
							|  |  |  |                 "[a, [b, *c, [d, e], f], g]", | 
					
						
							|  |  |  |                 "a, [b, c], d", | 
					
						
							|  |  |  |                 "[a, b, (c, d), (e, f)]", | 
					
						
							|  |  |  |                 "a, b, [*c], d, e" | 
					
						
							|  |  |  |             ]: | 
					
						
							|  |  |  |                 with self.subTest(source_type=source_type, target=target): | 
					
						
							|  |  |  |                     self.check_src_roundtrip(source.format(target=target)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_star_expr_assign_target_multiple(self): | 
					
						
							| 
									
										
										
										
											2022-05-16 15:38:06 +03:00
										 |  |  |         self.check_src_roundtrip("() = []") | 
					
						
							|  |  |  |         self.check_src_roundtrip("[] = ()") | 
					
						
							|  |  |  |         self.check_src_roundtrip("() = [a] = c, = [d] = e, f = () = g = h") | 
					
						
							| 
									
										
										
										
											2021-05-16 16:33:22 +03:00
										 |  |  |         self.check_src_roundtrip("a = b = c = d") | 
					
						
							|  |  |  |         self.check_src_roundtrip("a, b = c, d = e, f = g") | 
					
						
							|  |  |  |         self.check_src_roundtrip("[a, b] = [c, d] = [e, f] = g") | 
					
						
							|  |  |  |         self.check_src_roundtrip("a, b = [c, d] = e, f = g") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-18 06:56:19 -07:00
										 |  |  |     def test_multiquote_joined_string(self): | 
					
						
							|  |  |  |         self.check_ast_roundtrip("f\"'''{1}\\\"\\\"\\\"\" ") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("""f"'''{1}""\\"" """) | 
					
						
							|  |  |  |         self.check_ast_roundtrip("""f'""\"{1}''' """) | 
					
						
							|  |  |  |         self.check_ast_roundtrip("""f'""\"{1}""\\"' """) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.check_ast_roundtrip("""f"'''{"\\n"}""\\"" """) | 
					
						
							|  |  |  |         self.check_ast_roundtrip("""f'""\"{"\\n"}''' """) | 
					
						
							|  |  |  |         self.check_ast_roundtrip("""f'""\"{"\\n"}""\\"' """) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.check_ast_roundtrip("""f'''""\"''\\'{"\\n"}''' """) | 
					
						
							|  |  |  |         self.check_ast_roundtrip("""f'''""\"''\\'{"\\n\\"'"}''' """) | 
					
						
							|  |  |  |         self.check_ast_roundtrip("""f'''""\"''\\'{""\"\\n\\"'''""\" '''\\n'''}''' """) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-21 11:24:08 +01:00
										 |  |  |     def test_backslash_in_format_spec(self): | 
					
						
							| 
									
										
										
										
											2024-02-26 15:32:27 +03:00
										 |  |  |         import re | 
					
						
							| 
									
										
										
										
											2025-01-16 04:00:54 +11:00
										 |  |  |         msg = re.escape('"\\ " is an invalid escape sequence. ' | 
					
						
							|  |  |  |                         'Such sequences will not work in the future. ' | 
					
						
							|  |  |  |                         'Did you mean "\\\\ "? A raw string is also an option.') | 
					
						
							| 
									
										
										
										
											2024-02-26 15:32:27 +03:00
										 |  |  |         with self.assertWarnsRegex(SyntaxWarning, msg): | 
					
						
							|  |  |  |             self.check_ast_roundtrip("""f"{x:\\ }" """) | 
					
						
							|  |  |  |         self.check_ast_roundtrip("""f"{x:\\n}" """) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-21 11:24:08 +01:00
										 |  |  |         self.check_ast_roundtrip("""f"{x:\\\\ }" """) | 
					
						
							| 
									
										
										
										
											2024-02-26 15:32:27 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |         with self.assertWarnsRegex(SyntaxWarning, msg): | 
					
						
							|  |  |  |             self.check_ast_roundtrip("""f"{x:\\\\\\ }" """) | 
					
						
							|  |  |  |         self.check_ast_roundtrip("""f"{x:\\\\\\n}" """) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-21 11:24:08 +01:00
										 |  |  |         self.check_ast_roundtrip("""f"{x:\\\\\\\\ }" """) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_quote_in_format_spec(self): | 
					
						
							|  |  |  |         self.check_ast_roundtrip("""f"{x:'}" """) | 
					
						
							|  |  |  |         self.check_ast_roundtrip("""f"{x:\\'}" """) | 
					
						
							|  |  |  |         self.check_ast_roundtrip("""f"{x:\\\\'}" """) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.check_ast_roundtrip("""f'\\'{x:"}' """) | 
					
						
							|  |  |  |         self.check_ast_roundtrip("""f'\\'{x:\\"}' """) | 
					
						
							|  |  |  |         self.check_ast_roundtrip("""f'\\'{x:\\\\"}' """) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |     def test_type_params(self): | 
					
						
							|  |  |  |         self.check_ast_roundtrip("type A = int") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("type A[T] = int") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("type A[T: int] = int") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("type A[T = int] = int") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("type A[T: int = int] = int") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("type A[**P] = int") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("type A[**P = int] = int") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("type A[*Ts] = int") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("type A[*Ts = int] = int") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("type A[*Ts = *int] = int") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("def f[T: int = int, **P = int, *Ts = *int]():\n    pass") | 
					
						
							|  |  |  |         self.check_ast_roundtrip("class C[T: int = int, **P = int, *Ts = *int]():\n    pass") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-16 16:33:22 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-16 09:31:23 -07:00
										 |  |  | class ManualASTCreationTestCase(unittest.TestCase): | 
					
						
							|  |  |  |     """Test that AST nodes created without a type_params field unparse correctly.""" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_class(self): | 
					
						
							|  |  |  |         node = ast.ClassDef(name="X", bases=[], keywords=[], body=[ast.Pass()], decorator_list=[]) | 
					
						
							|  |  |  |         ast.fix_missing_locations(node) | 
					
						
							|  |  |  |         self.assertEqual(ast.unparse(node), "class X:\n    pass") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_class_with_type_params(self): | 
					
						
							|  |  |  |         node = ast.ClassDef(name="X", bases=[], keywords=[], body=[ast.Pass()], decorator_list=[], | 
					
						
							|  |  |  |                              type_params=[ast.TypeVar("T")]) | 
					
						
							|  |  |  |         ast.fix_missing_locations(node) | 
					
						
							|  |  |  |         self.assertEqual(ast.unparse(node), "class X[T]:\n    pass") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_function(self): | 
					
						
							|  |  |  |         node = ast.FunctionDef( | 
					
						
							|  |  |  |             name="f", | 
					
						
							|  |  |  |             args=ast.arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), | 
					
						
							|  |  |  |             body=[ast.Pass()], | 
					
						
							|  |  |  |             decorator_list=[], | 
					
						
							|  |  |  |             returns=None, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         ast.fix_missing_locations(node) | 
					
						
							|  |  |  |         self.assertEqual(ast.unparse(node), "def f():\n    pass") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_function_with_type_params(self): | 
					
						
							|  |  |  |         node = ast.FunctionDef( | 
					
						
							|  |  |  |             name="f", | 
					
						
							|  |  |  |             args=ast.arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), | 
					
						
							|  |  |  |             body=[ast.Pass()], | 
					
						
							|  |  |  |             decorator_list=[], | 
					
						
							|  |  |  |             returns=None, | 
					
						
							|  |  |  |             type_params=[ast.TypeVar("T")], | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         ast.fix_missing_locations(node) | 
					
						
							|  |  |  |         self.assertEqual(ast.unparse(node), "def f[T]():\n    pass") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_function_with_type_params_and_bound(self): | 
					
						
							|  |  |  |         node = ast.FunctionDef( | 
					
						
							|  |  |  |             name="f", | 
					
						
							|  |  |  |             args=ast.arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), | 
					
						
							|  |  |  |             body=[ast.Pass()], | 
					
						
							|  |  |  |             decorator_list=[], | 
					
						
							|  |  |  |             returns=None, | 
					
						
							| 
									
										
										
										
											2024-02-28 13:04:23 +02:00
										 |  |  |             type_params=[ast.TypeVar("T", bound=ast.Name("int", ctx=ast.Load()))], | 
					
						
							| 
									
										
										
										
											2023-06-16 09:31:23 -07:00
										 |  |  |         ) | 
					
						
							|  |  |  |         ast.fix_missing_locations(node) | 
					
						
							|  |  |  |         self.assertEqual(ast.unparse(node), "def f[T: int]():\n    pass") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |     def test_function_with_type_params_and_default(self): | 
					
						
							|  |  |  |         node = ast.FunctionDef( | 
					
						
							|  |  |  |             name="f", | 
					
						
							|  |  |  |             args=ast.arguments(), | 
					
						
							|  |  |  |             body=[ast.Pass()], | 
					
						
							|  |  |  |             type_params=[ | 
					
						
							|  |  |  |                 ast.TypeVar("T", default_value=ast.Constant(value=1)), | 
					
						
							|  |  |  |                 ast.TypeVarTuple("Ts", default_value=ast.Starred(value=ast.Constant(value=1), ctx=ast.Load())), | 
					
						
							|  |  |  |                 ast.ParamSpec("P", default_value=ast.Constant(value=1)), | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         ast.fix_missing_locations(node) | 
					
						
							|  |  |  |         self.assertEqual(ast.unparse(node), "def f[T = 1, *Ts = *1, **P = 1]():\n    pass") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-16 09:31:23 -07:00
										 |  |  |     def test_async_function(self): | 
					
						
							|  |  |  |         node = ast.AsyncFunctionDef( | 
					
						
							|  |  |  |             name="f", | 
					
						
							|  |  |  |             args=ast.arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), | 
					
						
							|  |  |  |             body=[ast.Pass()], | 
					
						
							|  |  |  |             decorator_list=[], | 
					
						
							|  |  |  |             returns=None, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         ast.fix_missing_locations(node) | 
					
						
							|  |  |  |         self.assertEqual(ast.unparse(node), "async def f():\n    pass") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_async_function_with_type_params(self): | 
					
						
							|  |  |  |         node = ast.AsyncFunctionDef( | 
					
						
							|  |  |  |             name="f", | 
					
						
							|  |  |  |             args=ast.arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), | 
					
						
							|  |  |  |             body=[ast.Pass()], | 
					
						
							|  |  |  |             decorator_list=[], | 
					
						
							|  |  |  |             returns=None, | 
					
						
							|  |  |  |             type_params=[ast.TypeVar("T")], | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         ast.fix_missing_locations(node) | 
					
						
							|  |  |  |         self.assertEqual(ast.unparse(node), "async def f[T]():\n    pass") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-03 06:17:32 -07:00
										 |  |  |     def test_async_function_with_type_params_and_default(self): | 
					
						
							|  |  |  |         node = ast.AsyncFunctionDef( | 
					
						
							|  |  |  |             name="f", | 
					
						
							|  |  |  |             args=ast.arguments(), | 
					
						
							|  |  |  |             body=[ast.Pass()], | 
					
						
							|  |  |  |             type_params=[ | 
					
						
							|  |  |  |                 ast.TypeVar("T", default_value=ast.Constant(value=1)), | 
					
						
							|  |  |  |                 ast.TypeVarTuple("Ts", default_value=ast.Starred(value=ast.Constant(value=1), ctx=ast.Load())), | 
					
						
							|  |  |  |                 ast.ParamSpec("P", default_value=ast.Constant(value=1)), | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         ast.fix_missing_locations(node) | 
					
						
							|  |  |  |         self.assertEqual(ast.unparse(node), "async def f[T = 1, *Ts = *1, **P = 1]():\n    pass") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-15 15:55:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-29 14:08:23 +00:00
										 |  |  | class DirectoryTestCase(ASTTestCase): | 
					
						
							|  |  |  |     """Test roundtrip behaviour on all files in Lib and Lib/test.""" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-24 23:02:40 +00:00
										 |  |  |     lib_dir = pathlib.Path(__file__).parent / ".." | 
					
						
							|  |  |  |     test_directories = (lib_dir, lib_dir / "test") | 
					
						
							| 
									
										
										
										
											2019-12-29 19:20:55 +00:00
										 |  |  |     run_always_files = {"test_grammar.py", "test_syntax.py", "test_compile.py", | 
					
						
							| 
									
										
										
										
											2021-04-29 15:58:44 +10:00
										 |  |  |                         "test_ast.py", "test_asdl_parser.py", "test_fstring.py", | 
					
						
							| 
									
										
										
										
											2023-10-05 14:26:44 +01:00
										 |  |  |                         "test_patma.py", "test_type_alias.py", "test_type_params.py", | 
					
						
							|  |  |  |                         "test_tokenize.py"} | 
					
						
							| 
									
										
										
										
											2010-06-29 14:08:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-09 17:57:50 +00:00
										 |  |  |     _files_to_test = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @classmethod | 
					
						
							|  |  |  |     def files_to_test(cls): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if cls._files_to_test is not None: | 
					
						
							|  |  |  |             return cls._files_to_test | 
					
						
							| 
									
										
										
										
											2010-06-29 14:08:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-24 23:02:40 +00:00
										 |  |  |         items = [ | 
					
						
							|  |  |  |             item.resolve() | 
					
						
							| 
									
										
										
										
											2019-12-09 17:57:50 +00:00
										 |  |  |             for directory in cls.test_directories | 
					
						
							| 
									
										
										
										
											2019-11-24 23:02:40 +00:00
										 |  |  |             for item in directory.glob("*.py") | 
					
						
							|  |  |  |             if not item.name.startswith("bad") | 
					
						
							|  |  |  |         ] | 
					
						
							| 
									
										
										
										
											2010-06-29 14:08:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-23 09:27:47 +01:00
										 |  |  |         # Test limited subset of files unless the 'cpu' resource is specified. | 
					
						
							|  |  |  |         if not test.support.is_resource_enabled("cpu"): | 
					
						
							| 
									
										
										
										
											2019-12-29 19:20:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-29 20:18:36 +00:00
										 |  |  |             tests_to_run_always = {item for item in items if | 
					
						
							|  |  |  |                                    item.name in cls.run_always_files} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             items = set(random.sample(items, 10)) | 
					
						
							| 
									
										
										
										
											2019-12-29 19:20:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-29 20:18:36 +00:00
										 |  |  |             # Make sure that at least tests that heavily use grammar features are | 
					
						
							|  |  |  |             # always considered in order to reduce the chance of missing something. | 
					
						
							|  |  |  |             items = list(items | tests_to_run_always) | 
					
						
							| 
									
										
										
										
											2019-12-09 17:57:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # bpo-31174: Store the names sample to always test the same files. | 
					
						
							|  |  |  |         # It prevents false alarms when hunting reference leaks. | 
					
						
							|  |  |  |         cls._files_to_test = items | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-24 23:02:40 +00:00
										 |  |  |         return items | 
					
						
							| 
									
										
										
										
											2017-10-24 03:33:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_files(self): | 
					
						
							| 
									
										
										
										
											2019-12-09 17:57:50 +00:00
										 |  |  |         for item in self.files_to_test(): | 
					
						
							| 
									
										
										
										
											2010-06-29 14:08:23 +00:00
										 |  |  |             if test.support.verbose: | 
					
						
							| 
									
										
										
										
											2019-11-24 23:02:40 +00:00
										 |  |  |                 print(f"Testing {item.absolute()}") | 
					
						
							| 
									
										
										
										
											2016-09-03 12:33:38 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-24 23:02:40 +00:00
										 |  |  |             with self.subTest(filename=item): | 
					
						
							|  |  |  |                 source = read_pyfile(item) | 
					
						
							| 
									
										
										
										
											2020-03-02 21:59:01 +03:00
										 |  |  |                 self.check_ast_roundtrip(source) | 
					
						
							| 
									
										
										
										
											2010-06-29 14:08:23 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-24 23:02:40 +00:00
										 |  |  | if __name__ == "__main__": | 
					
						
							| 
									
										
										
										
											2014-07-16 14:26:09 -05:00
										 |  |  |     unittest.main() |