summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2024-04-11 10:15:48 (GMT)
committerGitHub <noreply@github.com>2024-04-11 10:15:48 (GMT)
commita2ae84726b8b46e6970ae862244dad1a82cf5d19 (patch)
tree290d1352c5ddf26bae71187135bf3a3fa4d07871
parentd4963871b03cc76fe7d9648d022d12007585beae (diff)
downloadcpython-a2ae84726b8b46e6970ae862244dad1a82cf5d19.zip
cpython-a2ae84726b8b46e6970ae862244dad1a82cf5d19.tar.gz
cpython-a2ae84726b8b46e6970ae862244dad1a82cf5d19.tar.bz2
gh-113317: Add Codegen class to Argument Clinic (#117626)
* Move ifndef_symbols, includes and add_include() from Clinic to Codegen. Add a 'codegen' (Codegen) attribute to Clinic. * Remove libclinic.crenderdata module: move code to libclinic.codegen. * BlockPrinter.print_block(): remove unused 'limited_capi' argument. Remove also 'core_includes' parameter. * Add get_includes() methods. * Make Codegen.ifndef_symbols private. * Make Codegen.includes private. * Make CConverter.includes private.
-rw-r--r--Lib/test/test_clinic.py3
-rw-r--r--Tools/clinic/libclinic/app.py40
-rw-r--r--Tools/clinic/libclinic/clanguage.py100
-rw-r--r--Tools/clinic/libclinic/codegen.py126
-rw-r--r--Tools/clinic/libclinic/converter.py9
-rw-r--r--Tools/clinic/libclinic/converters.py2
-rw-r--r--Tools/clinic/libclinic/crenderdata.py81
-rw-r--r--Tools/clinic/libclinic/return_converters.py2
8 files changed, 183 insertions, 180 deletions
diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py
index e3ba3d9..e8c638e 100644
--- a/Lib/test/test_clinic.py
+++ b/Lib/test/test_clinic.py
@@ -877,9 +877,8 @@ class ClinicBlockParserTest(TestCase):
blocks = list(BlockParser(input, language))
writer = BlockPrinter(language)
- c = _make_clinic()
for block in blocks:
- writer.print_block(block, limited_capi=c.limited_capi, header_includes=c.includes)
+ writer.print_block(block)
output = writer.f.getvalue()
assert output == input, "output != input!\n\noutput " + repr(output) + "\n\n input " + repr(input)
diff --git a/Tools/clinic/libclinic/app.py b/Tools/clinic/libclinic/app.py
index 47a8977..62e9892 100644
--- a/Tools/clinic/libclinic/app.py
+++ b/Tools/clinic/libclinic/app.py
@@ -9,8 +9,7 @@ import libclinic
from libclinic import fail, warn
from libclinic.function import Class
from libclinic.block_parser import Block, BlockParser
-from libclinic.crenderdata import Include
-from libclinic.codegen import BlockPrinter, Destination
+from libclinic.codegen import BlockPrinter, Destination, Codegen
from libclinic.parser import Parser, PythonParser
from libclinic.dsl_parser import DSLParser
if TYPE_CHECKING:
@@ -102,8 +101,7 @@ impl_definition block
self.modules: ModuleDict = {}
self.classes: ClassDict = {}
self.functions: list[Function] = []
- # dict: include name => Include instance
- self.includes: dict[str, Include] = {}
+ self.codegen = Codegen(self.limited_capi)
self.line_prefix = self.line_suffix = ''
@@ -132,7 +130,6 @@ impl_definition block
DestBufferList = list[DestBufferType]
self.destination_buffers_stack: DestBufferList = []
- self.ifndef_symbols: set[str] = set()
self.presets: dict[str, dict[Any, Any]] = {}
preset = None
@@ -159,24 +156,6 @@ impl_definition block
assert name in self.destination_buffers
preset[name] = buffer
- def add_include(self, name: str, reason: str,
- *, condition: str | None = None) -> None:
- try:
- existing = self.includes[name]
- except KeyError:
- pass
- else:
- if existing.condition and not condition:
- # If the previous include has a condition and the new one is
- # unconditional, override the include.
- pass
- else:
- # Already included, do nothing. Only mention a single reason,
- # no need to list all of them.
- return
-
- self.includes[name] = Include(name, reason, condition)
-
def add_destination(
self,
name: str,
@@ -212,9 +191,7 @@ impl_definition block
self.parsers[dsl_name] = parsers[dsl_name](self)
parser = self.parsers[dsl_name]
parser.parse(block)
- printer.print_block(block,
- limited_capi=self.limited_capi,
- header_includes=self.includes)
+ printer.print_block(block)
# these are destinations not buffers
for name, destination in self.destinations.items():
@@ -229,9 +206,7 @@ impl_definition block
block.input = "dump " + name + "\n"
warn("Destination buffer " + repr(name) + " not empty at end of file, emptying.")
printer.write("\n")
- printer.print_block(block,
- limited_capi=self.limited_capi,
- header_includes=self.includes)
+ printer.print_block(block)
continue
if destination.type == 'file':
@@ -255,11 +230,10 @@ impl_definition block
pass
block.input = 'preserve\n'
+ includes = self.codegen.get_includes()
+
printer_2 = BlockPrinter(self.language)
- printer_2.print_block(block,
- core_includes=True,
- limited_capi=self.limited_capi,
- header_includes=self.includes)
+ printer_2.print_block(block, header_includes=includes)
libclinic.write_file(destination.filename,
printer_2.f.getvalue())
continue
diff --git a/Tools/clinic/libclinic/clanguage.py b/Tools/clinic/libclinic/clanguage.py
index ed08d12..5d1a273 100644
--- a/Tools/clinic/libclinic/clanguage.py
+++ b/Tools/clinic/libclinic/clanguage.py
@@ -11,7 +11,7 @@ from libclinic import (
unspecified, fail, warn, Sentinels, VersionTuple)
from libclinic.function import (
GETTER, SETTER, METHOD_INIT, METHOD_NEW)
-from libclinic.crenderdata import CRenderData, TemplateDict
+from libclinic.codegen import CRenderData, TemplateDict, Codegen
from libclinic.language import Language
from libclinic.function import (
Module, Class, Function, Parameter,
@@ -26,8 +26,7 @@ def declare_parser(
f: Function,
*,
hasformat: bool = False,
- clinic: Clinic,
- limited_capi: bool,
+ codegen: Codegen,
) -> str:
"""
Generates the code template for a static local PyArg_Parser variable,
@@ -35,6 +34,7 @@ def declare_parser(
kwtuple field is also statically initialized. Otherwise
it is initialized at runtime.
"""
+ limited_capi = codegen.limited_capi
if hasformat:
fname = ''
format_ = '.format = "{format_units}:{name}",'
@@ -80,8 +80,8 @@ def declare_parser(
""" % num_keywords
condition = '#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)'
- clinic.add_include('pycore_gc.h', 'PyGC_Head', condition=condition)
- clinic.add_include('pycore_runtime.h', '_Py_ID()', condition=condition)
+ codegen.add_include('pycore_gc.h', 'PyGC_Head', condition=condition)
+ codegen.add_include('pycore_runtime.h', '_Py_ID()', condition=condition)
declarations += """
static const char * const _keywords[] = {{{keywords_c} NULL}};
@@ -317,14 +317,14 @@ class CLanguage(Language):
self,
func: Function,
params: dict[int, Parameter],
- argname_fmt: str | None,
+ argname_fmt: str | None = None,
*,
fastcall: bool,
- limited_capi: bool,
- clinic: Clinic,
+ codegen: Codegen,
) -> str:
assert len(params) > 0
last_param = next(reversed(params.values()))
+ limited_capi = codegen.limited_capi
# Format the deprecation message.
containscheck = ""
@@ -336,11 +336,11 @@ class CLanguage(Language):
elif fastcall:
conditions.append(f"nargs < {i+1} && PySequence_Contains(kwnames, &_Py_ID({p.name}))")
containscheck = "PySequence_Contains"
- clinic.add_include('pycore_runtime.h', '_Py_ID()')
+ codegen.add_include('pycore_runtime.h', '_Py_ID()')
else:
conditions.append(f"nargs < {i+1} && PyDict_Contains(kwargs, &_Py_ID({p.name}))")
containscheck = "PyDict_Contains"
- clinic.add_include('pycore_runtime.h', '_Py_ID()')
+ codegen.add_include('pycore_runtime.h', '_Py_ID()')
else:
conditions = [f"nargs < {i+1}"]
condition = ") || (".join(conditions)
@@ -399,7 +399,7 @@ class CLanguage(Language):
def output_templates(
self,
f: Function,
- clinic: Clinic
+ codegen: Codegen,
) -> dict[str, str]:
parameters = list(f.parameters.values())
assert parameters
@@ -412,7 +412,7 @@ class CLanguage(Language):
converters = [p.converter for p in parameters]
if f.critical_section:
- clinic.add_include('pycore_critical_section.h', 'Py_BEGIN_CRITICAL_SECTION()')
+ codegen.add_include('pycore_critical_section.h', 'Py_BEGIN_CRITICAL_SECTION()')
has_option_groups = parameters and (parameters[0].group or parameters[-1].group)
simple_return = (f.return_converter.type == 'PyObject *'
and not f.critical_section)
@@ -517,7 +517,7 @@ class CLanguage(Language):
parser_declarations=declarations)
fastcall = not new_or_init
- limited_capi = clinic.limited_capi
+ limited_capi = codegen.limited_capi
if limited_capi and (pseudo_args or
(any(p.is_optional() for p in parameters) and
any(p.is_keyword_only() and not p.is_optional() for p in parameters)) or
@@ -673,8 +673,8 @@ class CLanguage(Language):
""",
indent=4))
else:
- clinic.add_include('pycore_modsupport.h',
- '_PyArg_CheckPositional()')
+ codegen.add_include('pycore_modsupport.h',
+ '_PyArg_CheckPositional()')
parser_code = [libclinic.normalize_snippet(f"""
if (!_PyArg_CheckPositional("{{name}}", {nargs}, {min_pos}, {max_args})) {{{{
goto exit;
@@ -735,8 +735,8 @@ class CLanguage(Language):
if limited_capi:
fastcall = False
if fastcall:
- clinic.add_include('pycore_modsupport.h',
- '_PyArg_ParseStack()')
+ codegen.add_include('pycore_modsupport.h',
+ '_PyArg_ParseStack()')
parser_code = [libclinic.normalize_snippet("""
if (!_PyArg_ParseStack(args, nargs, "{format_units}:{name}",
{parse_arguments})) {{
@@ -773,8 +773,8 @@ class CLanguage(Language):
fastcall = False
else:
if vararg == self.NO_VARARG:
- clinic.add_include('pycore_modsupport.h',
- '_PyArg_UnpackKeywords()')
+ codegen.add_include('pycore_modsupport.h',
+ '_PyArg_UnpackKeywords()')
args_declaration = "_PyArg_UnpackKeywords", "%s, %s, %s" % (
min_pos,
max_pos,
@@ -782,8 +782,8 @@ class CLanguage(Language):
)
nargs = "nargs"
else:
- clinic.add_include('pycore_modsupport.h',
- '_PyArg_UnpackKeywordsWithVararg()')
+ codegen.add_include('pycore_modsupport.h',
+ '_PyArg_UnpackKeywordsWithVararg()')
args_declaration = "_PyArg_UnpackKeywordsWithVararg", "%s, %s, %s, %s" % (
min_pos,
max_pos,
@@ -796,8 +796,7 @@ class CLanguage(Language):
flags = "METH_FASTCALL|METH_KEYWORDS"
parser_prototype = self.PARSER_PROTOTYPE_FASTCALL_KEYWORDS
argname_fmt = 'args[%d]'
- declarations = declare_parser(f, clinic=clinic,
- limited_capi=clinic.limited_capi)
+ declarations = declare_parser(f, codegen=codegen)
declarations += "\nPyObject *argsbuf[%s];" % len(converters)
if has_optional_kw:
declarations += "\nPy_ssize_t noptargs = %s + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - %d;" % (nargs, min_pos + min_kw_only)
@@ -812,8 +811,7 @@ class CLanguage(Language):
flags = "METH_VARARGS|METH_KEYWORDS"
parser_prototype = self.PARSER_PROTOTYPE_KEYWORD
argname_fmt = 'fastargs[%d]'
- declarations = declare_parser(f, clinic=clinic,
- limited_capi=clinic.limited_capi)
+ declarations = declare_parser(f, codegen=codegen)
declarations += "\nPyObject *argsbuf[%s];" % len(converters)
declarations += "\nPyObject * const *fastargs;"
declarations += "\nPy_ssize_t nargs = PyTuple_GET_SIZE(args);"
@@ -832,10 +830,10 @@ class CLanguage(Language):
if parser_code is not None:
if deprecated_keywords:
- code = self.deprecate_keyword_use(f, deprecated_keywords, argname_fmt,
- clinic=clinic,
- fastcall=fastcall,
- limited_capi=limited_capi)
+ code = self.deprecate_keyword_use(f, deprecated_keywords,
+ argname_fmt,
+ codegen=codegen,
+ fastcall=fastcall)
parser_code.append(code)
add_label: str | None = None
@@ -903,9 +901,8 @@ class CLanguage(Language):
for parameter in parameters:
parameter.converter.use_converter()
- declarations = declare_parser(f, clinic=clinic,
- hasformat=True,
- limited_capi=limited_capi)
+ declarations = declare_parser(f, codegen=codegen,
+ hasformat=True)
if limited_capi:
# positional-or-keyword arguments
assert not fastcall
@@ -921,8 +918,8 @@ class CLanguage(Language):
declarations += "\nPy_ssize_t nargs = PyTuple_Size(args);"
elif fastcall:
- clinic.add_include('pycore_modsupport.h',
- '_PyArg_ParseStackAndKeywords()')
+ codegen.add_include('pycore_modsupport.h',
+ '_PyArg_ParseStackAndKeywords()')
parser_code = [libclinic.normalize_snippet("""
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser{parse_arguments_comma}
{parse_arguments})) {{
@@ -930,8 +927,8 @@ class CLanguage(Language):
}}
""", indent=4)]
else:
- clinic.add_include('pycore_modsupport.h',
- '_PyArg_ParseTupleAndKeywordsFast()')
+ codegen.add_include('pycore_modsupport.h',
+ '_PyArg_ParseTupleAndKeywordsFast()')
parser_code = [libclinic.normalize_snippet("""
if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
{parse_arguments})) {{
@@ -941,10 +938,9 @@ class CLanguage(Language):
if deprecated_positionals or deprecated_keywords:
declarations += "\nPy_ssize_t nargs = PyTuple_GET_SIZE(args);"
if deprecated_keywords:
- code = self.deprecate_keyword_use(f, deprecated_keywords, None,
- clinic=clinic,
- fastcall=fastcall,
- limited_capi=limited_capi)
+ code = self.deprecate_keyword_use(f, deprecated_keywords,
+ codegen=codegen,
+ fastcall=fastcall)
parser_code.append(code)
if deprecated_positionals:
@@ -960,9 +956,9 @@ class CLanguage(Language):
# 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)
+ for include in converter.get_includes():
+ codegen.add_include(include.filename, include.reason,
+ condition=include.condition)
if new_or_init:
methoddef_define = ''
@@ -984,16 +980,16 @@ class CLanguage(Language):
if not parses_keywords:
declarations = '{base_type_ptr}'
- clinic.add_include('pycore_modsupport.h',
- '_PyArg_NoKeywords()')
+ codegen.add_include('pycore_modsupport.h',
+ '_PyArg_NoKeywords()')
fields.insert(0, libclinic.normalize_snippet("""
if ({self_type_check}!_PyArg_NoKeywords("{name}", kwargs)) {{
goto exit;
}}
""", indent=4))
if not parses_positional:
- clinic.add_include('pycore_modsupport.h',
- '_PyArg_NoPositional()')
+ codegen.add_include('pycore_modsupport.h',
+ '_PyArg_NoPositional()')
fields.insert(0, libclinic.normalize_snippet("""
if ({self_type_check}!_PyArg_NoPositional("{name}", args)) {{
goto exit;
@@ -1030,8 +1026,7 @@ class CLanguage(Language):
cpp_if = "#if " + conditional
cpp_endif = "#endif /* " + conditional + " */"
- if methoddef_define and f.full_name not in clinic.ifndef_symbols:
- clinic.ifndef_symbols.add(f.full_name)
+ if methoddef_define and codegen.add_ifndef_symbol(f.full_name):
methoddef_ifndef = self.METHODDEF_PROTOTYPE_IFNDEF
# add ';' to the end of parser_prototype and impl_prototype
@@ -1190,16 +1185,17 @@ class CLanguage(Language):
clinic: Clinic,
f: Function | None
) -> str:
- if f is None or clinic is None:
+ if f is None:
return ""
+ codegen = clinic.codegen
data = CRenderData()
assert f.parameters, "We should always have a 'self' at this point!"
parameters = f.render_parameters
converters = [p.converter for p in parameters]
- templates = self.output_templates(f, clinic)
+ templates = self.output_templates(f, codegen)
f_self = parameters[0]
selfless = parameters[1:]
@@ -1323,7 +1319,7 @@ class CLanguage(Language):
if has_option_groups:
self.render_option_group_parsing(f, template_dict,
- limited_capi=clinic.limited_capi)
+ limited_capi=codegen.limited_capi)
# buffers, not destination
for name, destination in clinic.destination_buffers.items():
diff --git a/Tools/clinic/libclinic/codegen.py b/Tools/clinic/libclinic/codegen.py
index ad08e22..83f3451 100644
--- a/Tools/clinic/libclinic/codegen.py
+++ b/Tools/clinic/libclinic/codegen.py
@@ -6,13 +6,92 @@ from typing import Final, TYPE_CHECKING
import libclinic
from libclinic import fail
-from libclinic.crenderdata import Include
from libclinic.language import Language
from libclinic.block_parser import Block
if TYPE_CHECKING:
from libclinic.app import Clinic
+TemplateDict = dict[str, str]
+
+
+class CRenderData:
+ def __init__(self) -> None:
+
+ # The C statements to declare variables.
+ # Should be full lines with \n eol characters.
+ self.declarations: list[str] = []
+
+ # The C statements required to initialize the variables before the parse call.
+ # Should be full lines with \n eol characters.
+ self.initializers: list[str] = []
+
+ # The C statements needed to dynamically modify the values
+ # parsed by the parse call, before calling the impl.
+ self.modifications: list[str] = []
+
+ # The entries for the "keywords" array for PyArg_ParseTuple.
+ # Should be individual strings representing the names.
+ self.keywords: list[str] = []
+
+ # The "format units" for PyArg_ParseTuple.
+ # Should be individual strings that will get
+ self.format_units: list[str] = []
+
+ # The varargs arguments for PyArg_ParseTuple.
+ self.parse_arguments: list[str] = []
+
+ # The parameter declarations for the impl function.
+ self.impl_parameters: list[str] = []
+
+ # The arguments to the impl function at the time it's called.
+ self.impl_arguments: list[str] = []
+
+ # For return converters: the name of the variable that
+ # should receive the value returned by the impl.
+ self.return_value = "return_value"
+
+ # For return converters: the code to convert the return
+ # value from the parse function. This is also where
+ # you should check the _return_value for errors, and
+ # "goto exit" if there are any.
+ self.return_conversion: list[str] = []
+ self.converter_retval = "_return_value"
+
+ # The C statements required to do some operations
+ # after the end of parsing but before cleaning up.
+ # These operations may be, for example, memory deallocations which
+ # can only be done without any error happening during argument parsing.
+ self.post_parsing: list[str] = []
+
+ # The C statements required to clean up after the impl call.
+ self.cleanup: list[str] = []
+
+ # The C statements to generate critical sections (per-object locking).
+ self.lock: list[str] = []
+ self.unlock: list[str] = []
+
+
+@dc.dataclass(slots=True, frozen=True)
+class Include:
+ """
+ An include like: #include "pycore_long.h" // _Py_ID()
+ """
+ # Example: "pycore_long.h".
+ filename: str
+
+ # Example: "_Py_ID()".
+ reason: str
+
+ # None means unconditional include.
+ # Example: "#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)".
+ condition: str | None
+
+ def sort_key(self) -> tuple[str, str]:
+ # order: '#if' comes before 'NO_CONDITION'
+ return (self.condition or 'NO_CONDITION', self.filename)
+
+
@dc.dataclass(slots=True)
class BlockPrinter:
language: Language
@@ -25,9 +104,7 @@ class BlockPrinter:
self,
block: Block,
*,
- core_includes: bool = False,
- limited_capi: bool,
- header_includes: dict[str, Include],
+ header_includes: list[Include] | None = None,
) -> None:
input = block.input
output = block.output
@@ -56,13 +133,12 @@ class BlockPrinter:
write("\n")
output = ''
- if core_includes and header_includes:
+ if header_includes:
# Emit optional "#include" directives for C headers
output += '\n'
current_condition: str | None = None
- includes = sorted(header_includes.values(), key=Include.sort_key)
- for include in includes:
+ for include in header_includes:
if include.condition != current_condition:
if current_condition:
output += '#endif\n'
@@ -188,3 +264,39 @@ class Destination:
DestinationDict = dict[str, Destination]
+
+
+class Codegen:
+ def __init__(self, limited_capi: bool) -> None:
+ self.limited_capi = limited_capi
+ self._ifndef_symbols: set[str] = set()
+ # dict: include name => Include instance
+ self._includes: dict[str, Include] = {}
+
+ def add_ifndef_symbol(self, name: str) -> bool:
+ if name in self._ifndef_symbols:
+ return False
+ self._ifndef_symbols.add(name)
+ return True
+
+ def add_include(self, name: str, reason: str,
+ *, condition: str | None = None) -> None:
+ try:
+ existing = self._includes[name]
+ except KeyError:
+ pass
+ else:
+ if existing.condition and not condition:
+ # If the previous include has a condition and the new one is
+ # unconditional, override the include.
+ pass
+ else:
+ # Already included, do nothing. Only mention a single reason,
+ # no need to list all of them.
+ return
+
+ self._includes[name] = Include(name, reason, condition)
+
+ def get_includes(self) -> list[Include]:
+ return sorted(self._includes.values(),
+ key=Include.sort_key)
diff --git a/Tools/clinic/libclinic/converter.py b/Tools/clinic/libclinic/converter.py
index ac78be3..86853bb 100644
--- a/Tools/clinic/libclinic/converter.py
+++ b/Tools/clinic/libclinic/converter.py
@@ -7,7 +7,7 @@ from collections.abc import Callable
import libclinic
from libclinic import fail
from libclinic import Sentinels, unspecified, unknown
-from libclinic.crenderdata import CRenderData, Include, TemplateDict
+from libclinic.codegen import CRenderData, Include, TemplateDict
from libclinic.function import Function, Parameter
@@ -180,7 +180,7 @@ class CConverter(metaclass=CConverterAutoRegister):
self.name = libclinic.ensure_legal_c_identifier(name)
self.py_name = py_name
self.unused = unused
- self.includes: list[Include] = []
+ self._includes: list[Include] = []
if default is not unspecified:
if (self.default_type
@@ -513,7 +513,10 @@ class CConverter(metaclass=CConverterAutoRegister):
def add_include(self, name: str, reason: str,
*, condition: str | None = None) -> None:
include = Include(name, reason, condition)
- self.includes.append(include)
+ self._includes.append(include)
+
+ def get_includes(self) -> list[Include]:
+ return self._includes
ConverterType = Callable[..., CConverter]
diff --git a/Tools/clinic/libclinic/converters.py b/Tools/clinic/libclinic/converters.py
index 7fc16f1..0778961 100644
--- a/Tools/clinic/libclinic/converters.py
+++ b/Tools/clinic/libclinic/converters.py
@@ -9,7 +9,7 @@ from libclinic.function import (
Function, Parameter,
CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW,
GETTER, SETTER)
-from libclinic.crenderdata import CRenderData, TemplateDict
+from libclinic.codegen import CRenderData, TemplateDict
from libclinic.converter import (
CConverter, legacy_converters, add_legacy_c_converter)
diff --git a/Tools/clinic/libclinic/crenderdata.py b/Tools/clinic/libclinic/crenderdata.py
deleted file mode 100644
index 58976b8..0000000
--- a/Tools/clinic/libclinic/crenderdata.py
+++ /dev/null
@@ -1,81 +0,0 @@
-import dataclasses as dc
-
-
-TemplateDict = dict[str, str]
-
-
-class CRenderData:
- def __init__(self) -> None:
-
- # The C statements to declare variables.
- # Should be full lines with \n eol characters.
- self.declarations: list[str] = []
-
- # The C statements required to initialize the variables before the parse call.
- # Should be full lines with \n eol characters.
- self.initializers: list[str] = []
-
- # The C statements needed to dynamically modify the values
- # parsed by the parse call, before calling the impl.
- self.modifications: list[str] = []
-
- # The entries for the "keywords" array for PyArg_ParseTuple.
- # Should be individual strings representing the names.
- self.keywords: list[str] = []
-
- # The "format units" for PyArg_ParseTuple.
- # Should be individual strings that will get
- self.format_units: list[str] = []
-
- # The varargs arguments for PyArg_ParseTuple.
- self.parse_arguments: list[str] = []
-
- # The parameter declarations for the impl function.
- self.impl_parameters: list[str] = []
-
- # The arguments to the impl function at the time it's called.
- self.impl_arguments: list[str] = []
-
- # For return converters: the name of the variable that
- # should receive the value returned by the impl.
- self.return_value = "return_value"
-
- # For return converters: the code to convert the return
- # value from the parse function. This is also where
- # you should check the _return_value for errors, and
- # "goto exit" if there are any.
- self.return_conversion: list[str] = []
- self.converter_retval = "_return_value"
-
- # The C statements required to do some operations
- # after the end of parsing but before cleaning up.
- # These operations may be, for example, memory deallocations which
- # can only be done without any error happening during argument parsing.
- self.post_parsing: list[str] = []
-
- # The C statements required to clean up after the impl call.
- self.cleanup: list[str] = []
-
- # The C statements to generate critical sections (per-object locking).
- self.lock: list[str] = []
- self.unlock: list[str] = []
-
-
-@dc.dataclass(slots=True, frozen=True)
-class Include:
- """
- An include like: #include "pycore_long.h" // _Py_ID()
- """
- # Example: "pycore_long.h".
- filename: str
-
- # Example: "_Py_ID()".
- reason: str
-
- # None means unconditional include.
- # Example: "#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)".
- condition: str | None
-
- def sort_key(self) -> tuple[str, str]:
- # order: '#if' comes before 'NO_CONDITION'
- return (self.condition or 'NO_CONDITION', self.filename)
diff --git a/Tools/clinic/libclinic/return_converters.py b/Tools/clinic/libclinic/return_converters.py
index 7bdd257..b41e053 100644
--- a/Tools/clinic/libclinic/return_converters.py
+++ b/Tools/clinic/libclinic/return_converters.py
@@ -1,6 +1,6 @@
import sys
from collections.abc import Callable
-from libclinic.crenderdata import CRenderData
+from libclinic.codegen import CRenderData
from libclinic.function import Function
from typing import Any