From 73957ae71bb1ca2dbc62573b4276a6d1babe62d3 Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Sat, 13 Jul 2024 10:30:11 +0000 Subject: [PATCH 01/13] Fix signature of functools.reduce --- Lib/functools.py | 2 +- .../Library/2024-07-13-13-25-31.gh-issue-121676.KDLS11.rst | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2024-07-13-13-25-31.gh-issue-121676.KDLS11.rst diff --git a/Lib/functools.py b/Lib/functools.py index a10493f0e25360..9de0e8d75fea27 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -236,7 +236,7 @@ def __ge__(self, other): _initial_missing = object() -def reduce(function, sequence, initial=_initial_missing): +def reduce(function, sequence, initial=_initial_missing, /): """ reduce(function, iterable[, initial], /) -> value 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..b0f6cb2d488e21 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-07-13-13-25-31.gh-issue-121676.KDLS11.rst @@ -0,0 +1,3 @@ +Fix the Python implementation of the :meth:`functools.reduce`. +Now it accepts only positional-only arguments, as well as the C implementtaion. + From dba4c4d902f720bcb635e7198740d6a5298cbc5e Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Mon, 15 Jul 2024 23:18:25 +0300 Subject: [PATCH 02/13] Raise a deprecation warning --- Lib/functools.py | 18 +++++++++++++++++- Lib/test/test_functools.py | 4 ++++ ...4-07-13-13-25-31.gh-issue-121676.KDLS11.rst | 5 +++-- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py index 9de0e8d75fea27..7988a67ee055bf 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -236,7 +236,7 @@ def __ge__(self, other): _initial_missing = object() -def reduce(function, sequence, initial=_initial_missing, /): +def reduce(function, sequence, initial=_initial_missing): """ reduce(function, iterable[, initial], /) -> value @@ -1042,3 +1042,19 @@ def __get__(self, instance, owner=None): return val __class_getitem__ = classmethod(GenericAlias) + +def _warn_kwargs(func): + @wraps(func) + def wrapper(*args, **kwargs): + if kwargs: + import os + import warnings + warnings.warn("""\ +Calling functools.reduce with keyword arguments is deprecated +in Python 3.13 and will be forbidden in Python 3.15.""", + DeprecationWarning, + skip_file_prefixes=(os.path.dirname(__file__),)) + return func(*args, **kwargs) + return wrapper + +reduce = _warn_kwargs(reduce) diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 492a16a8c7ff45..d3fe1bbc376461 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -892,6 +892,10 @@ 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=object()) + 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 index b0f6cb2d488e21..fa81c36887d371 100644 --- 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 @@ -1,3 +1,4 @@ -Fix the Python implementation of the :meth:`functools.reduce`. -Now it accepts only positional-only arguments, as well as the C implementtaion. +Now calling the Python implementation of the :meth:`functools.reduce` with a +:term:`keyword argument` is raises a :exc:`DeprecationWarning`. +This will be forbidden in Python 3.15 in order to match the C implementation. From d81f9f1012cf3337df3a228f01e525fedce55002 Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Mon, 15 Jul 2024 23:21:17 +0300 Subject: [PATCH 03/13] Fix versions --- Lib/functools.py | 2 +- .../next/Library/2024-07-13-13-25-31.gh-issue-121676.KDLS11.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py index 7988a67ee055bf..867f7d23b4475f 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -1051,7 +1051,7 @@ def wrapper(*args, **kwargs): import warnings warnings.warn("""\ Calling functools.reduce with keyword arguments is deprecated -in Python 3.13 and will be forbidden in Python 3.15.""", +in Python 3.14 and will be forbidden in Python 3.16.""", DeprecationWarning, skip_file_prefixes=(os.path.dirname(__file__),)) return func(*args, **kwargs) 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 index fa81c36887d371..3603345c69ac40 100644 --- 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 @@ -1,4 +1,4 @@ Now calling the Python implementation of the :meth:`functools.reduce` with a :term:`keyword argument` is raises a :exc:`DeprecationWarning`. -This will be forbidden in Python 3.15 in order to match the C implementation. +This will be forbidden in Python 3.16 in order to match the C implementation. From 6563f67c83d41fd5654a1d80ee6fdcbe52c73201 Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Mon, 15 Jul 2024 23:36:35 +0300 Subject: [PATCH 04/13] Fix indent --- Lib/functools.py | 2 +- Lib/test/test_functools.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py index 867f7d23b4475f..316c1489adf252 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -1054,7 +1054,7 @@ def wrapper(*args, **kwargs): in Python 3.14 and will be forbidden in Python 3.16.""", DeprecationWarning, skip_file_prefixes=(os.path.dirname(__file__),)) - return func(*args, **kwargs) + return func(*args, **kwargs) return wrapper reduce = _warn_kwargs(reduce) diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index d3fe1bbc376461..a85bdf83172a3b 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -894,7 +894,7 @@ class TestReducePy(TestReduce, unittest.TestCase): 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=object()) + self.reduce(function=lambda x, y: x + y, sequence=[1, 2, 3, 4, 5], initial=1) class TestCmpToKey: From d1faaee1c96aa0a21175945c65eac95c1fc93329 Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Tue, 16 Jul 2024 00:05:06 +0300 Subject: [PATCH 05/13] Move import right after the definition --- Lib/functools.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py index 316c1489adf252..9fddc58c09a156 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 @@ -1058,3 +1053,8 @@ def wrapper(*args, **kwargs): return wrapper reduce = _warn_kwargs(reduce) + +try: + from _functools import reduce +except ImportError: + pass From 0359eec53a16137400c08f667cea40c027cc46fd Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Wed, 7 Aug 2024 12:32:05 +0300 Subject: [PATCH 06/13] Address review --- Lib/functools.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py index 9fddc58c09a156..9af6f673241d91 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -1044,11 +1044,12 @@ def wrapper(*args, **kwargs): if kwargs: import os import warnings - warnings.warn("""\ -Calling functools.reduce with keyword arguments is deprecated -in Python 3.14 and will be forbidden in Python 3.16.""", - DeprecationWarning, - skip_file_prefixes=(os.path.dirname(__file__),)) + warnings.warn( + 'Calling functools.reduce with keyword arguments' + + ' is deprecated in Python 3.14 and will be' + + ' forbidden in Python 3.16.', + DeprecationWarning, + skip_file_prefixes=(os.path.dirname(__file__),)) return func(*args, **kwargs) return wrapper From eda166e0611f34dab64ff84817033bdeae290e00 Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Wed, 7 Aug 2024 13:19:10 +0300 Subject: [PATCH 07/13] Update Lib/functools.py Co-authored-by: Victor Stinner --- Lib/functools.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py index 9af6f673241d91..5264b00f0e3c1a 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -1045,9 +1045,9 @@ def wrapper(*args, **kwargs): import os import warnings warnings.warn( - 'Calling functools.reduce with keyword arguments' - + ' is deprecated in Python 3.14 and will be' - + ' forbidden in Python 3.16.', + 'Calling functools.reduce with keyword arguments ' + 'is deprecated in Python 3.14 and will be ' + 'forbidden in Python 3.16.', DeprecationWarning, skip_file_prefixes=(os.path.dirname(__file__),)) return func(*args, **kwargs) From 1a04c13d1e99162de9b7cfac03194eaa87d00cc0 Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Wed, 7 Aug 2024 13:22:40 +0300 Subject: [PATCH 08/13] Remove newline; add a test case --- Lib/test/test_functools.py | 2 ++ .../next/Library/2024-07-13-13-25-31.gh-issue-121676.KDLS11.rst | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index a85bdf83172a3b..dbc058ee893c07 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -895,6 +895,8 @@ class TestReducePy(TestReduce, unittest.TestCase): 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 index 3603345c69ac40..e91245d150625a 100644 --- 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 @@ -1,4 +1,3 @@ Now calling the Python implementation of the :meth:`functools.reduce` with a :term:`keyword argument` is raises a :exc:`DeprecationWarning`. This will be forbidden in Python 3.16 in order to match the C implementation. - From 991e3304d3f20bd064cd241cb8a8be3b42cc0d84 Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Sat, 28 Dec 2024 18:16:15 +0200 Subject: [PATCH 09/13] Allow initial as keyword arg --- Doc/deprecations/pending-removal-in-3.16.rst | 5 +++++ Lib/functools.py | 3 ++- .../Library/2024-07-13-13-25-31.gh-issue-121676.KDLS11.rst | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Doc/deprecations/pending-removal-in-3.16.rst b/Doc/deprecations/pending-removal-in-3.16.rst index 446cc63cb34ff9..9d3e5857897d87 100644 --- a/Doc/deprecations/pending-removal-in-3.16.rst +++ b/Doc/deprecations/pending-removal-in-3.16.rst @@ -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. \ No newline at end of file diff --git a/Lib/functools.py b/Lib/functools.py index 9371e944a4728f..5384ad256afdc5 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -1121,11 +1121,12 @@ def __get__(self, instance, owner=None): def _warn_kwargs(func): @wraps(func) def wrapper(*args, **kwargs): - if 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, 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 index e91245d150625a..e674c3d3f7c064 100644 --- 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 @@ -1,3 +1,3 @@ -Now calling the Python implementation of the :meth:`functools.reduce` with a -:term:`keyword argument` is raises a :exc:`DeprecationWarning`. +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. From 1cc1ce18d91428909613f6c2c134d501436e7e62 Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Sat, 28 Dec 2024 18:20:32 +0200 Subject: [PATCH 10/13] Fix typos --- Doc/deprecations/pending-removal-in-3.16.rst | 2 +- .../next/Library/2024-07-13-13-25-31.gh-issue-121676.KDLS11.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/deprecations/pending-removal-in-3.16.rst b/Doc/deprecations/pending-removal-in-3.16.rst index 9d3e5857897d87..a6fb42d87af33c 100644 --- a/Doc/deprecations/pending-removal-in-3.16.rst +++ b/Doc/deprecations/pending-removal-in-3.16.rst @@ -44,4 +44,4 @@ Pending Removal in Python 3.16 * :mod:`functools`: * Calling the Python implementation of :func:`functools.reduce` with *function* - or *sequence* as keyword arguments has been deprecated since Python 3.14. \ No newline at end of file + or *sequence* as keyword arguments has been deprecated since Python 3.14. 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 index e674c3d3f7c064..be589b727a1968 100644 --- 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 @@ -1,3 +1,3 @@ Deprecate calling the Python implementation of :meth:`functools.reduce` -with a ``function`` or ``sequence`` as a `:term:`keyword argument`. +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. From 578f22e14135c7c7370a323837f6ef2462dc0980 Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Sat, 28 Dec 2024 18:58:40 +0200 Subject: [PATCH 11/13] Add an entry to the whatsnew --- Doc/whatsnew/3.14.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 5b9b01860045fd..bbb6dd04f92bc0 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -385,6 +385,10 @@ 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. + * :mod:`os`: :term:`Soft deprecate ` :func:`os.popen` and :func:`os.spawn* ` functions. They should no longer be used to From b8c9acecd44f8e227a9b20f29b853ceb3a2ab554 Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Sun, 29 Dec 2024 14:57:10 +0200 Subject: [PATCH 12/13] Address review --- Doc/whatsnew/3.14.rst | 1 + Lib/functools.py | 3 +++ 2 files changed, 4 insertions(+) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index bbb6dd04f92bc0..2b63e5fea5dc90 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -388,6 +388,7 @@ Deprecated * :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 ` :func:`os.popen` and diff --git a/Lib/functools.py b/Lib/functools.py index 5384ad256afdc5..2ea97b7009f15b 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -1136,6 +1136,9 @@ def wrapper(*args, **kwargs): reduce = _warn_kwargs(reduce) +# This import has been moved here due to gh-121676 +# In Python3.16 _warn_kwargs should be removed, and this +# import should be moved right after the reduce definition try: from _functools import reduce except ImportError: From b7e305b2cc228764a452e223fe475eec0e3a5af4 Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Wed, 1 Jan 2025 12:52:57 +0200 Subject: [PATCH 13/13] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- Lib/functools.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py index 2ea97b7009f15b..67ebcc032c7031 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -1118,8 +1118,8 @@ def __get__(self, instance, owner=None): __class_getitem__ = classmethod(GenericAlias) -def _warn_kwargs(func): - @wraps(func) +def _warn_python_reduce_kwargs(py_reduce): + @wraps(py_reduce) def wrapper(*args, **kwargs): if 'function' in kwargs or 'sequence' in kwargs: import os @@ -1131,14 +1131,16 @@ def wrapper(*args, **kwargs): 'forbidden in Python 3.16.', DeprecationWarning, skip_file_prefixes=(os.path.dirname(__file__),)) - return func(*args, **kwargs) + return py_reduce(*args, **kwargs) return wrapper -reduce = _warn_kwargs(reduce) +reduce = _warn_python_reduce_kwargs(reduce) +del _warn_python_reduce_kwargs -# This import has been moved here due to gh-121676 -# In Python3.16 _warn_kwargs should be removed, and this -# import should be moved right after the reduce definition +# 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: