Skip to content

Commit 633c497

Browse files
committed
Make iscoroutinefunction, isgeneratorfunction and isasyncgenfunction work with partial
1 parent ea75187 commit 633c497

File tree

3 files changed

+38
-5
lines changed

3 files changed

+38
-5
lines changed

Lib/inspect.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,25 +173,35 @@ def isgeneratorfunction(object):
173173
174174
Generator function objects provide the same attributes as functions.
175175
See help(isfunction) for a list of attributes."""
176-
return bool((isfunction(object) or ismethod(object)) and
176+
is_generator_function = bool((isfunction(object) or ismethod(object)) and
177177
object.__code__.co_flags & CO_GENERATOR)
178+
is_partial_generator = bool((isinstance(object, functools.partial) and
179+
object.func.__code__.co_flags & CO_GENERATOR))
180+
return is_generator_function or is_partial_generator
178181

179182
def iscoroutinefunction(object):
180183
"""Return true if the object is a coroutine function.
181184
182185
Coroutine functions are defined with "async def" syntax.
183186
"""
184-
return bool((isfunction(object) or ismethod(object)) and
185-
object.__code__.co_flags & CO_COROUTINE)
187+
is_coroutine_function = bool(((isfunction(object) or ismethod(object)) and
188+
object.__code__.co_flags & CO_COROUTINE))
189+
is_partial_coroutine = bool((isinstance(object, functools.partial) and
190+
object.func.__code__.co_flags & CO_COROUTINE))
191+
return is_coroutine_function or is_partial_coroutine
186192

187193
def isasyncgenfunction(object):
188194
"""Return true if the object is an asynchronous generator function.
189195
190196
Asynchronous generator functions are defined with "async def"
191197
syntax and have "yield" expressions in their body.
192198
"""
193-
return bool((isfunction(object) or ismethod(object)) and
199+
is_async_gen_function = bool((isfunction(object) or ismethod(object)) and
194200
object.__code__.co_flags & CO_ASYNC_GENERATOR)
201+
is_partial_async_gen = bool((isinstance(object, functools.partial) and
202+
object.func.__code__.co_flags & CO_ASYNC_GENERATOR))
203+
return is_async_gen_function or is_partial_async_gen
204+
195205

196206
def isasyncgen(object):
197207
"""Return true if the object is an asynchronous generator."""

Lib/test/test_inspect.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,26 +166,46 @@ def test_excluding_predicates(self):
166166
self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
167167

168168
def test_iscoroutine(self):
169+
async_gen_coro = async_generator_function_example(1)
169170
gen_coro = gen_coroutine_function_example(1)
170171
coro = coroutine_function_example(1)
171172

172173
self.assertFalse(
173174
inspect.iscoroutinefunction(gen_coroutine_function_example))
175+
self.assertFalse(
176+
inspect.iscoroutinefunction(
177+
functools.partial(gen_coroutine_function_example)))
174178
self.assertFalse(inspect.iscoroutine(gen_coro))
175179

176180
self.assertTrue(
177181
inspect.isgeneratorfunction(gen_coroutine_function_example))
182+
self.assertTrue(
183+
inspect.isgeneratorfunction(
184+
functools.partial(gen_coroutine_function_example)))
178185
self.assertTrue(inspect.isgenerator(gen_coro))
179186

180187
self.assertTrue(
181188
inspect.iscoroutinefunction(coroutine_function_example))
189+
self.assertTrue(
190+
inspect.iscoroutinefunction(
191+
functools.partial(coroutine_function_example)))
182192
self.assertTrue(inspect.iscoroutine(coro))
183193

184194
self.assertFalse(
185195
inspect.isgeneratorfunction(coroutine_function_example))
196+
self.assertFalse(
197+
inspect.isgeneratorfunction(
198+
functools.partial(coroutine_function_example)))
186199
self.assertFalse(inspect.isgenerator(coro))
187200

188-
coro.close(); gen_coro.close() # silence warnings
201+
self.assertTrue(
202+
inspect.isasyncgenfunction(async_generator_function_example))
203+
self.assertTrue(
204+
inspect.isasyncgenfunction(
205+
functools.partial(async_generator_function_example)))
206+
self.assertTrue(inspect.isasyncgen(async_gen_coro))
207+
208+
coro.close(); gen_coro.close(); # silence warnings
189209

190210
def test_isawaitable(self):
191211
def gen(): yield
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Make :func:`inspect.iscoroutinefunction`,
2+
:func:`inspect.isgeneratorfunction` and :func:`inspect.isasyncgenfunction`
3+
work with :func:`functools.partial`. Patch by Pablo Galindo.

0 commit comments

Comments
 (0)