问题
Is it possible to use Sphinx autodoc to generate documentation for my fabfile, from the function docstrings?
E.g. for a fabfile containing a setup_development
task i've tried:
.. automodule::fabfile
:members:
.. autofunction:: setup_development
But nothing is generated.
fabfile snippet:
@task
def setup_development(remote='origin', branch='development'):
"""Setup your development environment.
* Checkout development branch & pull updates from remote
* Install required python packages
* Symlink development settings
* Sync and migrate database
* Build HTML Documentation and open in web browser
Args:
remote: Name of remote git repository. Default: 'origin'.
branch: Name of your development branch. Default: 'development'.
"""
<code>
回答1:
I was able to produce full documentation with preserved function signature by using the decorator_apply
recipe found in the documentation for the decorator module.
""" myfabfile.py """
from fabric.api import task as origtask
from decorator import FunctionMaker
def decorator_apply(dec, func):
return FunctionMaker.create(
func, 'return decorated(%(signature)s)',
dict(decorated=dec(func)), __wrapped__=func)
def task(func):
return decorator_apply(origtask, func)
@task
def setup_development(remote='origin', branch='development'):
"""Setup your development environment.
* Checkout development branch & pull updates from remote
* Install required python packages
* Symlink development settings
* Sync and migrate database
* Build HTML Documentation and open in web browser
:param remote: Name of remote git repository.
:param branch: Name of your development branch.
"""
pass
This is the simple ReST source that I used:
.. automodule:: myfabfile
:members:
Some comments:
The answer submitted by shahjapan explains how to preserve the docstring in the general case, but it does not address the fact that the @task
decorator is defined in an external library.
Anyway, it turns out that the docstring is preserved automatically for functions decorated with @task
. The following is in the __init__
method of Fabric's tasks.WrappedCallableTask
class:
if hasattr(callable, '__doc__'):
self.__doc__ = callable.__doc__
So that already works as it is (an explicit .. autofunction::
is needed). To ensure that the function signature is preserved as well, the decorator
module can be used as shown above.
Update
The use of the decorator
module breaks things in the workings of Fabric (see comment). So that may not be feasible after all. As an alternative I suggest the following modified reST markup:
.. automodule:: myfabfile2
:members:
.. autofunction:: setup_development(remote='origin', branch='development')
That is, you'll have to include the full function signature. This is also what is suggested in the Sphinx documentation (see "This is useful if the signature from the method is hidden by a decorator.").
回答2:
Its because you've applied decorator on your function setup_development
you need to update your task
function with functools.wraps
as below,
from functools import wraps
def task(calling_func):
@wraps(calling_func)
def wrapper_func(self, *args, **kw):
return calling_func(*args, **kw)
return wrapper_func
If you document decorated functions or methods, keep in mind that autodoc retrieves its docstrings by importing the module and inspecting the __doc__
attribute of the given function or method.
That means that if a decorator replaces the decorated function with another, it must copy the original __doc__
to the new function.
From Python 2.5
, functools.wraps()
can be used to create well-behaved decorating functions.
References:
Python Sphinx autodoc and decorated members
http://sphinx.pocoo.org/ext/autodoc.html#directive-autoexception
来源:https://stackoverflow.com/questions/8845195/using-sphinx-autodoc-for-a-fabfile