@@ -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
@@ -2127,6 +2132,7 @@ def print_block(
2127
2132
block : Block ,
2128
2133
* ,
2129
2134
core_includes : bool = False ,
2135
+ # needed if core_includes is true
2130
2136
clinic : Clinic | None = None ,
2131
2137
) -> None :
2132
2138
input = block .input
@@ -2169,6 +2175,13 @@ def print_block(
2169
2175
2170
2176
""" )
2171
2177
2178
+ if clinic :
2179
+ # Emit optional includes
2180
+ for include , reason in sorted (clinic .includes .items ()):
2181
+ line = f'#include "{ include } "'
2182
+ line = line .ljust (35 ) + f'// { reason } \n '
2183
+ output += line
2184
+
2172
2185
input = '' .join (block .input )
2173
2186
output += '' .join (block .output )
2174
2187
if output :
@@ -2311,7 +2324,7 @@ def __init__(self, clinic: Clinic) -> None: ...
2311
2324
def parse (self , block : Block ) -> None : ...
2312
2325
2313
2326
2314
- clinic = None
2327
+ clinic : Clinic | None = None
2315
2328
class Clinic :
2316
2329
2317
2330
presets_text = """
@@ -2379,6 +2392,9 @@ def __init__(
2379
2392
self .modules : ModuleDict = {}
2380
2393
self .classes : ClassDict = {}
2381
2394
self .functions : list [Function ] = []
2395
+ # dict: include name => reason
2396
+ # Example: 'pycore_long.h' => '_PyLong_UnsignedShort_Converter()'
2397
+ self .includes : dict [str , str ] = {}
2382
2398
2383
2399
self .line_prefix = self .line_suffix = ''
2384
2400
@@ -2437,6 +2453,12 @@ def __init__(
2437
2453
global clinic
2438
2454
clinic = self
2439
2455
2456
+ def add_include (self , name : str , reason : str ) -> None :
2457
+ if name in self .includes :
2458
+ # Mention a single reason is enough, no need to list all of them
2459
+ return
2460
+ self .includes [name ] = reason
2461
+
2440
2462
def add_destination (
2441
2463
self ,
2442
2464
name : str ,
@@ -3066,6 +3088,9 @@ class CConverter(metaclass=CConverterAutoRegister):
3066
3088
# Only set by self_converter.
3067
3089
signature_name : str | None = None
3068
3090
3091
+ # Optional #include "name" // reason
3092
+ include : tuple [str , str ] | None = None
3093
+
3069
3094
# keep in sync with self_converter.__init__!
3070
3095
def __init__ (self ,
3071
3096
# Positional args:
@@ -3370,6 +3395,11 @@ def parser_name(self) -> str:
3370
3395
else :
3371
3396
return self .name
3372
3397
3398
+ def add_include (self , name : str , reason : str ) -> None :
3399
+ if self .include :
3400
+ raise ValueError ("a converter only supports a single include" )
3401
+ self .include = (name , reason )
3402
+
3373
3403
type_checks = {
3374
3404
'&PyLong_Type' : ('PyLong_Check' , 'int' ),
3375
3405
'&PyTuple_Type' : ('PyTuple_Check' , 'tuple' ),
@@ -5989,9 +6019,6 @@ def do_post_block_processing_cleanup(self, lineno: int) -> None:
5989
6019
}
5990
6020
5991
6021
5992
- clinic = None
5993
-
5994
-
5995
6022
def create_cli () -> argparse .ArgumentParser :
5996
6023
cmdline = argparse .ArgumentParser (
5997
6024
prog = "clinic.py" ,
0 commit comments