From 198c87a625ecb0aeac723fda539290698bfce428 Mon Sep 17 00:00:00 2001 From: donBarbos Date: Sat, 3 May 2025 09:00:03 +0400 Subject: [PATCH 01/11] Add tests for `ast` command-line interface --- Lib/ast.py | 6 +- Lib/test/test_ast/test_ast.py | 162 ++++++++++++++++++++++++++++++---- 2 files changed, 150 insertions(+), 18 deletions(-) diff --git a/Lib/ast.py b/Lib/ast.py index aa788e6eb62c4f..4940c6381a7a15 100644 --- a/Lib/ast.py +++ b/Lib/ast.py @@ -626,7 +626,7 @@ def unparse(ast_obj): return unparser.visit(ast_obj) -def main(): +def _main(args=None): import argparse import sys @@ -643,7 +643,7 @@ def main(): 'column offsets') parser.add_argument('-i', '--indent', type=int, default=3, help='indentation of nodes (number of spaces)') - args = parser.parse_args() + args = parser.parse_args(args) if args.infile == '-': name = '' @@ -656,4 +656,4 @@ def main(): print(dump(tree, include_attributes=args.include_attributes, indent=args.indent)) if __name__ == '__main__': - main() + _main() diff --git a/Lib/test/test_ast/test_ast.py b/Lib/test/test_ast/test_ast.py index 7d64b1c0e3a0c3..b7f06537fb0d4f 100644 --- a/Lib/test/test_ast/test_ast.py +++ b/Lib/test/test_ast/test_ast.py @@ -1,12 +1,16 @@ import _ast_unparse import ast import builtins +import contextlib import copy import dis import enum +import io +import itertools import os import re import sys +import tempfile import textwrap import types import unittest @@ -3175,23 +3179,151 @@ def test_subinterpreter(self): self.assertEqual(res, 0) -class ASTMainTests(unittest.TestCase): - # Tests `ast.main()` function. +class CommandLineTests(unittest.TestCase): + def setUp(self): + self.filename = tempfile.mktemp() + self.addCleanup(os_helper.unlink, self.filename) - def test_cli_file_input(self): - code = "print(1, 2, 3)" - expected = ast.dump(ast.parse(code), indent=3) - - 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: - f.write(code) - res, _ = script_helper.run_python_until_end("-m", "ast", filename) + @staticmethod + def text_normalize(string): + """Dedent *string* and strip it from its surrounding whitespaces. + This method is used by the other utility functions so that any + string to write or to match against can be freely indented. + """ + return textwrap.dedent(string).strip() + + def set_source(self, content): + with open(self.filename, 'w') as f: + f.write(self.text_normalize(content)) + + def invoke_ast(self, *flags): + output = io.StringIO() + with contextlib.redirect_stdout(output): + ast._main(args=[*flags, self.filename]) + return self.text_normalize(output.getvalue()) + + def check_output(self, source, expect, *flags): + with self.subTest(source=source, flags=flags): + self.set_source(source) + res = self.invoke_ast(*flags) + expect = self.text_normalize(expect) + self.assertListEqual(res.splitlines(), expect.splitlines()) + + def test_invocation(self): + # test various combinations of parameters + base_flags = [ + ('-m=exec', '--mode=exec'), + ('--no-type-comments', '--no-type-comments'), + ('-a', '--include-attributes'), + ('-i=4', '--indent=4'), + ] + self.set_source(''' + print(1, 2, 3) + def f(x): + x -= 1 + return x + ''') - self.assertEqual(res.err, b"") - self.assertEqual(expected.splitlines(), - res.out.decode("utf8").splitlines()) - self.assertEqual(res.rc, 0) + for r in range(1, len(base_flags) + 1): + for choices in itertools.combinations(base_flags, r=r): + for args in itertools.product(*choices): + with self.subTest(args=args[1:]): + _ = self.invoke_ast(*args) + + with self.assertRaises(SystemExit): + # suppress argparse error message + with contextlib.redirect_stderr(io.StringIO()): + _ = self.invoke_ast('--unknown') + + def test_mode_flag(self): + # test 'python -m ast -m/--mode' + source = 'print(1, 2, 3)' + expect = ''' + Module( + body=[ + Expr( + value=Call( + func=Name(id='print', ctx=Load()), + args=[ + Constant(value=1), + Constant(value=2), + Constant(value=3)]))]) + ''' + for flag in ['-m=exec', '--mode=exec']: + self.check_output(source, expect, flag) + source = 'pass' + expect = ''' + Interactive( + body=[ + Pass()]) + ''' + for flag in ['-m=single', '--mode=single']: + self.check_output(source, expect, flag) + source = 'print(1, 2, 3)' + expect = ''' + Expression( + body=Call( + func=Name(id='print', ctx=Load()), + args=[ + Constant(value=1), + Constant(value=2), + Constant(value=3)])) + ''' + for flag in ['-m=eval', '--mode=eval']: + self.check_output(source, expect, flag) + source = '(int, str) -> list[int]' + expect = ''' + FunctionType( + argtypes=[ + Name(id='int', ctx=Load()), + Name(id='str', ctx=Load())], + returns=Subscript( + value=Name(id='list', ctx=Load()), + slice=Name(id='int', ctx=Load()), + ctx=Load())) + ''' + for flag in ['-m=func_type', '--mode=func_type']: + self.check_output(source, expect, flag) + + def test_no_type_comments_flag(self): + # test 'python -m ast --no-type-comments' + source = 'x: bool = 1 # type: ignore[assignment]' + expect = ''' + Module( + body=[ + AnnAssign( + target=Name(id='x', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + value=Constant(value=1), + simple=1)]) + ''' + self.check_output(source, expect, '--no-type-comments') + + def test_include_attributes_flag(self): + # test 'python -m ast -a/--include-attributes' + source = 'pass' + expect = ''' + Module( + body=[ + Pass( + lineno=1, + col_offset=0, + end_lineno=1, + end_col_offset=4)]) + ''' + for flag in ['-a', '--include-attributes']: + self.check_output(source, expect, flag) + + def test_indent_flag(self): + # test 'python -m ast -i/--indent' + source = 'pass' + expect = ''' + Module( + body=[ + Pass()]) + ''' + for flag in ['-i=0', '--indent=0']: + self.check_output(source, expect, flag) class ASTOptimiziationTests(unittest.TestCase): From bc12715b56572dc77eedb03df3bd0d2206df5a0a Mon Sep 17 00:00:00 2001 From: donBarbos Date: Sat, 3 May 2025 09:14:56 +0400 Subject: [PATCH 02/11] check unknown flag output --- Lib/test/test_ast/test_ast.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_ast/test_ast.py b/Lib/test/test_ast/test_ast.py index b7f06537fb0d4f..7a77b94a49604e 100644 --- a/Lib/test/test_ast/test_ast.py +++ b/Lib/test/test_ast/test_ast.py @@ -5,7 +5,6 @@ import copy import dis import enum -import io import itertools import os import re @@ -15,6 +14,7 @@ import types import unittest import weakref +from io import StringIO from pathlib import Path from textwrap import dedent try: @@ -3197,7 +3197,7 @@ def set_source(self, content): f.write(self.text_normalize(content)) def invoke_ast(self, *flags): - output = io.StringIO() + output = StringIO() with contextlib.redirect_stdout(output): ast._main(args=[*flags, self.filename]) return self.text_normalize(output.getvalue()) @@ -3232,8 +3232,9 @@ def f(x): with self.assertRaises(SystemExit): # suppress argparse error message - with contextlib.redirect_stderr(io.StringIO()): - _ = self.invoke_ast('--unknown') + with contextlib.redirect_stderr(StringIO()): + output = self.invoke_ast('--unknown') + self.assertStartsWith(output, 'usage: ') def test_mode_flag(self): # test 'python -m ast -m/--mode' From 75d3cb71e1c9e50ad8f9d12f84ad02bcaf4792c3 Mon Sep 17 00:00:00 2001 From: donBarbos Date: Sat, 3 May 2025 09:56:26 +0400 Subject: [PATCH 03/11] remove unused import --- Lib/test/test_ast/test_ast.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_ast/test_ast.py b/Lib/test/test_ast/test_ast.py index 7a77b94a49604e..17190f24256c82 100644 --- a/Lib/test/test_ast/test_ast.py +++ b/Lib/test/test_ast/test_ast.py @@ -23,7 +23,7 @@ _testinternalcapi = None from test import support -from test.support import os_helper, script_helper +from test.support import os_helper from test.support import skip_emscripten_stack_overflow, skip_wasi_stack_overflow from test.support.ast_helper import ASTTestMixin from test.test_ast.utils import to_tuple From de328afc20b10ef45b8cd85488c91d0419c4d49a Mon Sep 17 00:00:00 2001 From: donBarbos Date: Sun, 4 May 2025 00:42:37 +0400 Subject: [PATCH 04/11] Accept suggestions --- Lib/test/test_ast/test_ast.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/Lib/test/test_ast/test_ast.py b/Lib/test/test_ast/test_ast.py index 17190f24256c82..045dca3db3a5be 100644 --- a/Lib/test/test_ast/test_ast.py +++ b/Lib/test/test_ast/test_ast.py @@ -3193,8 +3193,7 @@ def text_normalize(string): return textwrap.dedent(string).strip() def set_source(self, content): - with open(self.filename, 'w') as f: - f.write(self.text_normalize(content)) + Path(self.filename).write_text(self.text_normalize(content)) def invoke_ast(self, *flags): output = StringIO() @@ -3207,16 +3206,16 @@ def check_output(self, source, expect, *flags): self.set_source(source) res = self.invoke_ast(*flags) expect = self.text_normalize(expect) - self.assertListEqual(res.splitlines(), expect.splitlines()) + self.assertEqual(res, expect) def test_invocation(self): # test various combinations of parameters - base_flags = [ + base_flags = ( ('-m=exec', '--mode=exec'), ('--no-type-comments', '--no-type-comments'), ('-a', '--include-attributes'), ('-i=4', '--indent=4'), - ] + ) self.set_source(''' print(1, 2, 3) def f(x): @@ -3250,7 +3249,7 @@ def test_mode_flag(self): Constant(value=2), Constant(value=3)]))]) ''' - for flag in ['-m=exec', '--mode=exec']: + for flag in ('-m=exec', '--mode=exec'): self.check_output(source, expect, flag) source = 'pass' expect = ''' @@ -3258,7 +3257,7 @@ def test_mode_flag(self): body=[ Pass()]) ''' - for flag in ['-m=single', '--mode=single']: + for flag in ('-m=single', '--mode=single'): self.check_output(source, expect, flag) source = 'print(1, 2, 3)' expect = ''' @@ -3270,7 +3269,7 @@ def test_mode_flag(self): Constant(value=2), Constant(value=3)])) ''' - for flag in ['-m=eval', '--mode=eval']: + for flag in ('-m=eval', '--mode=eval'): self.check_output(source, expect, flag) source = '(int, str) -> list[int]' expect = ''' @@ -3283,7 +3282,7 @@ def test_mode_flag(self): slice=Name(id='int', ctx=Load()), ctx=Load())) ''' - for flag in ['-m=func_type', '--mode=func_type']: + for flag in ('-m=func_type', '--mode=func_type'): self.check_output(source, expect, flag) def test_no_type_comments_flag(self): @@ -3312,7 +3311,7 @@ def test_include_attributes_flag(self): end_lineno=1, end_col_offset=4)]) ''' - for flag in ['-a', '--include-attributes']: + for flag in ('-a', '--include-attributes'): self.check_output(source, expect, flag) def test_indent_flag(self): @@ -3323,7 +3322,7 @@ def test_indent_flag(self): body=[ Pass()]) ''' - for flag in ['-i=0', '--indent=0']: + for flag in ('-i=0', '--indent=0'): self.check_output(source, expect, flag) From 6aa5cd7ec4d9148dcd45a3ede7054bb88e4547c5 Mon Sep 17 00:00:00 2001 From: donBarbos Date: Sun, 4 May 2025 12:29:34 +0400 Subject: [PATCH 05/11] Accept suggestions --- Lib/ast.py | 4 +-- Lib/test/test_ast/test_ast.py | 67 ++++++++++++++++++++++------------- 2 files changed, 44 insertions(+), 27 deletions(-) diff --git a/Lib/ast.py b/Lib/ast.py index 4940c6381a7a15..af4fe8ff5a8e95 100644 --- a/Lib/ast.py +++ b/Lib/ast.py @@ -626,7 +626,7 @@ def unparse(ast_obj): return unparser.visit(ast_obj) -def _main(args=None): +def main(args=None): import argparse import sys @@ -656,4 +656,4 @@ def _main(args=None): print(dump(tree, include_attributes=args.include_attributes, indent=args.indent)) if __name__ == '__main__': - _main() + main() diff --git a/Lib/test/test_ast/test_ast.py b/Lib/test/test_ast/test_ast.py index 045dca3db3a5be..4cb4d73ce445d0 100644 --- a/Lib/test/test_ast/test_ast.py +++ b/Lib/test/test_ast/test_ast.py @@ -3186,20 +3186,21 @@ def setUp(self): @staticmethod def text_normalize(string): - """Dedent *string* and strip it from its surrounding whitespaces. - This method is used by the other utility functions so that any - string to write or to match against can be freely indented. - """ return textwrap.dedent(string).strip() def set_source(self, content): Path(self.filename).write_text(self.text_normalize(content)) def invoke_ast(self, *flags): - output = StringIO() - with contextlib.redirect_stdout(output): - ast._main(args=[*flags, self.filename]) - return self.text_normalize(output.getvalue()) + stderr = StringIO() + stdout = StringIO() + with ( + contextlib.redirect_stdout(stdout), + contextlib.redirect_stderr(stderr), + ): + ast.main(args=[*flags, self.filename]) + self.assertEqual(stderr.getvalue(), '') + return self.text_normalize(stdout.getvalue()) def check_output(self, source, expect, *flags): with self.subTest(source=source, flags=flags): @@ -3218,7 +3219,7 @@ def test_invocation(self): ) self.set_source(''' print(1, 2, 3) - def f(x): + def f(x: int) -> int: x -= 1 return x ''') @@ -3226,31 +3227,41 @@ def f(x): for r in range(1, len(base_flags) + 1): for choices in itertools.combinations(base_flags, r=r): for args in itertools.product(*choices): - with self.subTest(args=args[1:]): + with self.subTest(flags=args[1:]): _ = self.invoke_ast(*args) + def test_unknown_flag(self): with self.assertRaises(SystemExit): - # suppress argparse error message - with contextlib.redirect_stderr(StringIO()): - output = self.invoke_ast('--unknown') - self.assertStartsWith(output, 'usage: ') - - def test_mode_flag(self): - # test 'python -m ast -m/--mode' - source = 'print(1, 2, 3)' + output = self.invoke_ast('--unknown') + self.assertStartsWith(output, 'usage: ') + + def test_help_flag(self): + # test 'python -m ast -h/--help' + for flag in ('-h', '--help'): + with self.subTest(flags=flag): + with self.assertRaises(SystemExit): + output = self.invoke_ast(flag) + self.assertStartsWith(output, 'usage: ') + + def test_exec_mode_flag(self): + # test 'python -m ast -m/--mode exec' + source = 'x: bool = 1 # type: ignore[assignment]' expect = ''' Module( body=[ - Expr( - value=Call( - func=Name(id='print', ctx=Load()), - args=[ - Constant(value=1), - Constant(value=2), - Constant(value=3)]))]) + AnnAssign( + target=Name(id='x', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + value=Constant(value=1), + simple=1)], + type_ignores=[ + TypeIgnore(lineno=1, tag='[assignment]')]) ''' for flag in ('-m=exec', '--mode=exec'): self.check_output(source, expect, flag) + + def test_single_mode_flag(self): + # test 'python -m ast -m/--mode single' source = 'pass' expect = ''' Interactive( @@ -3259,6 +3270,9 @@ def test_mode_flag(self): ''' for flag in ('-m=single', '--mode=single'): self.check_output(source, expect, flag) + + def test_eval_mode_flag(self): + # test 'python -m ast -m/--mode eval' source = 'print(1, 2, 3)' expect = ''' Expression( @@ -3271,6 +3285,9 @@ def test_mode_flag(self): ''' for flag in ('-m=eval', '--mode=eval'): self.check_output(source, expect, flag) + + def test_func_type_mode_flag(self): + # test 'python -m ast -m/--mode func_type' source = '(int, str) -> list[int]' expect = ''' FunctionType( From b804f6152fcb03a022d9a629a2e658a617ed9c46 Mon Sep 17 00:00:00 2001 From: donBarbos Date: Sun, 4 May 2025 15:35:23 +0400 Subject: [PATCH 06/11] accept again --- Lib/test/test_ast/test_ast.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_ast/test_ast.py b/Lib/test/test_ast/test_ast.py index 4cb4d73ce445d0..37116f7b644fd4 100644 --- a/Lib/test/test_ast/test_ast.py +++ b/Lib/test/test_ast/test_ast.py @@ -3227,8 +3227,8 @@ def f(x: int) -> int: for r in range(1, len(base_flags) + 1): for choices in itertools.combinations(base_flags, r=r): for args in itertools.product(*choices): - with self.subTest(flags=args[1:]): - _ = self.invoke_ast(*args) + with self.subTest(flags=args): + self.invoke_ast(*args) def test_unknown_flag(self): with self.assertRaises(SystemExit): @@ -3258,7 +3258,8 @@ def test_exec_mode_flag(self): TypeIgnore(lineno=1, tag='[assignment]')]) ''' for flag in ('-m=exec', '--mode=exec'): - self.check_output(source, expect, flag) + with self.subTest(flags=flag): + self.check_output(source, expect, flag) def test_single_mode_flag(self): # test 'python -m ast -m/--mode single' @@ -3269,7 +3270,8 @@ def test_single_mode_flag(self): Pass()]) ''' for flag in ('-m=single', '--mode=single'): - self.check_output(source, expect, flag) + with self.subTest(flags=flag): + self.check_output(source, expect, flag) def test_eval_mode_flag(self): # test 'python -m ast -m/--mode eval' @@ -3284,7 +3286,8 @@ def test_eval_mode_flag(self): Constant(value=3)])) ''' for flag in ('-m=eval', '--mode=eval'): - self.check_output(source, expect, flag) + with self.subTest(flags=flag): + self.check_output(source, expect, flag) def test_func_type_mode_flag(self): # test 'python -m ast -m/--mode func_type' @@ -3300,7 +3303,8 @@ def test_func_type_mode_flag(self): ctx=Load())) ''' for flag in ('-m=func_type', '--mode=func_type'): - self.check_output(source, expect, flag) + with self.subTest(flags=flag): + self.check_output(source, expect, flag) def test_no_type_comments_flag(self): # test 'python -m ast --no-type-comments' @@ -3329,7 +3333,8 @@ def test_include_attributes_flag(self): end_col_offset=4)]) ''' for flag in ('-a', '--include-attributes'): - self.check_output(source, expect, flag) + with self.subTest(flags=flag): + self.check_output(source, expect, flag) def test_indent_flag(self): # test 'python -m ast -i/--indent' @@ -3340,7 +3345,8 @@ def test_indent_flag(self): Pass()]) ''' for flag in ('-i=0', '--indent=0'): - self.check_output(source, expect, flag) + with self.subTest(flags=flag): + self.check_output(source, expect, flag) class ASTOptimiziationTests(unittest.TestCase): From 21097ebfa5f23bcf295094f200744c090864dd29 Mon Sep 17 00:00:00 2001 From: donBarbos Date: Sun, 4 May 2025 15:36:29 +0400 Subject: [PATCH 07/11] Rename from flags to flag --- Lib/test/test_ast/test_ast.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_ast/test_ast.py b/Lib/test/test_ast/test_ast.py index 37116f7b644fd4..3f29981c102ad1 100644 --- a/Lib/test/test_ast/test_ast.py +++ b/Lib/test/test_ast/test_ast.py @@ -3238,7 +3238,7 @@ def test_unknown_flag(self): def test_help_flag(self): # test 'python -m ast -h/--help' for flag in ('-h', '--help'): - with self.subTest(flags=flag): + with self.subTest(flag=flag): with self.assertRaises(SystemExit): output = self.invoke_ast(flag) self.assertStartsWith(output, 'usage: ') @@ -3258,7 +3258,7 @@ def test_exec_mode_flag(self): TypeIgnore(lineno=1, tag='[assignment]')]) ''' for flag in ('-m=exec', '--mode=exec'): - with self.subTest(flags=flag): + with self.subTest(flag=flag): self.check_output(source, expect, flag) def test_single_mode_flag(self): @@ -3270,7 +3270,7 @@ def test_single_mode_flag(self): Pass()]) ''' for flag in ('-m=single', '--mode=single'): - with self.subTest(flags=flag): + with self.subTest(flag=flag): self.check_output(source, expect, flag) def test_eval_mode_flag(self): @@ -3286,7 +3286,7 @@ def test_eval_mode_flag(self): Constant(value=3)])) ''' for flag in ('-m=eval', '--mode=eval'): - with self.subTest(flags=flag): + with self.subTest(flag=flag): self.check_output(source, expect, flag) def test_func_type_mode_flag(self): @@ -3303,7 +3303,7 @@ def test_func_type_mode_flag(self): ctx=Load())) ''' for flag in ('-m=func_type', '--mode=func_type'): - with self.subTest(flags=flag): + with self.subTest(flag=flag): self.check_output(source, expect, flag) def test_no_type_comments_flag(self): @@ -3333,7 +3333,7 @@ def test_include_attributes_flag(self): end_col_offset=4)]) ''' for flag in ('-a', '--include-attributes'): - with self.subTest(flags=flag): + with self.subTest(flag=flag): self.check_output(source, expect, flag) def test_indent_flag(self): @@ -3345,7 +3345,7 @@ def test_indent_flag(self): Pass()]) ''' for flag in ('-i=0', '--indent=0'): - with self.subTest(flags=flag): + with self.subTest(flag=flag): self.check_output(source, expect, flag) From 42ff309fbeeee688efa5776e71a9602c1a72cd1b Mon Sep 17 00:00:00 2001 From: donBarbos Date: Sun, 4 May 2025 16:40:04 +0400 Subject: [PATCH 08/11] Rewrite tests with help messages --- Lib/test/test_ast/test_ast.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_ast/test_ast.py b/Lib/test/test_ast/test_ast.py index 3f29981c102ad1..c6d19d3c254f54 100644 --- a/Lib/test/test_ast/test_ast.py +++ b/Lib/test/test_ast/test_ast.py @@ -3230,18 +3230,14 @@ def f(x: int) -> int: with self.subTest(flags=args): self.invoke_ast(*args) - def test_unknown_flag(self): - with self.assertRaises(SystemExit): - output = self.invoke_ast('--unknown') - self.assertStartsWith(output, 'usage: ') - - def test_help_flag(self): - # test 'python -m ast -h/--help' - for flag in ('-h', '--help'): + def test_help_message(self): + for flag in ('-h', '--help', '--unknown'): with self.subTest(flag=flag): + output = StringIO() with self.assertRaises(SystemExit): - output = self.invoke_ast(flag) - self.assertStartsWith(output, 'usage: ') + with contextlib.redirect_stderr(output): + ast.main(args=(flag)) + self.assertStartsWith(output.getvalue(), 'usage: ') def test_exec_mode_flag(self): # test 'python -m ast -m/--mode exec' From ac71310df3b3486b1b8a70bfb817aeb15b5b85bb Mon Sep 17 00:00:00 2001 From: donBarbos Date: Sun, 4 May 2025 23:31:15 +0400 Subject: [PATCH 09/11] Remove normalize for result --- Lib/test/test_ast/test_ast.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_ast/test_ast.py b/Lib/test/test_ast/test_ast.py index c6d19d3c254f54..ec7e6cf767d8ab 100644 --- a/Lib/test/test_ast/test_ast.py +++ b/Lib/test/test_ast/test_ast.py @@ -3200,7 +3200,7 @@ def invoke_ast(self, *flags): ): ast.main(args=[*flags, self.filename]) self.assertEqual(stderr.getvalue(), '') - return self.text_normalize(stdout.getvalue()) + return stdout.getvalue().strip() def check_output(self, source, expect, *flags): with self.subTest(source=source, flags=flags): From 9f6f5b2907dc173f67709b8166949b5ce58978c2 Mon Sep 17 00:00:00 2001 From: Semyon Moroz Date: Mon, 5 May 2025 00:45:32 +0400 Subject: [PATCH 10/11] Update test_ast.py --- Lib/test/test_ast/test_ast.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_ast/test_ast.py b/Lib/test/test_ast/test_ast.py index ec7e6cf767d8ab..5b81ee629260b4 100644 --- a/Lib/test/test_ast/test_ast.py +++ b/Lib/test/test_ast/test_ast.py @@ -3203,11 +3203,10 @@ def invoke_ast(self, *flags): return stdout.getvalue().strip() def check_output(self, source, expect, *flags): - with self.subTest(source=source, flags=flags): - self.set_source(source) - res = self.invoke_ast(*flags) - expect = self.text_normalize(expect) - self.assertEqual(res, expect) + self.set_source(source) + res = self.invoke_ast(*flags) + expect = self.text_normalize(expect) + self.assertEqual(res, expect) def test_invocation(self): # test various combinations of parameters From 361706a92dfabeb33833b6c1283ee0247ebb8b25 Mon Sep 17 00:00:00 2001 From: Semyon Moroz Date: Mon, 5 May 2025 00:45:59 +0400 Subject: [PATCH 11/11] Update test_ast.py Co-authored-by: sobolevn --- Lib/test/test_ast/test_ast.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_ast/test_ast.py b/Lib/test/test_ast/test_ast.py index 5b81ee629260b4..a6fc35585b13b2 100644 --- a/Lib/test/test_ast/test_ast.py +++ b/Lib/test/test_ast/test_ast.py @@ -3235,7 +3235,7 @@ def test_help_message(self): output = StringIO() with self.assertRaises(SystemExit): with contextlib.redirect_stderr(output): - ast.main(args=(flag)) + ast.main(args=flag) self.assertStartsWith(output.getvalue(), 'usage: ') def test_exec_mode_flag(self):