Skip to content

Commit e270fe8

Browse files
committed
rename is_coroutine_generator -> is_async_generator, implement is_async_generator_return_type
1 parent 6b3e81c commit e270fe8

File tree

3 files changed

+21
-6
lines changed

3 files changed

+21
-6
lines changed

mypy/checker.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,12 +334,19 @@ def check_overlapping_overloads(self, defn: OverloadedFuncDef) -> None:
334334
# for functions decorated with `@types.coroutine` or
335335
# `@asyncio.coroutine`. Its single parameter corresponds to tr.
336336
#
337+
# PEP 525 adds a new type, the asynchronous generator, which was
338+
# first released in Python 3.6. Async generators are `async def`
339+
# functions that can also `yield` values. They can be parameterized
340+
# with two types, ty and tc, because they cannot return a value.
341+
#
337342
# There are several useful methods, each taking a type t and a
338343
# flag c indicating whether it's for a generator or coroutine:
339344
#
340345
# - is_generator_return_type(t, c) returns whether t is a Generator,
341346
# Iterator, Iterable (if not c), or Awaitable (if c), or
342347
# AwaitableGenerator (regardless of c).
348+
# - is_async_generator_return_type(t) returns whether t is an
349+
# AsyncGenerator.
343350
# - get_generator_yield_type(t, c) returns ty.
344351
# - get_generator_receive_type(t, c) returns tc.
345352
# - get_generator_return_type(t, c) returns tr.
@@ -361,6 +368,14 @@ def is_generator_return_type(self, typ: Type, is_coroutine: bool) -> bool:
361368
return True
362369
return isinstance(typ, Instance) and typ.type.fullname() == 'typing.AwaitableGenerator'
363370

371+
def is_async_generator_return_type(self, typ: Type) -> bool:
372+
"""Is `typ` a valid type for an async generator?
373+
374+
True if `typ` is a supertype of AsyncGenerator.
375+
"""
376+
agt = self.named_generic_type('typing.AsyncGenerator', [AnyType(), AnyType()])
377+
return is_subtype(agt, typ)
378+
364379
def get_generator_yield_type(self, return_type: Type, is_coroutine: bool) -> Type:
365380
"""Given the declared return type of a generator (t), return the type it yields (ty)."""
366381
if isinstance(return_type, AnyType):
@@ -569,9 +584,9 @@ def is_implicit_any(t: Type) -> bool:
569584

570585
# Check that Generator functions have the appropriate return type.
571586
if defn.is_generator:
572-
if defn.is_coroutine:
587+
if defn.is_async_generator:
573588
if not self.is_async_generator_return_type(typ.ret_type):
574-
pass
589+
self.fail(messages.INVALID_RETURN_TYPE_FOR_ASYNC_GENERATOR, typ)
575590
else:
576591
if not self.is_generator_return_type(typ.ret_type, defn.is_coroutine):
577592
self.fail(messages.INVALID_RETURN_TYPE_FOR_GENERATOR, typ)

mypy/nodes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -465,15 +465,15 @@ class FuncItem(FuncBase):
465465
is_overload = False
466466
is_generator = False # Contains a yield statement?
467467
is_coroutine = False # Defined using 'async def' syntax?
468-
is_coroutine_generator = False # Is an async def generator?
468+
is_async_generator = False # Is an async def generator?
469469
is_awaitable_coroutine = False # Decorated with '@{typing,asyncio}.coroutine'?
470470
is_static = False # Uses @staticmethod?
471471
is_class = False # Uses @classmethod?
472472
# Variants of function with type variables with values expanded
473473
expanded = None # type: List[FuncItem]
474474

475475
FLAGS = [
476-
'is_overload', 'is_generator', 'is_coroutine', 'is_coroutine_generator',
476+
'is_overload', 'is_generator', 'is_coroutine', 'is_async_generator',
477477
'is_awaitable_coroutine', 'is_static', 'is_class',
478478
]
479479

mypy/semanal.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ def visit_func_def(self, defn: FuncDef) -> None:
318318
self.errors.push_function(defn.name())
319319
self.analyze_function(defn)
320320
if defn.is_coroutine and isinstance(defn.type, CallableType):
321-
if defn.is_coroutine_generator:
321+
if defn.is_async_generator:
322322
# Async generator types are handled elsewhere
323323
pass
324324
else:
@@ -2540,7 +2540,7 @@ def visit_yield_expr(self, expr: YieldExpr) -> None:
25402540
self.fail("'yield' in async function", expr, True, blocker=True)
25412541
else:
25422542
self.function_stack[-1].is_generator = True
2543-
self.function_stack[-1].is_coroutine_generator = True
2543+
self.function_stack[-1].is_async_generator = True
25442544
else:
25452545
self.function_stack[-1].is_generator = True
25462546
if expr.expr:

0 commit comments

Comments
 (0)