From bfb0c2444764d06411276669b9963e85d4933be0 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Salgado Date: Tue, 16 Jul 2024 19:57:22 +0100 Subject: [PATCH] [3.13] gh-121130: Fix f-string format specifiers with debug expressions (GH-121150) (cherry picked from commit c46d64e0ef8e92a6b4ab4805d813d7e4d6663380) Co-authored-by: Pablo Galindo Salgado --- Doc/library/ast.rst | 4 +- Lib/test/test_ast.py | 4969 +++++++++++++---- Lib/test/test_fstring.py | 9 + ...-06-29-10-46-14.gh-issue-121130.Rj66Xs.rst | 2 + Parser/action_helpers.c | 63 +- Parser/lexer/lexer.c | 24 +- Parser/lexer/state.c | 1 + Parser/lexer/state.h | 1 + 8 files changed, 4047 insertions(+), 1026 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-06-29-10-46-14.gh-issue-121130.Rj66Xs.rst diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index c5daa6e2439fa9..727d44df0c8b4a 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -316,9 +316,7 @@ Literals args=[ Name(id='a', ctx=Load())]), conversion=-1, - format_spec=JoinedStr( - values=[ - Constant(value='.3')]))])) + format_spec=Constant(value='.3'))])) .. class:: List(elts, ctx) diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index 4362ea61c6be26..e3383355d3c415 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -13,6 +13,7 @@ import weakref from functools import partial from textwrap import dedent + try: import _testinternalcapi except ImportError: @@ -23,15 +24,16 @@ from test.support import os_helper, script_helper from test.support.ast_helper import ASTTestMixin + def to_tuple(t): if t is None or isinstance(t, (str, int, complex, float, bytes)) or t is Ellipsis: return t elif isinstance(t, list): return [to_tuple(e) for e in t] result = [t.__class__.__name__] - if hasattr(t, 'lineno') and hasattr(t, 'col_offset'): + if hasattr(t, "lineno") and hasattr(t, "col_offset"): result.append((t.lineno, t.col_offset)) - if hasattr(t, 'end_lineno') and hasattr(t, 'end_col_offset'): + if hasattr(t, "end_lineno") and hasattr(t, "end_col_offset"): result[-1] += (t.end_lineno, t.end_col_offset) if t._fields is None: return tuple(result) @@ -214,86 +216,85 @@ def to_tuple(t): # These are compiled through "single" # because of overlap with "eval", it just tests what # can't be tested with "eval" -single_tests = [ - "1+2" -] +single_tests = ["1+2"] # These are compiled through "eval" # It should test all expressions eval_tests = [ - # None - "None", - # BoolOp - "a and b", - # BinOp - "a + b", - # UnaryOp - "not v", - # Lambda - "lambda:None", - # Dict - "{ 1:2 }", - # Empty dict - "{}", - # Set - "{None,}", - # Multiline dict (test for .lineno & .col_offset) - """{ + # None + "None", + # BoolOp + "a and b", + # BinOp + "a + b", + # UnaryOp + "not v", + # Lambda + "lambda:None", + # Dict + "{ 1:2 }", + # Empty dict + "{}", + # Set + "{None,}", + # Multiline dict (test for .lineno & .col_offset) + """{ 1 : 2 }""", - # ListComp - "[a for b in c if d]", - # GeneratorExp - "(a for b in c if d)", - # Comprehensions with multiple for targets - "[(a,b) for a,b in c]", - "[(a,b) for (a,b) in c]", - "[(a,b) for [a,b] in c]", - "{(a,b) for a,b in c}", - "{(a,b) for (a,b) in c}", - "{(a,b) for [a,b] in c}", - "((a,b) for a,b in c)", - "((a,b) for (a,b) in c)", - "((a,b) for [a,b] in c)", - # Yield - yield expressions can't work outside a function - # - # Compare - "1 < 2 < 3", - # Call - "f(1,2,c=3,*d,**e)", - # Call with multi-character starred - "f(*[0, 1])", - # Call with a generator argument - "f(a for a in b)", - # Num - "10", - # Str - "'string'", - # Attribute - "a.b", - # Subscript - "a[b:c]", - # Name - "v", - # List - "[1,2,3]", - # Empty list - "[]", - # Tuple - "1,2,3", - # Tuple - "(1,2,3)", - # Empty tuple - "()", - # Combination - "a.b.c.d(a.b[1:2])", + # ListComp + "[a for b in c if d]", + # GeneratorExp + "(a for b in c if d)", + # Comprehensions with multiple for targets + "[(a,b) for a,b in c]", + "[(a,b) for (a,b) in c]", + "[(a,b) for [a,b] in c]", + "{(a,b) for a,b in c}", + "{(a,b) for (a,b) in c}", + "{(a,b) for [a,b] in c}", + "((a,b) for a,b in c)", + "((a,b) for (a,b) in c)", + "((a,b) for [a,b] in c)", + # Yield - yield expressions can't work outside a function + # + # Compare + "1 < 2 < 3", + # Call + "f(1,2,c=3,*d,**e)", + # Call with multi-character starred + "f(*[0, 1])", + # Call with a generator argument + "f(a for a in b)", + # Num + "10", + # Str + "'string'", + # Attribute + "a.b", + # Subscript + "a[b:c]", + # Name + "v", + # List + "[1,2,3]", + # Empty list + "[]", + # Tuple + "1,2,3", + # Tuple + "(1,2,3)", + # Empty tuple + "()", + # Combination + "a.b.c.d(a.b[1:2])", ] # TODO: expr_context, slice, boolop, operator, unaryop, cmpop, comprehension # excepthandler, arguments, keywords, alias + class AST_Tests(unittest.TestCase): maxDiff = None @@ -302,7 +303,7 @@ def _is_ast_node(self, name, node): return False if "ast" not in node.__module__: return False - return name != 'AST' and name[0].isupper() + return name != "AST" and name[0].isupper() def _assertTrueorder(self, ast_node, parent_pos): if not isinstance(ast_node, ast.AST) or ast_node._fields is None: @@ -315,7 +316,7 @@ def _assertTrueorder(self, ast_node, parent_pos): value = getattr(ast_node, name) if isinstance(value, list): first_pos = parent_pos - if value and name == 'decorator_list': + if value and name == "decorator_list": first_pos = (value[0].lineno, value[0].col_offset) for child in value: self._assertTrueorder(child, first_pos) @@ -340,6 +341,7 @@ def test_AST_objects(self): def test_AST_garbage_collection(self): class X: pass + a = ast.AST() a.x = X() a.x.a = a @@ -349,9 +351,11 @@ class X: self.assertIsNone(ref()) def test_snippets(self): - for input, output, kind in ((exec_tests, exec_results, "exec"), - (single_tests, single_results, "single"), - (eval_tests, eval_results, "eval")): + for input, output, kind in ( + (exec_tests, exec_results, "exec"), + (single_tests, single_results, "single"), + (eval_tests, eval_results, "eval"), + ): for i, o in zip(input, output): with self.subTest(action="parsing", input=i): ast_tree = compile(i, "?", kind, ast.PyCF_ONLY_AST) @@ -365,11 +369,11 @@ def test_ast_validation(self): snippets_to_validate = exec_tests + single_tests + eval_tests for snippet in snippets_to_validate: tree = ast.parse(snippet) - compile(tree, '', 'exec') + compile(tree, "", "exec") def test_optimization_levels__debug__(self): - cases = [(-1, '__debug__'), (0, '__debug__'), (1, False), (2, False)] - for (optval, expected) in cases: + cases = [(-1, "__debug__"), (0, "__debug__"), (1, False), (2, False)] + for optval, expected in cases: with self.subTest(optval=optval, expected=expected): res1 = ast.parse("__debug__", optimize=optval) res2 = ast.parse(ast.parse("__debug__"), optimize=optval) @@ -383,15 +387,21 @@ def test_optimization_levels__debug__(self): self.assertEqual(res.body[0].value.id, expected) def test_optimization_levels_const_folding(self): - folded = ('Expr', (1, 0, 1, 5), ('Constant', (1, 0, 1, 5), 3, None)) - not_folded = ('Expr', (1, 0, 1, 5), - ('BinOp', (1, 0, 1, 5), - ('Constant', (1, 0, 1, 1), 1, None), - ('Add',), - ('Constant', (1, 4, 1, 5), 2, None))) + folded = ("Expr", (1, 0, 1, 5), ("Constant", (1, 0, 1, 5), 3, None)) + not_folded = ( + "Expr", + (1, 0, 1, 5), + ( + "BinOp", + (1, 0, 1, 5), + ("Constant", (1, 0, 1, 1), 1, None), + ("Add",), + ("Constant", (1, 4, 1, 5), 2, None), + ), + ) cases = [(-1, not_folded), (0, not_folded), (1, folded), (2, folded)] - for (optval, expected) in cases: + for optval, expected in cases: with self.subTest(optval=optval): tree1 = ast.parse("1 + 2", optimize=optval) tree2 = ast.parse(ast.parse("1 + 2"), optimize=optval) @@ -400,9 +410,7 @@ def test_optimization_levels_const_folding(self): self.assertEqual(res, expected) def test_invalid_position_information(self): - invalid_linenos = [ - (10, 1), (-10, -11), (10, -11), (-5, -2), (-5, 1) - ] + invalid_linenos = [(10, 1), (-10, -11), (10, -11), (-5, -2), (-5, 1)] for lineno, end_lineno in invalid_linenos: with self.subTest(f"Check invalid linenos {lineno}:{end_lineno}"): @@ -411,25 +419,36 @@ def test_invalid_position_information(self): tree.body[0].lineno = lineno tree.body[0].end_lineno = end_lineno with self.assertRaises(ValueError): - compile(tree, '', 'exec') + compile(tree, "", "exec") - invalid_col_offsets = [ - (10, 1), (-10, -11), (10, -11), (-5, -2), (-5, 1) - ] + invalid_col_offsets = [(10, 1), (-10, -11), (10, -11), (-5, -2), (-5, 1)] for col_offset, end_col_offset in invalid_col_offsets: - with self.subTest(f"Check invalid col_offset {col_offset}:{end_col_offset}"): + with self.subTest( + f"Check invalid col_offset {col_offset}:{end_col_offset}" + ): snippet = "a = 1" tree = ast.parse(snippet) tree.body[0].col_offset = col_offset tree.body[0].end_col_offset = end_col_offset with self.assertRaises(ValueError): - compile(tree, '', 'exec') + compile(tree, "", "exec") def test_compilation_of_ast_nodes_with_default_end_position_values(self): - tree = ast.Module(body=[ - ast.Import(names=[ast.alias(name='builtins', lineno=1, col_offset=0)], lineno=1, col_offset=0), - ast.Import(names=[ast.alias(name='traceback', lineno=0, col_offset=0)], lineno=0, col_offset=1) - ], type_ignores=[]) + tree = ast.Module( + body=[ + ast.Import( + names=[ast.alias(name="builtins", lineno=1, col_offset=0)], + lineno=1, + col_offset=0, + ), + ast.Import( + names=[ast.alias(name="traceback", lineno=0, col_offset=0)], + lineno=0, + col_offset=1, + ), + ], + type_ignores=[], + ) # Check that compilation doesn't crash. Note: this may crash explicitly only on debug mode. compile(tree, "", "exec") @@ -454,7 +473,7 @@ def test_alias(self): im = ast.parse("from bar import y").body[0] self.assertEqual(len(im.names), 1) alias = im.names[0] - self.assertEqual(alias.name, 'y') + self.assertEqual(alias.name, "y") self.assertIsNone(alias.asname) self.assertEqual(alias.lineno, 1) self.assertEqual(alias.end_lineno, 1) @@ -463,7 +482,7 @@ def test_alias(self): im = ast.parse("from bar import *").body[0] alias = im.names[0] - self.assertEqual(alias.name, '*') + self.assertEqual(alias.name, "*") self.assertIsNone(alias.asname) self.assertEqual(alias.lineno, 1) self.assertEqual(alias.end_lineno, 1) @@ -497,21 +516,21 @@ def test_base_classes(self): self.assertTrue(issubclass(ast.Gt, ast.AST)) def test_import_deprecated(self): - ast = import_fresh_module('ast') + ast = import_fresh_module("ast") depr_regex = ( - r'ast\.{} is deprecated and will be removed in Python 3.14; ' - r'use ast\.Constant instead' + r"ast\.{} is deprecated and will be removed in Python 3.14; " + r"use ast\.Constant instead" ) - for name in 'Num', 'Str', 'Bytes', 'NameConstant', 'Ellipsis': + for name in "Num", "Str", "Bytes", "NameConstant", "Ellipsis": with self.assertWarnsRegex(DeprecationWarning, depr_regex.format(name)): getattr(ast, name) def test_field_attr_existence_deprecated(self): with warnings.catch_warnings(): - warnings.filterwarnings('ignore', '', DeprecationWarning) + warnings.filterwarnings("ignore", "", DeprecationWarning) from ast import Num, Str, Bytes, NameConstant, Ellipsis - for name in ('Num', 'Str', 'Bytes', 'NameConstant', 'Ellipsis'): + for name in ("Num", "Str", "Bytes", "NameConstant", "Ellipsis"): item = getattr(ast, name) if self._is_ast_node(name, item): with self.subTest(item): @@ -523,10 +542,10 @@ def test_field_attr_existence_deprecated(self): def test_field_attr_existence(self): for name, item in ast.__dict__.items(): # These emit DeprecationWarnings - if name in {'Num', 'Str', 'Bytes', 'NameConstant', 'Ellipsis'}: + if name in {"Num", "Str", "Bytes", "NameConstant", "Ellipsis"}: continue # constructor has a different signature - if name == 'Index': + if name == "Index": continue if self._is_ast_node(name, item): x = self._construct_ast_class(item) @@ -537,28 +556,41 @@ def _construct_ast_class(self, cls): kwargs = {} for name, typ in cls.__annotations__.items(): if typ is str: - kwargs[name] = 'capybara' + kwargs[name] = "capybara" elif typ is int: kwargs[name] = 42 elif typ is object: - kwargs[name] = b'capybara' + kwargs[name] = b"capybara" elif isinstance(typ, type) and issubclass(typ, ast.AST): kwargs[name] = self._construct_ast_class(typ) return cls(**kwargs) def test_arguments(self): x = ast.arguments() - self.assertEqual(x._fields, ('posonlyargs', 'args', 'vararg', 'kwonlyargs', - 'kw_defaults', 'kwarg', 'defaults')) - self.assertEqual(x.__annotations__, { - 'posonlyargs': list[ast.arg], - 'args': list[ast.arg], - 'vararg': ast.arg | None, - 'kwonlyargs': list[ast.arg], - 'kw_defaults': list[ast.expr], - 'kwarg': ast.arg | None, - 'defaults': list[ast.expr], - }) + self.assertEqual( + x._fields, + ( + "posonlyargs", + "args", + "vararg", + "kwonlyargs", + "kw_defaults", + "kwarg", + "defaults", + ), + ) + self.assertEqual( + x.__annotations__, + { + "posonlyargs": list[ast.arg], + "args": list[ast.arg], + "vararg": ast.arg | None, + "kwonlyargs": list[ast.arg], + "kw_defaults": list[ast.expr], + "kwarg": ast.arg | None, + "defaults": list[ast.expr], + }, + ) self.assertEqual(x.args, []) self.assertIsNone(x.vararg) @@ -569,7 +601,7 @@ def test_arguments(self): def test_field_attr_writable_deprecated(self): with warnings.catch_warnings(): - warnings.filterwarnings('ignore', '', DeprecationWarning) + warnings.filterwarnings("ignore", "", DeprecationWarning) x = ast.Num() # We can assign to _fields x._fields = 666 @@ -583,13 +615,13 @@ def test_field_attr_writable(self): def test_classattrs_deprecated(self): with warnings.catch_warnings(): - warnings.filterwarnings('ignore', '', DeprecationWarning) + warnings.filterwarnings("ignore", "", DeprecationWarning) from ast import Num, Str, Bytes, NameConstant, Ellipsis with warnings.catch_warnings(record=True) as wlog: - warnings.filterwarnings('always', '', DeprecationWarning) + warnings.filterwarnings("always", "", DeprecationWarning) x = ast.Num() - self.assertEqual(x._fields, ('value', 'kind')) + self.assertEqual(x._fields, ("value", "kind")) with self.assertRaises(AttributeError): x.value @@ -612,7 +644,7 @@ def test_classattrs_deprecated(self): x = ast.Num(42, lineno=0) self.assertEqual(x.lineno, 0) - self.assertEqual(x._fields, ('value', 'kind')) + self.assertEqual(x._fields, ("value", "kind")) self.assertEqual(x.value, 42) self.assertEqual(x.n, 42) @@ -620,57 +652,62 @@ def test_classattrs_deprecated(self): self.assertRaises(TypeError, ast.Num, 1, None, 2, lineno=0) # Arbitrary keyword arguments are supported - self.assertEqual(ast.Num(1, foo='bar').foo, 'bar') + self.assertEqual(ast.Num(1, foo="bar").foo, "bar") - with self.assertRaisesRegex(TypeError, "Num got multiple values for argument 'n'"): + with self.assertRaisesRegex( + TypeError, "Num got multiple values for argument 'n'" + ): ast.Num(1, n=2) self.assertEqual(ast.Num(42).n, 42) self.assertEqual(ast.Num(4.25).n, 4.25) self.assertEqual(ast.Num(4.25j).n, 4.25j) - self.assertEqual(ast.Str('42').s, '42') - self.assertEqual(ast.Bytes(b'42').s, b'42') + self.assertEqual(ast.Str("42").s, "42") + self.assertEqual(ast.Bytes(b"42").s, b"42") self.assertIs(ast.NameConstant(True).value, True) self.assertIs(ast.NameConstant(False).value, False) self.assertIs(ast.NameConstant(None).value, None) - self.assertEqual([str(w.message) for w in wlog], [ - 'ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead', - "Constant.__init__ missing 1 required positional argument: 'value'. This will become " - 'an error in Python 3.15.', - 'Attribute n is deprecated and will be removed in Python 3.14; use value instead', - 'ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead', - 'Attribute n is deprecated and will be removed in Python 3.14; use value instead', - 'ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead', - "Constant.__init__ missing 1 required positional argument: 'value'. This will become " - 'an error in Python 3.15.', - 'ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead', - 'Attribute n is deprecated and will be removed in Python 3.14; use value instead', - 'ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead', - 'ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead', - 'ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead', - "Constant.__init__ got an unexpected keyword argument 'foo'. Support for " - 'arbitrary keyword arguments is deprecated and will be removed in Python ' - '3.15.', - 'ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead', - 'Attribute n is deprecated and will be removed in Python 3.14; use value instead', - 'ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead', - 'Attribute n is deprecated and will be removed in Python 3.14; use value instead', - 'ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead', - 'Attribute n is deprecated and will be removed in Python 3.14; use value instead', - 'ast.Str is deprecated and will be removed in Python 3.14; use ast.Constant instead', - 'Attribute s is deprecated and will be removed in Python 3.14; use value instead', - 'ast.Bytes is deprecated and will be removed in Python 3.14; use ast.Constant instead', - 'Attribute s is deprecated and will be removed in Python 3.14; use value instead', - 'ast.NameConstant is deprecated and will be removed in Python 3.14; use ast.Constant instead', - 'ast.NameConstant is deprecated and will be removed in Python 3.14; use ast.Constant instead', - 'ast.NameConstant is deprecated and will be removed in Python 3.14; use ast.Constant instead', - ]) + self.assertEqual( + [str(w.message) for w in wlog], + [ + "ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "Constant.__init__ missing 1 required positional argument: 'value'. This will become " + "an error in Python 3.15.", + "Attribute n is deprecated and will be removed in Python 3.14; use value instead", + "ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "Attribute n is deprecated and will be removed in Python 3.14; use value instead", + "ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "Constant.__init__ missing 1 required positional argument: 'value'. This will become " + "an error in Python 3.15.", + "ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "Attribute n is deprecated and will be removed in Python 3.14; use value instead", + "ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "Constant.__init__ got an unexpected keyword argument 'foo'. Support for " + "arbitrary keyword arguments is deprecated and will be removed in Python " + "3.15.", + "ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "Attribute n is deprecated and will be removed in Python 3.14; use value instead", + "ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "Attribute n is deprecated and will be removed in Python 3.14; use value instead", + "ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "Attribute n is deprecated and will be removed in Python 3.14; use value instead", + "ast.Str is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "Attribute s is deprecated and will be removed in Python 3.14; use value instead", + "ast.Bytes is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "Attribute s is deprecated and will be removed in Python 3.14; use value instead", + "ast.NameConstant is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "ast.NameConstant is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "ast.NameConstant is deprecated and will be removed in Python 3.14; use ast.Constant instead", + ], + ) def test_classattrs(self): with self.assertWarns(DeprecationWarning): x = ast.Constant() - self.assertEqual(x._fields, ('value', 'kind')) + self.assertEqual(x._fields, ("value", "kind")) with self.assertRaises(AttributeError): x.value @@ -689,7 +726,7 @@ def test_classattrs(self): x = ast.Constant(42, lineno=0) self.assertEqual(x.lineno, 0) - self.assertEqual(x._fields, ('value', 'kind')) + self.assertEqual(x._fields, ("value", "kind")) self.assertEqual(x.value, 42) self.assertRaises(TypeError, ast.Constant, 1, None, 2) @@ -697,16 +734,18 @@ def test_classattrs(self): # Arbitrary keyword arguments are supported (but deprecated) with self.assertWarns(DeprecationWarning): - self.assertEqual(ast.Constant(1, foo='bar').foo, 'bar') + self.assertEqual(ast.Constant(1, foo="bar").foo, "bar") - with self.assertRaisesRegex(TypeError, "Constant got multiple values for argument 'value'"): + with self.assertRaisesRegex( + TypeError, "Constant got multiple values for argument 'value'" + ): ast.Constant(1, value=2) self.assertEqual(ast.Constant(42).value, 42) self.assertEqual(ast.Constant(4.25).value, 4.25) self.assertEqual(ast.Constant(4.25j).value, 4.25j) - self.assertEqual(ast.Constant('42').value, '42') - self.assertEqual(ast.Constant(b'42').value, b'42') + self.assertEqual(ast.Constant("42").value, "42") + self.assertEqual(ast.Constant(b"42").value, b"42") self.assertIs(ast.Constant(True).value, True) self.assertIs(ast.Constant(False).value, False) self.assertIs(ast.Constant(None).value, None) @@ -714,43 +753,46 @@ def test_classattrs(self): def test_realtype(self): with warnings.catch_warnings(): - warnings.filterwarnings('ignore', '', DeprecationWarning) + warnings.filterwarnings("ignore", "", DeprecationWarning) from ast import Num, Str, Bytes, NameConstant, Ellipsis with warnings.catch_warnings(record=True) as wlog: - warnings.filterwarnings('always', '', DeprecationWarning) + warnings.filterwarnings("always", "", DeprecationWarning) self.assertIs(type(ast.Num(42)), ast.Constant) self.assertIs(type(ast.Num(4.25)), ast.Constant) self.assertIs(type(ast.Num(4.25j)), ast.Constant) - self.assertIs(type(ast.Str('42')), ast.Constant) - self.assertIs(type(ast.Bytes(b'42')), ast.Constant) + self.assertIs(type(ast.Str("42")), ast.Constant) + self.assertIs(type(ast.Bytes(b"42")), ast.Constant) self.assertIs(type(ast.NameConstant(True)), ast.Constant) self.assertIs(type(ast.NameConstant(False)), ast.Constant) self.assertIs(type(ast.NameConstant(None)), ast.Constant) self.assertIs(type(ast.Ellipsis()), ast.Constant) - self.assertEqual([str(w.message) for w in wlog], [ - 'ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead', - 'ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead', - 'ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead', - 'ast.Str is deprecated and will be removed in Python 3.14; use ast.Constant instead', - 'ast.Bytes is deprecated and will be removed in Python 3.14; use ast.Constant instead', - 'ast.NameConstant is deprecated and will be removed in Python 3.14; use ast.Constant instead', - 'ast.NameConstant is deprecated and will be removed in Python 3.14; use ast.Constant instead', - 'ast.NameConstant is deprecated and will be removed in Python 3.14; use ast.Constant instead', - 'ast.Ellipsis is deprecated and will be removed in Python 3.14; use ast.Constant instead', - ]) + self.assertEqual( + [str(w.message) for w in wlog], + [ + "ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "ast.Str is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "ast.Bytes is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "ast.NameConstant is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "ast.NameConstant is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "ast.NameConstant is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "ast.Ellipsis is deprecated and will be removed in Python 3.14; use ast.Constant instead", + ], + ) def test_isinstance(self): from ast import Constant with warnings.catch_warnings(): - warnings.filterwarnings('ignore', '', DeprecationWarning) + warnings.filterwarnings("ignore", "", DeprecationWarning) from ast import Num, Str, Bytes, NameConstant, Ellipsis cls_depr_msg = ( - 'ast.{} is deprecated and will be removed in Python 3.14; ' - 'use ast.Constant instead' + "ast.{} is deprecated and will be removed in Python 3.14; " + "use ast.Constant instead" ) assertNumDeprecated = partial( @@ -765,7 +807,7 @@ def test_isinstance(self): assertNameConstantDeprecated = partial( self.assertWarnsRegex, DeprecationWarning, - cls_depr_msg.format("NameConstant") + cls_depr_msg.format("NameConstant"), ) assertEllipsisDeprecated = partial( self.assertWarnsRegex, DeprecationWarning, cls_depr_msg.format("Ellipsis") @@ -779,12 +821,12 @@ def test_isinstance(self): self.assertIsInstance(n, Num) with assertStrDeprecated(): - s = Str('42') + s = Str("42") with assertStrDeprecated(): self.assertIsInstance(s, Str) with assertBytesDeprecated(): - b = Bytes(b'42') + b = Bytes(b"42") with assertBytesDeprecated(): self.assertIsInstance(b, Bytes) @@ -806,10 +848,10 @@ def test_isinstance(self): self.assertIsInstance(Constant(arg), Num) with assertStrDeprecated(): - self.assertIsInstance(Constant('42'), Str) + self.assertIsInstance(Constant("42"), Str) with assertBytesDeprecated(): - self.assertIsInstance(Constant(b'42'), Bytes) + self.assertIsInstance(Constant(b"42"), Bytes) for arg in True, False, None: with self.subTest(arg=arg): @@ -820,7 +862,7 @@ def test_isinstance(self): self.assertIsInstance(Constant(...), Ellipsis) with assertStrDeprecated(): - s = Str('42') + s = Str("42") assertNumDeprecated(self.assertNotIsInstance, s, Num) assertBytesDeprecated(self.assertNotIsInstance, s, Bytes) @@ -840,44 +882,52 @@ def test_isinstance(self): with assertNumDeprecated(): self.assertNotIsInstance(n, Num) - for arg in '42', True, False: + for arg in "42", True, False: with self.subTest(arg=arg): with assertNumDeprecated(): self.assertNotIsInstance(Constant(arg), Num) assertStrDeprecated(self.assertNotIsInstance, Constant(42), Str) - assertBytesDeprecated(self.assertNotIsInstance, Constant('42'), Bytes) - assertNameConstantDeprecated(self.assertNotIsInstance, Constant(42), NameConstant) + assertBytesDeprecated(self.assertNotIsInstance, Constant("42"), Bytes) + assertNameConstantDeprecated( + self.assertNotIsInstance, Constant(42), NameConstant + ) assertEllipsisDeprecated(self.assertNotIsInstance, Constant(42), Ellipsis) assertNumDeprecated(self.assertNotIsInstance, Constant(None), Num) assertStrDeprecated(self.assertNotIsInstance, Constant(None), Str) assertBytesDeprecated(self.assertNotIsInstance, Constant(None), Bytes) - assertNameConstantDeprecated(self.assertNotIsInstance, Constant(1), NameConstant) + assertNameConstantDeprecated( + self.assertNotIsInstance, Constant(1), NameConstant + ) assertEllipsisDeprecated(self.assertNotIsInstance, Constant(None), Ellipsis) - class S(str): pass + class S(str): + pass + with assertStrDeprecated(): - self.assertIsInstance(Constant(S('42')), Str) + self.assertIsInstance(Constant(S("42")), Str) with assertNumDeprecated(): - self.assertNotIsInstance(Constant(S('42')), Num) + self.assertNotIsInstance(Constant(S("42")), Num) def test_constant_subclasses_deprecated(self): with warnings.catch_warnings(): - warnings.filterwarnings('ignore', '', DeprecationWarning) + warnings.filterwarnings("ignore", "", DeprecationWarning) from ast import Num with warnings.catch_warnings(record=True) as wlog: - warnings.filterwarnings('always', '', DeprecationWarning) + warnings.filterwarnings("always", "", DeprecationWarning) + class N(ast.Num): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.z = 'spam' + self.z = "spam" + class N2(ast.Num): pass n = N(42) self.assertEqual(n.n, 42) - self.assertEqual(n.z, 'spam') + self.assertEqual(n.z, "spam") self.assertIs(type(n), N) self.assertIsInstance(n, N) self.assertIsInstance(n, ast.Num) @@ -887,26 +937,30 @@ class N2(ast.Num): self.assertEqual(n.n, 42) self.assertIs(type(n), N) - self.assertEqual([str(w.message) for w in wlog], [ - 'Attribute n is deprecated and will be removed in Python 3.14; use value instead', - 'Attribute n is deprecated and will be removed in Python 3.14; use value instead', - 'ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead', - 'ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead', - 'Attribute n is deprecated and will be removed in Python 3.14; use value instead', - 'Attribute n is deprecated and will be removed in Python 3.14; use value instead', - ]) + self.assertEqual( + [str(w.message) for w in wlog], + [ + "Attribute n is deprecated and will be removed in Python 3.14; use value instead", + "Attribute n is deprecated and will be removed in Python 3.14; use value instead", + "ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "Attribute n is deprecated and will be removed in Python 3.14; use value instead", + "Attribute n is deprecated and will be removed in Python 3.14; use value instead", + ], + ) def test_constant_subclasses(self): class N(ast.Constant): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.z = 'spam' + self.z = "spam" + class N2(ast.Constant): pass n = N(42) self.assertEqual(n.value, 42) - self.assertEqual(n.z, 'spam') + self.assertEqual(n.z, "spam") self.assertEqual(type(n), N) self.assertTrue(isinstance(n, N)) self.assertTrue(isinstance(n, ast.Constant)) @@ -925,7 +979,7 @@ def test_nodeclasses(self): # Zero arguments constructor explicitly allowed (but deprecated) with self.assertWarns(DeprecationWarning): x = ast.BinOp() - self.assertEqual(x._fields, ('left', 'op', 'right')) + self.assertEqual(x._fields, ("left", "op", "right")) # Random attribute allowed too x.foobarbaz = 5 @@ -990,9 +1044,7 @@ def test_invalid_constant(self): for invalid_constant in int, (1, 2, int), frozenset((1, 2, int)): e = ast.Expression(body=ast.Constant(invalid_constant)) ast.fix_missing_locations(e) - with self.assertRaisesRegex( - TypeError, "invalid type in Constant: type" - ): + with self.assertRaisesRegex(TypeError, "invalid type in Constant: type"): compile(e, "", "eval") def test_empty_yield_from(self): @@ -1008,13 +1060,15 @@ def test_issue31592(self): # There shouldn't be an assertion failure in case of a bad # unicodedata.normalize(). import unicodedata + def bad_normalize(*args): return None - with support.swap_attr(unicodedata, 'normalize', bad_normalize): - self.assertRaises(TypeError, ast.parse, '\u03D5') + + with support.swap_attr(unicodedata, "normalize", bad_normalize): + self.assertRaises(TypeError, ast.parse, "\u03d5") def test_issue18374_binop_col_offset(self): - tree = ast.parse('4+5+6+7') + tree = ast.parse("4+5+6+7") parent_binop = tree.body[0].value child_binop = parent_binop.left grandchild_binop = child_binop.left @@ -1025,7 +1079,7 @@ def test_issue18374_binop_col_offset(self): self.assertEqual(grandchild_binop.col_offset, 0) self.assertEqual(grandchild_binop.end_col_offset, 3) - tree = ast.parse('4+5-\\\n 6-7') + tree = ast.parse("4+5-\\\n 6-7") parent_binop = tree.body[0].value child_binop = parent_binop.left grandchild_binop = child_binop.left @@ -1045,48 +1099,53 @@ def test_issue18374_binop_col_offset(self): self.assertEqual(grandchild_binop.end_lineno, 1) def test_issue39579_dotted_name_end_col_offset(self): - tree = ast.parse('@a.b.c\ndef f(): pass') + tree = ast.parse("@a.b.c\ndef f(): pass") attr_b = tree.body[0].decorator_list[0].value self.assertEqual(attr_b.end_col_offset, 4) def test_ast_asdl_signature(self): - self.assertEqual(ast.withitem.__doc__, "withitem(expr context_expr, expr? optional_vars)") + self.assertEqual( + ast.withitem.__doc__, "withitem(expr context_expr, expr? optional_vars)" + ) self.assertEqual(ast.GtE.__doc__, "GtE") self.assertEqual(ast.Name.__doc__, "Name(identifier id, expr_context ctx)") - self.assertEqual(ast.cmpop.__doc__, "cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn") + self.assertEqual( + ast.cmpop.__doc__, + "cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn", + ) expressions = [f" | {node.__doc__}" for node in ast.expr.__subclasses__()] expressions[0] = f"expr = {ast.expr.__subclasses__()[0].__doc__}" self.assertCountEqual(ast.expr.__doc__.split("\n"), expressions) def test_positional_only_feature_version(self): - ast.parse('def foo(x, /): ...', feature_version=(3, 8)) - ast.parse('def bar(x=1, /): ...', feature_version=(3, 8)) + ast.parse("def foo(x, /): ...", feature_version=(3, 8)) + ast.parse("def bar(x=1, /): ...", feature_version=(3, 8)) with self.assertRaises(SyntaxError): - ast.parse('def foo(x, /): ...', feature_version=(3, 7)) + ast.parse("def foo(x, /): ...", feature_version=(3, 7)) with self.assertRaises(SyntaxError): - ast.parse('def bar(x=1, /): ...', feature_version=(3, 7)) + ast.parse("def bar(x=1, /): ...", feature_version=(3, 7)) - ast.parse('lambda x, /: ...', feature_version=(3, 8)) - ast.parse('lambda x=1, /: ...', feature_version=(3, 8)) + ast.parse("lambda x, /: ...", feature_version=(3, 8)) + ast.parse("lambda x=1, /: ...", feature_version=(3, 8)) with self.assertRaises(SyntaxError): - ast.parse('lambda x, /: ...', feature_version=(3, 7)) + ast.parse("lambda x, /: ...", feature_version=(3, 7)) with self.assertRaises(SyntaxError): - ast.parse('lambda x=1, /: ...', feature_version=(3, 7)) + ast.parse("lambda x=1, /: ...", feature_version=(3, 7)) def test_assignment_expression_feature_version(self): - ast.parse('(x := 0)', feature_version=(3, 8)) + ast.parse("(x := 0)", feature_version=(3, 8)) with self.assertRaises(SyntaxError): - ast.parse('(x := 0)', feature_version=(3, 7)) + ast.parse("(x := 0)", feature_version=(3, 7)) def test_conditional_context_managers_parse_with_low_feature_version(self): # regression test for gh-115881 - ast.parse('with (x() if y else z()): ...', feature_version=(3, 8)) + ast.parse("with (x() if y else z()): ...", feature_version=(3, 8)) def test_exception_groups_feature_version(self): - code = dedent(''' + code = dedent(""" try: ... except* Exception: ... - ''') + """) ast.parse(code) with self.assertRaises(SyntaxError): ast.parse(code, feature_version=(3, 10)) @@ -1117,45 +1176,50 @@ def test_type_params_default_feature_version(self): def test_invalid_major_feature_version(self): with self.assertRaises(ValueError): - ast.parse('pass', feature_version=(2, 7)) + ast.parse("pass", feature_version=(2, 7)) with self.assertRaises(ValueError): - ast.parse('pass', feature_version=(4, 0)) + ast.parse("pass", feature_version=(4, 0)) def test_constant_as_name(self): for constant in "True", "False", "None": expr = ast.Expression(ast.Name(constant, ast.Load())) ast.fix_missing_locations(expr) - with self.assertRaisesRegex(ValueError, f"identifier field can't represent '{constant}' constant"): + with self.assertRaisesRegex( + ValueError, f"identifier field can't represent '{constant}' constant" + ): compile(expr, "", "eval") def test_precedence_enum(self): class _Precedence(enum.IntEnum): """Precedence table that originated from python grammar.""" - NAMED_EXPR = enum.auto() # := - TUPLE = enum.auto() # , - YIELD = enum.auto() # 'yield', 'yield from' - TEST = enum.auto() # 'if'-'else', 'lambda' - OR = enum.auto() # 'or' - AND = enum.auto() # 'and' - NOT = enum.auto() # 'not' - CMP = enum.auto() # '<', '>', '==', '>=', '<=', '!=', - # 'in', 'not in', 'is', 'is not' + + NAMED_EXPR = enum.auto() # := + TUPLE = enum.auto() # , + YIELD = enum.auto() # 'yield', 'yield from' + TEST = enum.auto() # 'if'-'else', 'lambda' + OR = enum.auto() # 'or' + AND = enum.auto() # 'and' + NOT = enum.auto() # 'not' + CMP = enum.auto() # '<', '>', '==', '>=', '<=', '!=', + # 'in', 'not in', 'is', 'is not' EXPR = enum.auto() - BOR = EXPR # '|' - BXOR = enum.auto() # '^' - BAND = enum.auto() # '&' - SHIFT = enum.auto() # '<<', '>>' - ARITH = enum.auto() # '+', '-' - TERM = enum.auto() # '*', '@', '/', '%', '//' - FACTOR = enum.auto() # unary '+', '-', '~' - POWER = enum.auto() # '**' - AWAIT = enum.auto() # 'await' + BOR = EXPR # '|' + BXOR = enum.auto() # '^' + BAND = enum.auto() # '&' + SHIFT = enum.auto() # '<<', '>>' + ARITH = enum.auto() # '+', '-' + TERM = enum.auto() # '*', '@', '/', '%', '//' + FACTOR = enum.auto() # unary '+', '-', '~' + POWER = enum.auto() # '**' + AWAIT = enum.auto() # 'await' ATOM = enum.auto() + def next(self): try: return self.__class__(self + 1) except ValueError: return self + enum._test_simple_enum(_Precedence, ast._Precedence) @support.cpython_only @@ -1172,8 +1236,7 @@ def check_limit(prefix, repeated): ast.parse(expect_ok) for depth in (fail_depth, crash_depth): broken = prefix + repeated * depth - details = "Compiling ({!r} + {!r} * {})".format( - prefix, repeated, depth) + details = "Compiling ({!r} + {!r} * {})".format(prefix, repeated, depth) with self.assertRaises(RecursionError, msg=details): with support.infinite_recursion(): ast.parse(broken) @@ -1184,8 +1247,9 @@ def check_limit(prefix, repeated): check_limit("a", "*a") def test_null_bytes(self): - with self.assertRaises(SyntaxError, - msg="source code string cannot contain null bytes"): + with self.assertRaises( + SyntaxError, msg="source code string cannot contain null bytes" + ): ast.parse("a\0b") def assert_none_check(self, node: type[ast.AST], attr: str, source: str) -> None: @@ -1282,9 +1346,16 @@ def test_copy_with_parents(self): for node in ast.walk(tree2): for child in ast.iter_child_nodes(node): - if hasattr(child, "parent") and not isinstance(child, ( - ast.expr_context, ast.boolop, ast.unaryop, ast.cmpop, ast.operator, - )): + if hasattr(child, "parent") and not isinstance( + child, + ( + ast.expr_context, + ast.boolop, + ast.unaryop, + ast.cmpop, + ast.operator, + ), + ): self.assertEqual(to_tuple(child.parent), to_tuple(node)) @@ -1292,13 +1363,13 @@ class ASTHelpers_Test(unittest.TestCase): maxDiff = None def test_parse(self): - a = ast.parse('foo(1 + 1)') - b = compile('foo(1 + 1)', '', 'exec', ast.PyCF_ONLY_AST) + a = ast.parse("foo(1 + 1)") + b = compile("foo(1 + 1)", "", "exec", ast.PyCF_ONLY_AST) self.assertEqual(ast.dump(a), ast.dump(b)) def test_parse_in_error(self): try: - 1/0 + 1 / 0 except Exception: with self.assertRaises(SyntaxError) as e: ast.literal_eval(r"'\U'") @@ -1306,27 +1377,32 @@ def test_parse_in_error(self): def test_dump(self): node = ast.parse('spam(eggs, "and cheese")') - self.assertEqual(ast.dump(node), + self.assertEqual( + ast.dump(node), "Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load()), " - "args=[Name(id='eggs', ctx=Load()), Constant(value='and cheese')]))])" + "args=[Name(id='eggs', ctx=Load()), Constant(value='and cheese')]))])", ) - self.assertEqual(ast.dump(node, annotate_fields=False), + self.assertEqual( + ast.dump(node, annotate_fields=False), "Module([Expr(Call(Name('spam', Load()), [Name('eggs', Load()), " - "Constant('and cheese')]))])" + "Constant('and cheese')]))])", ) - self.assertEqual(ast.dump(node, include_attributes=True), + self.assertEqual( + ast.dump(node, include_attributes=True), "Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load(), " "lineno=1, col_offset=0, end_lineno=1, end_col_offset=4), " "args=[Name(id='eggs', ctx=Load(), lineno=1, col_offset=5, " "end_lineno=1, end_col_offset=9), Constant(value='and cheese', " "lineno=1, col_offset=11, end_lineno=1, end_col_offset=23)], " "lineno=1, col_offset=0, end_lineno=1, end_col_offset=24), " - "lineno=1, col_offset=0, end_lineno=1, end_col_offset=24)])" + "lineno=1, col_offset=0, end_lineno=1, end_col_offset=24)])", ) def test_dump_indent(self): node = ast.parse('spam(eggs, "and cheese")') - self.assertEqual(ast.dump(node, indent=3), """\ + self.assertEqual( + ast.dump(node, indent=3), + """\ Module( body=[ Expr( @@ -1334,8 +1410,11 @@ def test_dump_indent(self): func=Name(id='spam', ctx=Load()), args=[ Name(id='eggs', ctx=Load()), - Constant(value='and cheese')]))])""") - self.assertEqual(ast.dump(node, annotate_fields=False, indent='\t'), """\ + Constant(value='and cheese')]))])""", + ) + self.assertEqual( + ast.dump(node, annotate_fields=False, indent="\t"), + """\ Module( \t[ \t\tExpr( @@ -1343,8 +1422,11 @@ def test_dump_indent(self): \t\t\t\tName('spam', Load()), \t\t\t\t[ \t\t\t\t\tName('eggs', Load()), -\t\t\t\t\tConstant('and cheese')]))])""") - self.assertEqual(ast.dump(node, include_attributes=True, indent=3), """\ +\t\t\t\t\tConstant('and cheese')]))])""", + ) + self.assertEqual( + ast.dump(node, include_attributes=True, indent=3), + """\ Module( body=[ Expr( @@ -1377,69 +1459,73 @@ def test_dump_indent(self): lineno=1, col_offset=0, end_lineno=1, - end_col_offset=24)])""") + end_col_offset=24)])""", + ) def test_dump_incomplete(self): node = ast.Raise(lineno=3, col_offset=4) - self.assertEqual(ast.dump(node), - "Raise()" + self.assertEqual(ast.dump(node), "Raise()") + self.assertEqual( + ast.dump(node, include_attributes=True), "Raise(lineno=3, col_offset=4)" ) - self.assertEqual(ast.dump(node, include_attributes=True), - "Raise(lineno=3, col_offset=4)" + node = ast.Raise(exc=ast.Name(id="e", ctx=ast.Load()), lineno=3, col_offset=4) + self.assertEqual(ast.dump(node), "Raise(exc=Name(id='e', ctx=Load()))") + self.assertEqual( + ast.dump(node, annotate_fields=False), "Raise(Name('e', Load()))" ) - node = ast.Raise(exc=ast.Name(id='e', ctx=ast.Load()), lineno=3, col_offset=4) - self.assertEqual(ast.dump(node), - "Raise(exc=Name(id='e', ctx=Load()))" + self.assertEqual( + ast.dump(node, include_attributes=True), + "Raise(exc=Name(id='e', ctx=Load()), lineno=3, col_offset=4)", ) - self.assertEqual(ast.dump(node, annotate_fields=False), - "Raise(Name('e', Load()))" + self.assertEqual( + ast.dump(node, annotate_fields=False, include_attributes=True), + "Raise(Name('e', Load()), lineno=3, col_offset=4)", ) - self.assertEqual(ast.dump(node, include_attributes=True), - "Raise(exc=Name(id='e', ctx=Load()), lineno=3, col_offset=4)" - ) - self.assertEqual(ast.dump(node, annotate_fields=False, include_attributes=True), - "Raise(Name('e', Load()), lineno=3, col_offset=4)" - ) - node = ast.Raise(cause=ast.Name(id='e', ctx=ast.Load())) - self.assertEqual(ast.dump(node), - "Raise(cause=Name(id='e', ctx=Load()))" - ) - self.assertEqual(ast.dump(node, annotate_fields=False), - "Raise(cause=Name('e', Load()))" + node = ast.Raise(cause=ast.Name(id="e", ctx=ast.Load())) + self.assertEqual(ast.dump(node), "Raise(cause=Name(id='e', ctx=Load()))") + self.assertEqual( + ast.dump(node, annotate_fields=False), "Raise(cause=Name('e', Load()))" ) # Arguments: node = ast.arguments(args=[ast.arg("x")]) - self.assertEqual(ast.dump(node, annotate_fields=False), + self.assertEqual( + ast.dump(node, annotate_fields=False), "arguments([], [arg('x')])", ) node = ast.arguments(posonlyargs=[ast.arg("x")]) - self.assertEqual(ast.dump(node, annotate_fields=False), + self.assertEqual( + ast.dump(node, annotate_fields=False), "arguments([arg('x')])", ) - node = ast.arguments(posonlyargs=[ast.arg("x")], kwonlyargs=[ast.arg('y')]) - self.assertEqual(ast.dump(node, annotate_fields=False), + node = ast.arguments(posonlyargs=[ast.arg("x")], kwonlyargs=[ast.arg("y")]) + self.assertEqual( + ast.dump(node, annotate_fields=False), "arguments([arg('x')], kwonlyargs=[arg('y')])", ) - node = ast.arguments(args=[ast.arg("x")], kwonlyargs=[ast.arg('y')]) - self.assertEqual(ast.dump(node, annotate_fields=False), + node = ast.arguments(args=[ast.arg("x")], kwonlyargs=[ast.arg("y")]) + self.assertEqual( + ast.dump(node, annotate_fields=False), "arguments([], [arg('x')], kwonlyargs=[arg('y')])", ) node = ast.arguments() - self.assertEqual(ast.dump(node, annotate_fields=False), + self.assertEqual( + ast.dump(node, annotate_fields=False), "arguments()", ) # Classes: node = ast.ClassDef( - 'T', + "T", [], - [ast.keyword('a', ast.Constant(None))], + [ast.keyword("a", ast.Constant(None))], [], - [ast.Name('dataclass', ctx=ast.Load())], + [ast.Name("dataclass", ctx=ast.Load())], ) - self.assertEqual(ast.dump(node), + self.assertEqual( + ast.dump(node), "ClassDef(name='T', keywords=[keyword(arg='a', value=Constant(value=None))], decorator_list=[Name(id='dataclass', ctx=Load())])", ) - self.assertEqual(ast.dump(node, annotate_fields=False), + self.assertEqual( + ast.dump(node, annotate_fields=False), "ClassDef('T', [], [keyword('a', Constant(None))], [], [Name('dataclass', Load())])", ) @@ -1467,7 +1553,7 @@ def check_text(code, empty, full, **kwargs): check_node( # Corner case: there are no real `Name` instances with `id=''`: - ast.Name(id='', ctx=ast.Load()), + ast.Name(id="", ctx=ast.Load()), empty="Name(id='', ctx=Load())", full="Name(id='', ctx=Load())", ) @@ -1485,7 +1571,7 @@ def check_text(code, empty, full, **kwargs): ) check_node( - ast.Constant(value=''), + ast.Constant(value=""), empty="Constant(value='')", full="Constant(value='')", ) @@ -1522,16 +1608,19 @@ def check_text(code, empty, full, **kwargs): ) def test_copy_location(self): - src = ast.parse('1 + 1', mode='eval') + src = ast.parse("1 + 1", mode="eval") src.body.right = ast.copy_location(ast.Constant(2), src.body.right) - self.assertEqual(ast.dump(src, include_attributes=True), - 'Expression(body=BinOp(left=Constant(value=1, lineno=1, col_offset=0, ' - 'end_lineno=1, end_col_offset=1), op=Add(), right=Constant(value=2, ' - 'lineno=1, col_offset=4, end_lineno=1, end_col_offset=5), lineno=1, ' - 'col_offset=0, end_lineno=1, end_col_offset=5))' - ) - func = ast.Name('spam', ast.Load()) - src = ast.Call(col_offset=1, lineno=1, end_lineno=1, end_col_offset=1, func=func) + self.assertEqual( + ast.dump(src, include_attributes=True), + "Expression(body=BinOp(left=Constant(value=1, lineno=1, col_offset=0, " + "end_lineno=1, end_col_offset=1), op=Add(), right=Constant(value=2, " + "lineno=1, col_offset=4, end_lineno=1, end_col_offset=5), lineno=1, " + "col_offset=0, end_lineno=1, end_col_offset=5))", + ) + func = ast.Name("spam", ast.Load()) + src = ast.Call( + col_offset=1, lineno=1, end_lineno=1, end_col_offset=1, func=func + ) new = ast.copy_location(src, ast.Call(col_offset=None, lineno=None, func=func)) self.assertIsNone(new.end_lineno) self.assertIsNone(new.end_col_offset) @@ -1540,11 +1629,13 @@ def test_copy_location(self): def test_fix_missing_locations(self): src = ast.parse('write("spam")') - src.body.append(ast.Expr(ast.Call(ast.Name('spam', ast.Load()), - [ast.Constant('eggs')], []))) + src.body.append( + ast.Expr(ast.Call(ast.Name("spam", ast.Load()), [ast.Constant("eggs")], [])) + ) self.assertEqual(src, ast.fix_missing_locations(src)) self.maxDiff = None - self.assertEqual(ast.dump(src, include_attributes=True), + self.assertEqual( + ast.dump(src, include_attributes=True), "Module(body=[Expr(value=Call(func=Name(id='write', ctx=Load(), " "lineno=1, col_offset=0, end_lineno=1, end_col_offset=5), " "args=[Constant(value='spam', lineno=1, col_offset=6, end_lineno=1, " @@ -1554,26 +1645,28 @@ def test_fix_missing_locations(self): "lineno=1, col_offset=0, end_lineno=1, end_col_offset=0), " "args=[Constant(value='eggs', lineno=1, col_offset=0, end_lineno=1, " "end_col_offset=0)], lineno=1, col_offset=0, end_lineno=1, " - "end_col_offset=0), lineno=1, col_offset=0, end_lineno=1, end_col_offset=0)])" + "end_col_offset=0), lineno=1, col_offset=0, end_lineno=1, end_col_offset=0)])", ) def test_increment_lineno(self): - src = ast.parse('1 + 1', mode='eval') + src = ast.parse("1 + 1", mode="eval") self.assertEqual(ast.increment_lineno(src, n=3), src) - self.assertEqual(ast.dump(src, include_attributes=True), - 'Expression(body=BinOp(left=Constant(value=1, lineno=4, col_offset=0, ' - 'end_lineno=4, end_col_offset=1), op=Add(), right=Constant(value=1, ' - 'lineno=4, col_offset=4, end_lineno=4, end_col_offset=5), lineno=4, ' - 'col_offset=0, end_lineno=4, end_col_offset=5))' + self.assertEqual( + ast.dump(src, include_attributes=True), + "Expression(body=BinOp(left=Constant(value=1, lineno=4, col_offset=0, " + "end_lineno=4, end_col_offset=1), op=Add(), right=Constant(value=1, " + "lineno=4, col_offset=4, end_lineno=4, end_col_offset=5), lineno=4, " + "col_offset=0, end_lineno=4, end_col_offset=5))", ) # issue10869: do not increment lineno of root twice - src = ast.parse('1 + 1', mode='eval') + src = ast.parse("1 + 1", mode="eval") self.assertEqual(ast.increment_lineno(src.body, n=3), src.body) - self.assertEqual(ast.dump(src, include_attributes=True), - 'Expression(body=BinOp(left=Constant(value=1, lineno=4, col_offset=0, ' - 'end_lineno=4, end_col_offset=1), op=Add(), right=Constant(value=1, ' - 'lineno=4, col_offset=4, end_lineno=4, end_col_offset=5), lineno=4, ' - 'col_offset=0, end_lineno=4, end_col_offset=5))' + self.assertEqual( + ast.dump(src, include_attributes=True), + "Expression(body=BinOp(left=Constant(value=1, lineno=4, col_offset=0, " + "end_lineno=4, end_col_offset=1), op=Add(), right=Constant(value=1, " + "lineno=4, col_offset=4, end_lineno=4, end_col_offset=5), lineno=4, " + "col_offset=0, end_lineno=4, end_col_offset=5))", ) src = ast.Call( func=ast.Name("test", ast.Load()), args=[], keywords=[], lineno=1 @@ -1582,81 +1675,82 @@ def test_increment_lineno(self): self.assertIsNone(ast.increment_lineno(src).end_lineno) def test_increment_lineno_on_module(self): - src = ast.parse(dedent("""\ + src = ast.parse( + dedent("""\ a = 1 b = 2 # type: ignore c = 3 d = 4 # type: ignore@tag - """), type_comments=True) + """), + type_comments=True, + ) ast.increment_lineno(src, n=5) self.assertEqual(src.type_ignores[0].lineno, 7) self.assertEqual(src.type_ignores[1].lineno, 9) - self.assertEqual(src.type_ignores[1].tag, '@tag') + self.assertEqual(src.type_ignores[1].tag, "@tag") def test_iter_fields(self): - node = ast.parse('foo()', mode='eval') + node = ast.parse("foo()", mode="eval") d = dict(ast.iter_fields(node.body)) - self.assertEqual(d.pop('func').id, 'foo') - self.assertEqual(d, {'keywords': [], 'args': []}) + self.assertEqual(d.pop("func").id, "foo") + self.assertEqual(d, {"keywords": [], "args": []}) def test_iter_child_nodes(self): - node = ast.parse("spam(23, 42, eggs='leek')", mode='eval') + node = ast.parse("spam(23, 42, eggs='leek')", mode="eval") self.assertEqual(len(list(ast.iter_child_nodes(node.body))), 4) iterator = ast.iter_child_nodes(node.body) - self.assertEqual(next(iterator).id, 'spam') + self.assertEqual(next(iterator).id, "spam") self.assertEqual(next(iterator).value, 23) self.assertEqual(next(iterator).value, 42) - self.assertEqual(ast.dump(next(iterator)), - "keyword(arg='eggs', value=Constant(value='leek'))" + self.assertEqual( + ast.dump(next(iterator)), + "keyword(arg='eggs', value=Constant(value='leek'))", ) def test_get_docstring(self): node = ast.parse('"""line one\n line two"""') - self.assertEqual(ast.get_docstring(node), - 'line one\nline two') + self.assertEqual(ast.get_docstring(node), "line one\nline two") node = ast.parse('class foo:\n """line one\n line two"""') - self.assertEqual(ast.get_docstring(node.body[0]), - 'line one\nline two') + self.assertEqual(ast.get_docstring(node.body[0]), "line one\nline two") node = ast.parse('def foo():\n """line one\n line two"""') - self.assertEqual(ast.get_docstring(node.body[0]), - 'line one\nline two') + self.assertEqual(ast.get_docstring(node.body[0]), "line one\nline two") node = ast.parse('async def foo():\n """spam\n ham"""') - self.assertEqual(ast.get_docstring(node.body[0]), 'spam\nham') + self.assertEqual(ast.get_docstring(node.body[0]), "spam\nham") node = ast.parse('async def foo():\n """spam\n ham"""') - self.assertEqual(ast.get_docstring(node.body[0], clean=False), 'spam\n ham') + self.assertEqual(ast.get_docstring(node.body[0], clean=False), "spam\n ham") - node = ast.parse('x') + node = ast.parse("x") self.assertRaises(TypeError, ast.get_docstring, node.body[0]) def test_get_docstring_none(self): - self.assertIsNone(ast.get_docstring(ast.parse(''))) + self.assertIsNone(ast.get_docstring(ast.parse(""))) node = ast.parse('x = "not docstring"') self.assertIsNone(ast.get_docstring(node)) - node = ast.parse('def foo():\n pass') + node = ast.parse("def foo():\n pass") self.assertIsNone(ast.get_docstring(node)) - node = ast.parse('class foo:\n pass') + node = ast.parse("class foo:\n pass") self.assertIsNone(ast.get_docstring(node.body[0])) node = ast.parse('class foo:\n x = "not docstring"') self.assertIsNone(ast.get_docstring(node.body[0])) - node = ast.parse('class foo:\n def bar(self): pass') + node = ast.parse("class foo:\n def bar(self): pass") self.assertIsNone(ast.get_docstring(node.body[0])) - node = ast.parse('def foo():\n pass') + node = ast.parse("def foo():\n pass") self.assertIsNone(ast.get_docstring(node.body[0])) node = ast.parse('def foo():\n x = "not docstring"') self.assertIsNone(ast.get_docstring(node.body[0])) - node = ast.parse('async def foo():\n pass') + node = ast.parse("async def foo():\n pass") self.assertIsNone(ast.get_docstring(node.body[0])) node = ast.parse('async def foo():\n x = "not docstring"') self.assertIsNone(ast.get_docstring(node.body[0])) - node = ast.parse('async def foo():\n 42') + node = ast.parse("async def foo():\n 42") self.assertIsNone(ast.get_docstring(node.body[0])) def test_multi_line_docstring_col_offset_and_lineno_issue16806(self): @@ -1679,75 +1773,79 @@ def test_multi_line_docstring_col_offset_and_lineno_issue16806(self): self.assertEqual(node.body[2].lineno, 13) def test_elif_stmt_start_position(self): - node = ast.parse('if a:\n pass\nelif b:\n pass\n') + node = ast.parse("if a:\n pass\nelif b:\n pass\n") elif_stmt = node.body[0].orelse[0] self.assertEqual(elif_stmt.lineno, 3) self.assertEqual(elif_stmt.col_offset, 0) def test_elif_stmt_start_position_with_else(self): - node = ast.parse('if a:\n pass\nelif b:\n pass\nelse:\n pass\n') + node = ast.parse("if a:\n pass\nelif b:\n pass\nelse:\n pass\n") elif_stmt = node.body[0].orelse[0] self.assertEqual(elif_stmt.lineno, 3) self.assertEqual(elif_stmt.col_offset, 0) def test_starred_expr_end_position_within_call(self): - node = ast.parse('f(*[0, 1])') + node = ast.parse("f(*[0, 1])") starred_expr = node.body[0].value.args[0] self.assertEqual(starred_expr.end_lineno, 1) self.assertEqual(starred_expr.end_col_offset, 9) def test_literal_eval(self): - self.assertEqual(ast.literal_eval('[1, 2, 3]'), [1, 2, 3]) + self.assertEqual(ast.literal_eval("[1, 2, 3]"), [1, 2, 3]) self.assertEqual(ast.literal_eval('{"foo": 42}'), {"foo": 42}) - self.assertEqual(ast.literal_eval('(True, False, None)'), (True, False, None)) - self.assertEqual(ast.literal_eval('{1, 2, 3}'), {1, 2, 3}) + self.assertEqual(ast.literal_eval("(True, False, None)"), (True, False, None)) + self.assertEqual(ast.literal_eval("{1, 2, 3}"), {1, 2, 3}) self.assertEqual(ast.literal_eval('b"hi"'), b"hi") - self.assertEqual(ast.literal_eval('set()'), set()) - self.assertRaises(ValueError, ast.literal_eval, 'foo()') - self.assertEqual(ast.literal_eval('6'), 6) - self.assertEqual(ast.literal_eval('+6'), 6) - self.assertEqual(ast.literal_eval('-6'), -6) - self.assertEqual(ast.literal_eval('3.25'), 3.25) - self.assertEqual(ast.literal_eval('+3.25'), 3.25) - self.assertEqual(ast.literal_eval('-3.25'), -3.25) - self.assertEqual(repr(ast.literal_eval('-0.0')), '-0.0') - self.assertRaises(ValueError, ast.literal_eval, '++6') - self.assertRaises(ValueError, ast.literal_eval, '+True') - self.assertRaises(ValueError, ast.literal_eval, '2+3') + self.assertEqual(ast.literal_eval("set()"), set()) + self.assertRaises(ValueError, ast.literal_eval, "foo()") + self.assertEqual(ast.literal_eval("6"), 6) + self.assertEqual(ast.literal_eval("+6"), 6) + self.assertEqual(ast.literal_eval("-6"), -6) + self.assertEqual(ast.literal_eval("3.25"), 3.25) + self.assertEqual(ast.literal_eval("+3.25"), 3.25) + self.assertEqual(ast.literal_eval("-3.25"), -3.25) + self.assertEqual(repr(ast.literal_eval("-0.0")), "-0.0") + self.assertRaises(ValueError, ast.literal_eval, "++6") + self.assertRaises(ValueError, ast.literal_eval, "+True") + self.assertRaises(ValueError, ast.literal_eval, "2+3") def test_literal_eval_str_int_limit(self): with support.adjust_int_max_str_digits(4000): - ast.literal_eval('3'*4000) # no error + ast.literal_eval("3" * 4000) # no error with self.assertRaises(SyntaxError) as err_ctx: - ast.literal_eval('3'*4001) - self.assertIn('Exceeds the limit ', str(err_ctx.exception)) - self.assertIn(' Consider hexadecimal ', str(err_ctx.exception)) + ast.literal_eval("3" * 4001) + self.assertIn("Exceeds the limit ", str(err_ctx.exception)) + self.assertIn(" Consider hexadecimal ", str(err_ctx.exception)) def test_literal_eval_complex(self): # Issue #4907 - self.assertEqual(ast.literal_eval('6j'), 6j) - self.assertEqual(ast.literal_eval('-6j'), -6j) - self.assertEqual(ast.literal_eval('6.75j'), 6.75j) - self.assertEqual(ast.literal_eval('-6.75j'), -6.75j) - self.assertEqual(ast.literal_eval('3+6j'), 3+6j) - self.assertEqual(ast.literal_eval('-3+6j'), -3+6j) - self.assertEqual(ast.literal_eval('3-6j'), 3-6j) - self.assertEqual(ast.literal_eval('-3-6j'), -3-6j) - self.assertEqual(ast.literal_eval('3.25+6.75j'), 3.25+6.75j) - self.assertEqual(ast.literal_eval('-3.25+6.75j'), -3.25+6.75j) - self.assertEqual(ast.literal_eval('3.25-6.75j'), 3.25-6.75j) - self.assertEqual(ast.literal_eval('-3.25-6.75j'), -3.25-6.75j) - self.assertEqual(ast.literal_eval('(3+6j)'), 3+6j) - self.assertRaises(ValueError, ast.literal_eval, '-6j+3') - self.assertRaises(ValueError, ast.literal_eval, '-6j+3j') - self.assertRaises(ValueError, ast.literal_eval, '3+-6j') - self.assertRaises(ValueError, ast.literal_eval, '3+(0+6j)') - self.assertRaises(ValueError, ast.literal_eval, '-(3+6j)') + self.assertEqual(ast.literal_eval("6j"), 6j) + self.assertEqual(ast.literal_eval("-6j"), -6j) + self.assertEqual(ast.literal_eval("6.75j"), 6.75j) + self.assertEqual(ast.literal_eval("-6.75j"), -6.75j) + self.assertEqual(ast.literal_eval("3+6j"), 3 + 6j) + self.assertEqual(ast.literal_eval("-3+6j"), -3 + 6j) + self.assertEqual(ast.literal_eval("3-6j"), 3 - 6j) + self.assertEqual(ast.literal_eval("-3-6j"), -3 - 6j) + self.assertEqual(ast.literal_eval("3.25+6.75j"), 3.25 + 6.75j) + self.assertEqual(ast.literal_eval("-3.25+6.75j"), -3.25 + 6.75j) + self.assertEqual(ast.literal_eval("3.25-6.75j"), 3.25 - 6.75j) + self.assertEqual(ast.literal_eval("-3.25-6.75j"), -3.25 - 6.75j) + self.assertEqual(ast.literal_eval("(3+6j)"), 3 + 6j) + self.assertRaises(ValueError, ast.literal_eval, "-6j+3") + self.assertRaises(ValueError, ast.literal_eval, "-6j+3j") + self.assertRaises(ValueError, ast.literal_eval, "3+-6j") + self.assertRaises(ValueError, ast.literal_eval, "3+(0+6j)") + self.assertRaises(ValueError, ast.literal_eval, "-(3+6j)") def test_literal_eval_malformed_dict_nodes(self): - malformed = ast.Dict(keys=[ast.Constant(1), ast.Constant(2)], values=[ast.Constant(3)]) + malformed = ast.Dict( + keys=[ast.Constant(1), ast.Constant(2)], values=[ast.Constant(3)] + ) self.assertRaises(ValueError, ast.literal_eval, malformed) - malformed = ast.Dict(keys=[ast.Constant(1)], values=[ast.Constant(2), ast.Constant(3)]) + malformed = ast.Dict( + keys=[ast.Constant(1)], values=[ast.Constant(2), ast.Constant(3)] + ) self.assertRaises(ValueError, ast.literal_eval, malformed) def test_literal_eval_trailing_ws(self): @@ -1757,46 +1855,54 @@ def test_literal_eval_trailing_ws(self): self.assertRaises(IndentationError, ast.literal_eval, "\n -1") def test_literal_eval_malformed_lineno(self): - msg = r'malformed node or string on line 3:' + msg = r"malformed node or string on line 3:" with self.assertRaisesRegex(ValueError, msg): ast.literal_eval("{'a': 1,\n'b':2,\n'c':++3,\n'd':4}") - node = ast.UnaryOp( - ast.UAdd(), ast.UnaryOp(ast.UAdd(), ast.Constant(6))) - self.assertIsNone(getattr(node, 'lineno', None)) - msg = r'malformed node or string:' + node = ast.UnaryOp(ast.UAdd(), ast.UnaryOp(ast.UAdd(), ast.Constant(6))) + self.assertIsNone(getattr(node, "lineno", None)) + msg = r"malformed node or string:" with self.assertRaisesRegex(ValueError, msg): ast.literal_eval(node) def test_literal_eval_syntax_errors(self): with self.assertRaisesRegex(SyntaxError, "unexpected indent"): - ast.literal_eval(r''' + ast.literal_eval(r""" \ (\ - \ ''') + \ """) def test_bad_integer(self): # issue13436: Bad error message with invalid numeric values - body = [ast.ImportFrom(module='time', - names=[ast.alias(name='sleep')], - level=None, - lineno=None, col_offset=None)] + body = [ + ast.ImportFrom( + module="time", + names=[ast.alias(name="sleep")], + level=None, + lineno=None, + col_offset=None, + ) + ] mod = ast.Module(body, []) with self.assertRaises(ValueError) as cm: - compile(mod, 'test', 'exec') + compile(mod, "test", "exec") self.assertIn("invalid integer value: None", str(cm.exception)) def test_level_as_none(self): - body = [ast.ImportFrom(module='time', - names=[ast.alias(name='sleep', - lineno=0, col_offset=0)], - level=None, - lineno=0, col_offset=0)] + body = [ + ast.ImportFrom( + module="time", + names=[ast.alias(name="sleep", lineno=0, col_offset=0)], + level=None, + lineno=0, + col_offset=0, + ) + ] mod = ast.Module(body, []) - code = compile(mod, 'test', 'exec') + code = compile(mod, "test", "exec") ns = {} exec(code, ns) - self.assertIn('sleep', ns) + self.assertIn("sleep", ns) def test_recursion_direct(self): e = ast.UnaryOp(op=ast.Not(), lineno=0, col_offset=0, operand=ast.Constant(1)) @@ -1816,7 +1922,6 @@ def test_recursion_indirect(self): class ASTValidatorTests(unittest.TestCase): - def mod(self, mod, msg=None, mode="exec", *, exc=ValueError): mod.lineno = mod.col_offset = 0 ast.fix_missing_locations(mod) @@ -1842,9 +1947,15 @@ def test_module(self): self.mod(m, "must have Load context", "eval") def _check_arguments(self, fac, check): - def arguments(args=None, posonlyargs=None, vararg=None, - kwonlyargs=None, kwarg=None, - defaults=None, kw_defaults=None): + def arguments( + args=None, + posonlyargs=None, + vararg=None, + kwonlyargs=None, + kwarg=None, + defaults=None, + kw_defaults=None, + ): if args is None: args = [] if posonlyargs is None: @@ -1855,49 +1966,67 @@ def arguments(args=None, posonlyargs=None, vararg=None, defaults = [] if kw_defaults is None: kw_defaults = [] - args = ast.arguments(args, posonlyargs, vararg, kwonlyargs, - kw_defaults, kwarg, defaults) + args = ast.arguments( + args, posonlyargs, vararg, kwonlyargs, kw_defaults, kwarg, defaults + ) return fac(args) + args = [ast.arg("x", ast.Name("x", ast.Store()))] check(arguments(args=args), "must have Load context") check(arguments(posonlyargs=args), "must have Load context") check(arguments(kwonlyargs=args), "must have Load context") - check(arguments(defaults=[ast.Constant(3)]), - "more positional defaults than args") - check(arguments(kw_defaults=[ast.Constant(4)]), - "length of kwonlyargs is not the same as kw_defaults") + check( + arguments(defaults=[ast.Constant(3)]), "more positional defaults than args" + ) + check( + arguments(kw_defaults=[ast.Constant(4)]), + "length of kwonlyargs is not the same as kw_defaults", + ) args = [ast.arg("x", ast.Name("x", ast.Load()))] - check(arguments(args=args, defaults=[ast.Name("x", ast.Store())]), - "must have Load context") - args = [ast.arg("a", ast.Name("x", ast.Load())), - ast.arg("b", ast.Name("y", ast.Load()))] - check(arguments(kwonlyargs=args, - kw_defaults=[None, ast.Name("x", ast.Store())]), - "must have Load context") + check( + arguments(args=args, defaults=[ast.Name("x", ast.Store())]), + "must have Load context", + ) + args = [ + ast.arg("a", ast.Name("x", ast.Load())), + ast.arg("b", ast.Name("y", ast.Load())), + ] + check( + arguments(kwonlyargs=args, kw_defaults=[None, ast.Name("x", ast.Store())]), + "must have Load context", + ) def test_funcdef(self): a = ast.arguments([], [], None, [], [], None, []) f = ast.FunctionDef("x", a, [], [], None, None, []) self.stmt(f, "empty body on FunctionDef") - f = ast.FunctionDef("x", a, [ast.Pass()], [ast.Name("x", ast.Store())], None, None, []) + f = ast.FunctionDef( + "x", a, [ast.Pass()], [ast.Name("x", ast.Store())], None, None, [] + ) self.stmt(f, "must have Load context") - f = ast.FunctionDef("x", a, [ast.Pass()], [], - ast.Name("x", ast.Store()), None, []) + f = ast.FunctionDef( + "x", a, [ast.Pass()], [], ast.Name("x", ast.Store()), None, [] + ) self.stmt(f, "must have Load context") f = ast.FunctionDef("x", ast.arguments(), [ast.Pass()]) self.stmt(f) + def fac(args): return ast.FunctionDef("x", args, [ast.Pass()], [], None, None, []) + self._check_arguments(fac, self.stmt) def test_funcdef_pattern_matching(self): # gh-104799: New fields on FunctionDef should be added at the end def matcher(node): match node: - case ast.FunctionDef("foo", ast.arguments(args=[ast.arg("bar")]), - [ast.Pass()], - [ast.Name("capybara", ast.Load())], - ast.Name("pacarana", ast.Load())): + case ast.FunctionDef( + "foo", + ast.arguments(args=[ast.arg("bar")]), + [ast.Pass()], + [ast.Name("capybara", ast.Load())], + ast.Name("pacarana", ast.Load()), + ): return True case _: return False @@ -1913,7 +2042,9 @@ def foo(bar) -> pacarana: self.assertTrue(matcher(funcdef)) def test_classdef(self): - def cls(bases=None, keywords=None, body=None, decorator_list=None, type_params=None): + def cls( + bases=None, keywords=None, body=None, decorator_list=None, type_params=None + ): if bases is None: bases = [] if keywords is None: @@ -1924,38 +2055,46 @@ def cls(bases=None, keywords=None, body=None, decorator_list=None, type_params=N decorator_list = [] if type_params is None: type_params = [] - return ast.ClassDef("myclass", bases, keywords, - body, decorator_list, type_params) - self.stmt(cls(bases=[ast.Name("x", ast.Store())]), - "must have Load context") - self.stmt(cls(keywords=[ast.keyword("x", ast.Name("x", ast.Store()))]), - "must have Load context") + return ast.ClassDef( + "myclass", bases, keywords, body, decorator_list, type_params + ) + + self.stmt(cls(bases=[ast.Name("x", ast.Store())]), "must have Load context") + self.stmt( + cls(keywords=[ast.keyword("x", ast.Name("x", ast.Store()))]), + "must have Load context", + ) self.stmt(cls(body=[]), "empty body on ClassDef") self.stmt(cls(body=[None]), "None disallowed") - self.stmt(cls(decorator_list=[ast.Name("x", ast.Store())]), - "must have Load context") + self.stmt( + cls(decorator_list=[ast.Name("x", ast.Store())]), "must have Load context" + ) def test_delete(self): self.stmt(ast.Delete([]), "empty targets on Delete") self.stmt(ast.Delete([None]), "None disallowed") - self.stmt(ast.Delete([ast.Name("x", ast.Load())]), - "must have Del context") + self.stmt(ast.Delete([ast.Name("x", ast.Load())]), "must have Del context") def test_assign(self): self.stmt(ast.Assign([], ast.Constant(3)), "empty targets on Assign") self.stmt(ast.Assign([None], ast.Constant(3)), "None disallowed") - self.stmt(ast.Assign([ast.Name("x", ast.Load())], ast.Constant(3)), - "must have Store context") - self.stmt(ast.Assign([ast.Name("x", ast.Store())], - ast.Name("y", ast.Store())), - "must have Load context") + self.stmt( + ast.Assign([ast.Name("x", ast.Load())], ast.Constant(3)), + "must have Store context", + ) + self.stmt( + ast.Assign([ast.Name("x", ast.Store())], ast.Name("y", ast.Store())), + "must have Load context", + ) def test_augassign(self): - aug = ast.AugAssign(ast.Name("x", ast.Load()), ast.Add(), - ast.Name("y", ast.Load())) + aug = ast.AugAssign( + ast.Name("x", ast.Load()), ast.Add(), ast.Name("y", ast.Load()) + ) self.stmt(aug, "must have Store context") - aug = ast.AugAssign(ast.Name("x", ast.Store()), ast.Add(), - ast.Name("y", ast.Store())) + aug = ast.AugAssign( + ast.Name("x", ast.Store()), ast.Add(), ast.Name("y", ast.Store()) + ) self.stmt(aug, "must have Load context") def test_for(self): @@ -1963,21 +2102,28 @@ def test_for(self): y = ast.Name("y", ast.Load()) p = ast.Pass() self.stmt(ast.For(x, y, [], []), "empty body on For") - self.stmt(ast.For(ast.Name("x", ast.Load()), y, [p], []), - "must have Store context") - self.stmt(ast.For(x, ast.Name("y", ast.Store()), [p], []), - "must have Load context") + self.stmt( + ast.For(ast.Name("x", ast.Load()), y, [p], []), "must have Store context" + ) + self.stmt( + ast.For(x, ast.Name("y", ast.Store()), [p], []), "must have Load context" + ) e = ast.Expr(ast.Name("x", ast.Store())) self.stmt(ast.For(x, y, [e], []), "must have Load context") self.stmt(ast.For(x, y, [p], [e]), "must have Load context") def test_while(self): self.stmt(ast.While(ast.Constant(3), [], []), "empty body on While") - self.stmt(ast.While(ast.Name("x", ast.Store()), [ast.Pass()], []), - "must have Load context") - self.stmt(ast.While(ast.Constant(3), [ast.Pass()], - [ast.Expr(ast.Name("x", ast.Store()))]), - "must have Load context") + self.stmt( + ast.While(ast.Name("x", ast.Store()), [ast.Pass()], []), + "must have Load context", + ) + self.stmt( + ast.While( + ast.Constant(3), [ast.Pass()], [ast.Expr(ast.Name("x", ast.Store()))] + ), + "must have Load context", + ) def test_if(self): self.stmt(ast.If(ast.Constant(3), [], []), "empty body on If") @@ -1985,8 +2131,9 @@ def test_if(self): self.stmt(i, "must have Load context") i = ast.If(ast.Constant(3), [ast.Expr(ast.Name("x", ast.Store()))], []) self.stmt(i, "must have Load context") - i = ast.If(ast.Constant(3), [ast.Pass()], - [ast.Expr(ast.Name("x", ast.Store()))]) + i = ast.If( + ast.Constant(3), [ast.Pass()], [ast.Expr(ast.Name("x", ast.Store()))] + ) self.stmt(i, "must have Load context") def test_with(self): @@ -2048,10 +2195,10 @@ def test_try_star(self): self.stmt(t, "must have Load context") def test_assert(self): - self.stmt(ast.Assert(ast.Name("x", ast.Store()), None), - "must have Load context") - assrt = ast.Assert(ast.Name("x", ast.Load()), - ast.Name("y", ast.Store())) + self.stmt( + ast.Assert(ast.Name("x", ast.Store()), None), "must have Load context" + ) + assrt = ast.Assert(ast.Name("x", ast.Load()), ast.Name("y", ast.Store())) self.stmt(assrt, "must have Load context") def test_import(self): @@ -2088,10 +2235,11 @@ def test_unaryop(self): def test_lambda(self): a = ast.arguments([], [], None, [], [], None, []) - self.expr(ast.Lambda(a, ast.Name("x", ast.Store())), - "must have Load context") + self.expr(ast.Lambda(a, ast.Name("x", ast.Store())), "must have Load context") + def fac(args): return ast.Lambda(args, ast.Name("x", ast.Load())) + self._check_arguments(fac, self.expr) def test_ifexp(self): @@ -2113,11 +2261,13 @@ def test_set(self): def _check_comprehension(self, fac): self.expr(fac([]), "comprehension with no generators") - g = ast.comprehension(ast.Name("x", ast.Load()), - ast.Name("x", ast.Load()), [], 0) + g = ast.comprehension( + ast.Name("x", ast.Load()), ast.Name("x", ast.Load()), [], 0 + ) self.expr(fac([g]), "must have Store context") - g = ast.comprehension(ast.Name("x", ast.Store()), - ast.Name("x", ast.Store()), [], 0) + g = ast.comprehension( + ast.Name("x", ast.Store()), ast.Name("x", ast.Store()), [], 0 + ) self.expr(fac([g]), "must have Load context") x = ast.Name("x", ast.Store()) y = ast.Name("y", ast.Load()) @@ -2127,12 +2277,14 @@ def _check_comprehension(self, fac): self.expr(fac([g]), "must have Load context") def _simple_comp(self, fac): - g = ast.comprehension(ast.Name("x", ast.Store()), - ast.Name("x", ast.Load()), [], 0) - self.expr(fac(ast.Name("x", ast.Store()), [g]), - "must have Load context") + g = ast.comprehension( + ast.Name("x", ast.Store()), ast.Name("x", ast.Load()), [], 0 + ) + self.expr(fac(ast.Name("x", ast.Store()), [g]), "must have Load context") + def wrap(gens): return fac(ast.Name("x", ast.Store()), gens) + self._check_comprehension(wrap) def test_listcomp(self): @@ -2145,18 +2297,19 @@ def test_generatorexp(self): self._simple_comp(ast.GeneratorExp) def test_dictcomp(self): - g = ast.comprehension(ast.Name("y", ast.Store()), - ast.Name("p", ast.Load()), [], 0) - c = ast.DictComp(ast.Name("x", ast.Store()), - ast.Name("y", ast.Load()), [g]) + g = ast.comprehension( + ast.Name("y", ast.Store()), ast.Name("p", ast.Load()), [], 0 + ) + c = ast.DictComp(ast.Name("x", ast.Store()), ast.Name("y", ast.Load()), [g]) self.expr(c, "must have Load context") - c = ast.DictComp(ast.Name("x", ast.Load()), - ast.Name("y", ast.Store()), [g]) + c = ast.DictComp(ast.Name("x", ast.Load()), ast.Name("y", ast.Store()), [g]) self.expr(c, "must have Load context") + def factory(comps): k = ast.Name("x", ast.Load()) v = ast.Name("y", ast.Load()) return ast.DictComp(k, v, comps) + self._check_comprehension(factory) def test_yield(self): @@ -2188,62 +2341,68 @@ def test_call(self): def test_num(self): with warnings.catch_warnings(record=True) as wlog: - warnings.filterwarnings('ignore', '', DeprecationWarning) + warnings.filterwarnings("ignore", "", DeprecationWarning) from ast import Num with warnings.catch_warnings(record=True) as wlog: - warnings.filterwarnings('always', '', DeprecationWarning) + warnings.filterwarnings("always", "", DeprecationWarning) + class subint(int): pass + class subfloat(float): pass + class subcomplex(complex): pass + for obj in "0", "hello": self.expr(ast.Num(obj)) for obj in subint(), subfloat(), subcomplex(): self.expr(ast.Num(obj), "invalid type", exc=TypeError) - self.assertEqual([str(w.message) for w in wlog], [ - 'ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead', - 'ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead', - 'ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead', - 'ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead', - 'ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead', - ]) + self.assertEqual( + [str(w.message) for w in wlog], + [ + "ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead", + "ast.Num is deprecated and will be removed in Python 3.14; use ast.Constant instead", + ], + ) def test_attribute(self): attr = ast.Attribute(ast.Name("x", ast.Store()), "y", ast.Load()) self.expr(attr, "must have Load context") def test_subscript(self): - sub = ast.Subscript(ast.Name("x", ast.Store()), ast.Constant(3), - ast.Load()) + sub = ast.Subscript(ast.Name("x", ast.Store()), ast.Constant(3), ast.Load()) self.expr(sub, "must have Load context") x = ast.Name("x", ast.Load()) - sub = ast.Subscript(x, ast.Name("y", ast.Store()), - ast.Load()) + sub = ast.Subscript(x, ast.Name("y", ast.Store()), ast.Load()) self.expr(sub, "must have Load context") s = ast.Name("x", ast.Store()) for args in (s, None, None), (None, s, None), (None, None, s): sl = ast.Slice(*args) - self.expr(ast.Subscript(x, sl, ast.Load()), - "must have Load context") + self.expr(ast.Subscript(x, sl, ast.Load()), "must have Load context") sl = ast.Tuple([], ast.Load()) self.expr(ast.Subscript(x, sl, ast.Load())) sl = ast.Tuple([s], ast.Load()) self.expr(ast.Subscript(x, sl, ast.Load()), "must have Load context") def test_starred(self): - left = ast.List([ast.Starred(ast.Name("x", ast.Load()), ast.Store())], - ast.Store()) + left = ast.List( + [ast.Starred(ast.Name("x", ast.Load()), ast.Store())], ast.Store() + ) assign = ast.Assign([left], ast.Constant(4)) self.stmt(assign, "must have Store context") def _sequence(self, fac): self.expr(fac([None], ast.Load()), "None disallowed") - self.expr(fac([ast.Name("x", ast.Store())], ast.Load()), - "must have Load context") + self.expr( + fac([ast.Name("x", ast.Store())], ast.Load()), "must have Load context" + ) def test_list(self): self._sequence(ast.List) @@ -2253,18 +2412,21 @@ def test_tuple(self): def test_nameconstant(self): with warnings.catch_warnings(record=True) as wlog: - warnings.filterwarnings('ignore', '', DeprecationWarning) + warnings.filterwarnings("ignore", "", DeprecationWarning) from ast import NameConstant with warnings.catch_warnings(record=True) as wlog: - warnings.filterwarnings('always', '', DeprecationWarning) + warnings.filterwarnings("always", "", DeprecationWarning) self.expr(ast.NameConstant(4)) - self.assertEqual([str(w.message) for w in wlog], [ - 'ast.NameConstant is deprecated and will be removed in Python 3.14; use ast.Constant instead', - ]) + self.assertEqual( + [str(w.message) for w in wlog], + [ + "ast.NameConstant is deprecated and will be removed in Python 3.14; use ast.Constant instead", + ], + ) - @support.requires_resource('cpu') + @support.requires_resource("cpu") def test_stdlib_validates(self): stdlib = os.path.dirname(ast.__file__) tests = [fn for fn in os.listdir(stdlib) if fn.endswith(".py")] @@ -2280,130 +2442,79 @@ def test_stdlib_validates(self): constant_1 = ast.Constant(1) pattern_1 = ast.MatchValue(constant_1) - constant_x = ast.Constant('x') + constant_x = ast.Constant("x") pattern_x = ast.MatchValue(constant_x) constant_true = ast.Constant(True) pattern_true = ast.MatchSingleton(True) - name_carter = ast.Name('carter', ast.Load()) + name_carter = ast.Name("carter", ast.Load()) _MATCH_PATTERNS = [ ast.MatchValue( ast.Attribute( - ast.Attribute( - ast.Name('x', ast.Store()), - 'y', ast.Load() - ), - 'z', ast.Load() + ast.Attribute(ast.Name("x", ast.Store()), "y", ast.Load()), + "z", + ast.Load(), ) ), ast.MatchValue( ast.Attribute( - ast.Attribute( - ast.Name('x', ast.Load()), - 'y', ast.Store() - ), - 'z', ast.Load() + ast.Attribute(ast.Name("x", ast.Load()), "y", ast.Store()), + "z", + ast.Load(), ) ), - ast.MatchValue( - ast.Constant(...) - ), - ast.MatchValue( - ast.Constant(True) - ), - ast.MatchValue( - ast.Constant((1,2,3)) - ), - ast.MatchSingleton('string'), - ast.MatchSequence([ - ast.MatchSingleton('string') - ]), - ast.MatchSequence( - [ - ast.MatchSequence( - [ - ast.MatchSingleton('string') - ] - ) - ] - ), - ast.MatchMapping( - [constant_1, constant_true], - [pattern_x] - ), + ast.MatchValue(ast.Constant(...)), + ast.MatchValue(ast.Constant(True)), + ast.MatchValue(ast.Constant((1, 2, 3))), + ast.MatchSingleton("string"), + ast.MatchSequence([ast.MatchSingleton("string")]), + ast.MatchSequence([ast.MatchSequence([ast.MatchSingleton("string")])]), + ast.MatchMapping([constant_1, constant_true], [pattern_x]), ast.MatchMapping( - [constant_true, constant_1], - [pattern_x, pattern_1], - rest='True' + [constant_true, constant_1], [pattern_x, pattern_1], rest="True" ), ast.MatchMapping( - [constant_true, ast.Starred(ast.Name('lol', ast.Load()), ast.Load())], + [constant_true, ast.Starred(ast.Name("lol", ast.Load()), ast.Load())], [pattern_x, pattern_1], - rest='legit' + rest="legit", ), ast.MatchClass( - ast.Attribute( - ast.Attribute( - constant_x, - 'y', ast.Load()), - 'z', ast.Load()), - patterns=[], kwd_attrs=[], kwd_patterns=[] + ast.Attribute(ast.Attribute(constant_x, "y", ast.Load()), "z", ast.Load()), + patterns=[], + kwd_attrs=[], + kwd_patterns=[], ), ast.MatchClass( - name_carter, - patterns=[], - kwd_attrs=['True'], - kwd_patterns=[pattern_1] + name_carter, patterns=[], kwd_attrs=["True"], kwd_patterns=[pattern_1] ), ast.MatchClass( - name_carter, - patterns=[], - kwd_attrs=[], - kwd_patterns=[pattern_1] + name_carter, patterns=[], kwd_attrs=[], kwd_patterns=[pattern_1] ), ast.MatchClass( name_carter, - patterns=[ast.MatchSingleton('string')], + patterns=[ast.MatchSingleton("string")], kwd_attrs=[], - kwd_patterns=[] + kwd_patterns=[], ), ast.MatchClass( - name_carter, - patterns=[ast.MatchStar()], - kwd_attrs=[], - kwd_patterns=[] + name_carter, patterns=[ast.MatchStar()], kwd_attrs=[], kwd_patterns=[] ), ast.MatchClass( - name_carter, - patterns=[], - kwd_attrs=[], - kwd_patterns=[ast.MatchStar()] + name_carter, patterns=[], kwd_attrs=[], kwd_patterns=[ast.MatchStar()] ), ast.MatchClass( constant_true, # invalid name patterns=[], - kwd_attrs=['True'], - kwd_patterns=[pattern_1] - ), - ast.MatchSequence( - [ - ast.MatchStar("True") - ] - ), - ast.MatchAs( - name='False' - ), - ast.MatchOr( - [] - ), - ast.MatchOr( - [pattern_1] - ), - ast.MatchOr( - [pattern_1, pattern_x, ast.MatchSingleton('xxx')] + kwd_attrs=["True"], + kwd_patterns=[pattern_1], ), + ast.MatchSequence([ast.MatchStar("True")]), + ast.MatchAs(name="False"), + ast.MatchOr([]), + ast.MatchOr([pattern_1]), + ast.MatchOr([pattern_1, pattern_x, ast.MatchSingleton("xxx")]), ast.MatchAs(name="_"), ast.MatchStar(name="x"), ast.MatchSequence([ast.MatchStar("_")]), @@ -2411,17 +2522,12 @@ def test_stdlib_validates(self): ] def test_match_validation_pattern(self): - name_x = ast.Name('x', ast.Load()) + name_x = ast.Name("x", ast.Load()) for pattern in self._MATCH_PATTERNS: with self.subTest(ast.dump(pattern, indent=4)): node = ast.Match( subject=name_x, - cases = [ - ast.match_case( - pattern=pattern, - body = [ast.Pass()] - ) - ] + cases=[ast.match_case(pattern=pattern, body=[ast.Pass()])], ) node = ast.fix_missing_locations(node) module = ast.Module([node], []) @@ -2444,16 +2550,15 @@ def compile_constant(self, value): ns = {} exec(code, ns) - return ns['x'] + return ns["x"] def test_validation(self): with self.assertRaises(TypeError) as cm: self.compile_constant([1, 2, 3]) - self.assertEqual(str(cm.exception), - "got an invalid type in Constant: list") + self.assertEqual(str(cm.exception), "got an invalid type in Constant: list") def test_singletons(self): - for const in (None, False, True, Ellipsis, b'', frozenset()): + for const in (None, False, True, Ellipsis, b"", frozenset()): with self.subTest(const=const): value = self.compile_constant(const) self.assertIs(value, const) @@ -2464,10 +2569,17 @@ def test_values(self): for level in range(3): nested_tuple = (nested_tuple, 2) nested_frozenset = frozenset({nested_frozenset, 2}) - values = (123, 123.0, 123j, - "unicode", b'bytes', - tuple("tuple"), frozenset("frozenset"), - nested_tuple, nested_frozenset) + values = ( + 123, + 123.0, + 123j, + "unicode", + b"bytes", + tuple("tuple"), + frozenset("frozenset"), + nested_tuple, + nested_frozenset, + ) for value in values: with self.subTest(value=value): result = self.compile_constant(value) @@ -2483,42 +2595,35 @@ def test_assign_to_constant(self): with self.assertRaises(ValueError) as cm: compile(tree, "string", "exec") - self.assertEqual(str(cm.exception), - "expression which can't be assigned " - "to in Store context") + self.assertEqual( + str(cm.exception), + "expression which can't be assigned " "to in Store context", + ) def test_get_docstring(self): tree = ast.parse("'docstring'\nx = 1") - self.assertEqual(ast.get_docstring(tree), 'docstring') + self.assertEqual(ast.get_docstring(tree), "docstring") def get_load_const(self, tree): # Compile to bytecode, disassemble and get parameter of LOAD_CONST # instructions - co = compile(tree, '', 'exec') + co = compile(tree, "", "exec") consts = [] for instr in dis.get_instructions(co): - if instr.opname == 'LOAD_CONST' or instr.opname == 'RETURN_CONST': + if instr.opname == "LOAD_CONST" or instr.opname == "RETURN_CONST": consts.append(instr.argval) return consts @support.cpython_only def test_load_const(self): - consts = [None, - True, False, - 124, - 2.0, - 3j, - "unicode", - b'bytes', - (1, 2, 3)] - - code = '\n'.join(['x={!r}'.format(const) for const in consts]) - code += '\nx = ...' + consts = [None, True, False, 124, 2.0, 3j, "unicode", b"bytes", (1, 2, 3)] + + code = "\n".join(["x={!r}".format(const) for const in consts]) + code += "\nx = ..." consts.extend((Ellipsis, None)) tree = ast.parse(code) - self.assertEqual(self.get_load_const(tree), - consts) + self.assertEqual(self.get_load_const(tree), consts) # Replace expression nodes with constants for assign, const in zip(tree.body, consts): @@ -2527,8 +2632,7 @@ def test_load_const(self): ast.copy_location(new_node, assign.value) assign.value = new_node - self.assertEqual(self.get_load_const(tree), - consts) + self.assertEqual(self.get_load_const(tree), consts) def test_literal_eval(self): tree = ast.parse("1 + 2") @@ -2542,22 +2646,22 @@ def test_literal_eval(self): ast.copy_location(new_right, binop.right) binop.right = new_right - self.assertEqual(ast.literal_eval(binop), 10+20j) + self.assertEqual(ast.literal_eval(binop), 10 + 20j) def test_string_kind(self): - c = ast.parse('"x"', mode='eval').body + c = ast.parse('"x"', mode="eval").body self.assertEqual(c.value, "x") self.assertEqual(c.kind, None) - c = ast.parse('u"x"', mode='eval').body + c = ast.parse('u"x"', mode="eval").body self.assertEqual(c.value, "x") self.assertEqual(c.kind, "u") - c = ast.parse('r"x"', mode='eval').body + c = ast.parse('r"x"', mode="eval").body self.assertEqual(c.value, "x") self.assertEqual(c.kind, None) - c = ast.parse('b"x"', mode='eval').body + c = ast.parse('b"x"', mode="eval").body self.assertEqual(c.value, b"x") self.assertEqual(c.kind, None) @@ -2568,6 +2672,7 @@ class EndPositionTests(unittest.TestCase): Testing end positions of nodes requires a bit of extra care because of how LL parsers work. """ + def _check_end_pos(self, ast_node, end_lineno, end_col_offset): self.assertEqual(ast_node.end_lineno, end_lineno) self.assertEqual(ast_node.end_col_offset, end_col_offset) @@ -2581,55 +2686,55 @@ def _parse_value(self, s): return ast.parse(s).body[0].value def test_lambda(self): - s = 'lambda x, *y: None' + s = "lambda x, *y: None" lam = self._parse_value(s) - self._check_content(s, lam.body, 'None') - self._check_content(s, lam.args.args[0], 'x') - self._check_content(s, lam.args.vararg, 'y') + self._check_content(s, lam.body, "None") + self._check_content(s, lam.args.args[0], "x") + self._check_content(s, lam.args.vararg, "y") def test_func_def(self): - s = dedent(''' + s = dedent(""" def func(x: int, *args: str, z: float = 0, **kwargs: Any) -> bool: return True - ''').strip() + """).strip() fdef = ast.parse(s).body[0] self._check_end_pos(fdef, 5, 15) - self._check_content(s, fdef.body[0], 'return True') - self._check_content(s, fdef.args.args[0], 'x: int') - self._check_content(s, fdef.args.args[0].annotation, 'int') - self._check_content(s, fdef.args.kwarg, 'kwargs: Any') - self._check_content(s, fdef.args.kwarg.annotation, 'Any') + self._check_content(s, fdef.body[0], "return True") + self._check_content(s, fdef.args.args[0], "x: int") + self._check_content(s, fdef.args.args[0].annotation, "int") + self._check_content(s, fdef.args.kwarg, "kwargs: Any") + self._check_content(s, fdef.args.kwarg.annotation, "Any") def test_call(self): - s = 'func(x, y=2, **kw)' + s = "func(x, y=2, **kw)" call = self._parse_value(s) - self._check_content(s, call.func, 'func') - self._check_content(s, call.keywords[0].value, '2') - self._check_content(s, call.keywords[1].value, 'kw') + self._check_content(s, call.func, "func") + self._check_content(s, call.keywords[0].value, "2") + self._check_content(s, call.keywords[1].value, "kw") def test_call_noargs(self): - s = 'x[0]()' + s = "x[0]()" call = self._parse_value(s) - self._check_content(s, call.func, 'x[0]') + self._check_content(s, call.func, "x[0]") self._check_end_pos(call, 1, 6) def test_class_def(self): - s = dedent(''' + s = dedent(""" class C(A, B): x: int = 0 - ''').strip() + """).strip() cdef = ast.parse(s).body[0] self._check_end_pos(cdef, 2, 14) - self._check_content(s, cdef.bases[1], 'B') - self._check_content(s, cdef.body[0], 'x: int = 0') + self._check_content(s, cdef.bases[1], "B") + self._check_content(s, cdef.body[0], "x: int = 0") def test_class_kw(self): - s = 'class S(metaclass=abc.ABCMeta): pass' + s = "class S(metaclass=abc.ABCMeta): pass" cdef = ast.parse(s).body[0] - self._check_content(s, cdef.keywords[0].value, 'abc.ABCMeta') + self._check_content(s, cdef.keywords[0].value, "abc.ABCMeta") def test_multi_line_str(self): s = dedent(''' @@ -2642,10 +2747,10 @@ def test_multi_line_str(self): self._check_end_pos(assign.value, 3, 40) def test_continued_str(self): - s = dedent(''' + s = dedent(""" x = "first part" \\ "second part" - ''').strip() + """).strip() assign = ast.parse(s).body[0] self._check_end_pos(assign, 2, 13) self._check_end_pos(assign.value, 2, 13) @@ -2653,7 +2758,7 @@ def test_continued_str(self): def test_suites(self): # We intentionally put these into the same string to check # that empty lines are not part of the suite. - s = dedent(''' + s = dedent(""" while True: pass @@ -2673,7 +2778,7 @@ def test_suites(self): pass pass - ''').strip() + """).strip() mod = ast.parse(s) while_loop = mod.body[0] if_stmt = mod.body[1] @@ -2687,18 +2792,18 @@ def test_suites(self): self._check_end_pos(try_stmt, 17, 8) self._check_end_pos(pass_stmt, 19, 4) - self._check_content(s, while_loop.test, 'True') - self._check_content(s, if_stmt.body[0], 'x = None') - self._check_content(s, if_stmt.orelse[0].test, 'other()') - self._check_content(s, for_loop.target, 'x, y') - self._check_content(s, try_stmt.body[0], 'raise RuntimeError') - self._check_content(s, try_stmt.handlers[0].type, 'TypeError') + self._check_content(s, while_loop.test, "True") + self._check_content(s, if_stmt.body[0], "x = None") + self._check_content(s, if_stmt.orelse[0].test, "other()") + self._check_content(s, for_loop.target, "x, y") + self._check_content(s, try_stmt.body[0], "raise RuntimeError") + self._check_content(s, try_stmt.handlers[0].type, "TypeError") def test_fstring(self): s = 'x = f"abc {x + y} abc"' fstr = self._parse_value(s) binop = fstr.values[1].value - self._check_content(s, binop, 'x + y') + self._check_content(s, binop, "x + y") def test_fstring_multi_line(self): s = dedent(''' @@ -2713,200 +2818,198 @@ def test_fstring_multi_line(self): fstr = self._parse_value(s) binop = fstr.values[1].value self._check_end_pos(binop, 5, 7) - self._check_content(s, binop.left, 'arg_one') - self._check_content(s, binop.right, 'arg_two') + self._check_content(s, binop.left, "arg_one") + self._check_content(s, binop.right, "arg_two") def test_import_from_multi_line(self): - s = dedent(''' + s = dedent(""" from x.y.z import ( a, b, c as c ) - ''').strip() + """).strip() imp = ast.parse(s).body[0] self._check_end_pos(imp, 3, 1) self._check_end_pos(imp.names[2], 2, 16) def test_slices(self): - s1 = 'f()[1, 2] [0]' - s2 = 'x[ a.b: c.d]' - sm = dedent(''' + s1 = "f()[1, 2] [0]" + s2 = "x[ a.b: c.d]" + sm = dedent(""" x[ a.b: f () , g () : c.d ] - ''').strip() + """).strip() i1, i2, im = map(self._parse_value, (s1, s2, sm)) - self._check_content(s1, i1.value, 'f()[1, 2]') - self._check_content(s1, i1.value.slice, '1, 2') - self._check_content(s2, i2.slice.lower, 'a.b') - self._check_content(s2, i2.slice.upper, 'c.d') - self._check_content(sm, im.slice.elts[0].upper, 'f ()') - self._check_content(sm, im.slice.elts[1].lower, 'g ()') + self._check_content(s1, i1.value, "f()[1, 2]") + self._check_content(s1, i1.value.slice, "1, 2") + self._check_content(s2, i2.slice.lower, "a.b") + self._check_content(s2, i2.slice.upper, "c.d") + self._check_content(sm, im.slice.elts[0].upper, "f ()") + self._check_content(sm, im.slice.elts[1].lower, "g ()") self._check_end_pos(im, 3, 3) def test_binop(self): - s = dedent(''' + s = dedent(""" (1 * 2 + (3 ) + 4 ) - ''').strip() + """).strip() binop = self._parse_value(s) self._check_end_pos(binop, 2, 6) - self._check_content(s, binop.right, '4') - self._check_content(s, binop.left, '1 * 2 + (3 )') - self._check_content(s, binop.left.right, '3') + self._check_content(s, binop.right, "4") + self._check_content(s, binop.left, "1 * 2 + (3 )") + self._check_content(s, binop.left.right, "3") def test_boolop(self): - s = dedent(''' + s = dedent(""" if (one_condition and (other_condition or yet_another_one)): pass - ''').strip() + """).strip() bop = ast.parse(s).body[0].test self._check_end_pos(bop, 2, 44) - self._check_content(s, bop.values[1], - 'other_condition or yet_another_one') + self._check_content(s, bop.values[1], "other_condition or yet_another_one") def test_tuples(self): - s1 = 'x = () ;' - s2 = 'x = 1 , ;' - s3 = 'x = (1 , 2 ) ;' - sm = dedent(''' + s1 = "x = () ;" + s2 = "x = 1 , ;" + s3 = "x = (1 , 2 ) ;" + sm = dedent(""" x = ( a, b, ) - ''').strip() + """).strip() t1, t2, t3, tm = map(self._parse_value, (s1, s2, s3, sm)) - self._check_content(s1, t1, '()') - self._check_content(s2, t2, '1 ,') - self._check_content(s3, t3, '(1 , 2 )') + self._check_content(s1, t1, "()") + self._check_content(s2, t2, "1 ,") + self._check_content(s3, t3, "(1 , 2 )") self._check_end_pos(tm, 3, 1) def test_attribute_spaces(self): - s = 'func(x. y .z)' + s = "func(x. y .z)" call = self._parse_value(s) self._check_content(s, call, s) - self._check_content(s, call.args[0], 'x. y .z') + self._check_content(s, call.args[0], "x. y .z") def test_redundant_parenthesis(self): - s = '( ( ( a + b ) ) )' + s = "( ( ( a + b ) ) )" v = ast.parse(s).body[0].value - self.assertEqual(type(v).__name__, 'BinOp') - self._check_content(s, v, 'a + b') - s2 = 'await ' + s + self.assertEqual(type(v).__name__, "BinOp") + self._check_content(s, v, "a + b") + s2 = "await " + s v = ast.parse(s2).body[0].value.value - self.assertEqual(type(v).__name__, 'BinOp') - self._check_content(s2, v, 'a + b') + self.assertEqual(type(v).__name__, "BinOp") + self._check_content(s2, v, "a + b") def test_trailers_with_redundant_parenthesis(self): tests = ( - ('( ( ( a ) ) ) ( )', 'Call'), - ('( ( ( a ) ) ) ( b )', 'Call'), - ('( ( ( a ) ) ) [ b ]', 'Subscript'), - ('( ( ( a ) ) ) . b', 'Attribute'), + ("( ( ( a ) ) ) ( )", "Call"), + ("( ( ( a ) ) ) ( b )", "Call"), + ("( ( ( a ) ) ) [ b ]", "Subscript"), + ("( ( ( a ) ) ) . b", "Attribute"), ) for s, t in tests: with self.subTest(s): v = ast.parse(s).body[0].value self.assertEqual(type(v).__name__, t) self._check_content(s, v, s) - s2 = 'await ' + s + s2 = "await " + s v = ast.parse(s2).body[0].value.value self.assertEqual(type(v).__name__, t) self._check_content(s2, v, s) def test_displays(self): - s1 = '[{}, {1, }, {1, 2,} ]' - s2 = '{a: b, f (): g () ,}' + s1 = "[{}, {1, }, {1, 2,} ]" + s2 = "{a: b, f (): g () ,}" c1 = self._parse_value(s1) c2 = self._parse_value(s2) - self._check_content(s1, c1.elts[0], '{}') - self._check_content(s1, c1.elts[1], '{1, }') - self._check_content(s1, c1.elts[2], '{1, 2,}') - self._check_content(s2, c2.keys[1], 'f ()') - self._check_content(s2, c2.values[1], 'g ()') + self._check_content(s1, c1.elts[0], "{}") + self._check_content(s1, c1.elts[1], "{1, }") + self._check_content(s1, c1.elts[2], "{1, 2,}") + self._check_content(s2, c2.keys[1], "f ()") + self._check_content(s2, c2.values[1], "g ()") def test_comprehensions(self): - s = dedent(''' + s = dedent(""" x = [{x for x, y in stuff if cond.x} for stuff in things] - ''').strip() + """).strip() cmp = self._parse_value(s) self._check_end_pos(cmp, 2, 37) - self._check_content(s, cmp.generators[0].iter, 'things') - self._check_content(s, cmp.elt.generators[0].iter, 'stuff') - self._check_content(s, cmp.elt.generators[0].ifs[0], 'cond.x') - self._check_content(s, cmp.elt.generators[0].target, 'x, y') + self._check_content(s, cmp.generators[0].iter, "things") + self._check_content(s, cmp.elt.generators[0].iter, "stuff") + self._check_content(s, cmp.elt.generators[0].ifs[0], "cond.x") + self._check_content(s, cmp.elt.generators[0].target, "x, y") def test_yield_await(self): - s = dedent(''' + s = dedent(""" async def f(): yield x await y - ''').strip() + """).strip() fdef = ast.parse(s).body[0] - self._check_content(s, fdef.body[0].value, 'yield x') - self._check_content(s, fdef.body[1].value, 'await y') + self._check_content(s, fdef.body[0].value, "yield x") + self._check_content(s, fdef.body[1].value, "await y") def test_source_segment_multi(self): - s_orig = dedent(''' + s_orig = dedent(""" x = ( a, b, ) + () - ''').strip() - s_tuple = dedent(''' + """).strip() + s_tuple = dedent(""" ( a, b, ) - ''').strip() + """).strip() binop = self._parse_value(s_orig) self.assertEqual(ast.get_source_segment(s_orig, binop.left), s_tuple) def test_source_segment_padded(self): - s_orig = dedent(''' + s_orig = dedent(""" class C: def fun(self) -> None: "ЖЖЖЖЖ" - ''').strip() - s_method = ' def fun(self) -> None:\n' \ - ' "ЖЖЖЖЖ"' + """).strip() + s_method = " def fun(self) -> None:\n" ' "ЖЖЖЖЖ"' cdef = ast.parse(s_orig).body[0] - self.assertEqual(ast.get_source_segment(s_orig, cdef.body[0], padded=True), - s_method) + self.assertEqual( + ast.get_source_segment(s_orig, cdef.body[0], padded=True), s_method + ) def test_source_segment_endings(self): - s = 'v = 1\r\nw = 1\nx = 1\n\ry = 1\rz = 1\r\n' + s = "v = 1\r\nw = 1\nx = 1\n\ry = 1\rz = 1\r\n" v, w, x, y, z = ast.parse(s).body - self._check_content(s, v, 'v = 1') - self._check_content(s, w, 'w = 1') - self._check_content(s, x, 'x = 1') - self._check_content(s, y, 'y = 1') - self._check_content(s, z, 'z = 1') + self._check_content(s, v, "v = 1") + self._check_content(s, w, "w = 1") + self._check_content(s, x, "x = 1") + self._check_content(s, y, "y = 1") + self._check_content(s, z, "z = 1") def test_source_segment_tabs(self): - s = dedent(''' + s = dedent(""" class C: \t\f def fun(self) -> None: \t\f pass - ''').strip() - s_method = ' \t\f def fun(self) -> None:\n' \ - ' \t\f pass' + """).strip() + s_method = " \t\f def fun(self) -> None:\n" " \t\f pass" cdef = ast.parse(s).body[0] self.assertEqual(ast.get_source_segment(s, cdef.body[0], padded=True), s_method) def test_source_segment_newlines(self): - s = 'def f():\n pass\ndef g():\r pass\r\ndef h():\r\n pass\r\n' + s = "def f():\n pass\ndef g():\r pass\r\ndef h():\r\n pass\r\n" f, g, h = ast.parse(s).body - self._check_content(s, f, 'def f():\n pass') - self._check_content(s, g, 'def g():\r pass') - self._check_content(s, h, 'def h():\r\n pass') + self._check_content(s, f, "def f():\n pass") + self._check_content(s, g, "def g():\r pass") + self._check_content(s, h, "def h():\r\n pass") - s = 'def f():\n a = 1\r b = 2\r\n c = 3\n' + s = "def f():\n a = 1\r b = 2\r\n c = 3\n" f = ast.parse(s).body[0] self._check_content(s, f, s.rstrip()) def test_source_segment_missing_info(self): - s = 'v = 1\r\nw = 1\nx = 1\n\ry = 1\r\n' + s = "v = 1\r\nw = 1\nx = 1\n\ry = 1\r\n" v, w, x, y = ast.parse(s).body del v.lineno del w.end_lineno @@ -2917,21 +3020,28 @@ def test_source_segment_missing_info(self): self.assertIsNone(ast.get_source_segment(s, x)) self.assertIsNone(ast.get_source_segment(s, y)) + class BaseNodeVisitorCases: # Both `NodeVisitor` and `NodeTranformer` must raise these warnings: def test_old_constant_nodes(self): class Visitor(self.visitor_class): def visit_Num(self, node): - log.append((node.lineno, 'Num', node.n)) + log.append((node.lineno, "Num", node.n)) + def visit_Str(self, node): - log.append((node.lineno, 'Str', node.s)) + log.append((node.lineno, "Str", node.s)) + def visit_Bytes(self, node): - log.append((node.lineno, 'Bytes', node.s)) + log.append((node.lineno, "Bytes", node.s)) + def visit_NameConstant(self, node): - log.append((node.lineno, 'NameConstant', node.value)) + log.append((node.lineno, "NameConstant", node.value)) + def visit_Ellipsis(self, node): - log.append((node.lineno, 'Ellipsis', ...)) - mod = ast.parse(dedent('''\ + log.append((node.lineno, "Ellipsis", ...)) + + mod = ast.parse( + dedent("""\ i = 42 f = 4.25 c = 4.25j @@ -2940,37 +3050,44 @@ def visit_Ellipsis(self, node): t = True n = None e = ... - ''')) + """) + ) visitor = Visitor() log = [] with warnings.catch_warnings(record=True) as wlog: - warnings.filterwarnings('always', '', DeprecationWarning) + warnings.filterwarnings("always", "", DeprecationWarning) visitor.visit(mod) - self.assertEqual(log, [ - (1, 'Num', 42), - (2, 'Num', 4.25), - (3, 'Num', 4.25j), - (4, 'Str', 'string'), - (5, 'Bytes', b'bytes'), - (6, 'NameConstant', True), - (7, 'NameConstant', None), - (8, 'Ellipsis', ...), - ]) - self.assertEqual([str(w.message) for w in wlog], [ - 'visit_Num is deprecated; add visit_Constant', - 'Attribute n is deprecated and will be removed in Python 3.14; use value instead', - 'visit_Num is deprecated; add visit_Constant', - 'Attribute n is deprecated and will be removed in Python 3.14; use value instead', - 'visit_Num is deprecated; add visit_Constant', - 'Attribute n is deprecated and will be removed in Python 3.14; use value instead', - 'visit_Str is deprecated; add visit_Constant', - 'Attribute s is deprecated and will be removed in Python 3.14; use value instead', - 'visit_Bytes is deprecated; add visit_Constant', - 'Attribute s is deprecated and will be removed in Python 3.14; use value instead', - 'visit_NameConstant is deprecated; add visit_Constant', - 'visit_NameConstant is deprecated; add visit_Constant', - 'visit_Ellipsis is deprecated; add visit_Constant', - ]) + self.assertEqual( + log, + [ + (1, "Num", 42), + (2, "Num", 4.25), + (3, "Num", 4.25j), + (4, "Str", "string"), + (5, "Bytes", b"bytes"), + (6, "NameConstant", True), + (7, "NameConstant", None), + (8, "Ellipsis", ...), + ], + ) + self.assertEqual( + [str(w.message) for w in wlog], + [ + "visit_Num is deprecated; add visit_Constant", + "Attribute n is deprecated and will be removed in Python 3.14; use value instead", + "visit_Num is deprecated; add visit_Constant", + "Attribute n is deprecated and will be removed in Python 3.14; use value instead", + "visit_Num is deprecated; add visit_Constant", + "Attribute n is deprecated and will be removed in Python 3.14; use value instead", + "visit_Str is deprecated; add visit_Constant", + "Attribute s is deprecated and will be removed in Python 3.14; use value instead", + "visit_Bytes is deprecated; add visit_Constant", + "Attribute s is deprecated and will be removed in Python 3.14; use value instead", + "visit_NameConstant is deprecated; add visit_Constant", + "visit_NameConstant is deprecated; add visit_Constant", + "visit_Ellipsis is deprecated; add visit_Constant", + ], + ) class NodeVisitorTests(BaseNodeVisitorCases, unittest.TestCase): @@ -2980,8 +3097,7 @@ class NodeVisitorTests(BaseNodeVisitorCases, unittest.TestCase): class NodeTransformerTests(ASTTestMixin, BaseNodeVisitorCases, unittest.TestCase): visitor_class = ast.NodeTransformer - def assertASTTransformation(self, tranformer_class, - initial_code, expected_code): + def assertASTTransformation(self, tranformer_class, initial_code, expected_code): initial_ast = ast.parse(dedent(initial_code)) expected_ast = ast.parse(dedent(expected_code)) @@ -2991,15 +3107,15 @@ def assertASTTransformation(self, tranformer_class, self.assertASTEqual(result_ast, expected_ast) def test_node_remove_single(self): - code = 'def func(arg) -> SomeType: ...' - expected = 'def func(arg): ...' + code = "def func(arg) -> SomeType: ..." + expected = "def func(arg): ..." # Since `FunctionDef.returns` is defined as a single value, we test # the `if isinstance(old_value, AST):` branch here. class SomeTypeRemover(ast.NodeTransformer): def visit_Name(self, node: ast.Name): self.generic_visit(node) - if node.id == 'SomeType': + if node.id == "SomeType": return None return node @@ -3038,11 +3154,11 @@ class DSL(Base, kw1=True, kw2=True, kw3=False): ... class ExtendKeywords(ast.NodeTransformer): def visit_keyword(self, node: ast.keyword): self.generic_visit(node) - if node.arg == 'kw1': + if node.arg == "kw1": return [ node, - ast.keyword('kw2', ast.Constant(True)), - ast.keyword('kw3', ast.Constant(False)), + ast.keyword("kw2", ast.Constant(True)), + ast.keyword("kw3", ast.Constant(False)), ] return node @@ -3061,8 +3177,8 @@ def func(arg): class PrintToLog(ast.NodeTransformer): def visit_Call(self, node: ast.Call): self.generic_visit(node) - if isinstance(node.func, ast.Name) and node.func.id == 'print': - node.func.id = 'log' + if isinstance(node.func, ast.Name) and node.func.id == "print": + node.func.id = "log" return node self.assertASTTransformation(PrintToLog, code, expected) @@ -3080,15 +3196,15 @@ def func(arg): class PrintToLog(ast.NodeTransformer): def visit_Call(self, node: ast.Call): self.generic_visit(node) - if isinstance(node.func, ast.Name) and node.func.id == 'print': + if isinstance(node.func, ast.Name) and node.func.id == "print": return ast.Call( func=ast.Attribute( - ast.Name('logger', ctx=ast.Load()), - attr='log', + ast.Name("logger", ctx=ast.Load()), + attr="log", ctx=ast.Load(), ), args=node.args, - keywords=[ast.keyword('debug', ast.Constant(True))], + keywords=[ast.keyword("debug", ast.Constant(True))], ) return node @@ -3102,13 +3218,15 @@ def test_FunctionDef(self): args = ast.arguments() self.assertEqual(args.args, []) self.assertEqual(args.posonlyargs, []) - with self.assertWarnsRegex(DeprecationWarning, - r"FunctionDef\.__init__ missing 1 required positional argument: 'name'"): + with self.assertWarnsRegex( + DeprecationWarning, + r"FunctionDef\.__init__ missing 1 required positional argument: 'name'", + ): node = ast.FunctionDef(args=args) self.assertFalse(hasattr(node, "name")) self.assertEqual(node.decorator_list, []) - node = ast.FunctionDef(name='foo', args=args) - self.assertEqual(node.name, 'foo') + node = ast.FunctionDef(name="foo", args=args) + self.assertEqual(node.name, "foo") self.assertEqual(node.decorator_list, []) def test_expr_context(self): @@ -3124,8 +3242,10 @@ def test_expr_context(self): self.assertEqual(name3.id, "x") self.assertIsInstance(name3.ctx, ast.Del) - with self.assertWarnsRegex(DeprecationWarning, - r"Name\.__init__ missing 1 required positional argument: 'id'"): + with self.assertWarnsRegex( + DeprecationWarning, + r"Name\.__init__ missing 1 required positional argument: 'id'", + ): name3 = ast.Name() def test_custom_subclass_with_no_fields(self): @@ -3138,7 +3258,7 @@ class NoInit(ast.AST): def test_fields_but_no_field_types(self): class Fields(ast.AST): - _fields = ('a',) + _fields = ("a",) obj = Fields() with self.assertRaises(AttributeError): @@ -3148,8 +3268,8 @@ class Fields(ast.AST): def test_fields_and_types(self): class FieldsAndTypes(ast.AST): - _fields = ('a',) - _field_types = {'a': int | None} + _fields = ("a",) + _field_types = {"a": int | None} a: int | None = None obj = FieldsAndTypes() @@ -3165,17 +3285,21 @@ class MyAttrs(ast.AST): self.assertEqual(obj.a, 1) self.assertEqual(obj.b, 2) - with self.assertWarnsRegex(DeprecationWarning, - r"MyAttrs.__init__ got an unexpected keyword argument 'c'."): + with self.assertWarnsRegex( + DeprecationWarning, + r"MyAttrs.__init__ got an unexpected keyword argument 'c'.", + ): obj = MyAttrs(c=3) def test_fields_and_types_no_default(self): class FieldsAndTypesNoDefault(ast.AST): - _fields = ('a',) - _field_types = {'a': int} + _fields = ("a",) + _field_types = {"a": int} - with self.assertWarnsRegex(DeprecationWarning, - r"FieldsAndTypesNoDefault\.__init__ missing 1 required positional argument: 'a'\."): + with self.assertWarnsRegex( + DeprecationWarning, + r"FieldsAndTypesNoDefault\.__init__ missing 1 required positional argument: 'a'\.", + ): obj = FieldsAndTypesNoDefault() with self.assertRaises(AttributeError): obj.a @@ -3184,14 +3308,14 @@ class FieldsAndTypesNoDefault(ast.AST): def test_incomplete_field_types(self): class MoreFieldsThanTypes(ast.AST): - _fields = ('a', 'b') - _field_types = {'a': int | None} + _fields = ("a", "b") + _field_types = {"a": int | None} a: int | None = None b: int | None = None with self.assertWarnsRegex( DeprecationWarning, - r"Field 'b' is missing from MoreFieldsThanTypes\._field_types" + r"Field 'b' is missing from MoreFieldsThanTypes\._field_types", ): obj = MoreFieldsThanTypes() self.assertIs(obj.a, None) @@ -3203,8 +3327,8 @@ class MoreFieldsThanTypes(ast.AST): def test_complete_field_types(self): class _AllFieldTypes(ast.AST): - _fields = ('a', 'b') - _field_types = {'a': int | None, 'b': list[str]} + _fields = ("a", "b") + _field_types = {"a": int | None, "b": list[str]} # This must be set explicitly a: int | None = None # This will add an implicit empty list default @@ -3221,9 +3345,9 @@ class ModuleStateTests(unittest.TestCase): def check_ast_module(self): # Check that the _ast module still works as expected - code = 'x + 1' - filename = '' - mode = 'eval' + code = "x + 1" + filename = "" + mode = "eval" # Create _ast.AST subclasses instances ast_tree = compile(code, filename, mode, flags=ast.PyCF_ONLY_AST) @@ -3234,11 +3358,11 @@ def check_ast_module(self): def test_reload_module(self): # bpo-41194: Importing the _ast module twice must not crash. - with support.swap_item(sys.modules, '_ast', None): - del sys.modules['_ast'] + with support.swap_item(sys.modules, "_ast", None): + del sys.modules["_ast"] import _ast as ast1 - del sys.modules['_ast'] + del sys.modules["_ast"] import _ast as ast2 self.check_ast_module() @@ -3259,22 +3383,23 @@ def my_import(name, *args, **kw): sys.modules[name] = lazy_mod return lazy_mod - with support.swap_item(sys.modules, '_ast', None): - del sys.modules['_ast'] + with support.swap_item(sys.modules, "_ast", None): + del sys.modules["_ast"] - with support.swap_attr(builtins, '__import__', my_import): + with support.swap_attr(builtins, "__import__", my_import): # Test that compile() does not import the _ast module self.check_ast_module() - self.assertNotIn('_ast', sys.modules) + self.assertNotIn("_ast", sys.modules) # Sanity check of the test itself import _ast + self.assertIs(_ast, lazy_mod) def test_subinterpreter(self): # bpo-41631: Importing and using the _ast module in a subinterpreter # must not crash. - code = dedent(''' + code = dedent(""" import _ast import ast import gc @@ -3292,7 +3417,7 @@ def test_subinterpreter(self): del ast, _ast del sys.modules['ast'], sys.modules['_ast'] gc.collect() - ''') + """) res = support.run_in_subinterp(code) self.assertEqual(res, 0) @@ -3306,23 +3431,25 @@ def test_cli_file_input(self): with os_helper.temp_dir() as tmp_dir: filename = os.path.join(tmp_dir, "test_module.py") - with open(filename, 'w', encoding='utf-8') as f: + with open(filename, "w", encoding="utf-8") as f: f.write(code) res, _ = script_helper.run_python_until_end("-m", "ast", filename) self.assertEqual(res.err, b"") - self.assertEqual(expected.splitlines(), - res.out.decode("utf8").splitlines()) + self.assertEqual(expected.splitlines(), res.out.decode("utf8").splitlines()) self.assertEqual(res.rc, 0) def main(): - if __name__ != '__main__': + if __name__ != "__main__": return - if sys.argv[1:] == ['-g']: - for statements, kind in ((exec_tests, "exec"), (single_tests, "single"), - (eval_tests, "eval")): - print(kind+"_results = [") + if sys.argv[1:] == ["-g"]: + for statements, kind in ( + (exec_tests, "exec"), + (single_tests, "single"), + (eval_tests, "eval"), + ): + print(kind + "_results = [") for statement in statements: tree = ast.parse(statement, "?", kind) print("%r," % (to_tuple(tree),)) @@ -3331,142 +3458,2992 @@ def main(): raise SystemExit unittest.main() + #### EVERYTHING BELOW IS GENERATED BY python Lib/test/test_ast.py -g ##### exec_results = [ -('Module', [('Expr', (1, 0, 1, 4), ('Constant', (1, 0, 1, 4), None, None))], []), -('Module', [('Expr', (1, 0, 1, 18), ('Constant', (1, 0, 1, 18), 'module docstring', None))], []), -('Module', [('FunctionDef', (1, 0, 1, 13), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 9, 1, 13))], [], None, None, [])], []), -('Module', [('FunctionDef', (1, 0, 1, 29), 'f', ('arguments', [], [], None, [], [], None, []), [('Expr', (1, 9, 1, 29), ('Constant', (1, 9, 1, 29), 'function docstring', None))], [], None, None, [])], []), -('Module', [('FunctionDef', (1, 0, 1, 14), 'f', ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None)], None, [], [], None, []), [('Pass', (1, 10, 1, 14))], [], None, None, [])], []), -('Module', [('FunctionDef', (1, 0, 1, 16), 'f', ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None)], None, [], [], None, [('Constant', (1, 8, 1, 9), 0, None)]), [('Pass', (1, 12, 1, 16))], [], None, None, [])], []), -('Module', [('FunctionDef', (1, 0, 1, 18), 'f', ('arguments', [], [], ('arg', (1, 7, 1, 11), 'args', None, None), [], [], None, []), [('Pass', (1, 14, 1, 18))], [], None, None, [])], []), -('Module', [('FunctionDef', (1, 0, 1, 23), 'f', ('arguments', [], [], ('arg', (1, 7, 1, 16), 'args', ('Starred', (1, 13, 1, 16), ('Name', (1, 14, 1, 16), 'Ts', ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 19, 1, 23))], [], None, None, [])], []), -('Module', [('FunctionDef', (1, 0, 1, 36), 'f', ('arguments', [], [], ('arg', (1, 7, 1, 29), 'args', ('Starred', (1, 13, 1, 29), ('Subscript', (1, 14, 1, 29), ('Name', (1, 14, 1, 19), 'tuple', ('Load',)), ('Tuple', (1, 20, 1, 28), [('Name', (1, 20, 1, 23), 'int', ('Load',)), ('Constant', (1, 25, 1, 28), Ellipsis, None)], ('Load',)), ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 32, 1, 36))], [], None, None, [])], []), -('Module', [('FunctionDef', (1, 0, 1, 36), 'f', ('arguments', [], [], ('arg', (1, 7, 1, 29), 'args', ('Starred', (1, 13, 1, 29), ('Subscript', (1, 14, 1, 29), ('Name', (1, 14, 1, 19), 'tuple', ('Load',)), ('Tuple', (1, 20, 1, 28), [('Name', (1, 20, 1, 23), 'int', ('Load',)), ('Starred', (1, 25, 1, 28), ('Name', (1, 26, 1, 28), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 32, 1, 36))], [], None, None, [])], []), -('Module', [('FunctionDef', (1, 0, 1, 21), 'f', ('arguments', [], [], None, [], [], ('arg', (1, 8, 1, 14), 'kwargs', None, None), []), [('Pass', (1, 17, 1, 21))], [], None, None, [])], []), -('Module', [('FunctionDef', (1, 0, 1, 71), 'f', ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None), ('arg', (1, 9, 1, 10), 'b', None, None), ('arg', (1, 14, 1, 15), 'c', None, None), ('arg', (1, 22, 1, 23), 'd', None, None), ('arg', (1, 28, 1, 29), 'e', None, None)], ('arg', (1, 35, 1, 39), 'args', None, None), [('arg', (1, 41, 1, 42), 'f', None, None)], [('Constant', (1, 43, 1, 45), 42, None)], ('arg', (1, 49, 1, 55), 'kwargs', None, None), [('Constant', (1, 11, 1, 12), 1, None), ('Constant', (1, 16, 1, 20), None, None), ('List', (1, 24, 1, 26), [], ('Load',)), ('Dict', (1, 30, 1, 32), [], [])]), [('Expr', (1, 58, 1, 71), ('Constant', (1, 58, 1, 71), 'doc for f()', None))], [], None, None, [])], []), -('Module', [('FunctionDef', (1, 0, 1, 27), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 23, 1, 27))], [], ('Subscript', (1, 11, 1, 21), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 20), [('Starred', (1, 17, 1, 20), ('Name', (1, 18, 1, 20), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), None, [])], []), -('Module', [('FunctionDef', (1, 0, 1, 32), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 28, 1, 32))], [], ('Subscript', (1, 11, 1, 26), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 25), [('Name', (1, 17, 1, 20), 'int', ('Load',)), ('Starred', (1, 22, 1, 25), ('Name', (1, 23, 1, 25), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), None, [])], []), -('Module', [('FunctionDef', (1, 0, 1, 45), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 41, 1, 45))], [], ('Subscript', (1, 11, 1, 39), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 38), [('Name', (1, 17, 1, 20), 'int', ('Load',)), ('Starred', (1, 22, 1, 38), ('Subscript', (1, 23, 1, 38), ('Name', (1, 23, 1, 28), 'tuple', ('Load',)), ('Tuple', (1, 29, 1, 37), [('Name', (1, 29, 1, 32), 'int', ('Load',)), ('Constant', (1, 34, 1, 37), Ellipsis, None)], ('Load',)), ('Load',)), ('Load',))], ('Load',)), ('Load',)), None, [])], []), -('Module', [('ClassDef', (1, 0, 1, 12), 'C', [], [], [('Pass', (1, 8, 1, 12))], [], [])], []), -('Module', [('ClassDef', (1, 0, 1, 32), 'C', [], [], [('Expr', (1, 9, 1, 32), ('Constant', (1, 9, 1, 32), 'docstring for class C', None))], [], [])], []), -('Module', [('ClassDef', (1, 0, 1, 21), 'C', [('Name', (1, 8, 1, 14), 'object', ('Load',))], [], [('Pass', (1, 17, 1, 21))], [], [])], []), -('Module', [('FunctionDef', (1, 0, 1, 16), 'f', ('arguments', [], [], None, [], [], None, []), [('Return', (1, 8, 1, 16), ('Constant', (1, 15, 1, 16), 1, None))], [], None, None, [])], []), -('Module', [('Delete', (1, 0, 1, 5), [('Name', (1, 4, 1, 5), 'v', ('Del',))])], []), -('Module', [('Assign', (1, 0, 1, 5), [('Name', (1, 0, 1, 1), 'v', ('Store',))], ('Constant', (1, 4, 1, 5), 1, None), None)], []), -('Module', [('Assign', (1, 0, 1, 7), [('Tuple', (1, 0, 1, 3), [('Name', (1, 0, 1, 1), 'a', ('Store',)), ('Name', (1, 2, 1, 3), 'b', ('Store',))], ('Store',))], ('Name', (1, 6, 1, 7), 'c', ('Load',)), None)], []), -('Module', [('Assign', (1, 0, 1, 9), [('Tuple', (1, 0, 1, 5), [('Name', (1, 1, 1, 2), 'a', ('Store',)), ('Name', (1, 3, 1, 4), 'b', ('Store',))], ('Store',))], ('Name', (1, 8, 1, 9), 'c', ('Load',)), None)], []), -('Module', [('Assign', (1, 0, 1, 9), [('List', (1, 0, 1, 5), [('Name', (1, 1, 1, 2), 'a', ('Store',)), ('Name', (1, 3, 1, 4), 'b', ('Store',))], ('Store',))], ('Name', (1, 8, 1, 9), 'c', ('Load',)), None)], []), -('Module', [('AnnAssign', (1, 0, 1, 13), ('Name', (1, 0, 1, 1), 'x', ('Store',)), ('Subscript', (1, 3, 1, 13), ('Name', (1, 3, 1, 8), 'tuple', ('Load',)), ('Tuple', (1, 9, 1, 12), [('Starred', (1, 9, 1, 12), ('Name', (1, 10, 1, 12), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), None, 1)], []), -('Module', [('AnnAssign', (1, 0, 1, 18), ('Name', (1, 0, 1, 1), 'x', ('Store',)), ('Subscript', (1, 3, 1, 18), ('Name', (1, 3, 1, 8), 'tuple', ('Load',)), ('Tuple', (1, 9, 1, 17), [('Name', (1, 9, 1, 12), 'int', ('Load',)), ('Starred', (1, 14, 1, 17), ('Name', (1, 15, 1, 17), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), None, 1)], []), -('Module', [('AnnAssign', (1, 0, 1, 31), ('Name', (1, 0, 1, 1), 'x', ('Store',)), ('Subscript', (1, 3, 1, 31), ('Name', (1, 3, 1, 8), 'tuple', ('Load',)), ('Tuple', (1, 9, 1, 30), [('Name', (1, 9, 1, 12), 'int', ('Load',)), ('Starred', (1, 14, 1, 30), ('Subscript', (1, 15, 1, 30), ('Name', (1, 15, 1, 20), 'tuple', ('Load',)), ('Tuple', (1, 21, 1, 29), [('Name', (1, 21, 1, 24), 'str', ('Load',)), ('Constant', (1, 26, 1, 29), Ellipsis, None)], ('Load',)), ('Load',)), ('Load',))], ('Load',)), ('Load',)), None, 1)], []), -('Module', [('AugAssign', (1, 0, 1, 6), ('Name', (1, 0, 1, 1), 'v', ('Store',)), ('Add',), ('Constant', (1, 5, 1, 6), 1, None))], []), -('Module', [('For', (1, 0, 1, 15), ('Name', (1, 4, 1, 5), 'v', ('Store',)), ('Name', (1, 9, 1, 10), 'v', ('Load',)), [('Pass', (1, 11, 1, 15))], [], None)], []), -('Module', [('While', (1, 0, 1, 12), ('Name', (1, 6, 1, 7), 'v', ('Load',)), [('Pass', (1, 8, 1, 12))], [])], []), -('Module', [('If', (1, 0, 1, 9), ('Name', (1, 3, 1, 4), 'v', ('Load',)), [('Pass', (1, 5, 1, 9))], [])], []), -('Module', [('If', (1, 0, 4, 6), ('Name', (1, 3, 1, 4), 'a', ('Load',)), [('Pass', (2, 2, 2, 6))], [('If', (3, 0, 4, 6), ('Name', (3, 5, 3, 6), 'b', ('Load',)), [('Pass', (4, 2, 4, 6))], [])])], []), -('Module', [('If', (1, 0, 6, 6), ('Name', (1, 3, 1, 4), 'a', ('Load',)), [('Pass', (2, 2, 2, 6))], [('If', (3, 0, 6, 6), ('Name', (3, 5, 3, 6), 'b', ('Load',)), [('Pass', (4, 2, 4, 6))], [('Pass', (6, 2, 6, 6))])])], []), -('Module', [('With', (1, 0, 1, 17), [('withitem', ('Name', (1, 5, 1, 6), 'x', ('Load',)), ('Name', (1, 10, 1, 11), 'y', ('Store',)))], [('Pass', (1, 13, 1, 17))], None)], []), -('Module', [('With', (1, 0, 1, 25), [('withitem', ('Name', (1, 5, 1, 6), 'x', ('Load',)), ('Name', (1, 10, 1, 11), 'y', ('Store',))), ('withitem', ('Name', (1, 13, 1, 14), 'z', ('Load',)), ('Name', (1, 18, 1, 19), 'q', ('Store',)))], [('Pass', (1, 21, 1, 25))], None)], []), -('Module', [('With', (1, 0, 1, 19), [('withitem', ('Name', (1, 6, 1, 7), 'x', ('Load',)), ('Name', (1, 11, 1, 12), 'y', ('Store',)))], [('Pass', (1, 15, 1, 19))], None)], []), -('Module', [('With', (1, 0, 1, 17), [('withitem', ('Name', (1, 6, 1, 7), 'x', ('Load',)), None), ('withitem', ('Name', (1, 9, 1, 10), 'y', ('Load',)), None)], [('Pass', (1, 13, 1, 17))], None)], []), -('Module', [('Raise', (1, 0, 1, 25), ('Call', (1, 6, 1, 25), ('Name', (1, 6, 1, 15), 'Exception', ('Load',)), [('Constant', (1, 16, 1, 24), 'string', None)], []), None)], []), -('Module', [('Try', (1, 0, 4, 6), [('Pass', (2, 2, 2, 6))], [('ExceptHandler', (3, 0, 4, 6), ('Name', (3, 7, 3, 16), 'Exception', ('Load',)), None, [('Pass', (4, 2, 4, 6))])], [], [])], []), -('Module', [('Try', (1, 0, 4, 6), [('Pass', (2, 2, 2, 6))], [], [], [('Pass', (4, 2, 4, 6))])], []), -('Module', [('TryStar', (1, 0, 4, 6), [('Pass', (2, 2, 2, 6))], [('ExceptHandler', (3, 0, 4, 6), ('Name', (3, 8, 3, 17), 'Exception', ('Load',)), None, [('Pass', (4, 2, 4, 6))])], [], [])], []), -('Module', [('Assert', (1, 0, 1, 8), ('Name', (1, 7, 1, 8), 'v', ('Load',)), None)], []), -('Module', [('Import', (1, 0, 1, 10), [('alias', (1, 7, 1, 10), 'sys', None)])], []), -('Module', [('ImportFrom', (1, 0, 1, 17), 'sys', [('alias', (1, 16, 1, 17), 'v', None)], 0)], []), -('Module', [('Global', (1, 0, 1, 8), ['v'])], []), -('Module', [('Expr', (1, 0, 1, 1), ('Constant', (1, 0, 1, 1), 1, None))], []), -('Module', [('Pass', (1, 0, 1, 4))], []), -('Module', [('For', (1, 0, 1, 16), ('Name', (1, 4, 1, 5), 'v', ('Store',)), ('Name', (1, 9, 1, 10), 'v', ('Load',)), [('Break', (1, 11, 1, 16))], [], None)], []), -('Module', [('For', (1, 0, 1, 19), ('Name', (1, 4, 1, 5), 'v', ('Store',)), ('Name', (1, 9, 1, 10), 'v', ('Load',)), [('Continue', (1, 11, 1, 19))], [], None)], []), -('Module', [('For', (1, 0, 1, 18), ('Tuple', (1, 4, 1, 7), [('Name', (1, 4, 1, 5), 'a', ('Store',)), ('Name', (1, 6, 1, 7), 'b', ('Store',))], ('Store',)), ('Name', (1, 11, 1, 12), 'c', ('Load',)), [('Pass', (1, 14, 1, 18))], [], None)], []), -('Module', [('For', (1, 0, 1, 20), ('Tuple', (1, 4, 1, 9), [('Name', (1, 5, 1, 6), 'a', ('Store',)), ('Name', (1, 7, 1, 8), 'b', ('Store',))], ('Store',)), ('Name', (1, 13, 1, 14), 'c', ('Load',)), [('Pass', (1, 16, 1, 20))], [], None)], []), -('Module', [('For', (1, 0, 1, 20), ('List', (1, 4, 1, 9), [('Name', (1, 5, 1, 6), 'a', ('Store',)), ('Name', (1, 7, 1, 8), 'b', ('Store',))], ('Store',)), ('Name', (1, 13, 1, 14), 'c', ('Load',)), [('Pass', (1, 16, 1, 20))], [], None)], []), -('Module', [('Expr', (1, 0, 11, 5), ('GeneratorExp', (1, 0, 11, 5), ('Tuple', (2, 4, 6, 5), [('Name', (3, 4, 3, 6), 'Aa', ('Load',)), ('Name', (5, 7, 5, 9), 'Bb', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (8, 4, 10, 6), [('Name', (8, 4, 8, 6), 'Aa', ('Store',)), ('Name', (10, 4, 10, 6), 'Bb', ('Store',))], ('Store',)), ('Name', (10, 10, 10, 12), 'Cc', ('Load',)), [], 0)]))], []), -('Module', [('Expr', (1, 0, 1, 34), ('DictComp', (1, 0, 1, 34), ('Name', (1, 1, 1, 2), 'a', ('Load',)), ('Name', (1, 5, 1, 6), 'b', ('Load',)), [('comprehension', ('Name', (1, 11, 1, 12), 'w', ('Store',)), ('Name', (1, 16, 1, 17), 'x', ('Load',)), [], 0), ('comprehension', ('Name', (1, 22, 1, 23), 'm', ('Store',)), ('Name', (1, 27, 1, 28), 'p', ('Load',)), [('Name', (1, 32, 1, 33), 'g', ('Load',))], 0)]))], []), -('Module', [('Expr', (1, 0, 1, 20), ('DictComp', (1, 0, 1, 20), ('Name', (1, 1, 1, 2), 'a', ('Load',)), ('Name', (1, 5, 1, 6), 'b', ('Load',)), [('comprehension', ('Tuple', (1, 11, 1, 14), [('Name', (1, 11, 1, 12), 'v', ('Store',)), ('Name', (1, 13, 1, 14), 'w', ('Store',))], ('Store',)), ('Name', (1, 18, 1, 19), 'x', ('Load',)), [], 0)]))], []), -('Module', [('Expr', (1, 0, 1, 19), ('SetComp', (1, 0, 1, 19), ('Name', (1, 1, 1, 2), 'r', ('Load',)), [('comprehension', ('Name', (1, 7, 1, 8), 'l', ('Store',)), ('Name', (1, 12, 1, 13), 'x', ('Load',)), [('Name', (1, 17, 1, 18), 'g', ('Load',))], 0)]))], []), -('Module', [('Expr', (1, 0, 1, 16), ('SetComp', (1, 0, 1, 16), ('Name', (1, 1, 1, 2), 'r', ('Load',)), [('comprehension', ('Tuple', (1, 7, 1, 10), [('Name', (1, 7, 1, 8), 'l', ('Store',)), ('Name', (1, 9, 1, 10), 'm', ('Store',))], ('Store',)), ('Name', (1, 14, 1, 15), 'x', ('Load',)), [], 0)]))], []), -('Module', [('AsyncFunctionDef', (1, 0, 3, 18), 'f', ('arguments', [], [], None, [], [], None, []), [('Expr', (2, 1, 2, 17), ('Constant', (2, 1, 2, 17), 'async function', None)), ('Expr', (3, 1, 3, 18), ('Await', (3, 1, 3, 18), ('Call', (3, 7, 3, 18), ('Name', (3, 7, 3, 16), 'something', ('Load',)), [], [])))], [], None, None, [])], []), -('Module', [('AsyncFunctionDef', (1, 0, 3, 8), 'f', ('arguments', [], [], None, [], [], None, []), [('AsyncFor', (2, 1, 3, 8), ('Name', (2, 11, 2, 12), 'e', ('Store',)), ('Name', (2, 16, 2, 17), 'i', ('Load',)), [('Expr', (2, 19, 2, 20), ('Constant', (2, 19, 2, 20), 1, None))], [('Expr', (3, 7, 3, 8), ('Constant', (3, 7, 3, 8), 2, None))], None)], [], None, None, [])], []), -('Module', [('AsyncFunctionDef', (1, 0, 2, 21), 'f', ('arguments', [], [], None, [], [], None, []), [('AsyncWith', (2, 1, 2, 21), [('withitem', ('Name', (2, 12, 2, 13), 'a', ('Load',)), ('Name', (2, 17, 2, 18), 'b', ('Store',)))], [('Expr', (2, 20, 2, 21), ('Constant', (2, 20, 2, 21), 1, None))], None)], [], None, None, [])], []), -('Module', [('Expr', (1, 0, 1, 14), ('Dict', (1, 0, 1, 14), [None, ('Constant', (1, 10, 1, 11), 2, None)], [('Dict', (1, 3, 1, 8), [('Constant', (1, 4, 1, 5), 1, None)], [('Constant', (1, 6, 1, 7), 2, None)]), ('Constant', (1, 12, 1, 13), 3, None)]))], []), -('Module', [('Expr', (1, 0, 1, 12), ('Set', (1, 0, 1, 12), [('Starred', (1, 1, 1, 8), ('Set', (1, 2, 1, 8), [('Constant', (1, 3, 1, 4), 1, None), ('Constant', (1, 6, 1, 7), 2, None)]), ('Load',)), ('Constant', (1, 10, 1, 11), 3, None)]))], []), -('Module', [('AsyncFunctionDef', (1, 0, 2, 21), 'f', ('arguments', [], [], None, [], [], None, []), [('Expr', (2, 1, 2, 21), ('ListComp', (2, 1, 2, 21), ('Name', (2, 2, 2, 3), 'i', ('Load',)), [('comprehension', ('Name', (2, 14, 2, 15), 'b', ('Store',)), ('Name', (2, 19, 2, 20), 'c', ('Load',)), [], 1)]))], [], None, None, [])], []), -('Module', [('FunctionDef', (4, 0, 4, 13), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (4, 9, 4, 13))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])], None, None, [])], []), -('Module', [('AsyncFunctionDef', (4, 0, 4, 19), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (4, 15, 4, 19))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])], None, None, [])], []), -('Module', [('ClassDef', (4, 0, 4, 13), 'C', [], [], [('Pass', (4, 9, 4, 13))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])], [])], []), -('Module', [('FunctionDef', (2, 0, 2, 13), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (2, 9, 2, 13))], [('Call', (1, 1, 1, 19), ('Name', (1, 1, 1, 5), 'deco', ('Load',)), [('GeneratorExp', (1, 5, 1, 19), ('Name', (1, 6, 1, 7), 'a', ('Load',)), [('comprehension', ('Name', (1, 12, 1, 13), 'a', ('Store',)), ('Name', (1, 17, 1, 18), 'b', ('Load',)), [], 0)])], [])], None, None, [])], []), -('Module', [('FunctionDef', (2, 0, 2, 13), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (2, 9, 2, 13))], [('Attribute', (1, 1, 1, 6), ('Attribute', (1, 1, 1, 4), ('Name', (1, 1, 1, 2), 'a', ('Load',)), 'b', ('Load',)), 'c', ('Load',))], None, None, [])], []), -('Module', [('Expr', (1, 0, 1, 8), ('NamedExpr', (1, 1, 1, 7), ('Name', (1, 1, 1, 2), 'a', ('Store',)), ('Constant', (1, 6, 1, 7), 1, None)))], []), -('Module', [('FunctionDef', (1, 0, 1, 18), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [], None, [], [], None, []), [('Pass', (1, 14, 1, 18))], [], None, None, [])], []), -('Module', [('FunctionDef', (1, 0, 1, 26), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None), ('arg', (1, 15, 1, 16), 'd', None, None), ('arg', (1, 18, 1, 19), 'e', None, None)], None, [], [], None, []), [('Pass', (1, 22, 1, 26))], [], None, None, [])], []), -('Module', [('FunctionDef', (1, 0, 1, 29), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None)], None, [('arg', (1, 18, 1, 19), 'd', None, None), ('arg', (1, 21, 1, 22), 'e', None, None)], [None, None], None, []), [('Pass', (1, 25, 1, 29))], [], None, None, [])], []), -('Module', [('FunctionDef', (1, 0, 1, 39), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None)], None, [('arg', (1, 18, 1, 19), 'd', None, None), ('arg', (1, 21, 1, 22), 'e', None, None)], [None, None], ('arg', (1, 26, 1, 32), 'kwargs', None, None), []), [('Pass', (1, 35, 1, 39))], [], None, None, [])], []), -('Module', [('FunctionDef', (1, 0, 1, 20), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [], None, [], [], None, [('Constant', (1, 8, 1, 9), 1, None)]), [('Pass', (1, 16, 1, 20))], [], None, None, [])], []), -('Module', [('FunctionDef', (1, 0, 1, 29), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None), ('arg', (1, 19, 1, 20), 'c', None, None)], None, [], [], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None), ('Constant', (1, 21, 1, 22), 4, None)]), [('Pass', (1, 25, 1, 29))], [], None, None, [])], []), -('Module', [('FunctionDef', (1, 0, 1, 32), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [('Constant', (1, 24, 1, 25), 4, None)], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 28, 1, 32))], [], None, None, [])], []), -('Module', [('FunctionDef', (1, 0, 1, 30), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [None], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 26, 1, 30))], [], None, None, [])], []), -('Module', [('FunctionDef', (1, 0, 1, 42), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [('Constant', (1, 24, 1, 25), 4, None)], ('arg', (1, 29, 1, 35), 'kwargs', None, None), [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 38, 1, 42))], [], None, None, [])], []), -('Module', [('FunctionDef', (1, 0, 1, 40), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [None], ('arg', (1, 27, 1, 33), 'kwargs', None, None), [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 36, 1, 40))], [], None, None, [])], []), -('Module', [('TypeAlias', (1, 0, 1, 12), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [], ('Name', (1, 9, 1, 12), 'int', ('Load',)))], []), -('Module', [('TypeAlias', (1, 0, 1, 15), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [('TypeVar', (1, 7, 1, 8), 'T', None, None)], ('Name', (1, 12, 1, 15), 'int', ('Load',)))], []), -('Module', [('TypeAlias', (1, 0, 1, 32), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [('TypeVar', (1, 7, 1, 8), 'T', None, None), ('TypeVarTuple', (1, 10, 1, 13), 'Ts', None), ('ParamSpec', (1, 15, 1, 18), 'P', None)], ('Tuple', (1, 22, 1, 32), [('Name', (1, 23, 1, 24), 'T', ('Load',)), ('Name', (1, 26, 1, 28), 'Ts', ('Load',)), ('Name', (1, 30, 1, 31), 'P', ('Load',))], ('Load',)))], []), -('Module', [('TypeAlias', (1, 0, 1, 37), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [('TypeVar', (1, 7, 1, 13), 'T', ('Name', (1, 10, 1, 13), 'int', ('Load',)), None), ('TypeVarTuple', (1, 15, 1, 18), 'Ts', None), ('ParamSpec', (1, 20, 1, 23), 'P', None)], ('Tuple', (1, 27, 1, 37), [('Name', (1, 28, 1, 29), 'T', ('Load',)), ('Name', (1, 31, 1, 33), 'Ts', ('Load',)), ('Name', (1, 35, 1, 36), 'P', ('Load',))], ('Load',)))], []), -('Module', [('TypeAlias', (1, 0, 1, 44), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [('TypeVar', (1, 7, 1, 20), 'T', ('Tuple', (1, 10, 1, 20), [('Name', (1, 11, 1, 14), 'int', ('Load',)), ('Name', (1, 16, 1, 19), 'str', ('Load',))], ('Load',)), None), ('TypeVarTuple', (1, 22, 1, 25), 'Ts', None), ('ParamSpec', (1, 27, 1, 30), 'P', None)], ('Tuple', (1, 34, 1, 44), [('Name', (1, 35, 1, 36), 'T', ('Load',)), ('Name', (1, 38, 1, 40), 'Ts', ('Load',)), ('Name', (1, 42, 1, 43), 'P', ('Load',))], ('Load',)))], []), -('Module', [('TypeAlias', (1, 0, 1, 48), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [('TypeVar', (1, 7, 1, 17), 'T', ('Name', (1, 10, 1, 13), 'int', ('Load',)), ('Constant', (1, 16, 1, 17), 1, None)), ('TypeVarTuple', (1, 19, 1, 26), 'Ts', ('Constant', (1, 25, 1, 26), 2, None)), ('ParamSpec', (1, 28, 1, 34), 'P', ('Constant', (1, 33, 1, 34), 3, None))], ('Tuple', (1, 38, 1, 48), [('Name', (1, 39, 1, 40), 'T', ('Load',)), ('Name', (1, 42, 1, 44), 'Ts', ('Load',)), ('Name', (1, 46, 1, 47), 'P', ('Load',))], ('Load',)))], []), -('Module', [('ClassDef', (1, 0, 1, 16), 'X', [], [], [('Pass', (1, 12, 1, 16))], [], [('TypeVar', (1, 8, 1, 9), 'T', None, None)])], []), -('Module', [('ClassDef', (1, 0, 1, 26), 'X', [], [], [('Pass', (1, 22, 1, 26))], [], [('TypeVar', (1, 8, 1, 9), 'T', None, None), ('TypeVarTuple', (1, 11, 1, 14), 'Ts', None), ('ParamSpec', (1, 16, 1, 19), 'P', None)])], []), -('Module', [('ClassDef', (1, 0, 1, 31), 'X', [], [], [('Pass', (1, 27, 1, 31))], [], [('TypeVar', (1, 8, 1, 14), 'T', ('Name', (1, 11, 1, 14), 'int', ('Load',)), None), ('TypeVarTuple', (1, 16, 1, 19), 'Ts', None), ('ParamSpec', (1, 21, 1, 24), 'P', None)])], []), -('Module', [('ClassDef', (1, 0, 1, 38), 'X', [], [], [('Pass', (1, 34, 1, 38))], [], [('TypeVar', (1, 8, 1, 21), 'T', ('Tuple', (1, 11, 1, 21), [('Name', (1, 12, 1, 15), 'int', ('Load',)), ('Name', (1, 17, 1, 20), 'str', ('Load',))], ('Load',)), None), ('TypeVarTuple', (1, 23, 1, 26), 'Ts', None), ('ParamSpec', (1, 28, 1, 31), 'P', None)])], []), -('Module', [('ClassDef', (1, 0, 1, 43), 'X', [], [], [('Pass', (1, 39, 1, 43))], [], [('TypeVar', (1, 8, 1, 18), 'T', ('Name', (1, 11, 1, 14), 'int', ('Load',)), ('Constant', (1, 17, 1, 18), 1, None)), ('TypeVarTuple', (1, 20, 1, 27), 'Ts', ('Constant', (1, 26, 1, 27), 2, None)), ('ParamSpec', (1, 29, 1, 36), 'P', ('Constant', (1, 35, 1, 36), 3, None))])], []), -('Module', [('FunctionDef', (1, 0, 1, 16), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 12, 1, 16))], [], None, None, [('TypeVar', (1, 6, 1, 7), 'T', None, None)])], []), -('Module', [('FunctionDef', (1, 0, 1, 26), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 22, 1, 26))], [], None, None, [('TypeVar', (1, 6, 1, 7), 'T', None, None), ('TypeVarTuple', (1, 9, 1, 12), 'Ts', None), ('ParamSpec', (1, 14, 1, 17), 'P', None)])], []), -('Module', [('FunctionDef', (1, 0, 1, 31), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 27, 1, 31))], [], None, None, [('TypeVar', (1, 6, 1, 12), 'T', ('Name', (1, 9, 1, 12), 'int', ('Load',)), None), ('TypeVarTuple', (1, 14, 1, 17), 'Ts', None), ('ParamSpec', (1, 19, 1, 22), 'P', None)])], []), -('Module', [('FunctionDef', (1, 0, 1, 38), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 34, 1, 38))], [], None, None, [('TypeVar', (1, 6, 1, 19), 'T', ('Tuple', (1, 9, 1, 19), [('Name', (1, 10, 1, 13), 'int', ('Load',)), ('Name', (1, 15, 1, 18), 'str', ('Load',))], ('Load',)), None), ('TypeVarTuple', (1, 21, 1, 24), 'Ts', None), ('ParamSpec', (1, 26, 1, 29), 'P', None)])], []), -('Module', [('FunctionDef', (1, 0, 1, 43), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 39, 1, 43))], [], None, None, [('TypeVar', (1, 6, 1, 16), 'T', ('Name', (1, 9, 1, 12), 'int', ('Load',)), ('Constant', (1, 15, 1, 16), 1, None)), ('TypeVarTuple', (1, 18, 1, 25), 'Ts', ('Constant', (1, 24, 1, 25), 2, None)), ('ParamSpec', (1, 27, 1, 34), 'P', ('Constant', (1, 33, 1, 34), 3, None))])], []), -] -single_results = [ -('Interactive', [('Expr', (1, 0, 1, 3), ('BinOp', (1, 0, 1, 3), ('Constant', (1, 0, 1, 1), 1, None), ('Add',), ('Constant', (1, 2, 1, 3), 2, None)))]), -] -eval_results = [ -('Expression', ('Constant', (1, 0, 1, 4), None, None)), -('Expression', ('BoolOp', (1, 0, 1, 7), ('And',), [('Name', (1, 0, 1, 1), 'a', ('Load',)), ('Name', (1, 6, 1, 7), 'b', ('Load',))])), -('Expression', ('BinOp', (1, 0, 1, 5), ('Name', (1, 0, 1, 1), 'a', ('Load',)), ('Add',), ('Name', (1, 4, 1, 5), 'b', ('Load',)))), -('Expression', ('UnaryOp', (1, 0, 1, 5), ('Not',), ('Name', (1, 4, 1, 5), 'v', ('Load',)))), -('Expression', ('Lambda', (1, 0, 1, 11), ('arguments', [], [], None, [], [], None, []), ('Constant', (1, 7, 1, 11), None, None))), -('Expression', ('Dict', (1, 0, 1, 7), [('Constant', (1, 2, 1, 3), 1, None)], [('Constant', (1, 4, 1, 5), 2, None)])), -('Expression', ('Dict', (1, 0, 1, 2), [], [])), -('Expression', ('Set', (1, 0, 1, 7), [('Constant', (1, 1, 1, 5), None, None)])), -('Expression', ('Dict', (1, 0, 5, 6), [('Constant', (2, 6, 2, 7), 1, None)], [('Constant', (4, 10, 4, 11), 2, None)])), -('Expression', ('ListComp', (1, 0, 1, 19), ('Name', (1, 1, 1, 2), 'a', ('Load',)), [('comprehension', ('Name', (1, 7, 1, 8), 'b', ('Store',)), ('Name', (1, 12, 1, 13), 'c', ('Load',)), [('Name', (1, 17, 1, 18), 'd', ('Load',))], 0)])), -('Expression', ('GeneratorExp', (1, 0, 1, 19), ('Name', (1, 1, 1, 2), 'a', ('Load',)), [('comprehension', ('Name', (1, 7, 1, 8), 'b', ('Store',)), ('Name', (1, 12, 1, 13), 'c', ('Load',)), [('Name', (1, 17, 1, 18), 'd', ('Load',))], 0)])), -('Expression', ('ListComp', (1, 0, 1, 20), ('Tuple', (1, 1, 1, 6), [('Name', (1, 2, 1, 3), 'a', ('Load',)), ('Name', (1, 4, 1, 5), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11, 1, 14), [('Name', (1, 11, 1, 12), 'a', ('Store',)), ('Name', (1, 13, 1, 14), 'b', ('Store',))], ('Store',)), ('Name', (1, 18, 1, 19), 'c', ('Load',)), [], 0)])), -('Expression', ('ListComp', (1, 0, 1, 22), ('Tuple', (1, 1, 1, 6), [('Name', (1, 2, 1, 3), 'a', ('Load',)), ('Name', (1, 4, 1, 5), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11, 1, 16), [('Name', (1, 12, 1, 13), 'a', ('Store',)), ('Name', (1, 14, 1, 15), 'b', ('Store',))], ('Store',)), ('Name', (1, 20, 1, 21), 'c', ('Load',)), [], 0)])), -('Expression', ('ListComp', (1, 0, 1, 22), ('Tuple', (1, 1, 1, 6), [('Name', (1, 2, 1, 3), 'a', ('Load',)), ('Name', (1, 4, 1, 5), 'b', ('Load',))], ('Load',)), [('comprehension', ('List', (1, 11, 1, 16), [('Name', (1, 12, 1, 13), 'a', ('Store',)), ('Name', (1, 14, 1, 15), 'b', ('Store',))], ('Store',)), ('Name', (1, 20, 1, 21), 'c', ('Load',)), [], 0)])), -('Expression', ('SetComp', (1, 0, 1, 20), ('Tuple', (1, 1, 1, 6), [('Name', (1, 2, 1, 3), 'a', ('Load',)), ('Name', (1, 4, 1, 5), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11, 1, 14), [('Name', (1, 11, 1, 12), 'a', ('Store',)), ('Name', (1, 13, 1, 14), 'b', ('Store',))], ('Store',)), ('Name', (1, 18, 1, 19), 'c', ('Load',)), [], 0)])), -('Expression', ('SetComp', (1, 0, 1, 22), ('Tuple', (1, 1, 1, 6), [('Name', (1, 2, 1, 3), 'a', ('Load',)), ('Name', (1, 4, 1, 5), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11, 1, 16), [('Name', (1, 12, 1, 13), 'a', ('Store',)), ('Name', (1, 14, 1, 15), 'b', ('Store',))], ('Store',)), ('Name', (1, 20, 1, 21), 'c', ('Load',)), [], 0)])), -('Expression', ('SetComp', (1, 0, 1, 22), ('Tuple', (1, 1, 1, 6), [('Name', (1, 2, 1, 3), 'a', ('Load',)), ('Name', (1, 4, 1, 5), 'b', ('Load',))], ('Load',)), [('comprehension', ('List', (1, 11, 1, 16), [('Name', (1, 12, 1, 13), 'a', ('Store',)), ('Name', (1, 14, 1, 15), 'b', ('Store',))], ('Store',)), ('Name', (1, 20, 1, 21), 'c', ('Load',)), [], 0)])), -('Expression', ('GeneratorExp', (1, 0, 1, 20), ('Tuple', (1, 1, 1, 6), [('Name', (1, 2, 1, 3), 'a', ('Load',)), ('Name', (1, 4, 1, 5), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11, 1, 14), [('Name', (1, 11, 1, 12), 'a', ('Store',)), ('Name', (1, 13, 1, 14), 'b', ('Store',))], ('Store',)), ('Name', (1, 18, 1, 19), 'c', ('Load',)), [], 0)])), -('Expression', ('GeneratorExp', (1, 0, 1, 22), ('Tuple', (1, 1, 1, 6), [('Name', (1, 2, 1, 3), 'a', ('Load',)), ('Name', (1, 4, 1, 5), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11, 1, 16), [('Name', (1, 12, 1, 13), 'a', ('Store',)), ('Name', (1, 14, 1, 15), 'b', ('Store',))], ('Store',)), ('Name', (1, 20, 1, 21), 'c', ('Load',)), [], 0)])), -('Expression', ('GeneratorExp', (1, 0, 1, 22), ('Tuple', (1, 1, 1, 6), [('Name', (1, 2, 1, 3), 'a', ('Load',)), ('Name', (1, 4, 1, 5), 'b', ('Load',))], ('Load',)), [('comprehension', ('List', (1, 11, 1, 16), [('Name', (1, 12, 1, 13), 'a', ('Store',)), ('Name', (1, 14, 1, 15), 'b', ('Store',))], ('Store',)), ('Name', (1, 20, 1, 21), 'c', ('Load',)), [], 0)])), -('Expression', ('Compare', (1, 0, 1, 9), ('Constant', (1, 0, 1, 1), 1, None), [('Lt',), ('Lt',)], [('Constant', (1, 4, 1, 5), 2, None), ('Constant', (1, 8, 1, 9), 3, None)])), -('Expression', ('Call', (1, 0, 1, 17), ('Name', (1, 0, 1, 1), 'f', ('Load',)), [('Constant', (1, 2, 1, 3), 1, None), ('Constant', (1, 4, 1, 5), 2, None), ('Starred', (1, 10, 1, 12), ('Name', (1, 11, 1, 12), 'd', ('Load',)), ('Load',))], [('keyword', (1, 6, 1, 9), 'c', ('Constant', (1, 8, 1, 9), 3, None)), ('keyword', (1, 13, 1, 16), None, ('Name', (1, 15, 1, 16), 'e', ('Load',)))])), -('Expression', ('Call', (1, 0, 1, 10), ('Name', (1, 0, 1, 1), 'f', ('Load',)), [('Starred', (1, 2, 1, 9), ('List', (1, 3, 1, 9), [('Constant', (1, 4, 1, 5), 0, None), ('Constant', (1, 7, 1, 8), 1, None)], ('Load',)), ('Load',))], [])), -('Expression', ('Call', (1, 0, 1, 15), ('Name', (1, 0, 1, 1), 'f', ('Load',)), [('GeneratorExp', (1, 1, 1, 15), ('Name', (1, 2, 1, 3), 'a', ('Load',)), [('comprehension', ('Name', (1, 8, 1, 9), 'a', ('Store',)), ('Name', (1, 13, 1, 14), 'b', ('Load',)), [], 0)])], [])), -('Expression', ('Constant', (1, 0, 1, 2), 10, None)), -('Expression', ('Constant', (1, 0, 1, 8), 'string', None)), -('Expression', ('Attribute', (1, 0, 1, 3), ('Name', (1, 0, 1, 1), 'a', ('Load',)), 'b', ('Load',))), -('Expression', ('Subscript', (1, 0, 1, 6), ('Name', (1, 0, 1, 1), 'a', ('Load',)), ('Slice', (1, 2, 1, 5), ('Name', (1, 2, 1, 3), 'b', ('Load',)), ('Name', (1, 4, 1, 5), 'c', ('Load',)), None), ('Load',))), -('Expression', ('Name', (1, 0, 1, 1), 'v', ('Load',))), -('Expression', ('List', (1, 0, 1, 7), [('Constant', (1, 1, 1, 2), 1, None), ('Constant', (1, 3, 1, 4), 2, None), ('Constant', (1, 5, 1, 6), 3, None)], ('Load',))), -('Expression', ('List', (1, 0, 1, 2), [], ('Load',))), -('Expression', ('Tuple', (1, 0, 1, 5), [('Constant', (1, 0, 1, 1), 1, None), ('Constant', (1, 2, 1, 3), 2, None), ('Constant', (1, 4, 1, 5), 3, None)], ('Load',))), -('Expression', ('Tuple', (1, 0, 1, 7), [('Constant', (1, 1, 1, 2), 1, None), ('Constant', (1, 3, 1, 4), 2, None), ('Constant', (1, 5, 1, 6), 3, None)], ('Load',))), -('Expression', ('Tuple', (1, 0, 1, 2), [], ('Load',))), -('Expression', ('Call', (1, 0, 1, 17), ('Attribute', (1, 0, 1, 7), ('Attribute', (1, 0, 1, 5), ('Attribute', (1, 0, 1, 3), ('Name', (1, 0, 1, 1), 'a', ('Load',)), 'b', ('Load',)), 'c', ('Load',)), 'd', ('Load',)), [('Subscript', (1, 8, 1, 16), ('Attribute', (1, 8, 1, 11), ('Name', (1, 8, 1, 9), 'a', ('Load',)), 'b', ('Load',)), ('Slice', (1, 12, 1, 15), ('Constant', (1, 12, 1, 13), 1, None), ('Constant', (1, 14, 1, 15), 2, None), None), ('Load',))], [])), + ("Module", [("Expr", (1, 0, 1, 4), ("Constant", (1, 0, 1, 4), None, None))], []), + ( + "Module", + [ + ( + "Expr", + (1, 0, 1, 18), + ("Constant", (1, 0, 1, 18), "module docstring", None), + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 13), + "f", + ("arguments", [], [], None, [], [], None, []), + [("Pass", (1, 9, 1, 13))], + [], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 29), + "f", + ("arguments", [], [], None, [], [], None, []), + [ + ( + "Expr", + (1, 9, 1, 29), + ("Constant", (1, 9, 1, 29), "function docstring", None), + ) + ], + [], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 14), + "f", + ( + "arguments", + [], + [("arg", (1, 6, 1, 7), "a", None, None)], + None, + [], + [], + None, + [], + ), + [("Pass", (1, 10, 1, 14))], + [], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 16), + "f", + ( + "arguments", + [], + [("arg", (1, 6, 1, 7), "a", None, None)], + None, + [], + [], + None, + [("Constant", (1, 8, 1, 9), 0, None)], + ), + [("Pass", (1, 12, 1, 16))], + [], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 18), + "f", + ( + "arguments", + [], + [], + ("arg", (1, 7, 1, 11), "args", None, None), + [], + [], + None, + [], + ), + [("Pass", (1, 14, 1, 18))], + [], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 23), + "f", + ( + "arguments", + [], + [], + ( + "arg", + (1, 7, 1, 16), + "args", + ( + "Starred", + (1, 13, 1, 16), + ("Name", (1, 14, 1, 16), "Ts", ("Load",)), + ("Load",), + ), + None, + ), + [], + [], + None, + [], + ), + [("Pass", (1, 19, 1, 23))], + [], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 36), + "f", + ( + "arguments", + [], + [], + ( + "arg", + (1, 7, 1, 29), + "args", + ( + "Starred", + (1, 13, 1, 29), + ( + "Subscript", + (1, 14, 1, 29), + ("Name", (1, 14, 1, 19), "tuple", ("Load",)), + ( + "Tuple", + (1, 20, 1, 28), + [ + ("Name", (1, 20, 1, 23), "int", ("Load",)), + ("Constant", (1, 25, 1, 28), Ellipsis, None), + ], + ("Load",), + ), + ("Load",), + ), + ("Load",), + ), + None, + ), + [], + [], + None, + [], + ), + [("Pass", (1, 32, 1, 36))], + [], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 36), + "f", + ( + "arguments", + [], + [], + ( + "arg", + (1, 7, 1, 29), + "args", + ( + "Starred", + (1, 13, 1, 29), + ( + "Subscript", + (1, 14, 1, 29), + ("Name", (1, 14, 1, 19), "tuple", ("Load",)), + ( + "Tuple", + (1, 20, 1, 28), + [ + ("Name", (1, 20, 1, 23), "int", ("Load",)), + ( + "Starred", + (1, 25, 1, 28), + ("Name", (1, 26, 1, 28), "Ts", ("Load",)), + ("Load",), + ), + ], + ("Load",), + ), + ("Load",), + ), + ("Load",), + ), + None, + ), + [], + [], + None, + [], + ), + [("Pass", (1, 32, 1, 36))], + [], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 21), + "f", + ( + "arguments", + [], + [], + None, + [], + [], + ("arg", (1, 8, 1, 14), "kwargs", None, None), + [], + ), + [("Pass", (1, 17, 1, 21))], + [], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 71), + "f", + ( + "arguments", + [], + [ + ("arg", (1, 6, 1, 7), "a", None, None), + ("arg", (1, 9, 1, 10), "b", None, None), + ("arg", (1, 14, 1, 15), "c", None, None), + ("arg", (1, 22, 1, 23), "d", None, None), + ("arg", (1, 28, 1, 29), "e", None, None), + ], + ("arg", (1, 35, 1, 39), "args", None, None), + [("arg", (1, 41, 1, 42), "f", None, None)], + [("Constant", (1, 43, 1, 45), 42, None)], + ("arg", (1, 49, 1, 55), "kwargs", None, None), + [ + ("Constant", (1, 11, 1, 12), 1, None), + ("Constant", (1, 16, 1, 20), None, None), + ("List", (1, 24, 1, 26), [], ("Load",)), + ("Dict", (1, 30, 1, 32), [], []), + ], + ), + [ + ( + "Expr", + (1, 58, 1, 71), + ("Constant", (1, 58, 1, 71), "doc for f()", None), + ) + ], + [], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 27), + "f", + ("arguments", [], [], None, [], [], None, []), + [("Pass", (1, 23, 1, 27))], + [], + ( + "Subscript", + (1, 11, 1, 21), + ("Name", (1, 11, 1, 16), "tuple", ("Load",)), + ( + "Tuple", + (1, 17, 1, 20), + [ + ( + "Starred", + (1, 17, 1, 20), + ("Name", (1, 18, 1, 20), "Ts", ("Load",)), + ("Load",), + ) + ], + ("Load",), + ), + ("Load",), + ), + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 32), + "f", + ("arguments", [], [], None, [], [], None, []), + [("Pass", (1, 28, 1, 32))], + [], + ( + "Subscript", + (1, 11, 1, 26), + ("Name", (1, 11, 1, 16), "tuple", ("Load",)), + ( + "Tuple", + (1, 17, 1, 25), + [ + ("Name", (1, 17, 1, 20), "int", ("Load",)), + ( + "Starred", + (1, 22, 1, 25), + ("Name", (1, 23, 1, 25), "Ts", ("Load",)), + ("Load",), + ), + ], + ("Load",), + ), + ("Load",), + ), + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 45), + "f", + ("arguments", [], [], None, [], [], None, []), + [("Pass", (1, 41, 1, 45))], + [], + ( + "Subscript", + (1, 11, 1, 39), + ("Name", (1, 11, 1, 16), "tuple", ("Load",)), + ( + "Tuple", + (1, 17, 1, 38), + [ + ("Name", (1, 17, 1, 20), "int", ("Load",)), + ( + "Starred", + (1, 22, 1, 38), + ( + "Subscript", + (1, 23, 1, 38), + ("Name", (1, 23, 1, 28), "tuple", ("Load",)), + ( + "Tuple", + (1, 29, 1, 37), + [ + ("Name", (1, 29, 1, 32), "int", ("Load",)), + ( + "Constant", + (1, 34, 1, 37), + Ellipsis, + None, + ), + ], + ("Load",), + ), + ("Load",), + ), + ("Load",), + ), + ], + ("Load",), + ), + ("Load",), + ), + None, + [], + ) + ], + [], + ), + ( + "Module", + [("ClassDef", (1, 0, 1, 12), "C", [], [], [("Pass", (1, 8, 1, 12))], [], [])], + [], + ), + ( + "Module", + [ + ( + "ClassDef", + (1, 0, 1, 32), + "C", + [], + [], + [ + ( + "Expr", + (1, 9, 1, 32), + ("Constant", (1, 9, 1, 32), "docstring for class C", None), + ) + ], + [], + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "ClassDef", + (1, 0, 1, 21), + "C", + [("Name", (1, 8, 1, 14), "object", ("Load",))], + [], + [("Pass", (1, 17, 1, 21))], + [], + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 16), + "f", + ("arguments", [], [], None, [], [], None, []), + [("Return", (1, 8, 1, 16), ("Constant", (1, 15, 1, 16), 1, None))], + [], + None, + None, + [], + ) + ], + [], + ), + ("Module", [("Delete", (1, 0, 1, 5), [("Name", (1, 4, 1, 5), "v", ("Del",))])], []), + ( + "Module", + [ + ( + "Assign", + (1, 0, 1, 5), + [("Name", (1, 0, 1, 1), "v", ("Store",))], + ("Constant", (1, 4, 1, 5), 1, None), + None, + ) + ], + [], + ), + ( + "Module", + [ + ( + "Assign", + (1, 0, 1, 7), + [ + ( + "Tuple", + (1, 0, 1, 3), + [ + ("Name", (1, 0, 1, 1), "a", ("Store",)), + ("Name", (1, 2, 1, 3), "b", ("Store",)), + ], + ("Store",), + ) + ], + ("Name", (1, 6, 1, 7), "c", ("Load",)), + None, + ) + ], + [], + ), + ( + "Module", + [ + ( + "Assign", + (1, 0, 1, 9), + [ + ( + "Tuple", + (1, 0, 1, 5), + [ + ("Name", (1, 1, 1, 2), "a", ("Store",)), + ("Name", (1, 3, 1, 4), "b", ("Store",)), + ], + ("Store",), + ) + ], + ("Name", (1, 8, 1, 9), "c", ("Load",)), + None, + ) + ], + [], + ), + ( + "Module", + [ + ( + "Assign", + (1, 0, 1, 9), + [ + ( + "List", + (1, 0, 1, 5), + [ + ("Name", (1, 1, 1, 2), "a", ("Store",)), + ("Name", (1, 3, 1, 4), "b", ("Store",)), + ], + ("Store",), + ) + ], + ("Name", (1, 8, 1, 9), "c", ("Load",)), + None, + ) + ], + [], + ), + ( + "Module", + [ + ( + "AnnAssign", + (1, 0, 1, 13), + ("Name", (1, 0, 1, 1), "x", ("Store",)), + ( + "Subscript", + (1, 3, 1, 13), + ("Name", (1, 3, 1, 8), "tuple", ("Load",)), + ( + "Tuple", + (1, 9, 1, 12), + [ + ( + "Starred", + (1, 9, 1, 12), + ("Name", (1, 10, 1, 12), "Ts", ("Load",)), + ("Load",), + ) + ], + ("Load",), + ), + ("Load",), + ), + None, + 1, + ) + ], + [], + ), + ( + "Module", + [ + ( + "AnnAssign", + (1, 0, 1, 18), + ("Name", (1, 0, 1, 1), "x", ("Store",)), + ( + "Subscript", + (1, 3, 1, 18), + ("Name", (1, 3, 1, 8), "tuple", ("Load",)), + ( + "Tuple", + (1, 9, 1, 17), + [ + ("Name", (1, 9, 1, 12), "int", ("Load",)), + ( + "Starred", + (1, 14, 1, 17), + ("Name", (1, 15, 1, 17), "Ts", ("Load",)), + ("Load",), + ), + ], + ("Load",), + ), + ("Load",), + ), + None, + 1, + ) + ], + [], + ), + ( + "Module", + [ + ( + "AnnAssign", + (1, 0, 1, 31), + ("Name", (1, 0, 1, 1), "x", ("Store",)), + ( + "Subscript", + (1, 3, 1, 31), + ("Name", (1, 3, 1, 8), "tuple", ("Load",)), + ( + "Tuple", + (1, 9, 1, 30), + [ + ("Name", (1, 9, 1, 12), "int", ("Load",)), + ( + "Starred", + (1, 14, 1, 30), + ( + "Subscript", + (1, 15, 1, 30), + ("Name", (1, 15, 1, 20), "tuple", ("Load",)), + ( + "Tuple", + (1, 21, 1, 29), + [ + ("Name", (1, 21, 1, 24), "str", ("Load",)), + ( + "Constant", + (1, 26, 1, 29), + Ellipsis, + None, + ), + ], + ("Load",), + ), + ("Load",), + ), + ("Load",), + ), + ], + ("Load",), + ), + ("Load",), + ), + None, + 1, + ) + ], + [], + ), + ( + "Module", + [ + ( + "AugAssign", + (1, 0, 1, 6), + ("Name", (1, 0, 1, 1), "v", ("Store",)), + ("Add",), + ("Constant", (1, 5, 1, 6), 1, None), + ) + ], + [], + ), + ( + "Module", + [ + ( + "For", + (1, 0, 1, 15), + ("Name", (1, 4, 1, 5), "v", ("Store",)), + ("Name", (1, 9, 1, 10), "v", ("Load",)), + [("Pass", (1, 11, 1, 15))], + [], + None, + ) + ], + [], + ), + ( + "Module", + [ + ( + "While", + (1, 0, 1, 12), + ("Name", (1, 6, 1, 7), "v", ("Load",)), + [("Pass", (1, 8, 1, 12))], + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "If", + (1, 0, 1, 9), + ("Name", (1, 3, 1, 4), "v", ("Load",)), + [("Pass", (1, 5, 1, 9))], + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "If", + (1, 0, 4, 6), + ("Name", (1, 3, 1, 4), "a", ("Load",)), + [("Pass", (2, 2, 2, 6))], + [ + ( + "If", + (3, 0, 4, 6), + ("Name", (3, 5, 3, 6), "b", ("Load",)), + [("Pass", (4, 2, 4, 6))], + [], + ) + ], + ) + ], + [], + ), + ( + "Module", + [ + ( + "If", + (1, 0, 6, 6), + ("Name", (1, 3, 1, 4), "a", ("Load",)), + [("Pass", (2, 2, 2, 6))], + [ + ( + "If", + (3, 0, 6, 6), + ("Name", (3, 5, 3, 6), "b", ("Load",)), + [("Pass", (4, 2, 4, 6))], + [("Pass", (6, 2, 6, 6))], + ) + ], + ) + ], + [], + ), + ( + "Module", + [ + ( + "With", + (1, 0, 1, 17), + [ + ( + "withitem", + ("Name", (1, 5, 1, 6), "x", ("Load",)), + ("Name", (1, 10, 1, 11), "y", ("Store",)), + ) + ], + [("Pass", (1, 13, 1, 17))], + None, + ) + ], + [], + ), + ( + "Module", + [ + ( + "With", + (1, 0, 1, 25), + [ + ( + "withitem", + ("Name", (1, 5, 1, 6), "x", ("Load",)), + ("Name", (1, 10, 1, 11), "y", ("Store",)), + ), + ( + "withitem", + ("Name", (1, 13, 1, 14), "z", ("Load",)), + ("Name", (1, 18, 1, 19), "q", ("Store",)), + ), + ], + [("Pass", (1, 21, 1, 25))], + None, + ) + ], + [], + ), + ( + "Module", + [ + ( + "With", + (1, 0, 1, 19), + [ + ( + "withitem", + ("Name", (1, 6, 1, 7), "x", ("Load",)), + ("Name", (1, 11, 1, 12), "y", ("Store",)), + ) + ], + [("Pass", (1, 15, 1, 19))], + None, + ) + ], + [], + ), + ( + "Module", + [ + ( + "With", + (1, 0, 1, 17), + [ + ("withitem", ("Name", (1, 6, 1, 7), "x", ("Load",)), None), + ("withitem", ("Name", (1, 9, 1, 10), "y", ("Load",)), None), + ], + [("Pass", (1, 13, 1, 17))], + None, + ) + ], + [], + ), + ( + "Module", + [ + ( + "Raise", + (1, 0, 1, 25), + ( + "Call", + (1, 6, 1, 25), + ("Name", (1, 6, 1, 15), "Exception", ("Load",)), + [("Constant", (1, 16, 1, 24), "string", None)], + [], + ), + None, + ) + ], + [], + ), + ( + "Module", + [ + ( + "Try", + (1, 0, 4, 6), + [("Pass", (2, 2, 2, 6))], + [ + ( + "ExceptHandler", + (3, 0, 4, 6), + ("Name", (3, 7, 3, 16), "Exception", ("Load",)), + None, + [("Pass", (4, 2, 4, 6))], + ) + ], + [], + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "Try", + (1, 0, 4, 6), + [("Pass", (2, 2, 2, 6))], + [], + [], + [("Pass", (4, 2, 4, 6))], + ) + ], + [], + ), + ( + "Module", + [ + ( + "TryStar", + (1, 0, 4, 6), + [("Pass", (2, 2, 2, 6))], + [ + ( + "ExceptHandler", + (3, 0, 4, 6), + ("Name", (3, 8, 3, 17), "Exception", ("Load",)), + None, + [("Pass", (4, 2, 4, 6))], + ) + ], + [], + [], + ) + ], + [], + ), + ( + "Module", + [("Assert", (1, 0, 1, 8), ("Name", (1, 7, 1, 8), "v", ("Load",)), None)], + [], + ), + ( + "Module", + [("Import", (1, 0, 1, 10), [("alias", (1, 7, 1, 10), "sys", None)])], + [], + ), + ( + "Module", + [ + ( + "ImportFrom", + (1, 0, 1, 17), + "sys", + [("alias", (1, 16, 1, 17), "v", None)], + 0, + ) + ], + [], + ), + ("Module", [("Global", (1, 0, 1, 8), ["v"])], []), + ("Module", [("Expr", (1, 0, 1, 1), ("Constant", (1, 0, 1, 1), 1, None))], []), + ("Module", [("Pass", (1, 0, 1, 4))], []), + ( + "Module", + [ + ( + "For", + (1, 0, 1, 16), + ("Name", (1, 4, 1, 5), "v", ("Store",)), + ("Name", (1, 9, 1, 10), "v", ("Load",)), + [("Break", (1, 11, 1, 16))], + [], + None, + ) + ], + [], + ), + ( + "Module", + [ + ( + "For", + (1, 0, 1, 19), + ("Name", (1, 4, 1, 5), "v", ("Store",)), + ("Name", (1, 9, 1, 10), "v", ("Load",)), + [("Continue", (1, 11, 1, 19))], + [], + None, + ) + ], + [], + ), + ( + "Module", + [ + ( + "For", + (1, 0, 1, 18), + ( + "Tuple", + (1, 4, 1, 7), + [ + ("Name", (1, 4, 1, 5), "a", ("Store",)), + ("Name", (1, 6, 1, 7), "b", ("Store",)), + ], + ("Store",), + ), + ("Name", (1, 11, 1, 12), "c", ("Load",)), + [("Pass", (1, 14, 1, 18))], + [], + None, + ) + ], + [], + ), + ( + "Module", + [ + ( + "For", + (1, 0, 1, 20), + ( + "Tuple", + (1, 4, 1, 9), + [ + ("Name", (1, 5, 1, 6), "a", ("Store",)), + ("Name", (1, 7, 1, 8), "b", ("Store",)), + ], + ("Store",), + ), + ("Name", (1, 13, 1, 14), "c", ("Load",)), + [("Pass", (1, 16, 1, 20))], + [], + None, + ) + ], + [], + ), + ( + "Module", + [ + ( + "For", + (1, 0, 1, 20), + ( + "List", + (1, 4, 1, 9), + [ + ("Name", (1, 5, 1, 6), "a", ("Store",)), + ("Name", (1, 7, 1, 8), "b", ("Store",)), + ], + ("Store",), + ), + ("Name", (1, 13, 1, 14), "c", ("Load",)), + [("Pass", (1, 16, 1, 20))], + [], + None, + ) + ], + [], + ), + ( + "Module", + [ + ( + "Expr", + (1, 0, 11, 5), + ( + "GeneratorExp", + (1, 0, 11, 5), + ( + "Tuple", + (2, 4, 6, 5), + [ + ("Name", (3, 4, 3, 6), "Aa", ("Load",)), + ("Name", (5, 7, 5, 9), "Bb", ("Load",)), + ], + ("Load",), + ), + [ + ( + "comprehension", + ( + "Tuple", + (8, 4, 10, 6), + [ + ("Name", (8, 4, 8, 6), "Aa", ("Store",)), + ("Name", (10, 4, 10, 6), "Bb", ("Store",)), + ], + ("Store",), + ), + ("Name", (10, 10, 10, 12), "Cc", ("Load",)), + [], + 0, + ) + ], + ), + ) + ], + [], + ), + ( + "Module", + [ + ( + "Expr", + (1, 0, 1, 34), + ( + "DictComp", + (1, 0, 1, 34), + ("Name", (1, 1, 1, 2), "a", ("Load",)), + ("Name", (1, 5, 1, 6), "b", ("Load",)), + [ + ( + "comprehension", + ("Name", (1, 11, 1, 12), "w", ("Store",)), + ("Name", (1, 16, 1, 17), "x", ("Load",)), + [], + 0, + ), + ( + "comprehension", + ("Name", (1, 22, 1, 23), "m", ("Store",)), + ("Name", (1, 27, 1, 28), "p", ("Load",)), + [("Name", (1, 32, 1, 33), "g", ("Load",))], + 0, + ), + ], + ), + ) + ], + [], + ), + ( + "Module", + [ + ( + "Expr", + (1, 0, 1, 20), + ( + "DictComp", + (1, 0, 1, 20), + ("Name", (1, 1, 1, 2), "a", ("Load",)), + ("Name", (1, 5, 1, 6), "b", ("Load",)), + [ + ( + "comprehension", + ( + "Tuple", + (1, 11, 1, 14), + [ + ("Name", (1, 11, 1, 12), "v", ("Store",)), + ("Name", (1, 13, 1, 14), "w", ("Store",)), + ], + ("Store",), + ), + ("Name", (1, 18, 1, 19), "x", ("Load",)), + [], + 0, + ) + ], + ), + ) + ], + [], + ), + ( + "Module", + [ + ( + "Expr", + (1, 0, 1, 19), + ( + "SetComp", + (1, 0, 1, 19), + ("Name", (1, 1, 1, 2), "r", ("Load",)), + [ + ( + "comprehension", + ("Name", (1, 7, 1, 8), "l", ("Store",)), + ("Name", (1, 12, 1, 13), "x", ("Load",)), + [("Name", (1, 17, 1, 18), "g", ("Load",))], + 0, + ) + ], + ), + ) + ], + [], + ), + ( + "Module", + [ + ( + "Expr", + (1, 0, 1, 16), + ( + "SetComp", + (1, 0, 1, 16), + ("Name", (1, 1, 1, 2), "r", ("Load",)), + [ + ( + "comprehension", + ( + "Tuple", + (1, 7, 1, 10), + [ + ("Name", (1, 7, 1, 8), "l", ("Store",)), + ("Name", (1, 9, 1, 10), "m", ("Store",)), + ], + ("Store",), + ), + ("Name", (1, 14, 1, 15), "x", ("Load",)), + [], + 0, + ) + ], + ), + ) + ], + [], + ), + ( + "Module", + [ + ( + "AsyncFunctionDef", + (1, 0, 3, 18), + "f", + ("arguments", [], [], None, [], [], None, []), + [ + ( + "Expr", + (2, 1, 2, 17), + ("Constant", (2, 1, 2, 17), "async function", None), + ), + ( + "Expr", + (3, 1, 3, 18), + ( + "Await", + (3, 1, 3, 18), + ( + "Call", + (3, 7, 3, 18), + ("Name", (3, 7, 3, 16), "something", ("Load",)), + [], + [], + ), + ), + ), + ], + [], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "AsyncFunctionDef", + (1, 0, 3, 8), + "f", + ("arguments", [], [], None, [], [], None, []), + [ + ( + "AsyncFor", + (2, 1, 3, 8), + ("Name", (2, 11, 2, 12), "e", ("Store",)), + ("Name", (2, 16, 2, 17), "i", ("Load",)), + [ + ( + "Expr", + (2, 19, 2, 20), + ("Constant", (2, 19, 2, 20), 1, None), + ) + ], + [("Expr", (3, 7, 3, 8), ("Constant", (3, 7, 3, 8), 2, None))], + None, + ) + ], + [], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "AsyncFunctionDef", + (1, 0, 2, 21), + "f", + ("arguments", [], [], None, [], [], None, []), + [ + ( + "AsyncWith", + (2, 1, 2, 21), + [ + ( + "withitem", + ("Name", (2, 12, 2, 13), "a", ("Load",)), + ("Name", (2, 17, 2, 18), "b", ("Store",)), + ) + ], + [ + ( + "Expr", + (2, 20, 2, 21), + ("Constant", (2, 20, 2, 21), 1, None), + ) + ], + None, + ) + ], + [], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "Expr", + (1, 0, 1, 14), + ( + "Dict", + (1, 0, 1, 14), + [None, ("Constant", (1, 10, 1, 11), 2, None)], + [ + ( + "Dict", + (1, 3, 1, 8), + [("Constant", (1, 4, 1, 5), 1, None)], + [("Constant", (1, 6, 1, 7), 2, None)], + ), + ("Constant", (1, 12, 1, 13), 3, None), + ], + ), + ) + ], + [], + ), + ( + "Module", + [ + ( + "Expr", + (1, 0, 1, 12), + ( + "Set", + (1, 0, 1, 12), + [ + ( + "Starred", + (1, 1, 1, 8), + ( + "Set", + (1, 2, 1, 8), + [ + ("Constant", (1, 3, 1, 4), 1, None), + ("Constant", (1, 6, 1, 7), 2, None), + ], + ), + ("Load",), + ), + ("Constant", (1, 10, 1, 11), 3, None), + ], + ), + ) + ], + [], + ), + ( + "Module", + [ + ( + "AsyncFunctionDef", + (1, 0, 2, 21), + "f", + ("arguments", [], [], None, [], [], None, []), + [ + ( + "Expr", + (2, 1, 2, 21), + ( + "ListComp", + (2, 1, 2, 21), + ("Name", (2, 2, 2, 3), "i", ("Load",)), + [ + ( + "comprehension", + ("Name", (2, 14, 2, 15), "b", ("Store",)), + ("Name", (2, 19, 2, 20), "c", ("Load",)), + [], + 1, + ) + ], + ), + ) + ], + [], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (4, 0, 4, 13), + "f", + ("arguments", [], [], None, [], [], None, []), + [("Pass", (4, 9, 4, 13))], + [ + ("Name", (1, 1, 1, 6), "deco1", ("Load",)), + ( + "Call", + (2, 1, 2, 8), + ("Name", (2, 1, 2, 6), "deco2", ("Load",)), + [], + [], + ), + ( + "Call", + (3, 1, 3, 9), + ("Name", (3, 1, 3, 6), "deco3", ("Load",)), + [("Constant", (3, 7, 3, 8), 1, None)], + [], + ), + ], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "AsyncFunctionDef", + (4, 0, 4, 19), + "f", + ("arguments", [], [], None, [], [], None, []), + [("Pass", (4, 15, 4, 19))], + [ + ("Name", (1, 1, 1, 6), "deco1", ("Load",)), + ( + "Call", + (2, 1, 2, 8), + ("Name", (2, 1, 2, 6), "deco2", ("Load",)), + [], + [], + ), + ( + "Call", + (3, 1, 3, 9), + ("Name", (3, 1, 3, 6), "deco3", ("Load",)), + [("Constant", (3, 7, 3, 8), 1, None)], + [], + ), + ], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "ClassDef", + (4, 0, 4, 13), + "C", + [], + [], + [("Pass", (4, 9, 4, 13))], + [ + ("Name", (1, 1, 1, 6), "deco1", ("Load",)), + ( + "Call", + (2, 1, 2, 8), + ("Name", (2, 1, 2, 6), "deco2", ("Load",)), + [], + [], + ), + ( + "Call", + (3, 1, 3, 9), + ("Name", (3, 1, 3, 6), "deco3", ("Load",)), + [("Constant", (3, 7, 3, 8), 1, None)], + [], + ), + ], + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (2, 0, 2, 13), + "f", + ("arguments", [], [], None, [], [], None, []), + [("Pass", (2, 9, 2, 13))], + [ + ( + "Call", + (1, 1, 1, 19), + ("Name", (1, 1, 1, 5), "deco", ("Load",)), + [ + ( + "GeneratorExp", + (1, 5, 1, 19), + ("Name", (1, 6, 1, 7), "a", ("Load",)), + [ + ( + "comprehension", + ("Name", (1, 12, 1, 13), "a", ("Store",)), + ("Name", (1, 17, 1, 18), "b", ("Load",)), + [], + 0, + ) + ], + ) + ], + [], + ) + ], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (2, 0, 2, 13), + "f", + ("arguments", [], [], None, [], [], None, []), + [("Pass", (2, 9, 2, 13))], + [ + ( + "Attribute", + (1, 1, 1, 6), + ( + "Attribute", + (1, 1, 1, 4), + ("Name", (1, 1, 1, 2), "a", ("Load",)), + "b", + ("Load",), + ), + "c", + ("Load",), + ) + ], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "Expr", + (1, 0, 1, 8), + ( + "NamedExpr", + (1, 1, 1, 7), + ("Name", (1, 1, 1, 2), "a", ("Store",)), + ("Constant", (1, 6, 1, 7), 1, None), + ), + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 18), + "f", + ( + "arguments", + [("arg", (1, 6, 1, 7), "a", None, None)], + [], + None, + [], + [], + None, + [], + ), + [("Pass", (1, 14, 1, 18))], + [], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 26), + "f", + ( + "arguments", + [("arg", (1, 6, 1, 7), "a", None, None)], + [ + ("arg", (1, 12, 1, 13), "c", None, None), + ("arg", (1, 15, 1, 16), "d", None, None), + ("arg", (1, 18, 1, 19), "e", None, None), + ], + None, + [], + [], + None, + [], + ), + [("Pass", (1, 22, 1, 26))], + [], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 29), + "f", + ( + "arguments", + [("arg", (1, 6, 1, 7), "a", None, None)], + [("arg", (1, 12, 1, 13), "c", None, None)], + None, + [ + ("arg", (1, 18, 1, 19), "d", None, None), + ("arg", (1, 21, 1, 22), "e", None, None), + ], + [None, None], + None, + [], + ), + [("Pass", (1, 25, 1, 29))], + [], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 39), + "f", + ( + "arguments", + [("arg", (1, 6, 1, 7), "a", None, None)], + [("arg", (1, 12, 1, 13), "c", None, None)], + None, + [ + ("arg", (1, 18, 1, 19), "d", None, None), + ("arg", (1, 21, 1, 22), "e", None, None), + ], + [None, None], + ("arg", (1, 26, 1, 32), "kwargs", None, None), + [], + ), + [("Pass", (1, 35, 1, 39))], + [], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 20), + "f", + ( + "arguments", + [("arg", (1, 6, 1, 7), "a", None, None)], + [], + None, + [], + [], + None, + [("Constant", (1, 8, 1, 9), 1, None)], + ), + [("Pass", (1, 16, 1, 20))], + [], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 29), + "f", + ( + "arguments", + [("arg", (1, 6, 1, 7), "a", None, None)], + [ + ("arg", (1, 14, 1, 15), "b", None, None), + ("arg", (1, 19, 1, 20), "c", None, None), + ], + None, + [], + [], + None, + [ + ("Constant", (1, 8, 1, 9), 1, None), + ("Constant", (1, 16, 1, 17), 2, None), + ("Constant", (1, 21, 1, 22), 4, None), + ], + ), + [("Pass", (1, 25, 1, 29))], + [], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 32), + "f", + ( + "arguments", + [("arg", (1, 6, 1, 7), "a", None, None)], + [("arg", (1, 14, 1, 15), "b", None, None)], + None, + [("arg", (1, 22, 1, 23), "c", None, None)], + [("Constant", (1, 24, 1, 25), 4, None)], + None, + [ + ("Constant", (1, 8, 1, 9), 1, None), + ("Constant", (1, 16, 1, 17), 2, None), + ], + ), + [("Pass", (1, 28, 1, 32))], + [], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 30), + "f", + ( + "arguments", + [("arg", (1, 6, 1, 7), "a", None, None)], + [("arg", (1, 14, 1, 15), "b", None, None)], + None, + [("arg", (1, 22, 1, 23), "c", None, None)], + [None], + None, + [ + ("Constant", (1, 8, 1, 9), 1, None), + ("Constant", (1, 16, 1, 17), 2, None), + ], + ), + [("Pass", (1, 26, 1, 30))], + [], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 42), + "f", + ( + "arguments", + [("arg", (1, 6, 1, 7), "a", None, None)], + [("arg", (1, 14, 1, 15), "b", None, None)], + None, + [("arg", (1, 22, 1, 23), "c", None, None)], + [("Constant", (1, 24, 1, 25), 4, None)], + ("arg", (1, 29, 1, 35), "kwargs", None, None), + [ + ("Constant", (1, 8, 1, 9), 1, None), + ("Constant", (1, 16, 1, 17), 2, None), + ], + ), + [("Pass", (1, 38, 1, 42))], + [], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 40), + "f", + ( + "arguments", + [("arg", (1, 6, 1, 7), "a", None, None)], + [("arg", (1, 14, 1, 15), "b", None, None)], + None, + [("arg", (1, 22, 1, 23), "c", None, None)], + [None], + ("arg", (1, 27, 1, 33), "kwargs", None, None), + [ + ("Constant", (1, 8, 1, 9), 1, None), + ("Constant", (1, 16, 1, 17), 2, None), + ], + ), + [("Pass", (1, 36, 1, 40))], + [], + None, + None, + [], + ) + ], + [], + ), + ( + "Module", + [ + ( + "TypeAlias", + (1, 0, 1, 12), + ("Name", (1, 5, 1, 6), "X", ("Store",)), + [], + ("Name", (1, 9, 1, 12), "int", ("Load",)), + ) + ], + [], + ), + ( + "Module", + [ + ( + "TypeAlias", + (1, 0, 1, 15), + ("Name", (1, 5, 1, 6), "X", ("Store",)), + [("TypeVar", (1, 7, 1, 8), "T", None, None)], + ("Name", (1, 12, 1, 15), "int", ("Load",)), + ) + ], + [], + ), + ( + "Module", + [ + ( + "TypeAlias", + (1, 0, 1, 32), + ("Name", (1, 5, 1, 6), "X", ("Store",)), + [ + ("TypeVar", (1, 7, 1, 8), "T", None, None), + ("TypeVarTuple", (1, 10, 1, 13), "Ts", None), + ("ParamSpec", (1, 15, 1, 18), "P", None), + ], + ( + "Tuple", + (1, 22, 1, 32), + [ + ("Name", (1, 23, 1, 24), "T", ("Load",)), + ("Name", (1, 26, 1, 28), "Ts", ("Load",)), + ("Name", (1, 30, 1, 31), "P", ("Load",)), + ], + ("Load",), + ), + ) + ], + [], + ), + ( + "Module", + [ + ( + "TypeAlias", + (1, 0, 1, 37), + ("Name", (1, 5, 1, 6), "X", ("Store",)), + [ + ( + "TypeVar", + (1, 7, 1, 13), + "T", + ("Name", (1, 10, 1, 13), "int", ("Load",)), + None, + ), + ("TypeVarTuple", (1, 15, 1, 18), "Ts", None), + ("ParamSpec", (1, 20, 1, 23), "P", None), + ], + ( + "Tuple", + (1, 27, 1, 37), + [ + ("Name", (1, 28, 1, 29), "T", ("Load",)), + ("Name", (1, 31, 1, 33), "Ts", ("Load",)), + ("Name", (1, 35, 1, 36), "P", ("Load",)), + ], + ("Load",), + ), + ) + ], + [], + ), + ( + "Module", + [ + ( + "TypeAlias", + (1, 0, 1, 44), + ("Name", (1, 5, 1, 6), "X", ("Store",)), + [ + ( + "TypeVar", + (1, 7, 1, 20), + "T", + ( + "Tuple", + (1, 10, 1, 20), + [ + ("Name", (1, 11, 1, 14), "int", ("Load",)), + ("Name", (1, 16, 1, 19), "str", ("Load",)), + ], + ("Load",), + ), + None, + ), + ("TypeVarTuple", (1, 22, 1, 25), "Ts", None), + ("ParamSpec", (1, 27, 1, 30), "P", None), + ], + ( + "Tuple", + (1, 34, 1, 44), + [ + ("Name", (1, 35, 1, 36), "T", ("Load",)), + ("Name", (1, 38, 1, 40), "Ts", ("Load",)), + ("Name", (1, 42, 1, 43), "P", ("Load",)), + ], + ("Load",), + ), + ) + ], + [], + ), + ( + "Module", + [ + ( + "TypeAlias", + (1, 0, 1, 48), + ("Name", (1, 5, 1, 6), "X", ("Store",)), + [ + ( + "TypeVar", + (1, 7, 1, 17), + "T", + ("Name", (1, 10, 1, 13), "int", ("Load",)), + ("Constant", (1, 16, 1, 17), 1, None), + ), + ( + "TypeVarTuple", + (1, 19, 1, 26), + "Ts", + ("Constant", (1, 25, 1, 26), 2, None), + ), + ( + "ParamSpec", + (1, 28, 1, 34), + "P", + ("Constant", (1, 33, 1, 34), 3, None), + ), + ], + ( + "Tuple", + (1, 38, 1, 48), + [ + ("Name", (1, 39, 1, 40), "T", ("Load",)), + ("Name", (1, 42, 1, 44), "Ts", ("Load",)), + ("Name", (1, 46, 1, 47), "P", ("Load",)), + ], + ("Load",), + ), + ) + ], + [], + ), + ( + "Module", + [ + ( + "ClassDef", + (1, 0, 1, 16), + "X", + [], + [], + [("Pass", (1, 12, 1, 16))], + [], + [("TypeVar", (1, 8, 1, 9), "T", None, None)], + ) + ], + [], + ), + ( + "Module", + [ + ( + "ClassDef", + (1, 0, 1, 26), + "X", + [], + [], + [("Pass", (1, 22, 1, 26))], + [], + [ + ("TypeVar", (1, 8, 1, 9), "T", None, None), + ("TypeVarTuple", (1, 11, 1, 14), "Ts", None), + ("ParamSpec", (1, 16, 1, 19), "P", None), + ], + ) + ], + [], + ), + ( + "Module", + [ + ( + "ClassDef", + (1, 0, 1, 31), + "X", + [], + [], + [("Pass", (1, 27, 1, 31))], + [], + [ + ( + "TypeVar", + (1, 8, 1, 14), + "T", + ("Name", (1, 11, 1, 14), "int", ("Load",)), + None, + ), + ("TypeVarTuple", (1, 16, 1, 19), "Ts", None), + ("ParamSpec", (1, 21, 1, 24), "P", None), + ], + ) + ], + [], + ), + ( + "Module", + [ + ( + "ClassDef", + (1, 0, 1, 38), + "X", + [], + [], + [("Pass", (1, 34, 1, 38))], + [], + [ + ( + "TypeVar", + (1, 8, 1, 21), + "T", + ( + "Tuple", + (1, 11, 1, 21), + [ + ("Name", (1, 12, 1, 15), "int", ("Load",)), + ("Name", (1, 17, 1, 20), "str", ("Load",)), + ], + ("Load",), + ), + None, + ), + ("TypeVarTuple", (1, 23, 1, 26), "Ts", None), + ("ParamSpec", (1, 28, 1, 31), "P", None), + ], + ) + ], + [], + ), + ( + "Module", + [ + ( + "ClassDef", + (1, 0, 1, 43), + "X", + [], + [], + [("Pass", (1, 39, 1, 43))], + [], + [ + ( + "TypeVar", + (1, 8, 1, 18), + "T", + ("Name", (1, 11, 1, 14), "int", ("Load",)), + ("Constant", (1, 17, 1, 18), 1, None), + ), + ( + "TypeVarTuple", + (1, 20, 1, 27), + "Ts", + ("Constant", (1, 26, 1, 27), 2, None), + ), + ( + "ParamSpec", + (1, 29, 1, 36), + "P", + ("Constant", (1, 35, 1, 36), 3, None), + ), + ], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 16), + "f", + ("arguments", [], [], None, [], [], None, []), + [("Pass", (1, 12, 1, 16))], + [], + None, + None, + [("TypeVar", (1, 6, 1, 7), "T", None, None)], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 26), + "f", + ("arguments", [], [], None, [], [], None, []), + [("Pass", (1, 22, 1, 26))], + [], + None, + None, + [ + ("TypeVar", (1, 6, 1, 7), "T", None, None), + ("TypeVarTuple", (1, 9, 1, 12), "Ts", None), + ("ParamSpec", (1, 14, 1, 17), "P", None), + ], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 31), + "f", + ("arguments", [], [], None, [], [], None, []), + [("Pass", (1, 27, 1, 31))], + [], + None, + None, + [ + ( + "TypeVar", + (1, 6, 1, 12), + "T", + ("Name", (1, 9, 1, 12), "int", ("Load",)), + None, + ), + ("TypeVarTuple", (1, 14, 1, 17), "Ts", None), + ("ParamSpec", (1, 19, 1, 22), "P", None), + ], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 38), + "f", + ("arguments", [], [], None, [], [], None, []), + [("Pass", (1, 34, 1, 38))], + [], + None, + None, + [ + ( + "TypeVar", + (1, 6, 1, 19), + "T", + ( + "Tuple", + (1, 9, 1, 19), + [ + ("Name", (1, 10, 1, 13), "int", ("Load",)), + ("Name", (1, 15, 1, 18), "str", ("Load",)), + ], + ("Load",), + ), + None, + ), + ("TypeVarTuple", (1, 21, 1, 24), "Ts", None), + ("ParamSpec", (1, 26, 1, 29), "P", None), + ], + ) + ], + [], + ), + ( + "Module", + [ + ( + "FunctionDef", + (1, 0, 1, 43), + "f", + ("arguments", [], [], None, [], [], None, []), + [("Pass", (1, 39, 1, 43))], + [], + None, + None, + [ + ( + "TypeVar", + (1, 6, 1, 16), + "T", + ("Name", (1, 9, 1, 12), "int", ("Load",)), + ("Constant", (1, 15, 1, 16), 1, None), + ), + ( + "TypeVarTuple", + (1, 18, 1, 25), + "Ts", + ("Constant", (1, 24, 1, 25), 2, None), + ), + ( + "ParamSpec", + (1, 27, 1, 34), + "P", + ("Constant", (1, 33, 1, 34), 3, None), + ), + ], + ) + ], + [], + ), +] +single_results = [ + ( + "Interactive", + [ + ( + "Expr", + (1, 0, 1, 3), + ( + "BinOp", + (1, 0, 1, 3), + ("Constant", (1, 0, 1, 1), 1, None), + ("Add",), + ("Constant", (1, 2, 1, 3), 2, None), + ), + ) + ], + ), +] +eval_results = [ + ("Expression", ("Constant", (1, 0, 1, 4), None, None)), + ( + "Expression", + ( + "BoolOp", + (1, 0, 1, 7), + ("And",), + [ + ("Name", (1, 0, 1, 1), "a", ("Load",)), + ("Name", (1, 6, 1, 7), "b", ("Load",)), + ], + ), + ), + ( + "Expression", + ( + "BinOp", + (1, 0, 1, 5), + ("Name", (1, 0, 1, 1), "a", ("Load",)), + ("Add",), + ("Name", (1, 4, 1, 5), "b", ("Load",)), + ), + ), + ( + "Expression", + ("UnaryOp", (1, 0, 1, 5), ("Not",), ("Name", (1, 4, 1, 5), "v", ("Load",))), + ), + ( + "Expression", + ( + "Lambda", + (1, 0, 1, 11), + ("arguments", [], [], None, [], [], None, []), + ("Constant", (1, 7, 1, 11), None, None), + ), + ), + ( + "Expression", + ( + "Dict", + (1, 0, 1, 7), + [("Constant", (1, 2, 1, 3), 1, None)], + [("Constant", (1, 4, 1, 5), 2, None)], + ), + ), + ("Expression", ("Dict", (1, 0, 1, 2), [], [])), + ("Expression", ("Set", (1, 0, 1, 7), [("Constant", (1, 1, 1, 5), None, None)])), + ( + "Expression", + ( + "Dict", + (1, 0, 5, 6), + [("Constant", (2, 6, 2, 7), 1, None)], + [("Constant", (4, 10, 4, 11), 2, None)], + ), + ), + ( + "Expression", + ( + "ListComp", + (1, 0, 1, 19), + ("Name", (1, 1, 1, 2), "a", ("Load",)), + [ + ( + "comprehension", + ("Name", (1, 7, 1, 8), "b", ("Store",)), + ("Name", (1, 12, 1, 13), "c", ("Load",)), + [("Name", (1, 17, 1, 18), "d", ("Load",))], + 0, + ) + ], + ), + ), + ( + "Expression", + ( + "GeneratorExp", + (1, 0, 1, 19), + ("Name", (1, 1, 1, 2), "a", ("Load",)), + [ + ( + "comprehension", + ("Name", (1, 7, 1, 8), "b", ("Store",)), + ("Name", (1, 12, 1, 13), "c", ("Load",)), + [("Name", (1, 17, 1, 18), "d", ("Load",))], + 0, + ) + ], + ), + ), + ( + "Expression", + ( + "ListComp", + (1, 0, 1, 20), + ( + "Tuple", + (1, 1, 1, 6), + [ + ("Name", (1, 2, 1, 3), "a", ("Load",)), + ("Name", (1, 4, 1, 5), "b", ("Load",)), + ], + ("Load",), + ), + [ + ( + "comprehension", + ( + "Tuple", + (1, 11, 1, 14), + [ + ("Name", (1, 11, 1, 12), "a", ("Store",)), + ("Name", (1, 13, 1, 14), "b", ("Store",)), + ], + ("Store",), + ), + ("Name", (1, 18, 1, 19), "c", ("Load",)), + [], + 0, + ) + ], + ), + ), + ( + "Expression", + ( + "ListComp", + (1, 0, 1, 22), + ( + "Tuple", + (1, 1, 1, 6), + [ + ("Name", (1, 2, 1, 3), "a", ("Load",)), + ("Name", (1, 4, 1, 5), "b", ("Load",)), + ], + ("Load",), + ), + [ + ( + "comprehension", + ( + "Tuple", + (1, 11, 1, 16), + [ + ("Name", (1, 12, 1, 13), "a", ("Store",)), + ("Name", (1, 14, 1, 15), "b", ("Store",)), + ], + ("Store",), + ), + ("Name", (1, 20, 1, 21), "c", ("Load",)), + [], + 0, + ) + ], + ), + ), + ( + "Expression", + ( + "ListComp", + (1, 0, 1, 22), + ( + "Tuple", + (1, 1, 1, 6), + [ + ("Name", (1, 2, 1, 3), "a", ("Load",)), + ("Name", (1, 4, 1, 5), "b", ("Load",)), + ], + ("Load",), + ), + [ + ( + "comprehension", + ( + "List", + (1, 11, 1, 16), + [ + ("Name", (1, 12, 1, 13), "a", ("Store",)), + ("Name", (1, 14, 1, 15), "b", ("Store",)), + ], + ("Store",), + ), + ("Name", (1, 20, 1, 21), "c", ("Load",)), + [], + 0, + ) + ], + ), + ), + ( + "Expression", + ( + "SetComp", + (1, 0, 1, 20), + ( + "Tuple", + (1, 1, 1, 6), + [ + ("Name", (1, 2, 1, 3), "a", ("Load",)), + ("Name", (1, 4, 1, 5), "b", ("Load",)), + ], + ("Load",), + ), + [ + ( + "comprehension", + ( + "Tuple", + (1, 11, 1, 14), + [ + ("Name", (1, 11, 1, 12), "a", ("Store",)), + ("Name", (1, 13, 1, 14), "b", ("Store",)), + ], + ("Store",), + ), + ("Name", (1, 18, 1, 19), "c", ("Load",)), + [], + 0, + ) + ], + ), + ), + ( + "Expression", + ( + "SetComp", + (1, 0, 1, 22), + ( + "Tuple", + (1, 1, 1, 6), + [ + ("Name", (1, 2, 1, 3), "a", ("Load",)), + ("Name", (1, 4, 1, 5), "b", ("Load",)), + ], + ("Load",), + ), + [ + ( + "comprehension", + ( + "Tuple", + (1, 11, 1, 16), + [ + ("Name", (1, 12, 1, 13), "a", ("Store",)), + ("Name", (1, 14, 1, 15), "b", ("Store",)), + ], + ("Store",), + ), + ("Name", (1, 20, 1, 21), "c", ("Load",)), + [], + 0, + ) + ], + ), + ), + ( + "Expression", + ( + "SetComp", + (1, 0, 1, 22), + ( + "Tuple", + (1, 1, 1, 6), + [ + ("Name", (1, 2, 1, 3), "a", ("Load",)), + ("Name", (1, 4, 1, 5), "b", ("Load",)), + ], + ("Load",), + ), + [ + ( + "comprehension", + ( + "List", + (1, 11, 1, 16), + [ + ("Name", (1, 12, 1, 13), "a", ("Store",)), + ("Name", (1, 14, 1, 15), "b", ("Store",)), + ], + ("Store",), + ), + ("Name", (1, 20, 1, 21), "c", ("Load",)), + [], + 0, + ) + ], + ), + ), + ( + "Expression", + ( + "GeneratorExp", + (1, 0, 1, 20), + ( + "Tuple", + (1, 1, 1, 6), + [ + ("Name", (1, 2, 1, 3), "a", ("Load",)), + ("Name", (1, 4, 1, 5), "b", ("Load",)), + ], + ("Load",), + ), + [ + ( + "comprehension", + ( + "Tuple", + (1, 11, 1, 14), + [ + ("Name", (1, 11, 1, 12), "a", ("Store",)), + ("Name", (1, 13, 1, 14), "b", ("Store",)), + ], + ("Store",), + ), + ("Name", (1, 18, 1, 19), "c", ("Load",)), + [], + 0, + ) + ], + ), + ), + ( + "Expression", + ( + "GeneratorExp", + (1, 0, 1, 22), + ( + "Tuple", + (1, 1, 1, 6), + [ + ("Name", (1, 2, 1, 3), "a", ("Load",)), + ("Name", (1, 4, 1, 5), "b", ("Load",)), + ], + ("Load",), + ), + [ + ( + "comprehension", + ( + "Tuple", + (1, 11, 1, 16), + [ + ("Name", (1, 12, 1, 13), "a", ("Store",)), + ("Name", (1, 14, 1, 15), "b", ("Store",)), + ], + ("Store",), + ), + ("Name", (1, 20, 1, 21), "c", ("Load",)), + [], + 0, + ) + ], + ), + ), + ( + "Expression", + ( + "GeneratorExp", + (1, 0, 1, 22), + ( + "Tuple", + (1, 1, 1, 6), + [ + ("Name", (1, 2, 1, 3), "a", ("Load",)), + ("Name", (1, 4, 1, 5), "b", ("Load",)), + ], + ("Load",), + ), + [ + ( + "comprehension", + ( + "List", + (1, 11, 1, 16), + [ + ("Name", (1, 12, 1, 13), "a", ("Store",)), + ("Name", (1, 14, 1, 15), "b", ("Store",)), + ], + ("Store",), + ), + ("Name", (1, 20, 1, 21), "c", ("Load",)), + [], + 0, + ) + ], + ), + ), + ( + "Expression", + ( + "Compare", + (1, 0, 1, 9), + ("Constant", (1, 0, 1, 1), 1, None), + [("Lt",), ("Lt",)], + [("Constant", (1, 4, 1, 5), 2, None), ("Constant", (1, 8, 1, 9), 3, None)], + ), + ), + ( + "Expression", + ( + "Call", + (1, 0, 1, 17), + ("Name", (1, 0, 1, 1), "f", ("Load",)), + [ + ("Constant", (1, 2, 1, 3), 1, None), + ("Constant", (1, 4, 1, 5), 2, None), + ( + "Starred", + (1, 10, 1, 12), + ("Name", (1, 11, 1, 12), "d", ("Load",)), + ("Load",), + ), + ], + [ + ("keyword", (1, 6, 1, 9), "c", ("Constant", (1, 8, 1, 9), 3, None)), + ( + "keyword", + (1, 13, 1, 16), + None, + ("Name", (1, 15, 1, 16), "e", ("Load",)), + ), + ], + ), + ), + ( + "Expression", + ( + "Call", + (1, 0, 1, 10), + ("Name", (1, 0, 1, 1), "f", ("Load",)), + [ + ( + "Starred", + (1, 2, 1, 9), + ( + "List", + (1, 3, 1, 9), + [ + ("Constant", (1, 4, 1, 5), 0, None), + ("Constant", (1, 7, 1, 8), 1, None), + ], + ("Load",), + ), + ("Load",), + ) + ], + [], + ), + ), + ( + "Expression", + ( + "Call", + (1, 0, 1, 15), + ("Name", (1, 0, 1, 1), "f", ("Load",)), + [ + ( + "GeneratorExp", + (1, 1, 1, 15), + ("Name", (1, 2, 1, 3), "a", ("Load",)), + [ + ( + "comprehension", + ("Name", (1, 8, 1, 9), "a", ("Store",)), + ("Name", (1, 13, 1, 14), "b", ("Load",)), + [], + 0, + ) + ], + ) + ], + [], + ), + ), + ("Expression", ("Constant", (1, 0, 1, 2), 10, None)), + ("Expression", ("Constant", (1, 0, 1, 8), "string", None)), + ( + "Expression", + ( + "Attribute", + (1, 0, 1, 3), + ("Name", (1, 0, 1, 1), "a", ("Load",)), + "b", + ("Load",), + ), + ), + ( + "Expression", + ( + "Subscript", + (1, 0, 1, 6), + ("Name", (1, 0, 1, 1), "a", ("Load",)), + ( + "Slice", + (1, 2, 1, 5), + ("Name", (1, 2, 1, 3), "b", ("Load",)), + ("Name", (1, 4, 1, 5), "c", ("Load",)), + None, + ), + ("Load",), + ), + ), + ("Expression", ("Name", (1, 0, 1, 1), "v", ("Load",))), + ( + "Expression", + ( + "List", + (1, 0, 1, 7), + [ + ("Constant", (1, 1, 1, 2), 1, None), + ("Constant", (1, 3, 1, 4), 2, None), + ("Constant", (1, 5, 1, 6), 3, None), + ], + ("Load",), + ), + ), + ("Expression", ("List", (1, 0, 1, 2), [], ("Load",))), + ( + "Expression", + ( + "Tuple", + (1, 0, 1, 5), + [ + ("Constant", (1, 0, 1, 1), 1, None), + ("Constant", (1, 2, 1, 3), 2, None), + ("Constant", (1, 4, 1, 5), 3, None), + ], + ("Load",), + ), + ), + ( + "Expression", + ( + "Tuple", + (1, 0, 1, 7), + [ + ("Constant", (1, 1, 1, 2), 1, None), + ("Constant", (1, 3, 1, 4), 2, None), + ("Constant", (1, 5, 1, 6), 3, None), + ], + ("Load",), + ), + ), + ("Expression", ("Tuple", (1, 0, 1, 2), [], ("Load",))), + ( + "Expression", + ( + "Call", + (1, 0, 1, 17), + ( + "Attribute", + (1, 0, 1, 7), + ( + "Attribute", + (1, 0, 1, 5), + ( + "Attribute", + (1, 0, 1, 3), + ("Name", (1, 0, 1, 1), "a", ("Load",)), + "b", + ("Load",), + ), + "c", + ("Load",), + ), + "d", + ("Load",), + ), + [ + ( + "Subscript", + (1, 8, 1, 16), + ( + "Attribute", + (1, 8, 1, 11), + ("Name", (1, 8, 1, 9), "a", ("Load",)), + "b", + ("Load",), + ), + ( + "Slice", + (1, 12, 1, 15), + ("Constant", (1, 12, 1, 13), 1, None), + ("Constant", (1, 14, 1, 15), 2, None), + None, + ), + ("Load",), + ) + ], + [], + ), + ), ] main() diff --git a/Lib/test/test_fstring.py b/Lib/test/test_fstring.py index 27c7f70cef32e3..abec8081349fe8 100644 --- a/Lib/test/test_fstring.py +++ b/Lib/test/test_fstring.py @@ -8,6 +8,7 @@ # Unicode identifiers in tests is allowed by PEP 3131. import ast +import datetime import dis import os import re @@ -1602,6 +1603,12 @@ def f(a): self.assertEqual(f'{f(a=4)}', '3=') self.assertEqual(x, 4) + # Check debug expressions in format spec + y = 20 + self.assertEqual(f"{2:{y=}}", "yyyyyyyyyyyyyyyyyyy2") + self.assertEqual(f"{datetime.datetime.now():h1{y=}h2{y=}h3{y=}}", + 'h1y=20h2y=20h3y=20') + # Make sure __format__ is being called. class C: def __format__(self, s): @@ -1615,9 +1622,11 @@ def __repr__(self): self.assertEqual(f'{C()=: }', 'C()=FORMAT- ') self.assertEqual(f'{C()=:x}', 'C()=FORMAT-x') self.assertEqual(f'{C()=!r:*^20}', 'C()=********REPR********') + self.assertEqual(f"{C():{20=}}", 'FORMAT-20=20') self.assertRaises(SyntaxError, eval, "f'{C=]'") + # Make sure leading and following text works. x = 'foo' self.assertEqual(f'X{x=}Y', 'Xx='+repr(x)+'Y') diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-06-29-10-46-14.gh-issue-121130.Rj66Xs.rst b/Misc/NEWS.d/next/Core and Builtins/2024-06-29-10-46-14.gh-issue-121130.Rj66Xs.rst new file mode 100644 index 00000000000000..7084f0cbebbb73 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-06-29-10-46-14.gh-issue-121130.Rj66Xs.rst @@ -0,0 +1,2 @@ +Fix f-strings with debug expressions in format specifiers. Patch by Pablo +Galindo diff --git a/Parser/action_helpers.c b/Parser/action_helpers.c index 6353bacb5c625d..1354ef750556c3 100644 --- a/Parser/action_helpers.c +++ b/Parser/action_helpers.c @@ -961,6 +961,8 @@ _PyPegen_check_fstring_conversion(Parser *p, Token* conv_token, expr_ty conv) return result_token_with_metadata(p, conv, conv_token->metadata); } +static asdl_expr_seq * +unpack_top_level_joined_strs(Parser *p, asdl_expr_seq *raw_expressions); ResultTokenWithMetadata * _PyPegen_setup_full_format_spec(Parser *p, Token *colon, asdl_expr_seq *spec, int lineno, int col_offset, int end_lineno, int end_col_offset, PyArena *arena) @@ -999,8 +1001,15 @@ _PyPegen_setup_full_format_spec(Parser *p, Token *colon, asdl_expr_seq *spec, in assert(j == non_empty_count); spec = resized_spec; } - expr_ty res = _PyAST_JoinedStr(spec, lineno, col_offset, end_lineno, - end_col_offset, p->arena); + expr_ty res; + if (asdl_seq_LEN(spec) == 0) { + res = _PyAST_JoinedStr(spec, lineno, col_offset, end_lineno, + end_col_offset, p->arena); + } else { + res = _PyPegen_concatenate_strings(p, spec, + lineno, col_offset, end_lineno, + end_col_offset, arena); + } if (!res) { return NULL; } @@ -1300,6 +1309,7 @@ unpack_top_level_joined_strs(Parser *p, asdl_expr_seq *raw_expressions) expr_ty _PyPegen_joined_str(Parser *p, Token* a, asdl_expr_seq* raw_expressions, Token*b) { + asdl_expr_seq *expr = unpack_top_level_joined_strs(p, raw_expressions); Py_ssize_t n_items = asdl_seq_LEN(expr); @@ -1464,7 +1474,6 @@ expr_ty _PyPegen_formatted_value(Parser *p, expr_ty expression, Token *debug, Re debug_end_offset = end_col_offset; debug_metadata = closing_brace->metadata; } - expr_ty debug_text = _PyAST_Constant(debug_metadata, NULL, lineno, col_offset + 1, debug_end_line, debug_end_offset - 1, p->arena); if (!debug_text) { @@ -1497,16 +1506,23 @@ _PyPegen_concatenate_strings(Parser *p, asdl_expr_seq *strings, Py_ssize_t n_flattened_elements = 0; for (i = 0; i < len; i++) { expr_ty elem = asdl_seq_GET(strings, i); - if (elem->kind == Constant_kind) { - if (PyBytes_CheckExact(elem->v.Constant.value)) { - bytes_found = 1; - } else { - unicode_string_found = 1; - } - n_flattened_elements++; - } else { - n_flattened_elements += asdl_seq_LEN(elem->v.JoinedStr.values); - f_string_found = 1; + switch(elem->kind) { + case Constant_kind: + if (PyBytes_CheckExact(elem->v.Constant.value)) { + bytes_found = 1; + } else { + unicode_string_found = 1; + } + n_flattened_elements++; + break; + case JoinedStr_kind: + n_flattened_elements += asdl_seq_LEN(elem->v.JoinedStr.values); + f_string_found = 1; + break; + default: + n_flattened_elements++; + f_string_found = 1; + break; } } @@ -1548,16 +1564,19 @@ _PyPegen_concatenate_strings(Parser *p, asdl_expr_seq *strings, Py_ssize_t j = 0; for (i = 0; i < len; i++) { expr_ty elem = asdl_seq_GET(strings, i); - if (elem->kind == Constant_kind) { - asdl_seq_SET(flattened, current_pos++, elem); - } else { - for (j = 0; j < asdl_seq_LEN(elem->v.JoinedStr.values); j++) { - expr_ty subvalue = asdl_seq_GET(elem->v.JoinedStr.values, j); - if (subvalue == NULL) { - return NULL; + switch(elem->kind) { + case JoinedStr_kind: + for (j = 0; j < asdl_seq_LEN(elem->v.JoinedStr.values); j++) { + expr_ty subvalue = asdl_seq_GET(elem->v.JoinedStr.values, j); + if (subvalue == NULL) { + return NULL; + } + asdl_seq_SET(flattened, current_pos++, subvalue); } - asdl_seq_SET(flattened, current_pos++, subvalue); - } + break; + default: + asdl_seq_SET(flattened, current_pos++, elem); + break; } } diff --git a/Parser/lexer/lexer.c b/Parser/lexer/lexer.c index 82b0e4ee352d62..93b5fbd34a2a68 100644 --- a/Parser/lexer/lexer.c +++ b/Parser/lexer/lexer.c @@ -989,6 +989,7 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t the_current_tok->last_expr_buffer = NULL; the_current_tok->last_expr_size = 0; the_current_tok->last_expr_end = -1; + the_current_tok->in_format_spec = 0; the_current_tok->f_string_debug = 0; switch (*tok->start) { @@ -1137,15 +1138,20 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t * by the `{` case, so for ensuring that we are on the 0th level, we need * to adjust it manually */ int cursor = current_tok->curly_bracket_depth - (c != '{'); - if (cursor == 0 && !_PyLexer_update_fstring_expr(tok, c)) { + int in_format_spec = current_tok->in_format_spec; + int cursor_in_format_with_debug = + cursor == 1 && (current_tok->f_string_debug || in_format_spec); + int cursor_valid = cursor == 0 || cursor_in_format_with_debug; + if ((cursor_valid) && !_PyLexer_update_fstring_expr(tok, c)) { return MAKE_TOKEN(ENDMARKER); } - if (cursor == 0 && c != '{' && set_fstring_expr(tok, token, c)) { + if ((cursor_valid) && c != '{' && set_fstring_expr(tok, token, c)) { return MAKE_TOKEN(ERRORTOKEN); } if (c == ':' && cursor == current_tok->curly_bracket_expr_start_depth) { current_tok->kind = TOK_FSTRING_MODE; + current_tok->in_format_spec = 1; p_start = tok->start; p_end = tok->cur; return MAKE_TOKEN(_PyToken_OneChar(c)); @@ -1235,6 +1241,7 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t if (c == '}' && current_tok->curly_bracket_depth == current_tok->curly_bracket_expr_start_depth) { current_tok->curly_bracket_expr_start_depth--; current_tok->kind = TOK_FSTRING_MODE; + current_tok->in_format_spec = 0; current_tok->f_string_debug = 0; } } @@ -1317,11 +1324,11 @@ tok_get_fstring_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct tok->multi_line_start = tok->line_start; while (end_quote_size != current_tok->f_string_quote_size) { int c = tok_nextc(tok); - if (tok->done == E_ERROR) { + if (tok->done == E_ERROR || tok->done == E_DECODE) { return MAKE_TOKEN(ERRORTOKEN); } int in_format_spec = ( - current_tok->last_expr_end != -1 + current_tok->in_format_spec && INSIDE_FSTRING_EXPR(current_tok) ); @@ -1337,6 +1344,7 @@ tok_get_fstring_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct if (in_format_spec && c == '\n') { tok_backup(tok, c); TOK_GET_MODE(tok)->kind = TOK_REGULAR_MODE; + current_tok->in_format_spec = 0; p_start = tok->start; p_end = tok->cur; return MAKE_TOKEN(FSTRING_MIDDLE); @@ -1378,6 +1386,9 @@ tok_get_fstring_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct } if (c == '{') { + if (!_PyLexer_update_fstring_expr(tok, c)) { + return MAKE_TOKEN(ENDMARKER); + } int peek = tok_nextc(tok); if (peek != '{' || in_format_spec) { tok_backup(tok, peek); @@ -1387,6 +1398,7 @@ tok_get_fstring_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct return MAKE_TOKEN(_PyTokenizer_syntaxerror(tok, "f-string: expressions nested too deeply")); } TOK_GET_MODE(tok)->kind = TOK_REGULAR_MODE; + current_tok->in_format_spec = 0; p_start = tok->start; p_end = tok->cur; } else { @@ -1406,13 +1418,15 @@ tok_get_fstring_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct // scanning (indicated by the end of the expression being set) and we are not at the top level // of the bracket stack (-1 is the top level). Since format specifiers can't legally use double // brackets, we can bypass it here. - if (peek == '}' && !in_format_spec) { + int cursor = current_tok->curly_bracket_depth; + if (peek == '}' && !in_format_spec && cursor == 0) { p_start = tok->start; p_end = tok->cur - 1; } else { tok_backup(tok, peek); tok_backup(tok, c); TOK_GET_MODE(tok)->kind = TOK_REGULAR_MODE; + current_tok->in_format_spec = 0; p_start = tok->start; p_end = tok->cur; } diff --git a/Parser/lexer/state.c b/Parser/lexer/state.c index 653ddafd411095..647f291911564c 100644 --- a/Parser/lexer/state.c +++ b/Parser/lexer/state.c @@ -74,6 +74,7 @@ free_fstring_expressions(struct tok_state *tok) mode->last_expr_buffer = NULL; mode->last_expr_size = 0; mode->last_expr_end = -1; + mode->in_format_spec = 0; } } } diff --git a/Parser/lexer/state.h b/Parser/lexer/state.h index 61d090d6d2fe21..9ed3babfdbfbf1 100644 --- a/Parser/lexer/state.h +++ b/Parser/lexer/state.h @@ -58,6 +58,7 @@ typedef struct _tokenizer_mode { Py_ssize_t last_expr_end; char* last_expr_buffer; int f_string_debug; + int in_format_spec; } tokenizer_mode; /* Tokenizer state */