Plasma
Plasma

Reputation: 2439

Change docstring when inheriting but leave method the same

I'm building an HTTP API and I factored out a lot of code into a superclass that handles requests to a collection of objects. In my subclass, I specify what database models the operation should work on and the superclass takes care of the rest.

This means that I don't need to re-implement the get, post, etc. methods from the superclass, however, I want to change their docstrings in the subclass so that I can have some documentation more specific to the actual model the endpoint is operating on.

What is the cleanest way to inherit the parent class's functionality but change the docstrings?

Example:

class CollectionApi(Resource):
    """Operate on a collection of something.
    """
    class Meta(object):
        model = None
        schema = None


    def get(self):
        """Return a list of collections.
        """
        # snip

    def post(self):
        """Create a new item in this collection.
        """
        # snip

class ActivityListApi(CollectionApi):
    """Operations on the collection of Activities.
    """
    class Meta(object):
        model = models.Activity
        schema = schemas.ActivitySchema

Specifically, I need ActivityListApi to have get and post run like in CollectionApi, but I want different docstrings (for automatic documentation's sake).

I can do this:

    def get(self):
        """More detailed docs
        """
        return super(ActivityListApi, self).get()

But this seems messy.

Upvotes: 7

Views: 954

Answers (2)

duburcqa
duburcqa

Reputation: 1131

Better late than never. It is actually possible to change the doc while leaving the original method untouched by modifying __doc__ method attribute directly once the class has been declared.

With this approach, it avoids any overhead, and checks like CollectionApi.get is ActivityListApi.get will work as expected (ie return True unless inherited, even if the doc has been modified).

Here is what to do for your application:

class CollectionApi(Resource):
    """Operate on a collection of something.
    """
    class Meta(object):
        model = None
        schema = None


    def get(self):
        """Return a list of collections.
        """
        # snip

    def post(self):
        """Create a new item in this collection.
        """
        # snip

class ActivityListApi(CollectionApi):
    """Operations on the collection of Activities.
    """
    class Meta(object):
        model = models.Activity
        schema = schemas.ActivitySchema

ActivityListApi.get.__doc__ = \
    """user-intended doc for `get`.
    """

ActivityListApi.post.__doc__ = \
    """user-intended doc for `post`.
    """

At least in works nowadays in Python 3.6+. I did not check for Python 2.7 which has been deprecated long time ago.

Upvotes: 1

JL Peyret
JL Peyret

Reputation: 12154

class CollectionApi(Resource):
    """Operate on a collection of something.
    """

    def _get(self):
        """actual work... lotsa techy doc here!

           the get methods only serve to have something to hang 
           their user docstrings onto
        """

        pass

    def get(self):
        """user-intended doc for CollectionApi"""
        return self._get()

class ActivityListApi(CollectionApi):

    def get(self):
        """user-intended doc for ActivityListApi"""
        return self._get()

Upvotes: 4

Related Questions