@@ -1075,6 +1075,11 @@ def output_templates(
10751075 del parameters [0 ]
10761076 converters = [p .converter for p in parameters ]
10771077
1078+ # Copy includes from parameters to Clinic
1079+ for converter in converters :
1080+ if converter .include :
1081+ clinic .add_include (* converter .include )
1082+
10781083 has_option_groups = parameters and (parameters [0 ].group or parameters [- 1 ].group )
10791084 default_return_converter = f .return_converter .type == 'PyObject *'
10801085 new_or_init = f .kind .new_or_init
@@ -2126,8 +2131,8 @@ def print_block(
21262131 self ,
21272132 block : Block ,
21282133 * ,
2134+ clinic : Clinic ,
21292135 core_includes : bool = False ,
2130- clinic : Clinic | None = None ,
21312136 ) -> None :
21322137 input = block .input
21332138 output = block .output
@@ -2156,18 +2161,22 @@ def print_block(
21562161 write ("\n " )
21572162
21582163 output = ''
2159- if clinic :
2160- limited_capi = clinic .limited_capi
2161- else :
2162- limited_capi = DEFAULT_LIMITED_CAPI
2163- if core_includes and not limited_capi :
2164- output += textwrap .dedent ("""
2165- #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
2166- # include "pycore_gc.h" // PyGC_Head
2167- # include "pycore_runtime.h" // _Py_ID()
2168- #endif
2169-
2170- """ )
2164+ if core_includes :
2165+ if not clinic .limited_capi :
2166+ output += textwrap .dedent ("""
2167+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
2168+ # include "pycore_gc.h" // PyGC_Head
2169+ # include "pycore_runtime.h" // _Py_ID()
2170+ #endif
2171+
2172+ """ )
2173+
2174+ if clinic is not None :
2175+ # Emit optional includes
2176+ for include , reason in sorted (clinic .includes .items ()):
2177+ line = f'#include "{ include } "'
2178+ line = line .ljust (35 ) + f'// { reason } \n '
2179+ output += line
21712180
21722181 input = '' .join (block .input )
21732182 output += '' .join (block .output )
@@ -2311,7 +2320,7 @@ def __init__(self, clinic: Clinic) -> None: ...
23112320 def parse (self , block : Block ) -> None : ...
23122321
23132322
2314- clinic = None
2323+ clinic : Clinic | None = None
23152324class Clinic :
23162325
23172326 presets_text = """
@@ -2379,6 +2388,9 @@ def __init__(
23792388 self .modules : ModuleDict = {}
23802389 self .classes : ClassDict = {}
23812390 self .functions : list [Function ] = []
2391+ # dict: include name => reason
2392+ # Example: 'pycore_long.h' => '_PyLong_UnsignedShort_Converter()'
2393+ self .includes : dict [str , str ] = {}
23822394
23832395 self .line_prefix = self .line_suffix = ''
23842396
@@ -2437,6 +2449,12 @@ def __init__(
24372449 global clinic
24382450 clinic = self
24392451
2452+ def add_include (self , name : str , reason : str ) -> None :
2453+ if name in self .includes :
2454+ # Mention a single reason is enough, no need to list all of them
2455+ return
2456+ self .includes [name ] = reason
2457+
24402458 def add_destination (
24412459 self ,
24422460 name : str ,
@@ -3066,6 +3084,10 @@ class CConverter(metaclass=CConverterAutoRegister):
30663084 # Only set by self_converter.
30673085 signature_name : str | None = None
30683086
3087+ # Optional (name, reason) include which generate a line like:
3088+ # "#include "name" // reason"
3089+ include : tuple [str , str ] | None = None
3090+
30693091 # keep in sync with self_converter.__init__!
30703092 def __init__ (self ,
30713093 # Positional args:
@@ -3370,6 +3392,11 @@ def parser_name(self) -> str:
33703392 else :
33713393 return self .name
33723394
3395+ def add_include (self , name : str , reason : str ) -> None :
3396+ if self .include is not None :
3397+ raise ValueError ("a converter only supports a single include" )
3398+ self .include = (name , reason )
3399+
33733400type_checks = {
33743401 '&PyLong_Type' : ('PyLong_Check' , 'int' ),
33753402 '&PyTuple_Type' : ('PyTuple_Check' , 'tuple' ),
@@ -5989,9 +6016,6 @@ def do_post_block_processing_cleanup(self, lineno: int) -> None:
59896016}
59906017
59916018
5992- clinic = None
5993-
5994-
59956019def create_cli () -> argparse .ArgumentParser :
59966020 cmdline = argparse .ArgumentParser (
59976021 prog = "clinic.py" ,
0 commit comments