Skip to content

gh-121676: Raise a DeprecationWarning if the Python implementation of functools.reduce is called with a keyword args #121677

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Jan 1, 2025
5 changes: 5 additions & 0 deletions Doc/deprecations/pending-removal-in-3.16.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,8 @@ Pending Removal in Python 3.16

* The undocumented and unused :attr:`!TarFile.tarfile` attribute
has been deprecated since Python 3.13.

* :mod:`functools`:

* Calling the Python implementation of :func:`functools.reduce` with *function*
or *sequence* as keyword arguments has been deprecated since Python 3.14.
5 changes: 5 additions & 0 deletions Doc/whatsnew/3.14.rst
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,11 @@ Deprecated
as a single positional argument.
(Contributed by Serhiy Storchaka in :gh:`109218`.)

* :mod:`functools`:
Calling the Python implementation of :func:`functools.reduce` with *function*
or *sequence* as keyword arguments is now deprecated.
(Contributed by Kirill Podoprigora in :gh:`121676`.)

* :mod:`os`:
:term:`Soft deprecate <soft deprecated>` :func:`os.popen` and
:func:`os.spawn* <os.spawnl>` functions. They should no longer be used to
Expand Down
33 changes: 28 additions & 5 deletions Lib/functools.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,11 +265,6 @@ def reduce(function, sequence, initial=_initial_missing):

return value

try:
from _functools import reduce
except ImportError:
pass


################################################################################
### partial() argument application
Expand Down Expand Up @@ -1122,3 +1117,31 @@ def __get__(self, instance, owner=None):
return val

__class_getitem__ = classmethod(GenericAlias)

def _warn_python_reduce_kwargs(py_reduce):
@wraps(py_reduce)
def wrapper(*args, **kwargs):
if 'function' in kwargs or 'sequence' in kwargs:
import os
import warnings
warnings.warn(
'Calling functools.reduce with keyword arguments '
'"function" or "sequence" '
'is deprecated in Python 3.14 and will be '
'forbidden in Python 3.16.',
DeprecationWarning,
skip_file_prefixes=(os.path.dirname(__file__),))
return py_reduce(*args, **kwargs)
return wrapper

reduce = _warn_python_reduce_kwargs(reduce)
del _warn_python_reduce_kwargs

# The import of the C accelerated version of reduce() has been moved
# here due to gh-121676. In Python 3.16, _warn_python_reduce_kwargs()
# should be removed and the import block should be moved back right
# after the definition of reduce().
try:
from _functools import reduce
except ImportError:
pass
6 changes: 6 additions & 0 deletions Lib/test/test_functools.py
Original file line number Diff line number Diff line change
Expand Up @@ -1015,6 +1015,12 @@ class TestReduceC(TestReduce, unittest.TestCase):
class TestReducePy(TestReduce, unittest.TestCase):
reduce = staticmethod(py_functools.reduce)

def test_reduce_with_kwargs(self):
with self.assertWarns(DeprecationWarning):
self.reduce(function=lambda x, y: x + y, sequence=[1, 2, 3, 4, 5], initial=1)
with self.assertWarns(DeprecationWarning):
self.reduce(lambda x, y: x + y, sequence=[1, 2, 3, 4, 5], initial=1)


class TestCmpToKey:

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Deprecate calling the Python implementation of :meth:`functools.reduce`
with a ``function`` or ``sequence`` as a :term:`keyword argument`.
This will be forbidden in Python 3.16 in order to match the C implementation.
Loading