How could I create a docstring decorator in the presence of properties?

Viewed 49

I have a collection of ever more specialized classes which correspond to collections of the same kind of data (temperature, density, etc) but for different drifts, for example, one subclass has dimensions (nx, ny) and a different suclass has dimensions (ncv), and I want to reflect that in the docstrings, for having a better documentation using Sphinx.

After reading many very useful threads here in Stack Overflow, I have arrived to this model:

import numpy as np
from functools import wraps

def class_decorator(cls):
    import ipdb; ipdb.set_trace()
    clsdict = {}
    mro = cls.mro()
    mro.reverse()
    for tmp in mro[1:]: ##Ignore object class parent.
        clsdict.update(tmp.__dict__)
    for name, method in clsdict.items():
        if hasattr(method, '__og_doc__'):
            try:
                method.__doc__ = method.__og_doc__.format(**clsdict)
            except:
                pass
        else:
            try:
                method.__og_doc__ = method.__doc__
                method.__doc__ = method.__doc__.format(**clsdict)
            except:
                pass
    return cls


def mark_documentation(fn):
    if not hasattr(fn, '__og_doc__'):
        try:
            fn.__og_doc__ = fn.__doc__
        except:
            pass
    @wraps(fn)
    def wrapped(*args, **kwargs):
        return fn(*args, **kwargs)
    return wrapped

def documented_property(fn):
    if not hasattr(fn, '__og_doc__'):
        try:
            fn.__og_doc__ = fn.__doc__
        except:
            pass
    @wraps(fn)
    def wrapped(*args, **kwargs):
        return fn(*args, **kwargs)
    prp= property(wrapped)
    prp.__og_doc__ = fn.__og_doc__
    return  prp

 

 

@class_decorator
class Base(object):
    _GRID_DIM = 'nx, ny'
    _TYPE = 'BaseData'
    def __init__(self, name):
         self.name = name

    def shape(self):
        """ This docstring contains the type '{_TYPE}' of class."""
        print('Simple')



    def operation(self, a, b, oper=np.sum, **kwargs):
        """ Test for functions with args and kwargs in {_TYPE}"""
        return oper([a,b])


    @classmethod
    def help(cls, var):
        try:
            print(get(cls, var).__doc__)
        except:
            print("No docstring yet.")


@class_decorator
class Advanced(Base):
    _GRID_DIM = 'ncv'
    _TYPE = 'AdvancedData'
    def __init__(self,name):
        super().__init__(name)

    @property
    @mark_documentation
#     @documented_property
     def arkansas(self):
        """({_GRID_DIM}, ns): Size of Arkansaw."""
        return 'Yeah'

I am aiming to get the correctly formatted docstring when I call the help method or I use Sphinx, so that:

> adv = Advanced('ADV')
> adv.help("arkansas")
    (ncv, ns): Size of Arkansaw.
> adv.help("operation")
    Test for functions with args and kwargs in AdvancedData

I have managed to make it work so far, except for properties, because I assigned __og_doc__ to the function, but the property does not have that attribute. My last attempt at monkeypatching this, documented_property, fails because property is inmutable (as expected), and I cannot come up with any way to avoid this roadblock.

Is there any way around this problem?

0 Answers
Related