Override a method but inherit the docstring
Shai
shai at platonix.com
Thu Jul 23 19:51:43 EDT 2009
On Jul 17, 10:52 am, Steven D'Aprano <st... at REMOVE-THIS-
cybersource.com.au> wrote:
>
> When the decorator is called, the function object is just a function
> object, not a method, so there is no concept of "what class it is
> destined for".
>
... which points to the better solution: use a descriptor. With the
doc_inherit decorator defined below, one may write
class Foo(object):
def foo(self):
"Frobber"
pass
class Bar(Foo):
@doc_inherit
def foo(self):
pass
and it appears to work. The code below is a little longish because we
need to do slightly different things when called for a class and for
an instance. But there's no need to repeat the parent name, no need
to look into namespaces (which, as you said, is probably messy and
fragile), and it seems pretty readable, too.
from functools import wraps
class DocInherit(object):
"""
Docstring inheriting method descriptor
The class itself is also used as a decorator
"""
def __init__(self, mthd):
self.mthd = mthd
self.name = mthd.__name__
def __get__(self, obj, cls):
if obj:
return self.get_with_inst(obj, cls)
else:
return self.get_no_inst(cls)
def get_with_inst(self, obj, cls):
overridden = getattr(super(cls, obj), self.name, None)
@wraps(self.mthd, assigned=('__name__','__module__'))
def f(*args, **kwargs):
return self.mthd(obj, *args, **kwargs)
return self.use_parent_doc(f, overridden)
def get_no_inst(self, cls):
for parent in cls.__mro__[1:]:
overridden = getattr(parent, self.name, None)
if overridden: break
@wraps(self.mthd, assigned=('__name__','__module__'))
def f(*args, **kwargs):
return self.mthd(*args, **kwargs)
return self.use_parent_doc(f, overridden)
def use_parent_doc(self, func, source):
if source is None:
raise NameError, ("Can't find '%s' in parents"%self.name)
func.__doc__ = source.__doc__
return func
doc_inherit = DocInherit
Combining docstrings (as suggested by Jean-Paul Calderone), and
taking proper care of classmethods and staticmethods, are left
as an exercise to the reader.
Have fun,
Shai.
More information about the Python-list
mailing list