On Sun, Mar 9, 2008 at 5:54 AM, Greg Ewing <[EMAIL PROTECTED]> wrote: > Anthony Tolle wrote: > > As for a more concrete example, imagine the wrapper using the inspect > > module to gather some information about the stack frame and passing it > > along to selected methods. > > That's still not very concrete. It doesn't demonstrate > why you would want to find out that particular piece of > information. >
Ok, I have something that I hope is concrete enough. It is (yet another) version of autosuper that I put together for Python 2.5, since it doesn't have the magic version of super() from 3.0. Rather than write a new super function, I wanted to write something that would work by inserting the correct value of super into the argument list. In fact, this script is why I brought up the whole discussion. Now, while the point of the script itself is moot in version 3.0, it is still a concrete example of what I've been discussing. When I realized that the check for a static method wouldn't work in 3.0, I began to wonder if anyone else had run across the same problem, or if they even cared. Here's the script, which includes some assertions to test its behavior: ------------------------------------------------------------ class autosuper_method(object): def __init__(self, desc, cls=None): self.desc = desc self.cls = cls def __get__(self, obj, type=None): return autosuper_callable(self.desc, self.cls, self.desc.__get__(obj, type)) class autosuper_callable(autosuper_method): def __init__(self, desc, cls, callable): self.desc = desc self.cls = cls self.callable = callable def __call__(self, *args, **kwargs): if self.cls is None: raise TypeError('must inherit from autosuper') try: obj = self.callable.im_self except AttributeError: raise TypeError('autosuper used with static method') if obj is None: obj = args[0] return self.callable.__call__(obj, super(self.cls, obj), *args[1:], **kwargs) return self.callable.__call__(super(self.cls, obj), *args, **kwargs) class autosuper_meta(type): def __init__(cls, name, bases, clsdict): # fix up all autosuper_method instances in class for attr in clsdict.keys(): value = clsdict[attr] if isinstance(value, autosuper_method): type.__setattr__(cls, attr, autosuper_method(value.desc, cls)) def __setattr__(cls, attr, value): # catch assignment after class definition if isinstance(value, autosuper_method): value = autosuper_method(value.desc, cls) type.__setattr__(cls, attr, value) class autosuper(object): __metaclass__ = autosuper_meta if __name__ == '__main__': class A(autosuper): @classmethod def cm(cls): return 'A(%s)' % cls.name def im(self): return 'A(%s)' % self.name # Demo - standard use class B(A): @autosuper_method @classmethod def cm(cls, super): return 'B' + super.cm() @autosuper_method def im(self, super): return 'B' + super.im() # Demo - reference super in inner function class C(A): @autosuper_method @classmethod def cm(cls, super): def inner(): return 'C' + super.cm() return inner() @autosuper_method def im(self, super): def inner(): return 'C' + super.im() return inner() # Demo - define function before class definition @autosuper_method @classmethod def D_cm(cls, super): return 'D' + super.cm() @autosuper_method def D_im(self, super): return 'D' + super.im() class D(B, C): name = 'D' def __init__(self, name): self.name = name cm = D_cm im = D_im # Demo - define functions after class definition class E(B, C): name = 'E' def __init__(self, name): self.name = name @autosuper_method @classmethod def E_cm(cls, super): return 'E' + super.cm() @autosuper_method def E_im(self, super): return 'E' + super.im() E.cm = E_cm E.im = E_im # Test D d = D('d') assert d.cm() == 'DBCA(D)' # class method, instance binding assert D.cm() == 'DBCA(D)' # class method, class binding assert d.im() == 'DBCA(d)' # instance method, instance binding assert D.im(d) == 'DBCA(d)' # instance method, class binding # Test E e = E('e') assert e.cm() == 'EBCA(E)' # class method, instance binding assert E.cm() == 'EBCA(E)' # class method, class binding assert e.im() == 'EBCA(e)' # instance method, instance binding assert E.im(e) == 'EBCA(e)' # instance method, class binding # Give E cm and im from D E.cm = D.cm E.im = D.im assert e.cm() == 'DBCA(E)' # class method, instance binding assert E.cm() == 'DBCA(E)' # class method, class binding assert e.im() == 'DBCA(e)' # instance method, instance binding assert E.im(e) == 'DBCA(e)' # instance method, class binding ------------------------------------------------------------ I can imagine the next question: If this version of autosuper doesn't work for static methods (it doesn't make sense that it would, since super only works when bound), then why would I care if it couldn't check for static methods? Why not just assume it will be used for class methods and instance methods, and adjust the code accordingly? Well, that was my question from the beginning: When writing a wrapper like this, would anyone care if it could no longer distinguish between static methods and unbound methods, in Python 3.0? So far, it sounds like the answer is 'no', which is fine with me. I just thought I'd bring it to everyone's attention. _______________________________________________ Python-3000 mailing list Python-3000@python.org http://mail.python.org/mailman/listinfo/python-3000 Unsubscribe: http://mail.python.org/mailman/options/python-3000/archive%40mail-archive.com