Skip to content

Commit 573ec0b

Browse files
committed
Moved to decorator; extra tests.
1 parent 877597e commit 573ec0b

File tree

2 files changed

+30
-21
lines changed

2 files changed

+30
-21
lines changed

Lib/inspect.py

+11-1
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@
125125
"ismodule",
126126
"isroutine",
127127
"istraceback",
128+
"markcoroutinefunction",
128129
"signature",
129130
"stack",
130131
"trace",
@@ -391,13 +392,22 @@ def isgeneratorfunction(obj):
391392
See help(isfunction) for a list of attributes."""
392393
return _has_code_flag(obj, CO_GENERATOR)
393394

395+
def markcoroutinefunction(func):
396+
"""
397+
Decorator to ensure callable is recognised as a coroutine function.
398+
"""
399+
func.__code__ = func.__code__.replace(
400+
co_flags=func.__code__.co_flags | CO_COROUTINE
401+
)
402+
return func
403+
394404
def iscoroutinefunction(obj):
395405
"""Return true if the object is a coroutine function.
396406
397407
Coroutine functions are defined with "async def" syntax.
398408
"""
399409
return _has_code_flag(obj, CO_COROUTINE) or (
400-
callable(obj) and _has_code_flag(obj.__call__, CO_COROUTINE)
410+
not isclass(obj) and callable(obj) and _has_code_flag(obj.__call__, CO_COROUTINE)
401411
)
402412

403413
def isasyncgenfunction(obj):

Lib/test/test_inspect.py

+19-20
Original file line numberDiff line numberDiff line change
@@ -202,30 +202,29 @@ def test_iscoroutine(self):
202202
gen_coroutine_function_example))))
203203
self.assertTrue(inspect.isgenerator(gen_coro))
204204

205-
# Use subtest initially to see both failures.
206-
with self.subTest("Wrapper not recognised."):
207-
# First case: sync function returning an awaitable.
208-
async def _fn3():
209-
pass
205+
async def _fn3():
206+
pass
210207

211-
def fn3():
212-
return _fn3()
208+
@inspect.markcoroutinefunction
209+
def fn3():
210+
return _fn3()
213211

214-
# TODO: Move this to decorator function.
215-
fn3.__code__ = fn3.__code__.replace(
216-
co_flags=fn3.__code__.co_flags | inspect.CO_COROUTINE
217-
)
212+
self.assertTrue(inspect.iscoroutinefunction(fn3))
218213

219-
self.assertTrue(inspect.iscoroutinefunction(fn3))
214+
class Cl:
215+
async def __call__(self):
216+
pass
217+
218+
self.assertFalse(inspect.iscoroutinefunction(Cl))
219+
self.assertTrue(inspect.iscoroutinefunction(Cl()))
220+
221+
class Cl2:
222+
@inspect.markcoroutinefunction
223+
def __call__(self):
224+
pass
220225

221-
with self.subTest("Awaitable instance not recongnised."):
222-
# Second case: a class with an async def __call__.
223-
# - instance is awaitable.
224-
class Cl:
225-
async def __call__(self):
226-
pass
227-
cl = Cl()
228-
self.assertTrue(inspect.iscoroutinefunction(cl))
226+
self.assertFalse(inspect.iscoroutinefunction(Cl2))
227+
self.assertTrue(inspect.iscoroutinefunction(Cl2()))
229228

230229
self.assertFalse(
231230
inspect.iscoroutinefunction(unittest.mock.Mock()))

0 commit comments

Comments
 (0)