Account Options

  1. Sign in
Google Groups Home
« Groups Home
Override a method but inherit the docstring
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  17 messages - Collapse all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Ben Finney  
View profile  
 More options Jul 16 2009, 9:01 pm
Newsgroups: comp.lang.python
From: Ben Finney <ben+pyt...@benfinney.id.au>
Date: Fri, 17 Jul 2009 11:01:49 +1000
Local: Thurs, Jul 16 2009 9:01 pm
Subject: Override a method but inherit the docstring
Howdy all,

The following is a common idiom::

    class FooGonk(object):
        def frobnicate(self):
            """ Frobnicate this gonk. """
            basic_implementation(self.wobble)

    class BarGonk(FooGonk):
        def frobnicate(self):
            special_implementation(self.warble)

The docstring for ‘FooGonk.frobnicate’ is, intentionally, perfectly
applicable to the ‘BarGonk.frobnicate’ method also. Yet in overriding
the method, the original docstring is not associated with it.

Ideally there would be a way to specify that the docstring should be
inherited. The best I can come up with is::

    class BarGonk(FooGonk):
        def frobnicate(self):
            special_implementation(self.warble)
        frobnicate.__doc__ = FooGonk.frobnicate.__doc__

but that violates DRY (the association between BarGonk and FooGonk is
being repeated), puts the docstring assignment awkwardly after the end
of the method instead of at the beginning where docstrings normally go,
and reads poorly besides.

What is the most Pythonic, DRY-adherent, and preferably least-ugly
approach to override a method, but have the same docstring on both
methods?

--
 \           “Why, I'd horse-whip you if I had a horse.” —Groucho Marx |
  `\                                                                   |
_o__)                                                                  |
Ben Finney


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Jean-Paul Calderone  
View profile  
 More options Jul 16 2009, 9:13 pm
Newsgroups: comp.lang.python
From: Jean-Paul Calderone <exar...@divmod.com>
Date: Thu, 16 Jul 2009 21:13:34 -0400
Local: Thurs, Jul 16 2009 9:13 pm
Subject: Re: Override a method but inherit the docstring

How about this?

    class BarGonk(FooGonk):
        @inherit_docstring
        def frobnicate(self):
            special_implementation(self.warble)

The implementation of "inherit_docstring" is left as an exercise for the
reader (it's not utterly trivial, I admit, as "FooGonk" will not readily
be at hand, but it is still possible).

By the way, I don't think this is a particularly good idea.  Presumably
there is a reason your implementation is special.  It would probably be
better if this were reflected in the docstring somehow.  Perhaps this
idea is a better one:

    class BarGonk(FooGonk):
        @append_to_docstring
        def frobnicate(self):
            """
            This implementation takes the warble into consideration.
            """
            special_implementation(self.warble)

With the result of BarGonk.frobnicate.__doc__ being set to:

     Frobnicate this gonk.

     This implementation takes the warble into consideration.

Jean-Paul


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Maxim Khitrov  
View profile  
 More options Jul 16 2009, 9:21 pm
Newsgroups: comp.lang.python
From: Maxim Khitrov <mkhit...@gmail.com>
Date: Thu, 16 Jul 2009 21:21:16 -0400
Local: Thurs, Jul 16 2009 9:21 pm
Subject: Re: Override a method but inherit the docstring

Another way is to use a metaclass. Have its __new__ method loop
through all attributes and compare those with what is already defined
in bases. If you find a match, copy the __doc__ attribute. The
advantage here is that it will work for all methods without any
additional code, not counting the "__metaclass__ = ..." line. If you
define a metaclass for the base, then no modifications are required
for any subclasses. I do agree, however, that the best thing to do is
to write a very short explanation for what the override is for.

- Max


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Rhodri James  
View profile  
 More options Jul 16 2009, 9:31 pm
Newsgroups: comp.lang.python
From: "Rhodri James" <rho...@wildebst.demon.co.uk>
Date: Fri, 17 Jul 2009 02:31:43 +0100
Local: Thurs, Jul 16 2009 9:31 pm
Subject: Re: Override a method but inherit the docstring
On Fri, 17 Jul 2009 02:01:49 +0100, Ben Finney  

Not really.  Consider the case of BarGonk being a subclass of FooGonk
and BazGonk; which docstring would you wish to inherit?

> puts the docstring assignment awkwardly after the end
> of the method instead of at the beginning where docstrings normally go,
> and reads poorly besides.

Sounds like a job for a decorator!

(This is probably unbelievably ugly and unwise, since I don't use
decorators at all often.)

def copydoc(cls):
     def _fn(fn):
         if fn.__name__ in cls.__dict__:
             fn.__doc__ = cls.__dict__[fn.__name__].__doc__
         return fn
     return _fn

class BarGonk(FooGonk):
     @copydoc(FooGonk)
     def frobnicate(self):
         special_implementation(self.warble)

--
Rhodri James *-* Wildebeest Herder to the Masses


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Paul McGuire  
View profile  
 More options Jul 16 2009, 9:35 pm
Newsgroups: comp.lang.python
From: Paul McGuire <pt...@austin.rr.com>
Date: Thu, 16 Jul 2009 18:35:05 -0700 (PDT)
Local: Thurs, Jul 16 2009 9:35 pm
Subject: Re: Override a method but inherit the docstring
On Jul 16, 8:01 pm, Ben Finney <ben+pyt...@benfinney.id.au> wrote:

Two ideas come to mind, the decorator way and the metaclass way.  I am
not a guru at either, but these two examples work:

# the decorator way
def inherit_docstring_from(cls):
    def docstring_inheriting_decorator(fn):
        fn.__doc__ = getattr(cls,fn.__name__).__doc__
        return fn
    return docstring_inheriting_decorator

class FooGonk(object):
    def frobnicate(self):
        """ Frobnicate this gonk. """
        basic_implementation(self.wobble)

class BarGonk(FooGonk):
    @inherit_docstring_from(FooGonk)
    def frobnicate(self):
        special_implementation(self.warble)

bg = BarGonk()
help(bg.frobnicate)

Prints:
Help on method frobnicate in module __main__:

frobnicate(self) method of __main__.BarGonk instance
    Frobnicate this gonk.

Using a decorator in this manner requires repeating the super class
name.  Perhaps there is a way to get the bases of BarGonk, but I don't
think so, because at the time that the decorator is called, BarGonk is
not yet fully defined.

# The metaclass way

from types import FunctionType

class DocStringInheritor(type):
    def __new__(meta, classname, bases, classDict):
        newClassDict = {}
        for attributeName, attribute in classDict.items():
            if type(attribute) == FunctionType:
                # look through bases for matching function by name
                for baseclass in bases:
                    if hasattr(baseclass, attributeName):
                        basefn = getattr(baseclass,attributeName)
                        if basefn.__doc__:
                            attribute.__doc__ = basefn.__doc__
                            break

            newClassDict[attributeName] = attribute

        return type.__new__(meta, classname, bases, newClassDict)

class FooGonk2(object):
    def frobnicate(self):
        """ Frobnicate this gonk. """
        basic_implementation(self.wobble)

class BarGonk2(FooGonk2):
    __metaclass__ = DocStringInheritor
    def frobnicate(self):
        special_implementation(self.warble)

bg = BarGonk2()
help(bg.frobnicate)

Prints:

Help on method frobnicate in module __main__:

frobnicate(self) method of __main__.BarGonk2 instance
    Frobnicate this gonk.

This metaclass will walk the list of bases until the desired
superclass method is found AND if that method has a docstring and only
THEN does it attach the superdocstring to the derived class method.

Please use carefully, I just did the metaclass thing by following
Michael Foord's Metaclass tutorial (http://www.voidspace.org.uk/python/
articles/metaclasses.shtml), I may have missed a step or two.

-- Paul


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Ben Finney  
View profile  
 More options Jul 16 2009, 10:58 pm
Newsgroups: comp.lang.python
From: Ben Finney <ben+pyt...@benfinney.id.au>
Date: Fri, 17 Jul 2009 12:58:48 +1000
Local: Thurs, Jul 16 2009 10:58 pm
Subject: Re: Override a method but inherit the docstring

Paul McGuire <pt...@austin.rr.com> writes:
> Two ideas come to mind, the decorator way and the metaclass way. I am
> not a guru at either, but these two examples work:

I think the decorator idea is most attractive to me, since it can be
applied per method.

> # the decorator way
> def inherit_docstring_from(cls):
>     def docstring_inheriting_decorator(fn):
>         fn.__doc__ = getattr(cls,fn.__name__).__doc__
>         return fn
>     return docstring_inheriting_decorator

That works, thank you.

> Using a decorator in this manner requires repeating the super class
> name.  Perhaps there is a way to get the bases of BarGonk, but I don't
> think so, because at the time that the decorator is called, BarGonk is
> not yet fully defined.

Yes, I tried a few different ways, but within the decorator it seems the
function object is quite unaware of what class it is destined for.

--
 \     “We are human only to the extent that our ideas remain humane.” |
  `\                          —_Breakfast of Champions_, Kurt Vonnegut |
