diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2022-04-30 10:15:02 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-04-30 10:15:02 (GMT) |
commit | a055dac0b45031878a8196a8735522de018491e3 (patch) | |
tree | 5228f98a9ce93456c5d3db84a3fed0096b8f0f38 /Tools | |
parent | 19dca041212f9f58ee11833bff3f8c157d4fd3e8 (diff) | |
download | cpython-a055dac0b45031878a8196a8735522de018491e3.zip cpython-a055dac0b45031878a8196a8735522de018491e3.tar.gz cpython-a055dac0b45031878a8196a8735522de018491e3.tar.bz2 |
gh-91583: AC: Fix regression for functions with defining_class (GH-91739)
Argument Clinic now generates the same efficient code as before
adding the defining_class parameter.
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 14252b2..f660474 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -639,6 +639,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) @@ -667,10 +671,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 @@ -773,24 +773,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" @@ -993,6 +1009,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: |