summaryrefslogtreecommitdiffstats
path: root/Tools/clinic
diff options
context:
space:
mode:
authorErlend E. Aasland <erlend.aasland@protonmail.com>2022-08-13 10:09:40 (GMT)
committerGitHub <noreply@github.com>2022-08-13 10:09:40 (GMT)
commitf07adf82f338ebb7e69475537be050e63c2009fa (patch)
tree26c4cd000b95fc45befb2ea3c87c03d84d9aed75 /Tools/clinic
parentf235178beccf5eb5b47e770240f32d9ba24b26fd (diff)
downloadcpython-f07adf82f338ebb7e69475537be050e63c2009fa.zip
cpython-f07adf82f338ebb7e69475537be050e63c2009fa.tar.gz
cpython-f07adf82f338ebb7e69475537be050e63c2009fa.tar.bz2
gh-90928: Improve static initialization of keywords tuple in AC (#95907)
Diffstat (limited to 'Tools/clinic')
-rwxr-xr-xTools/clinic/clinic.py89
1 files changed, 47 insertions, 42 deletions
diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py
index 88f779e..805bdcb 100755
--- a/Tools/clinic/clinic.py
+++ b/Tools/clinic/clinic.py
@@ -535,7 +535,7 @@ def normalize_snippet(s, *, indent=0):
return s
-def declare_parser(*, hasformat=False):
+def declare_parser(f, *, hasformat=False):
"""
Generates the code template for a static local PyArg_Parser variable,
with an initializer. For core code (incl. builtin modules) the
@@ -548,43 +548,49 @@ def declare_parser(*, hasformat=False):
else:
fname = '.fname = "{name}",'
format_ = ''
- declarations = """
- #define NUM_KEYWORDS {num_keywords}
- #if NUM_KEYWORDS == 0
-
- # if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty)
- # else
- # define KWTUPLE NULL
- # endif
-
- #else // NUM_KEYWORDS != 0
- # if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
-
- static struct {{
- PyGC_Head _this_is_not_used;
- PyObject_VAR_HEAD
- PyObject *ob_item[NUM_KEYWORDS];
- }} _kwtuple = {{
- .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
- .ob_item = {{ {keywords_py} }},
- }};
- # define KWTUPLE (&_kwtuple.ob_base.ob_base)
-
- # else // !Py_BUILD_CORE
- # define KWTUPLE NULL
- # endif // !Py_BUILD_CORE
- #endif // NUM_KEYWORDS != 0
- #undef NUM_KEYWORDS
-
- static const char * const _keywords[] = {{{keywords_c} NULL}};
- static _PyArg_Parser _parser = {{
- .keywords = _keywords,
- %s
- .kwtuple = KWTUPLE,
- }};
- #undef KWTUPLE
- """ % (format_ or fname)
+
+ num_keywords = len([
+ p for p in f.parameters.values()
+ if not p.is_positional_only() and not p.is_vararg()
+ ])
+ if num_keywords == 0:
+ declarations = """
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+ # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty)
+ #else
+ # define KWTUPLE NULL
+ #endif
+ """
+ else:
+ declarations = """
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS %d
+ static struct {{
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ PyObject *ob_item[NUM_KEYWORDS];
+ }} _kwtuple = {{
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_item = {{ {keywords_py} }},
+ }};
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+ """ % num_keywords
+
+ declarations += """
+ static const char * const _keywords[] = {{{keywords_c} NULL}};
+ static _PyArg_Parser _parser = {{
+ .keywords = _keywords,
+ %s
+ .kwtuple = KWTUPLE,
+ }};
+ #undef KWTUPLE
+ """ % (format_ or fname)
return normalize_snippet(declarations)
@@ -1020,7 +1026,7 @@ class CLanguage(Language):
flags = "METH_FASTCALL|METH_KEYWORDS"
parser_prototype = parser_prototype_fastcall_keywords
argname_fmt = 'args[%d]'
- declarations = declare_parser()
+ declarations = declare_parser(f)
declarations += "\nPyObject *argsbuf[%s];" % len(converters)
if has_optional_kw:
pre_buffer = "0" if vararg != NO_VARARG else "nargs"
@@ -1036,7 +1042,7 @@ class CLanguage(Language):
flags = "METH_VARARGS|METH_KEYWORDS"
parser_prototype = parser_prototype_keyword
argname_fmt = 'fastargs[%d]'
- declarations = declare_parser()
+ declarations = declare_parser(f)
declarations += "\nPyObject *argsbuf[%s];" % len(converters)
declarations += "\nPyObject * const *fastargs;"
declarations += "\nPy_ssize_t nargs = PyTuple_GET_SIZE(args);"
@@ -1116,7 +1122,7 @@ class CLanguage(Language):
if add_label:
parser_code.append("%s:" % add_label)
else:
- declarations = declare_parser(hasformat=True)
+ declarations = declare_parser(f, hasformat=True)
if not new_or_init:
parser_code = [normalize_snippet("""
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser{parse_arguments_comma}
@@ -1442,7 +1448,6 @@ class CLanguage(Language):
template_dict['keywords_c'] = ' '.join('"' + k + '",'
for k in data.keywords)
keywords = [k for k in data.keywords if k]
- template_dict['num_keywords'] = len(keywords)
template_dict['keywords_py'] = ' '.join('&_Py_ID(' + k + '),'
for k in keywords)
template_dict['format_units'] = ''.join(data.format_units)