_o__)                                                                  |
Ben Finney


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Peter Otten  
View profile  
 More options Jul 17 2009, 2:58 am
Newsgroups: comp.lang.python
Followup-To: comp.lang.python
From: Peter Otten <__pete...@web.de>
Date: Fri, 17 Jul 2009 08:58:40 +0200
Local: Fri, Jul 17 2009 2:58 am
Subject: Re: Override a method but inherit the docstring

Just thinking aloud: Write a patch for pydoc that looks up the base-class
documentation.

B.f.__doc__ will continue to return None, but

help(B.f) will show something like

    No documentation available for B.f.

    Help for A.f:
    yadda yadda

Of course that might be misleading when A.f and B.f are up to something
completely different...

Peter


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Steven D'Aprano  
View profile  
 More options Jul 17 2009, 3:52 am
Newsgroups: comp.lang.python
From: Steven D'Aprano <st...@REMOVE-THIS-cybersource.com.au>
Date: 17 Jul 2009 07:52:19 GMT
Local: Fri, Jul 17 2009 3:52 am
Subject: Re: Override a method but inherit the docstring

On Fri, 17 Jul 2009 12:58:48 +1000, Ben Finney wrote:
>> Using a decorator in this manner requires repeating the super class
>> name.  Perhaps there is a way to get the bases of BarGonk, but I don't
>> think so, because at the time that the decorator is called, BarGonk is
>> not yet fully defined.

> Yes, I tried a few different ways, but within the decorator it seems the
> function object is quite unaware of what class it is destined for.

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".

>>> def dec(func):

...     print type(func)
...     try:
...             print func.im_class
...     except:
...             print "no im_class"
...     return func
...
>>> class Test(object):

...     @dec
...     def spam(self):
...             pass
...
<type 'function'>
no im_class
>>> type(Test.spam)

<type 'instancemethod'>
>>> Test.spam.im_class

<class '__main__.Test'>

I suppose you could try to determine what namespace you're currently when
the class is created, but that's surely going to be fragile and messy.

--
Steven


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Ben Finney  
View profile  
 More options Jul 17 2009, 6:03 am
Newsgroups: comp.lang.python
From: Ben Finney <ben+pyt...@benfinney.id.au>
Date: Fri, 17 Jul 2009 20:03:29 +1000
Local: Fri, Jul 17 2009 6:03 am
Subject: Re: Override a method but inherit the docstring

Peter Otten <__pete...@web.de> writes:
> Just thinking aloud: Write a patch for pydoc that looks up the
> base-class documentation.

That doesn't scale; I want the docstring to be discovered by the normal
interface (the ‘__doc__’ attribute) by *every* tool that gathers
docstrings from methods.

Also, I want to have this behaviour not for every method missing a
docstring, but only for selected methods.

> Of course that might be misleading when A.f and B.f are up to
> something completely different...

Exactly.

--
 \     “Facts do not cease to exist because they are ignored.” —Aldous |
  `\                                                            Huxley |
_o__)                                                                  |
Ben Finney


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
David Stanek  
View profile  
 More options Jul 17 2009, 8:08 am
Newsgroups: comp.lang.python
From: David Stanek <dsta...@dstanek.com>
Date: Fri, 17 Jul 2009 08:08:48 -0400
Local: Fri, Jul 17 2009 8:08 am
Subject: Re: Override a method but inherit the docstring

This should never be the case. It violates LSP and would be very confusing to
readers of the code.

--
David
blog: http://www.traceback.org
twitter: http://twitter.com/dstanek


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
David Stanek  
View profile  
 More options Jul 17 2009, 8:21 am
Newsgroups: comp.lang.python
From: David Stanek <dsta...@dstanek.com>
Date: Fri, 17 Jul 2009 08:21:39 -0400
Local: Fri, Jul 17 2009 8:21 am
Subject: Re: Override a method but inherit the docstring
On Fri, Jul 17, 2009 at 3:52 AM, Steven

It isn't too bad. I got the idea to use the method's enclosing
scope[1] in my decorator[2] from DecoratorTools. I am working to
remove it because it make me sad, but it does work.

[1] http://code.google.com/p/snake-guice/source/browse/snakeguice/decorat...
[2] http://code.google.com/p/snake-guice/source/browse/snakeguice/decorat...

--
David
blog: http://www.traceback.org
twitter: http://twitter.com/dstanek


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Shai  
View profile  
 More options Jul 23 2009, 7:51 pm
Newsgroups: comp.lang.python
From: Shai <s...@platonix.com>
Date: Thu, 23 Jul 2009 16:51:43 -0700 (PDT)
Local: Thurs, Jul 23 2009 7:51 pm
Subject: Re: Override a method but inherit the docstring
On Jul 17, 10:52 am, Steven D'Aprano <st...@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.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Aahz  
View profile  
 More options Jul 26 2009, 11:55 am
Newsgroups: comp.lang.python
From: a...@pythoncraft.com (Aahz)
Date: 26 Jul 2009 08:55:18 -0700
Local: Sun, Jul 26 2009 11:55 am
Subject: Re: Override a method but inherit the docstring
In article <056f629b-aa63-458a-ae16-ac40a759e...@h11g2000yqb.googlegroups.com>,

Shai  <s...@platonix.com> wrote:

>class DocInherit(object):
>    """
>    Docstring inheriting method descriptor

>    The class itself is also used as a decorator
>    """

Nice!  Maybe stick this on the Cookbook?
--
Aahz (a...@pythoncraft.com)           <*>         http://www.pythoncraft.com/

"At Resolver we've found it useful to short-circuit any doubt and just        
refer to comments in code as 'lies'. :-)"
--Michael Foord paraphrases Christian Muirhead on python-dev, 2009-03-22


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Jean-Michel Pichavant  
View profile  
 More options Jul 27 2009, 10:05 am
Newsgroups: comp.lang.python
From: Jean-Michel Pichavant <jeanmic...@sequans.com>
Date: Mon, 27 Jul 2009 16:05:11 +0200
Local: Mon, Jul 27 2009 10:05 am
Subject: Re: Override a method but inherit the docstring

I am using epydoc and if the docstring is present only in the baseclass
method, it will repeat the docstring for the child methods. So
basically, there's nothing to do.
I've also tried within the python interpreter, and it can perfectly
solve docstring inheritance. So why would you explicitly assign
docstring to child methods ?

JM


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Shai  
View profile  
 More options Jul 27 2009, 5:15 pm
Newsgroups: comp.lang.python
From: Shai <s...@platonix.com>
Date: Mon, 27 Jul 2009 14:15:00 -0700 (PDT)
Subject: Re: Override a method but inherit the docstring
On Jul 27, 5:05 pm, Jean-Michel Pichavant <jeanmic...@sequans.com>
wrote:

> Ben Finney wrote:

> > The docstring for ‘FooGonk.frobnicate’ is, intentionally, perfectly
> > applicable to the ‘BarGonk.frobnicate’ method also. Yet in overriding
> > the method, the original docstring is not associated with it.

> I've also tried within the python interpreter, and it can perfectly
> solve docstring inheritance. So why would you explicitly assign
> docstring to child methods ?

What do you mean by "can perfectly solve docstring inheritance" ?

After the following,

class Foo(object):
    def foo(self):
        "Frobber"
        pass

class Bar(Foo):
    def foo(self):
        pass

help(Bar.foo) does not display "Frobber" on my interpreter.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Jean-Michel Pichavant  
View profile  
 More options Jul 28 2009, 5:33 am
Newsgroups: comp.lang.python
From: Jean-Michel Pichavant <jeanmic...@sequans.com>
Date: Tue, 28 Jul 2009 11:33:43 +0200
Local: Tues, Jul 28 2009 5:33 am
Subject: Re: Override a method but inherit the docstring

You're right. I must have made some dumb mistake. So interpreters do not
solve docstring inheritance, Epydoc does.

JM


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Shai  
View profile  
 More options Jul 28 2009, 4:49 pm
Newsgroups: comp.lang.python
From: Shai <s...@platonix.com>
Date: Tue, 28 Jul 2009 13:49:57 -0700 (PDT)
Local: Tues, Jul 28 2009 4:49 pm
Subject: Re: Override a method but inherit the docstring
On Jul 26, 6:55 pm, a...@pythoncraft.com (Aahz) wrote:

> Nice!  Maybe stick this on the Cookbook?

http://code.activestate.com/recipes/576862/

Thanks for the suggestion,

Shai.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »