| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
|
I suspect that the reason is the Any types in type context in visit_await_expr. The type context should be derived from the type context of the await expression, perhaps. If the type context is X[Any], then mypy tries to infer type X[Any] for the expression, which is happening in the f() case. |
Sorry, something went wrong.
Ensure 'async def' is a syntax error in Python 2 (at least with the fast parser).
|
Taking a look at this now! |
Sorry, something went wrong.
| def visit_Index(self, n: ast35.Index) -> Node: | ||
| return self.visit(n.value) | ||
|
|
||
| # PEP 492 nodes: 'async def', 'await', 'async for', 'async with'. |
There was a problem hiding this comment.
This is a nit, but it'd be better if these were left in their original locations rather than separated out. Currently, the visit_* functions in this file are in the same order as the nodes in the Python.asdl, which is a nice property to maintain. Also, most of them are virtually identical to the non-async versions -- having them right next to each other will make it more likely they stay in sync.
Sorry, something went wrong.
There was a problem hiding this comment.
Sorry, something went wrong.
is_generator_return_type() now takes an extra is_coroutine flag.
| self.fail("'yield' in async function", expr, True, blocker=True) | ||
| else: | ||
| self.function_stack[-1].is_generator = True | ||
| if expr.expr: |
There was a problem hiding this comment.
Await is required to have an expr, right?
Sorry, something went wrong.
This revealed a spurious error "Function does not return a value", fixed that.
| # | ||
| # A classic generator must define a return type that's either | ||
| # `Generator[ty, ts, tr]`, Iterator[ty], or Iterable[ty] (or | ||
| # object or Any). If ts/tr are not given, both are Any. |
There was a problem hiding this comment.
I thought they were both None?
Sorry, something went wrong.
There was a problem hiding this comment.
Actually in the code below ts is Void, tr is Any. But I wonder if it isn't better to make both None -- forcing developers to declare the return type as Generator[ty, ts, tr] if they want to either receive or return values. There's a unit test that currently checks that return value is allowed in a generator declared as Iterator but I think I'll just change that too.
Sorry, something went wrong.
| elif return_type.type.fullname() == 'typing.Awaitable': | ||
| # Awaitable is the other type which specifies the type of values it returns into | ||
| # `yield from` expressions (using `return`). | ||
| if len(return_type.args) == 1: |
There was a problem hiding this comment.
Do you need this check? Doesn't an Awaitable always have a type parameter?
Sorry, something went wrong.
There was a problem hiding this comment.
IIUC when you use a generic class without parameters args is empty. I also worry about crashes when someone writes e.g. Generator[int] -- it may well produce an error message but also an Instance with len(args) == 1, so I'm doing this defensively.
Sorry, something went wrong.
There was a problem hiding this comment.
That seems reasonable. We should probably consider filling in the parameters at some earlier stage so we can later rely on the length...
Sorry, something went wrong.
… regular. Also Use get_generator_return_type() instead of manually unpacking the value.
|
Pushed responses to most of the review. I actually still haven't figured out how to extract the type parameter from a subclass of Awaitable[T](if it's even possible). I also found that the error message you get when the return type for __aenter__ or __aexit__ is wrong you get a pretty poor error message (just "Incompatible types"). I suspect it's much the same for async for. (But there's nice custom formatting code for the error coming out of await -- I probably need to refactor things to reuse more.) |
Sorry, something went wrong.
|
@ddfisher that's all I planned to do in this PR -- another review please? |
Sorry, something went wrong.
| return return_type.args[2] | ||
| else: | ||
| return AnyType() | ||
| elif return_type.type.fullname() == 'typing.Awaitable': |
There was a problem hiding this comment.
Do you still use this now that you have get_awaitable_return_type?
Sorry, something went wrong.
There was a problem hiding this comment.
get_awaitable_return_type() is for getting the type of the expression in await, async for and async def. get_generator_return_type() is for the return statement inside a generator or async def.
Sorry, something went wrong.
There was a problem hiding this comment.
Ah, I see. get_awaitable_return_type shouldn't have a parallel name, then. It'd also be nice to mention that in the docstrings -- those are also virtually identical at the moment.
Sorry, something went wrong.
|
The Awaitable parts of get_generator_yield_type and get_generator_recieve_type are never used anywhere. Are they necessary? With that in mind, maybe it makes sense to split out the Awaitable part of get_generator_return_type? |
Sorry, something went wrong.
| else: | ||
| # `return_type` is supertype of Generator, so callers won't be able to see the return | ||
| # type when used in a `yield from` expression. | ||
| return Void() |
There was a problem hiding this comment.
Can we not make this change as part of this diff?
Sorry, something went wrong.
There was a problem hiding this comment.
OK.
Sorry, something went wrong.
|
Finished with review! |
Sorry, something went wrong.
|
Just one remaining nit around the naming/documentation of get_awaitable_return_type. |
Sorry, something went wrong.
|
OK, done.
|
Sorry, something went wrong.
|
Thanks! Now I'll start with the follow-on PR...
|
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
This is not ready for merge, but I have a question. [UPDATE: it is ready!]
@JukkaL Why would these two functions not be equivalent?
from typing import * T = TypeVar('T') async def f(x: T) -> T: y = await f(x) reveal_type(y) return y async def g(x: T) -> T: gx = g(x) y = await gx reveal_type(y) return yIn f(), the revealed type is Any, while in g() it is T (spelled as 'T-1'). I would expect it to be T` in both cases.