> This would create a boundary, same as PEP 479 does for StopIteration,
> across which AttributeError becomes RuntimeError.
Although my problem is about property as I don't use descriptor here, I think descriptor other than property should also be considered, such as classmethod/staticmethod, and normal descriptor. Raising "RuntimeError: descriptor raised AttributeError" is acceptable for me, but maybe some c code need modification, I don't know.

> Do you have any examples that actually do demonstrate the problem to be solved?
So you want more details about AttributeError in property? I thought property is widely used, and AttributeError occurs at all times. Maybe I've used property too heavy.
In the window example, a simplified demonstration:

class Window():
    @property
    def backgroundImg(self):
        if self._backgroundImg is None: #need update, while the number of items changes
            self.set_backgroundImg()
        return self._backgroundImg

    def set_backgroundImg(self):
        self._backgroundImg = loadImg('white.bmp')
        for widget in self.widgets:
            widget.show(self._backgroundImg)

Class Widget():
    def show(self, img):
        img.draw(self.item.img, self.pos)

However, widget.item may be None, while e.g. there are four widgets but only three items in total. In this case I should fill the area with white. But in this version of show, I just FORGET item can be None. So the traceback infomation: 'Window' object has no attribute 'backgroundImg'. In fact it takes a while before I find the cause is the AttributeError/__getattr__ mechanism.

> But surely breaking that isn't the same as breaking code that's been explicitly stated to work, and used as sample code, for decades.
I don't know this is such a severe problem. I used to think raising AttributeError in __getattribute__ to trigger __getattr__ is rare.

> any solution that can fix descriptors without also "fixing" __getattribute__ is a lot better
In practice I don't concern __getattribute__. But in my opinion it's better to 'fix' this in python4.

> all of your solutions make it too hard to trigger __getattr__ from a descriptor when you really _do_ want to do so
This is a big problem, OK.

> You didn't comment on the alternative I suggested; would it not satisfy your needs, or have some other problem that makes it unacceptable?
I don't quite understand, you mean adding a subclass of object with the only difference of this behavior?

2015-11-28 5:37 GMT+08:00 Andrew Barnert <abarnert@yahoo.com>:
On Nov 27, 2015, at 12:18, 王珺 <wjun77@gmail.com> wrote:

I think the real world use case, as property is so common, is just when __getattr__ needed. So anyone using __getattr__ in practice?

Your own examples seem like reasonable uses of __getattr__ to me. But they don't demonstrate your problem, because you don't have any properties, other custom descriptors, or __getattribute__. Do you have any examples that actually do demonstrate the problem to be solved?

> Is that really an imperfection? It says right there in the docs for __getattribute__ that you can delegate to __getattr__ by raising AttributeError
Just like raising StopIteration in generator, as described in PEP479.

But the docs didn't recommend raising StopIteration to exit a generator. The docs implied it by omission, or at least we're ambiguous about what would happen, and you could test it and see that it did, which meant some people took advantage of it to do things like using a StopIteration-throwing function in a comprehension filter clause (with caveats about listcomp vs. genexpr and 2.x vs. 3.x and most readers having to guess why it works). But surely breaking that isn't the same as breaking code that's been explicitly stated to work, and used as sample code, for decades.

Although I'm not sure StopIteration has ever been documented as one way to exit generator. And I admit that an unintentional AttributeError in __getattribute__ is a rare case if ever.

That's my point: "fixing" __getattribute__ to eliminate a "rare case if ever" bug, while also introducing a possibly less-rare backward compatibility problem, seems like a terrible idea. Of course that isn't your intention; it's just a side effect of trying to eliminate a more common bug, with probably rarer intentional uses, in descriptors. But to me, that implies that any solution that can fix descriptors without also "fixing" __getattribute__ is a lot better. And, as you imply in the bug report, this could be done by having either the descriptor mechanism itself, or the object.__getattribute__ implementation, handle AttributeError from descriptor lookup by reraising it as something else.

But still, this is all a minor side issue about choosing between your different variations. The big problem is that I think all of your solutions make it too hard to trigger __getattr__ from a descriptor when you really _do_ want to do so. Maybe you don't want to do so very often, but is it really so rare that we can justify making it impossible? (Especially considering the backward-compat issues for any code that's been doing that for years...)

You didn't comment on the alternative I suggested; would it not satisfy your needs, or have some other problem that makes it unacceptable?

2015-11-28 2:34 GMT+08:00 Andrew Barnert <abarnert@yahoo.com>:
It seems like you can get some of the benefits of this proposal without backward compat issues.

Instead of changing things so AttributeError from __getattribute__ or a descriptor no longer calls __getattr__, just add a new subclass that doesn't, and change the Descriptor HOWTO to suggest using that subclass (with a bit of discussion that says you can use AttributeError if you want to trigger __getattr__, but usually you won't).

That wouldn't fix any current code, but it also wouldn't break any code that intentionally uses the features as documented. And it would make it easy to write correct new code.

One more thing:
Without descriptor, unexpected AttributeError could only come from overriding __getattribute__, which is a rare case, although still an imperfection.
Is that really an imperfection? It says right there in the docs for __getattribute__ that you can delegate to __getattr__ by raising AttributeError, so if someone does that, presumably it's intentional. It's not like the case with descriptors, where you have to think through the interaction of multiple features to figure out that raising an AttributeError will call __getattr__, and therefore many such uses are probably bugs.

Sent from my iPhone

On Nov 27, 2015, at 09:49, 王珺 <wjun77@gmail.com> wrote:

Hello everyone:

I'm suggesting a modification to the AttributeError/__getattr__ mechanism, see issue25634:
http://bugs.python.org/issue25634

I used __getattr__ sometimes, and descriptor especially property is so widely used. I wonder whether someone had encountered the same problem with me.

However, this is a complicated problem including performance issues, and backward compatibility.

Thanks for your attention,
Jun Wang
_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/