GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||||||||||||||||||
GeezerVison is showing github.com — bpo-46730: Add more info to @property AttributeError messages by Alex-Blade · Pull Request #31311 · python/cpython Conversation
|
|
Hello, and thanks for your contribution! I'm a bot set up to make sure that the project can legally accept this contribution by verifying everyone involved has signed the PSF contributor agreement (CLA). CLA MissingOur records indicate the following people have not signed the CLA: For legal reasons we need all the people listed to sign the CLA before we can look at your contribution. Please follow the steps outlined in the CPython devguide to rectify this issue. If you have recently signed the CLA, please wait at least one business day You can check yourself to see if the CLA has been received. Thanks again for the contribution, we look forward to reviewing it! |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Now, there are a few things to discuss: I absolutely agree with it, since it was the initial idea, however when trying it I've found out that the testing system expects the name of the attribute to be at the end: So in order to make the message in the proposed format, this should be subject to change as well. P.S. I have signed the CLA, just haven't got the response yet. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
I think those test cases can be adjusted appropriately to match the behavior.
Yep, it usually takes a business day or two to go through. I also think it would be useful to include the type name in the message: Compare to the current behavior for other attributes in other situations: I believe this is the relevant code for that case: Lines 1405 to 1407 in 6331c08
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Using |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
Isn't >>> from collections import defaultdict >>> dict.pop is defaultdict.pop True >>> dd = defaultdict() >>> dd.pop = 42 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'collections.defaultdict' object attribute 'pop' is read-only And there are parallel situations like this: >>> class Base: ... def __float__(self): ... return None ... >>> class Sub(Base): ... pass ... >>> float(Sub()) Traceback (most recent call last): File "<pyshell#28>", line 1, in <module> float(Sub()) TypeError: Sub.__float__ returned non-float (type NoneType) My thinking is that specifying the type is helpful for identifying which objects in the client code are being used and which line to look at, not where the implementation happens to live: >>> class BaseThingDoer: ... @property ... def attr(self): ... pass >>> # ( ... Suppose lots of other concrete implementations ... ) >>> class SpecialThingDoer(BaseThingDoer): ... pass >>> thing = SpecialThingDoer() # These two lines are the lines I'm looking at. >>> thing.attr = 42 # I think I would expect the error message to say SpecialThingDoer. AttributeError: can't set attribute 'attr' It's safer and easier to implement if I understand right. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
This is an improvement to the initial patch for the bpo-46730. It adds additional information on class that owns the property that caused an AttributeError.
|
@sweeneyde, I think your idea doesn't solve the problem of "which line to look at" because of subclasses. class A: @property def a(self) -> int: return None class B(A): @property def b(self) -> int: return None class C(B): pass >>> A().a = 2 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: property 'a' originating from 'A' has no setter >>> B().a = 2 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: property 'a' originating from 'A' has no setter >>> B().b = 2 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: property 'b' originating from 'B' has no setter >>> C().b = 2 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: property 'b' originating from 'B' has no setter Few points to discuss though:
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Oh, actually I think I've misunderstood your comment. To the example of Perhaps this could be resolved by choosing the sentence for the error message:
This one implies that the problem is within the current object and thus
And this one implies that the property is the problem and it should be fixed wherever it's defined - in I don't see any convenience difference, however implementing the first one requires less changes, resolves the issue with sketchiness of the first attempt and removes unnecessary size increase. Seems like I should retry it :) |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
I think I agree with lots of your assessments -- either type might be more helpful in different circumstances. But for simplicity of implementation and consistency with other similar situations, I'd prefer to just display the type of I don't know what the best verbiage is to convey that that's what is being displayed, but I agree that some word choices are more suggestive of that than others. Maybe something like what Bruce Leban suggested on Python-Ideas, or Another reason to avoid adding extra state to the property is that the same property object can theoretically live in multiple classes: |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
The misleading behaviour when a property is in two classes isn't really solvable, and also applies if you put it under a different attribute name - functions have the same issue. Since the decorator methods create copies, it's probably not too big of an issue. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
I'm suggesting that it is "solvable" in one sense: just don't store inside a |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
I've assessed all variants and came to a conclusion that a combination of all our suggestions would work great: class A: @property def a(self) -> int: return None class B(A): @property def b(self) -> int: return None B().b = 2 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: property 'b' in object of type 'B' has no setter B().a = 2 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: property 'a' in object of type 'B' has no setter
UPD. And yes, it's based on qualname |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
This is mostly looking good, just some minor nits remaining.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Properly escape dot character and return `_format_exc_msg` function to its initial state.
|
I have made the requested changes; please review again P.S. Seems like I also should make a NEWS entry, right? |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Thanks for making the requested changes! @sweeneyde: please review the changes made to this pull request. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Yes, please do. You can either click on "Details" of the bevedere/news check or you can use blurb |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
LGTM. I'll leave it open for a day or so to see if there are any more comments, but after that, I can merge.
If you want, you can add your name to MISC/ACKS as well.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
Shouldn't "object %R" be "%R object"? 42 is an int object, not object int. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Oh, that's what caused my confusion and I couldn't understand it! :) |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
@eryksun, what do you think now? |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
I'm okay with either "property %R of %R objects" or "property %R of %R object". I prefer the former. It's common in English when generalizing to a category or class of things, unless that class is already a mass noun. You can see this style used in "Objects/descrobject.c":
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Reasonable people will disagree, but the pattern I see is that usages of the plural as in "{p} for {T} objects" tend to be situations where the descriptor knows what type it's supposed to apply to, but there is no well-defined notion of "the associated type" for property objects, since you can do In contrast, other error messages tend to use the singular "object" when they display the type of the particular object in question (as this PR is set to do): |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
The commit introduced a reference leak and code was missing checks for NULL. #31389 addresses both problems. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.