diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2022-05-03 08:53:46 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-03 08:53:46 (GMT) |
commit | 62ddbbcfafc98aaa4d0345bba56f7d6cd346c83f (patch) | |
tree | b56472410c3b7a51c2311a081ccf7d8532e30484 /Tools | |
parent | adc06cd2d727d580cfeda1fc29b419ecce379687 (diff) | |
download | cpython-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-x | Tools/clinic/clinic.py | 53 |
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: |