-
Notifications
You must be signed in to change notification settings - Fork 23
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
Add Y036: check for badly-defined __(a)exit__
methods
#199
Conversation
There is one remaining typeshed hit, which I'm not quite sure what to do with: The check I've written argues that it should be rewritten: def __exit__(self, *args: Any) -> Any: ... # OLD
def __exit__(self, *args: object) -> Any: ... # NEW The only thing is, this method is part of a protocol definition. I'm not sure whether it's important to keep it as it is or not. I think it would probably be fine? But also protocols generally need more permissive definitions for argument types. So, I'm not sure. If we decide not to change that method in typeshed, we have two options:
|
@@ -972,6 +1052,103 @@ def visit_ClassDef(self, node: ast.ClassDef) -> None: | |||
): | |||
self.error(statement, Y013) | |||
|
|||
def _check_exit_method( # noqa: C901 |
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.
On the one hand, I agree with flake8 that this is quite complicated. On the other hand, it's good because all exit method checking is in the same place.
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.
Yes. I tried splitting it up, and, in my opinion, it made the code much less readable.
Co-authored-by: Akuli <akuviljanen17@gmail.com>
The typeshed hit seems buggy. Isn't it saying that for an object to be compatible with that protocol, it must have an exit method that accepts any number of arguments? To test this, I made this toy example: from types import TracebackType
from typing import Any
from typing_extensions import Protocol
class AbstractFoo(Protocol):
def __exit__(self, *args: Any) -> None: ...
class ConcreteFoo(AbstractFoo):
def __exit__(self, typ: type[BaseException] | None, exc: BaseException | None, tb: TracebackType | None) -> None:
print("Hi")
f: AbstractFoo = ConcreteFoo() Mypying it fails with:
|
I get that and it's fine, but |
Hah, good point. So the stub is broken anyway. |
Yeah sorry, I misread your message :) |
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.
One more nit.
Co-authored-by: Akuli <akuviljanen17@gmail.com>
The signature of this method currently doesn't work quite as intended: see PyCQA/flake8-pyi#199 (comment) Classes will [still be accepted](https://mypy-play.net/?mypy=latest&python=3.10&gist=77efe095d01edeb1a4614166f0c9cf68) as conforming to this protocol if they have more permissive signatures such as `def __exit__(self, *args: object) -> None: ...`
The signature of this method currently doesn't work quite as intended: see PyCQA/flake8-pyi#199 (comment) Classes will [still be accepted](https://mypy-play.net/?mypy=latest&python=3.10&gist=77efe095d01edeb1a4614166f0c9cf68) as conforming to this protocol if they have more permissive signatures such as `def __exit__(self, *args: object) -> None: ...`
Thanks for the reviews! |
Fixes #188