From ab33a36a23463d126739ff177520020b29416dc5 Mon Sep 17 00:00:00 2001 From: Illia Volochii Date: Mon, 15 Feb 2021 22:17:14 +0200 Subject: [PATCH 1/5] bpo-43234: Prohibit non-ThreadPoolExecutor in loop.set_default_executor --- Doc/library/asyncio-eventloop.rst | 12 ++++-------- Doc/whatsnew/3.10.rst | 4 ++++ Lib/asyncio/base_events.py | 6 ++---- Lib/test/test_asyncio/test_base_events.py | 2 +- .../Library/2021-02-15-22-14-31.bpo-43234.F-vKAT.rst | 3 +++ 5 files changed, 14 insertions(+), 13 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2021-02-15-22-14-31.bpo-43234.F-vKAT.rst diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index 7de5a0ab2595c5..4e8945b4adeafe 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -1127,16 +1127,12 @@ Executing code in thread or process pools .. method:: loop.set_default_executor(executor) Set *executor* as the default executor used by :meth:`run_in_executor`. - *executor* should be an instance of + *executor* must be an instance of :class:`~concurrent.futures.ThreadPoolExecutor`. - .. deprecated:: 3.8 - Using an executor that is not an instance of - :class:`~concurrent.futures.ThreadPoolExecutor` is deprecated and - will trigger an error in Python 3.9. - - *executor* must be an instance of - :class:`concurrent.futures.ThreadPoolExecutor`. + .. deprecated-removed:: 3.8 3.10 + Accepting an ``executor`` that is not an instance of + :class:`~concurrent.futures.ThreadPoolExecutor`. Error Handling API diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index c282edcc9d8f0e..8aa5665096c543 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -725,6 +725,10 @@ Removed (Contributed by Yurii Karabas, Andrew Svetlov, Yury Selivanov and Kyle Stanley in :issue:`42392`.) +* Prohibited passing non-:class:`concurrent.futures.ThreadPoolExecutor` + executors to :meth:`loop.set_default_executor` following a deprecation in + Python 3.8. + (Contributed by Illia Volochii in :issue:`43234`.) Porting to Python 3.10 ====================== diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index f789635e0f893a..5b077ba1b989b3 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -814,11 +814,9 @@ def run_in_executor(self, executor, func, *args): def set_default_executor(self, executor): if not isinstance(executor, concurrent.futures.ThreadPoolExecutor): - warnings.warn( + raise RuntimeError( 'Using the default executor that is not an instance of ' - 'ThreadPoolExecutor is deprecated and will be prohibited ' - 'in Python 3.9', - DeprecationWarning, 2) + 'ThreadPoolExecutor is prohibited') self._default_executor = executor def _getaddrinfo_debug(self, host, port, family, type, proto, flags): diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index e40e7999b64d15..f1ea5d41c9f5f1 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -227,7 +227,7 @@ def submit(self, fn, *args, **kwargs): def test_set_default_executor_deprecation_warnings(self): executor = mock.Mock() - with self.assertWarns(DeprecationWarning): + with self.assertRaises(RuntimeError): self.loop.set_default_executor(executor) # Avoid cleaning up the executor mock diff --git a/Misc/NEWS.d/next/Library/2021-02-15-22-14-31.bpo-43234.F-vKAT.rst b/Misc/NEWS.d/next/Library/2021-02-15-22-14-31.bpo-43234.F-vKAT.rst new file mode 100644 index 00000000000000..7f195cc752fc13 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-02-15-22-14-31.bpo-43234.F-vKAT.rst @@ -0,0 +1,3 @@ +Prohibit passing non-:class:`concurrent.futures.ThreadPoolExecutor` +executors to :meth:`loop.set_default_executor` following a deprecation in +Python 3.8. Patch by Illia Volochii. From 3df77a86a6d8f2c09ee38e4eb7fd974fc969b831 Mon Sep 17 00:00:00 2001 From: Illia Volochii Date: Tue, 29 Jun 2021 17:22:44 +0300 Subject: [PATCH 2/5] Apply documentation suggestions Co-authored-by: Serhiy Storchaka --- Doc/library/asyncio-eventloop.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index be44c697e05f66..f0f6ae6d98ff99 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -1135,8 +1135,8 @@ Executing code in thread or process pools *executor* must be an instance of :class:`~concurrent.futures.ThreadPoolExecutor`. - .. deprecated-removed:: 3.8 3.10 - Accepting an ``executor`` that is not an instance of + .. versionchanged:: 3.11 + *executor* must be an instance of :class:`~concurrent.futures.ThreadPoolExecutor`. From a78287fbc0ebd66c9ee4d108695feb5c4b530d5d Mon Sep 17 00:00:00 2001 From: Illia Volochii Date: Tue, 29 Jun 2021 17:26:53 +0300 Subject: [PATCH 3/5] Update a type of the used error Co-authored-by: Serhiy Storchaka --- Lib/asyncio/base_events.py | 4 +--- Lib/test/test_asyncio/test_base_events.py | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 5b077ba1b989b3..74d5670bf74edb 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -814,9 +814,7 @@ def run_in_executor(self, executor, func, *args): def set_default_executor(self, executor): if not isinstance(executor, concurrent.futures.ThreadPoolExecutor): - raise RuntimeError( - 'Using the default executor that is not an instance of ' - 'ThreadPoolExecutor is prohibited') + raise TypeError('executor must be ThreadPoolExecutor instance') self._default_executor = executor def _getaddrinfo_debug(self, host, port, family, type, proto, flags): diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index e47379a6d6ed58..f39adaa375cb87 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -227,7 +227,7 @@ def submit(self, fn, *args, **kwargs): def test_set_default_executor_deprecation_warnings(self): executor = mock.Mock() - with self.assertRaises(RuntimeError): + with self.assertRaises(TypeError): self.loop.set_default_executor(executor) # Avoid cleaning up the executor mock From 8eb365891db9d75aafa7c6d4fa244871a419061e Mon Sep 17 00:00:00 2001 From: Illia Volochii Date: Tue, 29 Jun 2021 17:34:11 +0300 Subject: [PATCH 4/5] Move a change note to the 3.11 what's new file --- Doc/whatsnew/3.10.rst | 4 ---- Doc/whatsnew/3.11.rst | 9 +++++++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index 8d5d8f374418e4..9b9dd31a3beabf 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -1699,10 +1699,6 @@ Removed (Contributed by Yurii Karabas, Andrew Svetlov, Yury Selivanov and Kyle Stanley in :issue:`42392`.) -* Prohibited passing non-:class:`concurrent.futures.ThreadPoolExecutor` - executors to :meth:`loop.set_default_executor` following a deprecation in - Python 3.8. - (Contributed by Illia Volochii in :issue:`43234`.) Porting to Python 3.10 ====================== diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 50d91a0adc141b..f6bfb7f92a311b 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -160,6 +160,15 @@ This section lists previously described changes and other bugfixes that may require changes to your code. +Changes in the Python API +------------------------- + +* Prohibited passing non-:class:`concurrent.futures.ThreadPoolExecutor` + executors to :meth:`loop.set_default_executor` following a deprecation in + Python 3.8. + (Contributed by Illia Volochii in :issue:`43234`.) + + C API Changes ============= From d5934a059b774580e9c078cfa00616d675b2e925 Mon Sep 17 00:00:00 2001 From: Illia Volochii Date: Wed, 30 Jun 2021 13:56:15 +0300 Subject: [PATCH 5/5] Update a related test Co-authored-by: Serhiy Storchaka --- Lib/test/test_asyncio/test_base_events.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index f39adaa375cb87..1a52f9f1a61afb 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -224,14 +224,14 @@ def submit(self, fn, *args, **kwargs): self.loop.set_default_executor(executor) self.assertIs(executor, self.loop._default_executor) - def test_set_default_executor_deprecation_warnings(self): + def test_set_default_executor_error(self): executor = mock.Mock() - with self.assertRaises(TypeError): + msg = 'executor must be ThreadPoolExecutor instance' + with self.assertRaisesRegex(TypeError, msg): self.loop.set_default_executor(executor) - # Avoid cleaning up the executor mock - self.loop._default_executor = None + self.assertIsNone(self.loop._default_executor) def test_call_soon(self): def cb():