del parameters[0]
converters = [p.converter for p in parameters]
+ # Copy includes from parameters to Clinic
+ for converter in converters:
+ if converter.include:
+ clinic.add_include(*converter.include)
+
has_option_groups = parameters and (parameters[0].group or parameters[-1].group)
default_return_converter = f.return_converter.type == 'PyObject *'
new_or_init = f.kind.new_or_init
self,
block: Block,
*,
+ clinic: Clinic,
core_includes: bool = False,
- clinic: Clinic | None = None,
) -> None:
input = block.input
output = block.output
write("\n")
output = ''
- if clinic:
- limited_capi = clinic.limited_capi
- else:
- limited_capi = DEFAULT_LIMITED_CAPI
- if core_includes and not limited_capi:
- output += textwrap.dedent("""
- #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- # include "pycore_gc.h" // PyGC_Head
- # include "pycore_runtime.h" // _Py_ID()
- #endif
-
- """)
+ if core_includes:
+ if not clinic.limited_capi:
+ output += textwrap.dedent("""
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+ # include "pycore_gc.h" // PyGC_Head
+ # include "pycore_runtime.h" // _Py_ID()
+ #endif
+
+ """)
+
+ if clinic is not None:
+ # Emit optional includes
+ for include, reason in sorted(clinic.includes.items()):
+ line = f'#include "{include}"'
+ line = line.ljust(35) + f'// {reason}\n'
+ output += line
input = ''.join(block.input)
output += ''.join(block.output)
def parse(self, block: Block) -> None: ...
-clinic = None
+clinic: Clinic | None = None
class Clinic:
presets_text = """
self.modules: ModuleDict = {}
self.classes: ClassDict = {}
self.functions: list[Function] = []
+ # dict: include name => reason
+ # Example: 'pycore_long.h' => '_PyLong_UnsignedShort_Converter()'
+ self.includes: dict[str, str] = {}
self.line_prefix = self.line_suffix = ''
global clinic
clinic = self
+ def add_include(self, name: str, reason: str) -> None:
+ if name in self.includes:
+ # Mention a single reason is enough, no need to list all of them
+ return
+ self.includes[name] = reason
+
def add_destination(
self,
name: str,
# Only set by self_converter.
signature_name: str | None = None
+ # Optional (name, reason) include which generate a line like:
+ # "#include "name" // reason"
+ include: tuple[str, str] | None = None
+
# keep in sync with self_converter.__init__!
def __init__(self,
# Positional args:
else:
return self.name
+ def add_include(self, name: str, reason: str) -> None:
+ if self.include is not None:
+ raise ValueError("a converter only supports a single include")
+ self.include = (name, reason)
+
type_checks = {
'&PyLong_Type': ('PyLong_Check', 'int'),
'&PyTuple_Type': ('PyTuple_Check', 'tuple'),
}
-clinic = None
-
-
def create_cli() -> argparse.ArgumentParser:
cmdline = argparse.ArgumentParser(
prog="clinic.py",