summaryrefslogtreecommitdiffstats
path: root/Tools
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2022-05-03 08:53:46 (GMT)
committerGitHub <noreply@github.com>2022-05-03 08:53:46 (GMT)
commit62ddbbcfafc98aaa4d0345bba56f7d6cd346c83f (patch)
treeb56472410c3b7a51c2311a081ccf7d8532e30484 /Tools
parentadc06cd2d727d580cfeda1fc29b419ecce379687 (diff)
downloadcpython-62ddbbcfafc98aaa4d0345bba56f7d6cd346c83f.zip
cpython-62ddbbcfafc98aaa4d0345bba56f7d6cd346c83f.tar.gz
cpython-62ddbbcfafc98aaa4d0345bba56f7d6cd346c83f.tar.bz2
[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 a055dac0b45031878a8196a8735522de018491e3)
Diffstat (limited to 'Tools')
-rwxr-xr-xTools/clinic/clinic.py53
1 files changed, 36 insertions, 17 deletions
diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py
index 969008a..b442c49 100755
--- a/Tools/clinic/clinic.py
+++ b/Tools/clinic/clinic.py
@@ -636,6 +636,10 @@ class CLanguage(Language):
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 @@ class CLanguage(Language):
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 @@ class CLanguage(Language):
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
- if default_return_converter:
- parser_definition = parser_prototype + '\n' + normalize_snippet("""
- {{
- return {c_basename}_impl({impl_arguments});
+ 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 = '\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 @@ class CLanguage(Language):
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: