https://github.com/python/cpython/commit/51ef54abc42e020d7e80549d49ca32310495b4eb
commit: 51ef54abc42e020d7e80549d49ca32310495b4eb
branch: main
author: Sergey B Kirpichev <[email protected]>
committer: erlend-aasland <[email protected]>
date: 2024-11-01T21:15:39+01:00
summary:

gh-125916: Adapt functools.reduce() to Argument Clinic (#125999)

files:
M Lib/test/test_inspect/test_inspect.py
M Modules/_functoolsmodule.c
M Modules/clinic/_functoolsmodule.c.h

diff --git a/Lib/test/test_inspect/test_inspect.py 
b/Lib/test/test_inspect/test_inspect.py
index 2250b7e76dac01..a4430a868676e2 100644
--- a/Lib/test/test_inspect/test_inspect.py
+++ b/Lib/test/test_inspect/test_inspect.py
@@ -5708,8 +5708,8 @@ def test_faulthandler_module_has_signatures(self):
         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 da4e088e54621e..d2afe1a1bea018 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 @@ functools_reduce(PyObject *self, PyObject *args)
     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 e98984dc4d3a09..0564921034be47 100644
--- a/Modules/clinic/_functoolsmodule.c.h
+++ b/Modules/clinic/_functoolsmodule.c.h
@@ -67,6 +67,50 @@ _functools_cmp_to_key(PyObject *module, PyObject *const 
*args, Py_ssize_t nargs,
     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]*/

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to