Re: [Zope-dev] Intercepting __getattr__ in a Python 2.3 old-style mixin class?
Python 2.7 is different because all classes are automatically new-style classes. In Python 2.7 you would have to overwrite __getattribute__() but I am on Python 2.3 here. And I have to stay on Python 2.3 for now…welcome to hell :-) Andreas On 7 Nov 2016, at 13:23, Michael Howitz wrote:
Am 07.11.2016 um 13:01 schrieb Andreas Jung <lists@zopyx.com>:
I have a large Python 2.3 based installation with 200k LOC. As part of a migration project I need to intercept all attribute lookups of all old-style class.
Old legacy code:
class Foo(Bar): ...
My idea is to inject a common mixin class like
class Foo(Bar, Mixin): ...
class Mixin:
def __getattr__(self, k) print repr(self), k return Foo.__getattr__(self, k)
Hi Andreas,
I doubt that your approach works. Attributes defined on `Foo` are _not_ resolved using __getattr__. See the following example using Python 2.7:
In [1]: 1 class A: 2 x = 'foo' 3 def __getattr__(self, key): 4 return 'bar'
In [2]: a = A()
In [3]: a.x Out[3]: 'foo'
In [4]: a.b = 'b'
In [5]: a.b Out[5]: 'b'
Maybe I am missing something here.
-- Mit freundlichen Grüßen Michael Howitz
On Mon, Nov 7, 2016, at 14:01, Andreas Jung wrote:
Python 2.7 is different because all classes are automatically new-style classes. In Python 2.7 you would have to overwrite __getattribute__() but I am on Python 2.3 here.
No :) In Python 3 all classes are new-style classes. In Python 2 (including 2.7) you have to be explicit and either inherit from object (new-style) or not (old-style). In Python 2.7 you get:
class A: pass class B(object): pass type(A) <type 'classobj'> type(B) <type 'type'>
In Python 3 both are of type 'type'. And only new-style classes use '__getattribute__'. '__getattr__' is the right approach for old-style classes in any Python 2 version, even in Python 2.7. Hanno
Hi Andreas, As Hanno said, you'll still be in old-style-classes-land even in Python 2.7 unless you inherit from `object` directly. You said: My idea is to inject a common mixin class like
class Foo(Bar, Mixin): ... class Mixin: def __getattr__(self, k) print repr(self), k return Foo.__getattr__(self, k)
Your recursion error is caused by calling `Foo.__getattr__(self, k)` from `Mixin`, but `Foo` inherits from `Mixin`. Calling a method of a subclass from the same-named method in the superclass is a recurssion. Instead `Mixin` needs to call `Bar.__getattr__` since `Bar` is the superclass to `Foo`. Alternatively, if you don't want to name any specific superclass inside the mixin method, (and since you can't use `super()` since you're using old-style classes), I suggest a different approach. Instead of a mixin class, use a method factory, like this: def my__getattr__factory(SuperClass):
def __getattr__(self, k): print repr(self), k return SuperClass.__getattr__(self, k)
Which you can then use as: class Foo(Bar): # <- No mixin
__getattr__ = my_getattr__generator(Bar) # <- Bar, not Foo
Regards, Leo On 7 November 2016 at 12:29, Hanno Schlichting <hanno@hannosch.eu> wrote:
On Mon, Nov 7, 2016, at 14:01, Andreas Jung wrote:
Python 2.7 is different because all classes are automatically new-style classes. In Python 2.7 you would have to overwrite __getattribute__() but I am on Python 2.3 here.
No :)
In Python 3 all classes are new-style classes. In Python 2 (including 2.7) you have to be explicit and either inherit from object (new-style) or not (old-style).
In Python 2.7 you get:
class A: pass class B(object): pass type(A) <type 'classobj'> type(B) <type 'type'>
In Python 3 both are of type 'type'.
And only new-style classes use '__getattribute__'. '__getattr__' is the right approach for old-style classes in any Python 2 version, even in Python 2.7.
Hanno _______________________________________________ Zope-Dev maillist - Zope-Dev@zope.org https://mail.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - https://mail.zope.org/mailman/listinfo/zope-announce https://mail.zope.org/mailman/listinfo/zope )
participants (3)
-
Andreas Jung -
Hanno Schlichting -
Leonardo Rochael Almeida