On Oct 24, 9:58 am, Peter Otten <[EMAIL PROTECTED]> wrote: > Rafe wrote: > > On Oct 24, 2:21 am, Christian Heimes <[EMAIL PROTECTED]> wrote: > >> Rafewrote: > >> > Hi, > > >> > I've encountered a problem which is making debugging less obvious than > >> > it should be. The @property decorator doesn't always raise exceptions. > >> > It seems like it is bound to the class but ignored when called. I can > >> > see the attribute using dir(self.__class__) on an instance, but when > >> > called, python enters __getattr__. If I correct the bug, the attribute > >> > calls work as expected and do not call __getattr__. > > >> > I can't seem to make a simple repro. Can anyone offer any clues as to > >> > what might cause this so I can try to prove it? > > >> You must subclass from "object" to get a new style class. properties > >> don't work correctly on old style classes. > > >> Christian > > > All classes are a sub-class of object. Any other ideas? > > Hard to tell when you don't give any code. > > >>> class A(object): > > ... @property > ... def attribute(self): > ... raise AttributeError > ... def __getattr__(self, name): > ... return "nobody expects the spanish inquisition" > ...>>> A().attribute > > 'nobody expects the spanish inquisition' > > Do you mean something like this? I don't think the __getattr__() call can be > avoided here. > > Peter
Peter nailed it, thanks! I thought __getattr__ was a symptom, not a cause of the misleading exceptions. Here is a complete repro: The expected behavior... >>> class A(object): ... @property ... def attribute(self): ... raise AttributeError("Correct Error.") >>> A().attribute Traceback (most recent call last): File "<console>", line 0, in <module> File "<console>", line 0, in attribute AttributeError: Correct Error. The misleading/unexpected behavior... >>> class A(object): ... @property ... def attribute(self): ... raise AttributeError("Correct Error.") ... def __getattr__(self, name): ... cls_name = self.__class__.__name__ ... msg = "%s has no attribute '%s'." % (cls_name, name) ... raise AttributeError(msg) >>> A().attribute Traceback (most recent call last): File "<console>", line 0, in <module> File "<console>", line 0, in __getattr__ AttributeError: A has no attribute 'attribute'. Removing @property works as expected... >>> class A(object): ... def attribute(self): ... raise AttributeError("Correct Error.") ... def __getattr__(self, name): ... cls_name = self.__class__.__name__ ... msg = "%s has no attribute '%s'." % (cls_name, name) ... raise AttributeError(msg) >>> A().attribute() # Note the '()' Traceback (most recent call last): File "<console>", line 0, in <module> File "<console>", line 0, in attribute AttributeError: Correct Error. The docs seem to suggest this is impossible: "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. This method should return the (computed) attribute value or raise an AttributeError exception." Can anyone explain why this is happening? Is it a bug? I can write a workaround to detect this by comparing the attribute name passed __getattr__ with dir(self.__class__) = self.__dict__.keys(), but how can I raise the expected exception? Thanks, - Rafe -- http://mail.python.org/mailman/listinfo/python-list