MCPcopy
hub / github.com/python/mypy / visit_yield_from_expr

Method visit_yield_from_expr

mypy/checkexpr.py:6331–6389  ·  view source on GitHub ↗
(self, e: YieldFromExpr, allow_none_return: bool = False)

Source from the content-addressed store, hash-verified

6329 return ret_type
6330
6331 def visit_yield_from_expr(self, e: YieldFromExpr, allow_none_return: bool = False) -> Type:
6332 # NOTE: Whether `yield from` accepts an `async def` decorated
6333 # with `@types.coroutine` (or `@asyncio.coroutine`) depends on
6334 # whether the generator containing the `yield from` is itself
6335 # thus decorated. But it accepts a generator regardless of
6336 # how it's decorated.
6337 return_type = self.chk.return_types[-1]
6338 # TODO: What should the context for the sub-expression be?
6339 # If the containing function has type Generator[X, Y, ...],
6340 # the context should be Generator[X, Y, T], where T is the
6341 # context of the 'yield from' itself (but it isn't known).
6342 subexpr_type = get_proper_type(self.accept(e.expr))
6343
6344 # Check that the expr is an instance of Iterable and get the type of the iterator produced
6345 # by __iter__.
6346 if isinstance(subexpr_type, AnyType):
6347 iter_type: Type = AnyType(TypeOfAny.from_another_any, source_any=subexpr_type)
6348 elif self.chk.type_is_iterable(subexpr_type):
6349 if is_async_def(subexpr_type) and not has_coroutine_decorator(return_type):
6350 self.chk.msg.yield_from_invalid_operand_type(subexpr_type, e)
6351
6352 any_type = AnyType(TypeOfAny.special_form)
6353 generic_generator_type = self.chk.named_generic_type(
6354 "typing.Generator", [any_type, any_type, any_type]
6355 )
6356 generic_generator_type.set_line(e)
6357 iter_type, _ = self.check_method_call_by_name(
6358 "__iter__", subexpr_type, [], [], context=generic_generator_type
6359 )
6360 else:
6361 if not (is_async_def(subexpr_type) and has_coroutine_decorator(return_type)):
6362 self.chk.msg.yield_from_invalid_operand_type(subexpr_type, e)
6363 iter_type = AnyType(TypeOfAny.from_error)
6364 else:
6365 iter_type = self.check_awaitable_expr(
6366 subexpr_type, e, message_registry.INCOMPATIBLE_TYPES_IN_YIELD_FROM
6367 )
6368
6369 # Check that the iterator's item type matches the type yielded by the Generator function
6370 # containing this `yield from` expression.
6371 expected_item_type = self.chk.get_generator_yield_type(return_type, False)
6372 actual_item_type = self.chk.get_generator_yield_type(iter_type, False)
6373
6374 self.chk.check_subtype(
6375 actual_item_type,
6376 expected_item_type,
6377 e,
6378 message_registry.INCOMPATIBLE_TYPES_IN_YIELD_FROM,
6379 "actual type",
6380 "expected type",
6381 )
6382
6383 # Determine the type of the entire yield from expression.
6384 iter_type = get_proper_type(iter_type)
6385 expr_type = self.chk.get_generator_return_type(iter_type, is_coroutine=False)
6386
6387 if not allow_none_return and isinstance(get_proper_type(expr_type), NoneType):
6388 self.chk.msg.does_not_return_value(None, e)

Callers 1

acceptMethod · 0.95

Calls 15

acceptMethod · 0.95
check_awaitable_exprMethod · 0.95
get_proper_typeFunction · 0.90
AnyTypeClass · 0.90
isinstanceFunction · 0.85
is_async_defFunction · 0.85
has_coroutine_decoratorFunction · 0.85
does_not_return_valueMethod · 0.80

Tested by

no test coverage detected