From f023f9410117f2160f124f8cb6769945fe728e3b Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Thu, 15 Feb 2024 11:47:40 +0100 Subject: [PATCH 1/2] gh-113317: Argument Clinic: don't use global state in warn() and fail() --- Lib/test/test_clinic.py | 10 +++++----- Tools/clinic/clinic.py | 28 +++++++++++++++++----------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index e987ce54605497..be35e80fb02c72 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -1900,7 +1900,7 @@ def test_parameters_no_more_than_one_vararg(self): *vararg1: object *vararg2: object """ - self.expect_failure(block, err, lineno=0) + self.expect_failure(block, err, lineno=3) def test_function_not_at_column_0(self): function = self.parse_function(""" @@ -2286,10 +2286,10 @@ def test_non_ascii_character_in_docstring(self): self.parse(block) # The line numbers are off; this is a known limitation. expected = dedent("""\ - Warning in file 'clinic_tests' on line 0: + Warning: Non-ascii characters are not allowed in docstrings: 'á' - Warning in file 'clinic_tests' on line 0: + Warning: Non-ascii characters are not allowed in docstrings: 'ü', 'á', 'ß' """) @@ -2390,7 +2390,7 @@ def test_state_func_docstring_no_summary(self): docstring1 docstring2 """ - self.expect_failure(block, err, lineno=0) + self.expect_failure(block, err, lineno=3) def test_state_func_docstring_only_one_param_template(self): err = "You may not specify {parameters} more than once in a docstring!" @@ -2404,7 +2404,7 @@ def test_state_func_docstring_only_one_param_template(self): these are the params again: {parameters} """ - self.expect_failure(block, err, lineno=0) + self.expect_failure(block, err, lineno=7) class ClinicExternalTest(TestCase): diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index e63596c3007940..8fcd2aba7eec5c 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -116,11 +116,6 @@ def warn_or_fail( line_number: int | None = None, ) -> None: joined = " ".join([str(a) for a in args]) - if clinic: - if filename is None: - filename = clinic.filename - if getattr(clinic, 'block_parser', None) and (line_number is None): - line_number = clinic.block_parser.line_number error = ClinicError(joined, filename=filename, lineno=line_number) if fail: raise error @@ -277,7 +272,7 @@ class Language(metaclass=abc.ABCMeta): checksum_line = "" def __init__(self, filename: str) -> None: - ... + self.filename = filename @abc.abstractmethod def render( @@ -833,8 +828,6 @@ def output_templates( if not p.is_optional(): min_kw_only = i - max_pos elif p.is_vararg(): - if vararg != self.NO_VARARG: - fail("Too many var args") pseudo_args += 1 vararg = i - 1 else: @@ -1889,7 +1882,12 @@ def __next__(self) -> Block: raise StopIteration if self.dsl_name: - return_value = self.parse_clinic_block(self.dsl_name) + try: + return_value = self.parse_clinic_block(self.dsl_name) + except ClinicError as exc: + exc.filename = self.language.filename + exc.lineno = self.line_number + raise self.dsl_name = None self.first_block = False return return_value @@ -5071,6 +5069,7 @@ def parse(self, block: Block) -> None: self.state(line) except ClinicError as exc: exc.lineno = line_number + exc.filename = self.clinic.filename raise self.do_post_block_processing_cleanup(line_number) @@ -5078,7 +5077,8 @@ def parse(self, block: Block) -> None: if self.preserve_output: if block.output: - fail("'preserve' only works for blocks that don't produce any output!") + fail("'preserve' only works for blocks that don't produce any output!", + line_number=line_number) block.output = self.saved_output def in_docstring(self) -> bool: @@ -5503,6 +5503,8 @@ def parse_parameter(self, line: str) -> None: f"invalid parameter declaration (**kwargs?): {line!r}") if function_args.vararg: + if any(p.is_vararg() for p in self.function.parameters.values()): + fail("Too many var args") is_vararg = True parameter = function_args.vararg else: @@ -6174,7 +6176,11 @@ def do_post_block_processing_cleanup(self, lineno: int) -> None: return self.check_remaining_star(lineno) - self.function.docstring = self.format_docstring() + try: + self.function.docstring = self.format_docstring() + except ClinicError as exc: + exc.lineno = lineno + raise From 3775ab38f90ae447466ee6cdead8777f4c3be29d Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Thu, 15 Feb 2024 12:26:23 +0100 Subject: [PATCH 2/2] Also explicitly add filename --- Tools/clinic/clinic.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index 8fcd2aba7eec5c..236ca809d530d4 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -6180,6 +6180,7 @@ def do_post_block_processing_cleanup(self, lineno: int) -> None: self.function.docstring = self.format_docstring() except ClinicError as exc: exc.lineno = lineno + exc.filename = self.clinic.filename raise