From e472f6d3184e71a496fadc04f755995b736fd595 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Tue, 12 May 2026 20:29:46 +0300 Subject: [PATCH] gh-149600: Remove deprecated `asyncio.iscoroutinefunction` function (#149601) --- Doc/whatsnew/3.16.rst | 7 ++++++ Lib/asyncio/base_events.py | 3 ++- Lib/asyncio/coroutines.py | 21 +---------------- Lib/asyncio/unix_events.py | 3 ++- Lib/test/test_asyncio/test_pep492.py | 5 ---- Lib/test/test_asyncio/test_tasks.py | 23 ++----------------- Lib/unittest/mock.py | 8 ------- ...-05-09-15-42-54.gh-issue-149600.ZbL-iv.rst | 1 + 8 files changed, 15 insertions(+), 56 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-05-09-15-42-54.gh-issue-149600.ZbL-iv.rst diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst index 3c29bda7d1fb..2db8866da60e 100644 --- a/Doc/whatsnew/3.16.rst +++ b/Doc/whatsnew/3.16.rst @@ -114,6 +114,13 @@ annotationlib Use :meth:`annotationlib.ForwardRef.evaluate` or :func:`typing.evaluate_forward_ref` instead. +asyncio +------- + +* The :func:`!asyncio.iscoroutinefunction` + which has been deprecated since Python 3.14. + Use :func:`inspect.iscoroutinefunction` instead. + functools --------- diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 7a6837546d93..1fedb066f94c 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -31,6 +31,7 @@ import time import traceback import warnings import weakref +import inspect try: import ssl @@ -840,7 +841,7 @@ class BaseEventLoop(events.AbstractEventLoop): def _check_callback(self, callback, method): if (coroutines.iscoroutine(callback) or - coroutines._iscoroutinefunction(callback)): + inspect.iscoroutinefunction(callback)): raise TypeError( f"coroutines cannot be used with {method}()") if not callable(callback): diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py index a51319cb72a6..bfffb6da4b19 100644 --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -1,4 +1,4 @@ -__all__ = 'iscoroutinefunction', 'iscoroutine' +__all__ = ('iscoroutine',) import collections.abc import inspect @@ -13,25 +13,6 @@ def _is_debug_mode(): bool(os.environ.get('PYTHONASYNCIODEBUG'))) -# A marker for iscoroutinefunction. -_is_coroutine = object() - - -def iscoroutinefunction(func): - import warnings - """Return True if func is a decorated coroutine function.""" - warnings._deprecated("asyncio.iscoroutinefunction", - f"{warnings._DEPRECATED_MSG}; " - "use inspect.iscoroutinefunction() instead", - remove=(3,16)) - return _iscoroutinefunction(func) - - -def _iscoroutinefunction(func): - return (inspect.iscoroutinefunction(func) or - getattr(func, '_is_coroutine', None) is _is_coroutine) - - # Prioritize native coroutine check to speed-up # asyncio.iscoroutine. _COROUTINE_TYPES = (types.CoroutineType, collections.abc.Coroutine) diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index 49e8067ee7b4..915ff8452491 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -12,6 +12,7 @@ import subprocess import sys import threading import warnings +import inspect from . import base_events from . import base_subprocess @@ -94,7 +95,7 @@ class _UnixSelectorEventLoop(selector_events.BaseSelectorEventLoop): Raise RuntimeError if there is a problem setting up the handler. """ if (coroutines.iscoroutine(callback) or - coroutines._iscoroutinefunction(callback)): + inspect.iscoroutinefunction(callback)): raise TypeError("coroutines cannot be used " "with add_signal_handler()") self._check_signal(sig) diff --git a/Lib/test/test_asyncio/test_pep492.py b/Lib/test/test_asyncio/test_pep492.py index a0c8434c9457..95a9f3a9a7cf 100644 --- a/Lib/test/test_asyncio/test_pep492.py +++ b/Lib/test/test_asyncio/test_pep492.py @@ -124,11 +124,6 @@ class CoroutineTests(BaseTest): self.assertFalse(asyncio.iscoroutine(foo())) - def test_iscoroutinefunction(self): - async def foo(): pass - with self.assertWarns(DeprecationWarning): - self.assertTrue(asyncio.iscoroutinefunction(foo)) - def test_async_def_coroutines(self): async def bar(): return 'spam' diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index dc179acd86e8..56b1494c8363 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -11,6 +11,7 @@ import sys import traceback import types import unittest +import inspect from unittest import mock from types import GenericAlias @@ -20,7 +21,6 @@ from asyncio import tasks from test.test_asyncio import utils as test_utils from test import support from test.support.script_helper import assert_python_ok -from test.support.warnings_helper import ignore_warnings def tearDownModule(): @@ -1940,30 +1940,11 @@ class BaseTaskTests: self.assertFalse(task.cancelled()) self.assertIs(task.exception(), base_exc) - @ignore_warnings(category=DeprecationWarning) - def test_iscoroutinefunction(self): - def fn(): - pass - - self.assertFalse(asyncio.iscoroutinefunction(fn)) - - def fn1(): - yield - self.assertFalse(asyncio.iscoroutinefunction(fn1)) - - async def fn2(): - pass - self.assertTrue(asyncio.iscoroutinefunction(fn2)) - - self.assertFalse(asyncio.iscoroutinefunction(mock.Mock())) - self.assertTrue(asyncio.iscoroutinefunction(mock.AsyncMock())) - - @ignore_warnings(category=DeprecationWarning) def test_coroutine_non_gen_function(self): async def func(): return 'test' - self.assertTrue(asyncio.iscoroutinefunction(func)) + self.assertTrue(inspect.iscoroutinefunction(func)) coro = func() self.assertTrue(asyncio.iscoroutine(coro)) diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 1cee67fa5d70..16f3699e89e7 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -281,7 +281,6 @@ def _setup_func(funcopy, mock, sig): def _setup_async_mock(mock): - mock._is_coroutine = asyncio.coroutines._is_coroutine mock.await_count = 0 mock.await_args = None mock.await_args_list = _CallList() @@ -2287,13 +2286,6 @@ class AsyncMockMixin(Base): def __init__(self, /, *args, **kwargs): super().__init__(*args, **kwargs) - # iscoroutinefunction() checks _is_coroutine property to say if an - # object is a coroutine. Without this check it looks to see if it is a - # function/method, which in this case it is not (since it is an - # AsyncMock). - # It is set through __dict__ because when spec_set is True, this - # attribute is likely undefined. - self.__dict__['_is_coroutine'] = asyncio.coroutines._is_coroutine self.__dict__['_mock_await_count'] = 0 self.__dict__['_mock_await_args'] = None self.__dict__['_mock_await_args_list'] = _CallList() diff --git a/Misc/NEWS.d/next/Library/2026-05-09-15-42-54.gh-issue-149600.ZbL-iv.rst b/Misc/NEWS.d/next/Library/2026-05-09-15-42-54.gh-issue-149600.ZbL-iv.rst new file mode 100644 index 000000000000..732787dc92c1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-05-09-15-42-54.gh-issue-149600.ZbL-iv.rst @@ -0,0 +1 @@ +Remove deprecated :func:`!asyncio.iscoroutinefunction` function. -- 2.47.3