I have a class MyClass
:
class MyClass(object):
def __init__(self):
pass
def my_function(self, x):
# MyClass.my_function.__doc__ is not writable!
# Otherwise, I could just set it here.
Origin.func(self, x)
The class borrows from Origin
:
class Origin(object):
def func(obj, x):
"""This is a function
"""
# do stuff
pass
How can I copy the docstring from Origin.func to MyClass.my_function automatically so that Sphinx Autodoc recognises it? And how can I extend the original docstring by a couple of words?
Edit:
Afaik, I cannot just change __doc__
after the definition of the function since Sphinx would not find it then. Or if it did, where would the "docfix" go?
I'm not clear on exactly how Sphinx works, but assuming it reads from __doc__
rather than parsing the source, there are a number of options.
Consider the simpler example...
def add(x, y):
return x + y
...which is virtually identical to...
add = lambda x, y: x + y
In either case, you cannot refer to the symbol add
inside its definition, since the symbol is not defined at that point. Nor can you refer to the function
object which the symbol add
will ultimately refer to, since it hasn't been created yet.
Therefore, you can only modify add.__doc__
after the symbol has been defined...
def add(x, y):
return x + y
add.__doc__ = 'This is my docstring'
...but this may be a little more verbose than we'd like.
Another option is to exploit the fact that the Python decorator syntax...
@my_decorator
def add(x, y):
return x + y
...is equivalent to...
def add(x, y):
return x + y
add = my_decorator(add)
...that is, although it's placed before the function definition, it's executed after the function is defined, so you can reference the function
object inside the body of the decorator function.
A decorator function is required to return a callable object, but given that we have no need to change the behavior of the add
function, we can just return the argument which is passed in to the decorator, so given the decorator function...
def set_fixed_docstring(func):
func.__doc___ = 'This is my docstring'
return func
...used like...
@set_fixed_docstring
def add(x, y):
return x + y
...is equivalent to...
def add(x, y):
return x + y
add = set_fixed_docstring(add)
...or...
def add(x, y):
return x + y
add.__doc__ = 'This is my docstring'
add = add
Obviously, a fixed docstring isn't much use here, so we need to parameterize the decorator, which is a little more complex.
In this instance, we need our decorator function to be callable with a string parameter, and to return a callable object which takes the target function as a parameter.
The most common way to do this is to define another function within the decorator function, such that the inner function can refer to symbols defined in the outer function. So the function...
def set_docstring_to(docstring):
def wrapper(func):
func.__doc___ = docstring
return func
return wrapper
...used like...
@set_docstring_to('This is my docstring')
def add(x, y):
return x + y
...is equivalent to...
def add(x, y):
return x + y
add = set_docstring_to('This is my docstring')(add)
...which boils down to the same code as before...
def add(x, y):
return x + y
add.__doc__ = 'This is my docstring'
add = add
Putting all this together, if you were to use a decorator like...
def copy_docstring_from(source):
def wrapper(func):
func.__doc__ = source.__doc__
return func
return wrapper
...then you can just do...
class Origin(object):
def func(obj, x):
"""This is a function
"""
# do stuff
pass
class MyClass(object):
def __init__(self):
pass
@copy_docstring_from(Origin.func)
def my_function(self, x):
# MyClass.my_function.__doc__ is not writable!
# Otherwise, I could just set it here.
Origin.func(self, x)
...which should achieve the desired result with the minimum amount of code.