-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Class attribute inheritance regression in 1.1.324 #5792
Comments
This was an intentional change, so I don't consider it a bug or a regression. It is a bug fix for #5686. This is also an open bug in the mypy issue tracker. When the Python runtime processes an attribute access on a class (such as class Meta(type):
@property
def some_attr(cls) -> str:
return "Meta"
other_attr = "Meta"
class Foo(metaclass=Meta):
other_attr = 0
print(Foo.some_attr) # This prints "Meta"
print(Foo.other_attr) # This prints 0
class Bar(Foo):
some_attr = 1
other_attr = 2
print(Bar.some_attr) # This prints "Meta"
print(Bar.other_attr) # This prints 2 Prior to 1.1.324, pyright was not correctly modeling the runtime behavior. Now it does. |
Oh, this is indeed surprising. Just tested here and you are correct regarding how the runtime behaves. So, on Django itself this is not actually a descriptor, The reason the stub is using a Doing some tests here I think the stubs can be typed as Thanks for the explanation about this! |
The way CPython works at runtime is to give a higher priority to the metaclass descriptors than the ones in the class itself. Pyright 1.1.324 adjusted that but made our `.objects` typing break when using our own custom managers. Nowadays we can use `Self` for that, which not only is more elegant but also solves this issue in a way that both mypy and pyright can resolve correctly. Related issues: - microsoft/pyright#5792 - microsoft/pyright#5686
This is a minimal reproduction to the issue I'm seeing in my django projects:
pip install django django-types
to test this codeBefore 1.1.323 this, this would be the output of pyright for this code:
On 1.1.324 this is the output:
OtherModel.objects
is ignoring theobjects
override in it and using its parent one, that comes from its metaclass: https://github.com/sbdchd/django-types/blob/main/django-stubs/db/models/base.pyi#L39A smaller reproduction example would be this, which doesn't rely on django but mimics what is happening in the previous example:
Before 1.1.323 this, this would be the output of pyright for this code:
On 1.1.324 this is the output:
The text was updated successfully, but these errors were encountered: