summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSergey B Kirpichev <skirpichev@gmail.com>2024-11-01 20:15:39 (GMT)
committerGitHub <noreply@github.com>2024-11-01 20:15:39 (GMT)
commit51ef54abc42e020d7e80549d49ca32310495b4eb (patch)
tree7aa3463b250f13b3ec5aa17d05314cdf16ae75a9
parent74cf5967f345f944f1c308e5e30fee21b438eb6c (diff)
downloadcpython-51ef54abc42e020d7e80549d49ca32310495b4eb.zip
cpython-51ef54abc42e020d7e80549d49ca32310495b4eb.tar.gz
cpython-51ef54abc42e020d7e80549d49ca32310495b4eb.tar.bz2
gh-125916: Adapt functools.reduce() to Argument Clinic (#125999)
-rw-r--r--Lib/test/test_inspect/test_inspect.py4
-rw-r--r--Modules/_functoolsmodule.c42
-rw-r--r--Modules/clinic/_functoolsmodule.c.h46
3 files changed, 70 insertions, 22 deletions
diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py
index 2250b7e..a4430a8 100644
--- a/Lib/test/test_inspect/test_inspect.py
+++ b/Lib/test/test_inspect/test_inspect.py
@@ -5708,8 +5708,8 @@ class TestSignatureDefinitions(unittest.TestCase):
self._test_module_has_signatures(faulthandler, unsupported_signature=unsupported_signature)
def test_functools_module_has_signatures(self):
- no_signature = {'reduce'}
- self._test_module_has_signatures(functools, no_signature)
+ unsupported_signature = {"reduce"}
+ self._test_module_has_signatures(functools, unsupported_signature=unsupported_signature)
def test_gc_module_has_signatures(self):
import gc
diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c
index da4e088..d2afe1a 100644
--- a/Modules/_functoolsmodule.c
+++ b/Modules/_functoolsmodule.c
@@ -932,15 +932,31 @@ _functools_cmp_to_key_impl(PyObject *module, PyObject *mycmp)
/* reduce (used to be a builtin) ********************************************/
-// Not converted to argument clinic, because of `args` in-place modification.
-// AC will affect performance.
+/*[clinic input]
+_functools.reduce
+
+ function as func: object
+ iterable as seq: object
+ initial as result: object = NULL
+ /
+
+Apply a function of two arguments cumulatively to the items of an iterable, from left to right.
+
+This effectively reduces the iterable to a single value. If initial is present,
+it is placed before the items of the iterable in the calculation, and serves as
+a default when the iterable is empty.
+
+For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])
+calculates ((((1 + 2) + 3) + 4) + 5).
+[clinic start generated code]*/
+
static PyObject *
-functools_reduce(PyObject *self, PyObject *args)
+_functools_reduce_impl(PyObject *module, PyObject *func, PyObject *seq,
+ PyObject *result)
+/*[clinic end generated code: output=30d898fe1267c79d input=d233c2670cba7f66]*/
{
- PyObject *seq, *func, *result = NULL, *it;
+ PyObject *args, *it;
- if (!PyArg_UnpackTuple(args, "reduce", 2, 3, &func, &seq, &result))
- return NULL;
if (result != NULL)
Py_INCREF(result);
@@ -1006,18 +1022,6 @@ Fail:
return NULL;
}
-PyDoc_STRVAR(functools_reduce_doc,
-"reduce(function, iterable[, initial], /) -> value\n\
-\n\
-Apply a function of two arguments cumulatively to the items of an iterable, from left to right.\n\
-\n\
-This effectively reduces the iterable to a single value. If initial is present,\n\
-it is placed before the items of the iterable in the calculation, and serves as\n\
-a default when the iterable is empty.\n\
-\n\
-For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])\n\
-calculates ((((1 + 2) + 3) + 4) + 5).");
-
/* lru_cache object **********************************************************/
/* There are four principal algorithmic differences from the pure python version:
@@ -1722,7 +1726,7 @@ PyDoc_STRVAR(_functools_doc,
"Tools that operate on functions.");
static PyMethodDef _functools_methods[] = {
- {"reduce", functools_reduce, METH_VARARGS, functools_reduce_doc},
+ _FUNCTOOLS_REDUCE_METHODDEF
_FUNCTOOLS_CMP_TO_KEY_METHODDEF
{NULL, NULL} /* sentinel */
};
diff --git a/Modules/clinic/_functoolsmodule.c.h b/Modules/clinic/_functoolsmodule.c.h
index e98984d..0564921 100644
--- a/Modules/clinic/_functoolsmodule.c.h
+++ b/Modules/clinic/_functoolsmodule.c.h
@@ -67,6 +67,50 @@ exit:
return return_value;
}
+PyDoc_STRVAR(_functools_reduce__doc__,
+"reduce($module, function, iterable, initial=<unrepresentable>, /)\n"
+"--\n"
+"\n"
+"Apply a function of two arguments cumulatively to the items of an iterable, from left to right.\n"
+"\n"
+"This effectively reduces the iterable to a single value. If initial is present,\n"
+"it is placed before the items of the iterable in the calculation, and serves as\n"
+"a default when the iterable is empty.\n"
+"\n"
+"For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])\n"
+"calculates ((((1 + 2) + 3) + 4) + 5).");
+
+#define _FUNCTOOLS_REDUCE_METHODDEF \
+ {"reduce", _PyCFunction_CAST(_functools_reduce), METH_FASTCALL, _functools_reduce__doc__},
+
+static PyObject *
+_functools_reduce_impl(PyObject *module, PyObject *func, PyObject *seq,
+ PyObject *result);
+
+static PyObject *
+_functools_reduce(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *func;
+ PyObject *seq;
+ PyObject *result = NULL;
+
+ if (!_PyArg_CheckPositional("reduce", nargs, 2, 3)) {
+ goto exit;
+ }
+ func = args[0];
+ seq = args[1];
+ if (nargs < 3) {
+ goto skip_optional;
+ }
+ result = args[2];
+skip_optional:
+ return_value = _functools_reduce_impl(module, func, seq, result);
+
+exit:
+ return return_value;
+}
+
PyDoc_STRVAR(_functools__lru_cache_wrapper_cache_info__doc__,
"cache_info($self, /)\n"
"--\n"
@@ -114,4 +158,4 @@ _functools__lru_cache_wrapper_cache_clear(PyObject *self, PyObject *Py_UNUSED(ig
return return_value;
}
-/*[clinic end generated code: output=755265bb6d5ea751 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=214d6c6307cfcd91 input=a9049054013a1b77]*/