0

I was playing with doc strings and I ended up with this code:

import inspect

class InheritedDoc(object):
    """ Decorator to find docstrings from parent classes of
        the method class.
        Decorator are interpreted on the import and not
        on the call, so the inherated docstrings will be
        read when we call help.

        @type mroOrder: bool
        @param mroOrder: follow the order of the
            method resolution order (True) or reserse it (False).
            Default: True.

        @Note: if this doc is seen in the code, instead of the
            docstring of a superClass, that must means the "()"
            are missing on the call of InheritedDoc:
                @InheritedDoc -> @InheritedDoc()
    """
    __empty_doc = 'No Doc found in parent classes.\n'
    __empty_doc += 'DocString needs to be set.'

    def __init__(self, mroOrder=True):
        """ Constructor
        """
        self.__mro_order = mroOrder

    def __call__(self, method):
        """ If there are decorator arguments, __call__()
            is only called once, as part of the decoration
            process!
            You can only give it a single argument,
            which is the function object.
        """
        # Generated only if help() were used.
        # Listing of super classes of the method class.
        #
        parent_classes = [
            element for name, element \
               in method.func_globals.items() \
                  if inspect.isclass(element)
        ]

        # We don't want to inheritate from the decorator itself.
        #
        parent_classes.remove(self.__class__)

        # Do we follow the order of the MRO or do we reverse it.
        #
        if not self.__mro_order:
            parent_classes = reversed(parent_classes)

        name = method.__name__

        doc = ''

        for parent_class in parent_classes:

            # Testing if the class define the method
            #
            if hasattr(parent_class, name):
                # Getting the method to find in it the doc.
                #
                class_method = eval('parent_class.%s' % name)
                doc = class_method.__doc__

                # We want to define the doc only if the method
                # got a doc set.
                #
                if doc:
                    # The doc is defined and we don't want
                    # to keep on defining it again and again. 
                    #
                    break

        # We may end up here without any docstring if none were 
        # actually set in parent classes.
        #
        method.__doc__ = doc or self.__empty_doc

        return method
Lucifer
  • 29,392
  • 25
  • 90
  • 143
Jordi Riera
  • 101
  • 1
  • 5
  • No need to use line continuation inside open brackets. So you can take the \ symbols out of the list comprehension. Also, I don't know about portability between python implementations but in CPython, the mro is available as the `__mro__` attribute of a class. – aaronasterling Apr 06 '12 at 02:02
  • 3
    This kind of question isn't really appropriate for stackoverflow. See http://blog.stackoverflow.com/2010/09/good-subjective-bad-subjective/ and http://stackoverflow.com/faq#dontask Specifically, this is a request for discussion rather than a request for an answer. – gfortune Apr 06 '12 at 02:11
  • If you're going to make something based on docstrings, you should really follow [the docstring PEP](http://www.python.org/dev/peps/pep-0257/), e.g. use single-line docstrings in a single line, "The docstring is a phrase ending in a period. It prescribes the function or method's effect as a command" ('Constructor' isn't very descriptive), etc – Casey Kuball Apr 06 '12 at 05:31
  • 1
    [PEP 8](http://www.python.org/dev/peps/pep-0008/) would like `mro_order` rather than `mroOrder` – Chris Morgan Apr 06 '12 at 07:30
  • @ChrisMorgan totally true. I will improve the docstring format to match docstring PEP. – Jordi Riera Apr 09 '12 at 19:41

0 Answers0