gh-121676: Raise a ``DeprecationWarning`` if the Python implementation of ``functools.reduce`` is called with `function` or `sequence` as a keyword args (#121677)
https://github.com/python/cpython/commit/d903b17499b1a3bfb3ea848f6a1b6da02ea... commit: d903b17499b1a3bfb3ea848f6a1b6da02eac3328 branch: main author: Kirill Podoprigora <kirill.bast9@mail.ru> committer: Eclips4 <kirill.bast9@mail.ru> date: 2025-01-01T13:36:47+02:00 summary: 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> files: A Misc/NEWS.d/next/Library/2024-07-13-13-25-31.gh-issue-121676.KDLS11.rst M Doc/deprecations/pending-removal-in-3.16.rst M Doc/whatsnew/3.14.rst M Lib/functools.py M Lib/test/test_functools.py diff --git a/Doc/deprecations/pending-removal-in-3.16.rst b/Doc/deprecations/pending-removal-in-3.16.rst index f2b818f14c63cd..d093deb648baf7 100644 --- a/Doc/deprecations/pending-removal-in-3.16.rst +++ b/Doc/deprecations/pending-removal-in-3.16.rst @@ -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. diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 63fa21e17bc834..4b3f1b2e8eed42 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -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 diff --git a/Lib/functools.py b/Lib/functools.py index 786b8aedfd77f5..fd33f0ae479ddc 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -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 @@ 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 diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 4a0252cb637a52..32224866082824 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -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: diff --git a/Misc/NEWS.d/next/Library/2024-07-13-13-25-31.gh-issue-121676.KDLS11.rst b/Misc/NEWS.d/next/Library/2024-07-13-13-25-31.gh-issue-121676.KDLS11.rst new file mode 100644 index 00000000000000..be589b727a1968 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-07-13-13-25-31.gh-issue-121676.KDLS11.rst @@ -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.
participants (1)
-
Eclips4