-
-
Notifications
You must be signed in to change notification settings - Fork 3k
MyPy v1.t6.0 cannot infer a descriptor's type through a Protocol
which v1.15.0 supports
#19274
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
Comments
Is it the same issue as below? from typing import Any, Protocol, overload
class Descriptor:
@overload
def __get__(self, obj: None, objtype: Any) -> "Descriptor": ...
@overload
def __get__(self, obj: object, objtype: Any) -> int: ...
def __get__(self, obj, objtype): ...
class Foo:
example = Descriptor()
class FooP(Protocol):
example: Descriptor
oc = Foo()
oc2: FooP = oc
reveal_type(oc.example)
reveal_type(oc2.example) https://mypy-play.net/?mypy=latest&python=3.12&flags=strict&gist=62b88bc128305716903821b1b3333f29 I'm not exactly sure what should protocol members annotated with descriptors mean, TBH. @ilevkivskyi was this change intentional? Bisects to #18831 |
Whoops, sorry, you already answered. Closing as duplicate of #19054 (sorry, I somehow missed that one entirely...) |
Yes, this is an intentional change. For long time mypy didn't support descriptors in protocols, so unfortunately some people used a workaround of writing descriptor type directly in the protocol. The motivation for the change is that protocols only specify the interface, so that we can reason about e.g. modules and class objects as implementation of protocols. By default, something like this class P(Protocol):
attr: SomeType is equivalent to this in a regular class: class C:
def __init__(self) -> None:
self.attr: SomeType Now (on current master) you should be able to write simply this: class HasExampleOption(Protocol):
example: int However, now I am thinking we should probably also allow something like this: class HasExampleOption(Protocol):
example: ClassVar[ExampleOption] Let me play a bit with this. |
@ilevkivskyi |
I am not sure what do you mean? On current master I get an error in |
Ough, I definitely need another coffee. Yes, works as intended on master, it's only 1.16 that is broken. Perhaps consider releasing 1.16.1 (either with some PRs cherry-picked or just from current master if there aren't any huge breaking changes)? Aside, I still think your |
Yeah, I will probably make a PR soon. Btw another thing is that last few days I was looking into the whole class variable vs instance variable story, and it is really messy. (And this is because in Python the distinction is blurry, similar to how we have enormous amount of complexity because positional-or-keyword arguments.) Maybe I would go as far as suggesting this is a topic for the typing council discussion. We should have some clear rules for:
|
For now I think we can do something like #19277 |
Thanks for the explanations! Some data points for any future work here:
( Thus, the owner class is no longer compliant with the protocol when switching the type of the descriptor in the protocol like that. |
Could you check the same using |
Tested with |
i will make a 1.16.1 bugfix release soon, but I think it won't include a fix to this issue. However, we are planning to start work on the 1.17 feature release pretty soon (hopefully within a week, but we'll see). |
Ref #19274 This is a bit ugly. But I propose to have this "hot-fix" until we have a proper overhaul of instance vs class variables. To be clear: attribute access already works correctly (on both `P` and `Type[P]`), but subtyping returns false because of ```python elif (IS_CLASSVAR in subflags) != (IS_CLASSVAR in superflags): return False ```
Uh oh!
There was an error while loading. Please reload this page.
MyPy v1.t6.0 is no longer able to infer a descriptor's type through a
Protocol
which it could do in v1.15.0.To Reproduce
The following code is a simplified form of the Pantsbuild option system in this file.
(This code could probably be further simplified, but is sufficient to reproduce the bug. )
Expected Behavior
The expected behavior is that the access through the
HasExampleOption
protocol to theexample
attribute has typeint
. Here is the output when running v1.15.0 against the code:Actual Behavior
v1.16.0 regresses and reports the type of
example
as the descriptor's classExampleOption
and not asint
:Your Environment
mypy.ini
(and other config files): noneThe text was updated successfully, but these errors were encountered: