Grrrr, sorry about the line wrapping horror; trying again. class InheritDoc(object): """ Docstring inheriting method descriptor
The class itself is used as a decorator that creates a class property for the method; the first time the property is used it installs the method's doc and then replaces itself as a class attribute with the method! Usage: >>> class Foo(object): ... def foo(self, x): ... 'Frobber' ... print 'Foo.foo()', x Correct usage for overridden method foo(), incorrect usage for method bar() >>> class Bar(Foo): ... @inherit_doc ... def foo(self, x): ... print 'Bar.foo()', x ... @inherit_doc ... def bar(self): ... print 'Bar.bar()' >>> Bar.foo.__doc__ == Bar().foo.__doc__ == Foo.foo.__doc__ == 'Frobber' True >>> Foo.foo <unbound method Foo.foo> >>> Foo().foo(10) Foo.foo() 10 >>> Bar.foo <unbound method Bar.foo> >>> Bar().foo(11) Bar.foo() 11 >>> Bar.bar Traceback (most recent call last): ... NameError: inherit_doc cannot find method 'bar' in parents of '__main__.Bar' >>> Bar().bar Traceback (most recent call last): ... NameError: inherit_doc cannot find method 'bar' in parents of '__main__.Bar' """ __slots__ = 'inherit_doc_unbound_method' def __init__(self, unbound_method): self.inherit_doc_unbound_method = unbound_method def __get__(self, obj, cls): # a self-destructing descriptor/property: # the first and only time it's used, it fixes the method's doc and then # replaces itself with the method # find the overridden method in mro sequence, skipping the class itself method_name = self.inherit_doc_unbound_method.__name__ mro_iter = iter(cls.__mro__) mro_iter.next() for parent in mro_iter: overridden = getattr(parent, method_name, None) if overridden is not None: break if overridden is None: raise NameError('inherit_doc cannot find method %r in parents of %r' % (method_name, '%s.%s'%(cls.__module__, cls.__name__))) # XXX next steps are not threadsafe, maybe not safe at all! # set the doc self.inherit_doc_unbound_method.__doc__ = overridden.__doc__ # replace the property with the function setattr(cls, method_name, self.inherit_doc_unbound_method) # use the replacement return getattr(obj if obj is not None else cls, method_name) inherit_doc = InheritDoc -- http://mail.python.org/mailman/listinfo/python-list