Search code examples
pythondocstring

Python docstrings templated


Why doesn't dynamically formatting docstrings work? Is there an acceptable workaround for doing this at function definition time?

>>> DEFAULT_BAR = "moe's tavern"
>>> def foo(bar=DEFAULT_BAR):
...     """
...     hello this is the docstring
...     
...     Args:
...       bar (str)    the bar argument (default: {})
...     """.format(DEFAULT_BAR)
... 
>>> foo.__doc__
>>> foo.__doc__ is None
True

I tried with old-skool style %s formatting and that didn't work either.


Solution

  • Try something like this (props to @user2357112 for the suggestion):

    #!python3
    
    def FORMAT_DOC(f):
        """Decorator to format docstring of a function. Supplies 
        `defaults` dictionary, positional values, and argname:value 
        pairs to format - use {defaults[a]} or {a} or {0} to access
        the 0th default value, etc.
        """
        defaults = f.__defaults__
        docs = f.__doc__
    
        if docs and defaults:
            nargs = f.__code__.co_argcount
            argnames = f.__code__.co_varnames[nargs-len(defaults):nargs]
            argdefaults = dict(zip(argnames, defaults))
            f.__doc__ = docs.format(defaults=argdefaults, *defaults, **argdefaults)
    
        return f
    
    @FORMAT_DOC
    def f(a):
        pass
    
    @FORMAT_DOC
    def f(a,b,c=1,d=2):
        """Docstring
    
        By default, c = {} and d = {}
        """
        v=a+c
        w=b+d
        x=w/v
        return x+1
    
    @FORMAT_DOC
    def f(a=0, b="foo", c="bar"):
        """Docstring: a={0}, b={defaults[b]}, c={c}"""
        pass