Skip to content

Commit d903b17

Browse files
Eclips4vstinnerpicnixz
authored
gh-121676: Raise a DeprecationWarning if the Python implementation of functools.reduce is called with function or sequence as a keyword args (#121677)
Python implementation of `functools` allows calling `reduce` with `function` or `sequence` as keyword args. This doesn't match behavior of our C accelerator and our documentation for `functools.reduce` states that `function`and `sequence` are positional-only arguments. Now calling a Python implementation of `functools.reduce` with `function` or `sequence` as keyword args would raise a `DeprecationWarning` and is planned to be prohibited in Python 3.16. Co-authored-by: Victor Stinner <[email protected]> Co-authored-by: Bénédikt Tran <[email protected]>
1 parent c5438fd commit d903b17

File tree

5 files changed

+47
-5
lines changed

5 files changed

+47
-5
lines changed

Doc/deprecations/pending-removal-in-3.16.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,8 @@ Pending removal in Python 3.16
7979

8080
* The undocumented and unused :attr:`!TarFile.tarfile` attribute
8181
has been deprecated since Python 3.13.
82+
83+
* :mod:`functools`:
84+
85+
* Calling the Python implementation of :func:`functools.reduce` with *function*
86+
or *sequence* as keyword arguments has been deprecated since Python 3.14.

Doc/whatsnew/3.14.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,11 @@ Deprecated
744744
as a single positional argument.
745745
(Contributed by Serhiy Storchaka in :gh:`109218`.)
746746

747+
* :mod:`functools`:
748+
Calling the Python implementation of :func:`functools.reduce` with *function*
749+
or *sequence* as keyword arguments is now deprecated.
750+
(Contributed by Kirill Podoprigora in :gh:`121676`.)
751+
747752
* :mod:`os`:
748753
:term:`Soft deprecate <soft deprecated>` :func:`os.popen` and
749754
:func:`os.spawn* <os.spawnl>` functions. They should no longer be used to

Lib/functools.py

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -264,11 +264,6 @@ def reduce(function, sequence, initial=_initial_missing):
264264

265265
return value
266266

267-
try:
268-
from _functools import reduce
269-
except ImportError:
270-
pass
271-
272267

273268
################################################################################
274269
### partial() argument application
@@ -1124,3 +1119,31 @@ def __get__(self, instance, owner=None):
11241119
return val
11251120

11261121
__class_getitem__ = classmethod(GenericAlias)
1122+
1123+
def _warn_python_reduce_kwargs(py_reduce):
1124+
@wraps(py_reduce)
1125+
def wrapper(*args, **kwargs):
1126+
if 'function' in kwargs or 'sequence' in kwargs:
1127+
import os
1128+
import warnings
1129+
warnings.warn(
1130+
'Calling functools.reduce with keyword arguments '
1131+
'"function" or "sequence" '
1132+
'is deprecated in Python 3.14 and will be '
1133+
'forbidden in Python 3.16.',
1134+
DeprecationWarning,
1135+
skip_file_prefixes=(os.path.dirname(__file__),))
1136+
return py_reduce(*args, **kwargs)
1137+
return wrapper
1138+
1139+
reduce = _warn_python_reduce_kwargs(reduce)
1140+
del _warn_python_reduce_kwargs
1141+
1142+
# The import of the C accelerated version of reduce() has been moved
1143+
# here due to gh-121676. In Python 3.16, _warn_python_reduce_kwargs()
1144+
# should be removed and the import block should be moved back right
1145+
# after the definition of reduce().
1146+
try:
1147+
from _functools import reduce
1148+
except ImportError:
1149+
pass

Lib/test/test_functools.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,6 +1045,12 @@ class TestReduceC(TestReduce, unittest.TestCase):
10451045
class TestReducePy(TestReduce, unittest.TestCase):
10461046
reduce = staticmethod(py_functools.reduce)
10471047

1048+
def test_reduce_with_kwargs(self):
1049+
with self.assertWarns(DeprecationWarning):
1050+
self.reduce(function=lambda x, y: x + y, sequence=[1, 2, 3, 4, 5], initial=1)
1051+
with self.assertWarns(DeprecationWarning):
1052+
self.reduce(lambda x, y: x + y, sequence=[1, 2, 3, 4, 5], initial=1)
1053+
10481054

10491055
class TestCmpToKey:
10501056

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Deprecate calling the Python implementation of :meth:`functools.reduce`
2+
with a ``function`` or ``sequence`` as a :term:`keyword argument`.
3+
This will be forbidden in Python 3.16 in order to match the C implementation.

0 commit comments

Comments
 (0)