[3.10] gh-91583: AC: Fix regression for functions with defining_class (GH-91739) (GH-92079)

Argument Clinic now generates the same efficient code as before
adding the defining_class parameter.
(cherry picked from commit a055dac0b4)
This commit is contained in:
Serhiy Storchaka 2022-05-03 11:53:46 +03:00 committed by GitHub
parent adc06cd2d7
commit 62ddbbcfaf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 661 additions and 389 deletions

View file

@ -636,6 +636,10 @@ def output_templates(self, f):
assert parameters
assert isinstance(parameters[0].converter, self_converter)
del parameters[0]
requires_defining_class = False
if parameters and isinstance(parameters[0].converter, defining_class_converter):
requires_defining_class = True
del parameters[0]
converters = [p.converter for p in parameters]
has_option_groups = parameters and (parameters[0].group or parameters[-1].group)
@ -657,10 +661,6 @@ def output_templates(self, f):
if not p.is_optional():
min_pos = i
requires_defining_class = any(
isinstance(p.converter, defining_class_converter)
for p in parameters)
meth_o = (len(parameters) == 1 and
parameters[0].is_positional_only() and
not converters[0].is_optional() and
@ -763,24 +763,40 @@ def parser_body(prototype, *fields, declarations=''):
return linear_format(output(), parser_declarations=declarations)
if not parameters:
# no parameters, METH_NOARGS
if not requires_defining_class:
# no parameters, METH_NOARGS
flags = "METH_NOARGS"
flags = "METH_NOARGS"
parser_prototype = normalize_snippet("""
static PyObject *
{c_basename}({self_type}{self_name}, PyObject *Py_UNUSED(ignored))
""")
parser_code = []
parser_prototype = normalize_snippet("""
static PyObject *
{c_basename}({self_type}{self_name}, PyObject *Py_UNUSED(ignored))
""")
parser_definition = parser_prototype
else:
assert not new_or_init
flags = "METH_METHOD|METH_FASTCALL|METH_KEYWORDS"
parser_prototype = parser_prototype_def_class
return_error = ('return NULL;' if default_return_converter
else 'goto exit;')
parser_code = [normalize_snippet("""
if (nargs) {{
PyErr_SetString(PyExc_TypeError, "{name}() takes no arguments");
%s
}}
""" % return_error, indent=4)]
if default_return_converter:
parser_definition = parser_prototype + '\n' + normalize_snippet("""
{{
return {c_basename}_impl({impl_arguments});
}}
""")
parser_definition = '\n'.join([
parser_prototype,
'{{',
*parser_code,
' return {c_basename}_impl({impl_arguments});',
'}}'])
else:
parser_definition = parser_body(parser_prototype)
parser_definition = parser_body(parser_prototype, *parser_code)
elif meth_o:
flags = "METH_O"
@ -939,6 +955,9 @@ def parser_body(prototype, *fields, declarations=''):
add_label = None
for i, p in enumerate(parameters):
if isinstance(p.converter, defining_class_converter):
raise ValueError("defining_class should be the first "
"parameter (after self)")
displayname = p.get_displayname(i+1)
parsearg = p.converter.parse_arg(argname_fmt % i, displayname)
if parsearg is None: