https://github.com/python/cpython/commit/e14930ff6397439759eb34ca70a3493baa845014
commit: e14930ff6397439759eb34ca70a3493baa845014
branch: main
author: Erlend E. Aasland <erl...@python.org>
committer: erlend-aasland <erlend.aasl...@protonmail.com>
date: 2024-01-23T11:07:56+01:00
summary:

gh-113317: Don't use global clinic instance in bad_argument() (#114330)

Make it possible for a converter to have multiple includes, by collecting
them in a list on the converter instance. This implies converter includes
are added during template generation, so we have to add them to the
clinic instance at the end of the template generation instead of in the
beginning.

files:
M Tools/clinic/clinic.py

diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py
index c247bd075321cd..770878a3f8d2c7 100755
--- a/Tools/clinic/clinic.py
+++ b/Tools/clinic/clinic.py
@@ -818,12 +818,6 @@ def output_templates(
             del parameters[0]
         converters = [p.converter for p in parameters]
 
-        # Copy includes from parameters to Clinic
-        for converter in converters:
-            include = converter.include
-            if include:
-                clinic.add_include(include.filename, include.reason,
-                                   condition=include.condition)
         if f.critical_section:
             clinic.add_include('pycore_critical_section.h', 
'Py_BEGIN_CRITICAL_SECTION()')
         has_option_groups = parameters and (parameters[0].group or 
parameters[-1].group)
@@ -1367,6 +1361,13 @@ def parser_body(
                                             declarations=declarations)
 
 
+        # Copy includes from parameters to Clinic after parse_arg() has been
+        # called above.
+        for converter in converters:
+            for include in converter.includes:
+                clinic.add_include(include.filename, include.reason,
+                                   condition=include.condition)
+
         if new_or_init:
             methoddef_define = ''
 
@@ -2988,7 +2989,6 @@ class CConverter(metaclass=CConverterAutoRegister):
     # Only set by self_converter.
     signature_name: str | None = None
 
-    include: Include | None = None
     broken_limited_capi: bool = False
 
     # keep in sync with self_converter.__init__!
@@ -3008,6 +3008,7 @@ def __init__(self,
         self.name = ensure_legal_c_identifier(name)
         self.py_name = py_name
         self.unused = unused
+        self.includes: list[Include] = []
 
         if default is not unspecified:
             if (self.default_type
@@ -3263,8 +3264,7 @@ def bad_argument(self, displayname: str, expected: str, 
*, limited_capi: bool, e
         else:
             if expected_literal:
                 expected = f'"{expected}"'
-            if clinic is not None:
-                clinic.add_include('pycore_modsupport.h', 
'_PyArg_BadArgument()')
+            self.add_include('pycore_modsupport.h', '_PyArg_BadArgument()')
             return f'_PyArg_BadArgument("{{{{name}}}}", "{displayname}", 
{expected}, {{argname}});'
 
     def format_code(self, fmt: str, *,
@@ -3336,9 +3336,8 @@ def parser_name(self) -> str:
 
     def add_include(self, name: str, reason: str,
                     *, condition: str | None = None) -> None:
-        if self.include is not None:
-            raise ValueError("a converter only supports a single include")
-        self.include = Include(name, reason, condition)
+        include = Include(name, reason, condition)
+        self.includes.append(include)
 
 type_checks = {
     '&PyLong_Type': ('PyLong_Check', 'int'),

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com

Reply via email to