docstring inheritance
HughSW
hugh.seckerwalker at gmail.com
Wed Dec 1 21:56:31 EST 2010
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
More information about the Python-list
mailing list