-
Notifications
You must be signed in to change notification settings - Fork 249
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 conformance test for @final
combined with @property
#1916
base: main
Are you sure you want to change the base?
Conversation
The language of the typing spec indicates that the @Final decorator may be used with properties: > The method decorator version may be used with all of instance methods, class methods, static methods, and properties. I noticed this case while working on Pyre. I observed that Mypy and Pyright also differ in behavior, so it seemed like a good conformance test to add. See discussion here: https://discuss.python.org/t/proposal-allow-chaining-final-decorator-when-previous-decorators-return-a-non-function/78918
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.
Looks good, although I think conformance in pyright/qualifiers_final_decorator.toml should be updated to match the new conformance_automated value
@@ -1,4 +1,4 @@ | |||
conformant = "Pass" | |||
conformant = "Fail" |
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.
This should say "Partial", not "Fail".
Thanks for reporting this and adding the conformance test. FYI, I've filed the following bug in the pyright issue tracker: microsoft/pyright#9795. |
aa381ae
to
f4d1db6
Compare
Thanks for the guidance! |
I guess always a risk changing a pyright conformant value, because odds are 50/50 that Eric will have fixed it before the PR is merged :-) |
@@ -66,6 +66,22 @@ implementation (or on the first overload, for stubs):: | |||
def method(self, x=None): | |||
... | |||
|
|||
The ``@final`` decorator can be combined with previous decorators, like |
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.
Somebody on Discuss brought up that perhaps you should put @property
above @final
. Do we need to specify that explicitly?
For classmethod
+ final
, currently both mypy and pyright allow putting the decorators in any order.
My preference would be to make the spec say explicitly that either order is allowed and add conformance tests for it.
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.
What is the correct behavior if a property getter is marked final but a setter or deleter is not (or vice versa)? I ask because the different ordering would seem to imply different behaviors. Does the final
apply to the property
object or the method that is wrapped by the property?
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 it's a good point that the spec text here it too specific ("previous" implies an order, should read "other").
On the other hand, I think it gets a bit too precise to enumerate orders. In Pyre (and I suspect Pyright too) the non-conformance arises from attaching the decorator metadata directly to a function type, so a chained decorator that returns a non-function runs into problems.
In terms of typing, the @property
and @final
signatures compose in either order, so I think it's clear that the definition is legal in either order.
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.
What is the correct behavior if a property getter is marked final but a setter or deleter is not (or vice versa)? I ask because the different ordering would seem to imply different behaviors. Does the
final
apply to theproperty
object or the method that is wrapped by the property?
This is a great question. I don't feel strongly, but one option:
- The
final
-ness applies to the slot on the class, not the type itself (property descriptor or otherwise) - If the final property is a descriptor, then the setter should not be called on that type (either through
p: Final = Descriptor()
or@final
-decorated descriptor) - [Edited to add] Specifically for the
@property
descriptor, defining a setter/deleter is an error when final.
The language of the typing spec indicates that the
@final
decorator may be used with properties:I noticed this case while working on Pyre. I observed that Mypy and Pyright also differ in behavior, so it seemed like a good conformance test to add.
See discussion here:
https://discuss.python.org/t/proposal-allow-chaining-final-decorator-when-previous-decorators-return-a-non-function/78918
I also added an example to the spec itself. I think it's a practical example, but also happy to remove it as well, since the existing content makes it pretty clear that the example should be allowed.