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 <vstinner@python.org>
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
This commit is contained in:
Kirill Podoprigora 2025-01-01 13:36:47 +02:00 committed by GitHub
parent c5438fdf47
commit d903b17499
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 47 additions and 5 deletions

View file

@ -79,3 +79,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.

View file

@ -744,6 +744,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

View file

@ -264,11 +264,6 @@ def reduce(function, sequence, initial=_initial_missing):
return value
try:
from _functools import reduce
except ImportError:
pass
################################################################################
### partial() argument application
@ -1124,3 +1119,31 @@ class cached_property:
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

View file

@ -1045,6 +1045,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:

View file

@ -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.