@@ -1075,6 +1075,11 @@ def output_templates(
1075
1075
del parameters [0 ]
1076
1076
converters = [p .converter for p in parameters ]
1077
1077
1078
+ # Copy includes from parameters to Clinic
1079
+ for converter in converters :
1080
+ if converter .include :
1081
+ clinic .add_include (* converter .include )
1082
+
1078
1083
has_option_groups = parameters and (parameters [0 ].group or parameters [- 1 ].group )
1079
1084
default_return_converter = f .return_converter .type == 'PyObject *'
1080
1085
new_or_init = f .kind .new_or_init
@@ -2126,8 +2131,8 @@ def print_block(
2126
2131
self ,
2127
2132
block : Block ,
2128
2133
* ,
2134
+ clinic : Clinic ,
2129
2135
core_includes : bool = False ,
2130
- clinic : Clinic | None = None ,
2131
2136
) -> None :
2132
2137
input = block .input
2133
2138
output = block .output
@@ -2156,18 +2161,22 @@ def print_block(
2156
2161
write ("\n " )
2157
2162
2158
2163
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
2171
2180
2172
2181
input = '' .join (block .input )
2173
2182
output += '' .join (block .output )
@@ -2311,7 +2320,7 @@ def __init__(self, clinic: Clinic) -> None: ...
2311
2320
def parse (self , block : Block ) -> None : ...
2312
2321
2313
2322
2314
- clinic = None
2323
+ clinic : Clinic | None = None
2315
2324
class Clinic :
2316
2325
2317
2326
presets_text = """
@@ -2379,6 +2388,9 @@ def __init__(
2379
2388
self .modules : ModuleDict = {}
2380
2389
self .classes : ClassDict = {}
2381
2390
self .functions : list [Function ] = []
2391
+ # dict: include name => reason
2392
+ # Example: 'pycore_long.h' => '_PyLong_UnsignedShort_Converter()'
2393
+ self .includes : dict [str , str ] = {}
2382
2394
2383
2395
self .line_prefix = self .line_suffix = ''
2384
2396
@@ -2437,6 +2449,12 @@ def __init__(
2437
2449
global clinic
2438
2450
clinic = self
2439
2451
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
+
2440
2458
def add_destination (
2441
2459
self ,
2442
2460
name : str ,
@@ -3066,6 +3084,10 @@ class CConverter(metaclass=CConverterAutoRegister):
3066
3084
# Only set by self_converter.
3067
3085
signature_name : str | None = None
3068
3086
3087
+ # Optional (name, reason) include which generate a line like:
3088
+ # "#include "name" // reason"
3089
+ include : tuple [str , str ] | None = None
3090
+
3069
3091
# keep in sync with self_converter.__init__!
3070
3092
def __init__ (self ,
3071
3093
# Positional args:
@@ -3370,6 +3392,11 @@ def parser_name(self) -> str:
3370
3392
else :
3371
3393
return self .name
3372
3394
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
+
3373
3400
type_checks = {
3374
3401
'&PyLong_Type' : ('PyLong_Check' , 'int' ),
3375
3402
'&PyTuple_Type' : ('PyTuple_Check' , 'tuple' ),
@@ -5989,9 +6016,6 @@ def do_post_block_processing_cleanup(self, lineno: int) -> None:
5989
6016
}
5990
6017
5991
6018
5992
- clinic = None
5993
-
5994
-
5995
6019
def create_cli () -> argparse .ArgumentParser :
5996
6020
cmdline = argparse .ArgumentParser (
5997
6021
prog = "clinic.py" ,
0 commit comments