https://github.com/python/cpython/commit/7f074a771bc4e3e299799fabf9b054a03f6693d2
commit: 7f074a771bc4e3e299799fabf9b054a03f6693d2
branch: main
author: Erlend E. Aasland <[email protected]>
committer: erlend-aasland <[email protected]>
date: 2024-02-15T13:22:21+01:00
summary:

gh-113317: Argument Clinic: don't use global state in warn() and fail() 
(#115510)

files:
M Lib/test/test_clinic.py
M Tools/clinic/clinic.py

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 2381004f02352a..4fa07ee3db2039 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,12 @@ 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
+            exc.filename = self.clinic.filename
+            raise
 
 
 

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to