-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
stubtest: relax async checking for abstract methods #12343
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
mypy/stubtest.py
Outdated
if isinstance(stub.type, mypy.types.CallableType): | ||
ret_type = mypy.types.get_proper_type(stub.type.ret_type) | ||
should_error = ( | ||
isinstance(ret_type, mypy.types.Instance) | ||
and "__await__" not in ret_type.type.names |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a more idiomatic way of figuring out whether the return type of a method in the stub is a subtype of Awaitable[Any]
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the unused awaitable stuff does something similar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I've modified my PR to add a helper property in mypy.types
to avoid code duplication
This comment has been minimized.
This comment has been minimized.
3 similar comments
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I fully understand this change, but I'm not yet convinced it's better than an allowlist entry. This seems to encourage LSP violations (nitpicky ones, but still — we seem to be trying to tighten up "returns coroutine" vs "returns awaitable" and this muddies the water). Note also that abstractmethods in Python can have implementations, so the use of an async def
in an abstractmethod might have runtime meaning.
I see it as similar to the various synchronous abstract methods where we have a looser signature in the stub than the default implementation at runtime. For example, In the same way, It seems to me that classes with abstract methods are generally going to represent abstract interfaces of some kind. As such, it might often be the case that the default implementation of an abstract method is a coroutine function, even if subclasses are not necessarily expected to implement the method as a coroutine function in order to be considered compatible with the interface. Hence, this PR :) |
If you're still not convinced, feel free to close this, no hard feelings :) |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅ |
class _CustomAwaitable2(Awaitable[Any]): ... | ||
class Foo: | ||
@abstractmethod | ||
def abstract(self) -> _CustomAwaitable: ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we want to allow this? Doesn't seem particularly useful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't remember, and I'm not sure I care anymore. I guess I'll just close this PR :)
Description
As has been pointed out in python/typeshed#7475, the current typeshed definitions for various async methods in the stub for
typing
are problematic.Until recently, these were all "synchronous" methods that returned
Awaitable[X]
. However, they were recently changed to beasync def
methods. This more closely match their definitions at runtime, but is problematic: the classes intyping.pyi
represent abstract interfaces, and it's not true that an object has to return a coroutine from its__anext__
method in order to be considered anAyncIterator
(it just has to return something that's awaitable).Unfortunately, following #12212, stubtest will now emit an error if a method is async at runtime but not in the stub.
I think it makes sense to relax this check for abstract methods, so that's what this PR proposes doing.
Test Plan
Three new test cases added to
teststubtest.py
.cc. @hauntsaninja, @graingert