msg105790 - (view) |
Author: Paul Davis (Paul.Davis) |
Date: 2010-05-15 04:10 |
The docs for __getattr__ in the object model section could be more specific on the behavior when a @property raises an AttributeError and there is a custom __getattr__ defined. Specifically, it wasn't exactly clear that __getattr__ would be invoked after a @property was found and evaluated.
The attached script demonstrates the issue on OS X 10.6, Python 2.6.1
I'm thinking something along the lines of:
If the attribute search encounters an AttributeError (perhaps due to a @property raising the error) the search is considered a failure and __getattr__ is invoked.
|
msg105791 - (view) |
Author: Paul Davis (Paul.Davis) |
Date: 2010-05-15 04:13 |
I should mention, in example.py, it wasn't immediately clear that "print f.bing" would actually print instead of raising the AttributeError. As in, I had a property raising an unexpected error that happend to be an AttributeError. If its not an attribute error, the error is not swallowed. I can see the obvious argument for "AttributeError means not found", it just wasn't immediately obvious what was going on.
|
msg113192 - (view) |
Author: Terry J. Reedy (terry.reedy) *  |
Date: 2010-08-07 19:45 |
The problem with changing 2.7 docs is that object access is different for old- and new-style properties. Does your example work if you remove 'object'? (IE, can old style classes have properties?)
For new-style classes, the example behavior is clear if you 1. know that object has a .__getattribute__ method inherited by everything when not overriden and 2. read the doc for that which says that __getattr__ is called whenever a __getattribute__ call raises AttributeError, which it does here by passing through the .get error.
For 3.x, I think in 3.3.2. Customizing attribute access,
object.__getattr__(self, name)
"Called when an attribute lookup has not found the attribute in the usual places (i.e. it is not an instance attribute nor is it found in the class tree for self). name is the attribute name. "
might be replaced by
"Called when self.__getattribute__(name) raise AttributeError because name is not an instance attribute, not found in the class tree for self, or is a property attribute whose .get() method raises AttributeError."
But this does not work for 2.7.
|
msg113193 - (view) |
Author: Terry J. Reedy (terry.reedy) *  |
Date: 2010-08-07 19:50 |
/raise/raises/
I am pretty sure that when __getattribute__ is bypassed, so is __getattr__.
|
msg113212 - (view) |
Author: Éric Araujo (eric.araujo) *  |
Date: 2010-08-07 21:36 |
Old-style classes can’t have descriptors, hence no properties, static methods, class methods or super.
|
msg307831 - (view) |
Author: Terry J. Reedy (terry.reedy) *  |
Date: 2017-12-08 02:12 |
Cheryl, thank you for reviving this, as it is still needed. A slightly revised example better illustrates the claim in the doc revision about when __getattr__ is called.
class Foo(object):
def __init__(self):
self.foo = 1
self.data = {"bing": 4}
def __getattr__(self, name):
print(f'Getting {name}')
return self.data.get(name)
@property
def bar(self):
return 3
@property
def bing(self):
raise AttributeError("blarg")
f = Foo()
print('foo', f.foo)
print('__str__', f.__str__)
print('bar', f.bar)
print('bing', f.bing)
f.__getattribute__('bing')
# prints
foo 1
__str__ <method-wrapper '__str__' of Foo object at 0x0000016712378128>
bar 3
Getting bing
bing 4
Traceback (most recent call last):
File "F:\Python\a\tem2.py", line 24, in <module>
f.__getattribute__('bing')
File "F:\Python\a\tem2.py", line 17, in bing
raise AttributeError("blarg")
AttributeError: blarg
|
msg307853 - (view) |
Author: Cheryl Sabella (cheryl.sabella) *  |
Date: 2017-12-08 16:32 |
Terry,
Thanks for clarifying with this example. I hadn't tried this when I was playing with the other example. I guess __getattribute__ might be defined by a class, but generally wouldn't be called directly, so the use of __getattr__ and __getattribute__ and the raising of AttributeError is more for an `attributeref` (https://docs.python.org/3/reference/expressions.html#attribute-references) usage?
|
msg307876 - (view) |
Author: Terry J. Reedy (terry.reedy) *  |
Date: 2017-12-09 02:27 |
Before testing, let alone documenting, the status quo, I would like to be sure that suppressing the exception is truly the intended behavior. Is there a way to get an annotated listing from git (given which patch, and therefore which person, is responsible for each line)? I will try asking on pydev.
Calling __getattr__ on property failure is a behavior of __getattribute__, not of the property, and I would expect object.__getattribute__ to be tested wherever object is, but I have not found such tests. If we do add a test, the best model in test_desc.py looks like `def test_module_subclasses(self):`. The test class would only need __getattr__ and the faulty property.
class Foo(object):
def __getattr__(self, name):
print(f'Getattr {name}')
return True
@property
def bing(self):
print('Property bing')
raise AttributeError("blarg")
f = Foo()
print(f.bing)
#prints (which would be the log list in a test)
Property bing
Getattr bing
True
|
msg307877 - (view) |
Author: Terry J. Reedy (terry.reedy) *  |
Date: 2017-12-09 02:29 |
The behavior and doc for __setattr__ and __delattr__ should also be checked.
|
msg307894 - (view) |
Author: Cheryl Sabella (cheryl.sabella) *  |
Date: 2017-12-09 12:25 |
>> Is there a way to get an annotated listing from git (given which patch, and therefore which person, is responsible for each line)?
Which source did you want to look at? In github, if you go into any source, you can click on a line and it gives an option for 'git blame'. That shows the last commit change for each line. You can then click an icon to see a previous commit, etc. For the .rst sources, it's a little different and there is a Blame button at the top of the source that will bring up the same view (commit annotations to the left of the source) as right-clicking.
I had posted about git blame a few months ago on core mentorship and Carol Willing mentioned another tool to get all the changes by line. Here was her post:
Thanks for passing along the tip for others. You may also find the npm package `git-guilt` useful as it will display all the contributors to a particular line's history. https://www.npmjs.com/package/git-guilt <https://www.npmjs.com/package/git-guilt>
|
msg307907 - (view) |
Author: Terry J. Reedy (terry.reedy) *  |
Date: 2017-12-09 18:12 |
Thanks. I normally look at source in my local clone with an editor. I found 'view blame' and 'view blame prior' on github.
|
msg311535 - (view) |
Author: Terry J. Reedy (terry.reedy) *  |
Date: 2018-02-03 05:03 |
Nick, this is about better documenting the behavior of __get(set/del)attr__ in 3.x it relations to AttributeError in a property. I think I understand what it does and think the patch is correct. Could you either review or suggest someone else who better understands core behavior like this?
|
msg311633 - (view) |
Author: Alyssa Coghlan (ncoghlan) *  |
Date: 2018-02-05 02:03 |
New changeset d1f318105b8781b01f3507d5cb0fd841b977d5f2 by Nick Coghlan (Cheryl Sabella) in branch 'master':
bpo-8722: Document __getattr__ behavior with AttributeError in property (GH-4754)
https://github.com/python/cpython/commit/d1f318105b8781b01f3507d5cb0fd841b977d5f2
|
msg311637 - (view) |
Author: Alyssa Coghlan (ncoghlan) *  |
Date: 2018-02-05 03:10 |
New changeset a8c25d1c7f0d395861cc3e10dd01989150891c95 by Nick Coghlan (Miss Islington (bot)) in branch '3.6':
[3.6] bpo-8722: Document __getattr__ behavior with AttributeError in property (GH-5542)
https://github.com/python/cpython/commit/a8c25d1c7f0d395861cc3e10dd01989150891c95
|
msg311638 - (view) |
Author: Alyssa Coghlan (ncoghlan) *  |
Date: 2018-02-05 03:16 |
New changeset fea0a12f6bee4a36b2c9533003e33a12c58d2d91 by Nick Coghlan (Miss Islington (bot)) in branch '3.7':
[3.7] bpo-8722: Document __getattr__ behavior with AttributeError in property (GH-5543)
https://github.com/python/cpython/commit/fea0a12f6bee4a36b2c9533003e33a12c58d2d91
|
msg311640 - (view) |
Author: Alyssa Coghlan (ncoghlan) *  |
Date: 2018-02-05 03:27 |
Thanks for the patch Cheryl, and for the reviews Terry!
|
|
Date |
User |
Action |
Args |
2022-04-11 14:57:01 | admin | set | github: 52968 |
2018-02-05 03:27:03 | ncoghlan | set | status: open -> closed resolution: fixed messages:
+ msg311640
stage: patch review -> resolved |
2018-02-05 03:16:51 | ncoghlan | set | messages:
+ msg311638 |
2018-02-05 03:10:03 | ncoghlan | set | messages:
+ msg311637 |
2018-02-05 02:42:30 | miss-islington | set | pull_requests:
+ pull_request5369 |
2018-02-05 02:41:28 | miss-islington | set | keywords:
+ patch pull_requests:
+ pull_request5368 |
2018-02-05 02:03:25 | ncoghlan | set | messages:
+ msg311633 |
2018-02-03 05:03:04 | terry.reedy | set | versions:
+ Python 3.8 nosy:
+ ncoghlan
messages:
+ msg311535
components:
+ Interpreter Core |
2017-12-09 18:12:31 | terry.reedy | set | keywords:
- patch
messages:
+ msg307907 |
2017-12-09 12:25:16 | cheryl.sabella | set | messages:
+ msg307894 |
2017-12-09 09:30:13 | berker.peksag | set | keywords:
+ patch |
2017-12-09 02:29:44 | terry.reedy | set | messages:
+ msg307877 |
2017-12-09 02:27:28 | terry.reedy | set | messages:
+ msg307876 |
2017-12-08 16:32:03 | cheryl.sabella | set | nosy:
+ cheryl.sabella messages:
+ msg307853
|
2017-12-08 02:12:48 | terry.reedy | set | messages:
+ msg307831 |
2017-12-08 01:27:13 | cheryl.sabella | set | keywords:
+ needs review, - patch versions:
+ Python 3.6, Python 3.7, - Python 3.1, Python 2.7, Python 3.2, Python 3.3 |
2017-12-08 01:25:20 | cheryl.sabella | set | stage: needs patch -> patch review pull_requests:
+ pull_request4657 |
2011-03-09 02:39:38 | terry.reedy | set | nosy:
terry.reedy, dstanek, eric.araujo, docs@python, Paul.Davis versions:
+ Python 3.3 |
2010-08-18 00:14:47 | dstanek | set | nosy:
+ dstanek
|
2010-08-07 21:36:07 | eric.araujo | set | nosy:
+ eric.araujo messages:
+ msg113212
|
2010-08-07 19:50:06 | terry.reedy | set | messages:
+ msg113193 |
2010-08-07 19:45:18 | terry.reedy | set | versions:
- Python 2.6 nosy:
+ terry.reedy
messages:
+ msg113192
keywords:
+ patch stage: needs patch |
2010-07-11 02:18:07 | terry.reedy | set | versions:
+ Python 3.1, Python 2.7, Python 3.2 |
2010-05-15 04:13:32 | Paul.Davis | set | messages:
+ msg105791 |
2010-05-15 04:10:57 | Paul.Davis | create | |