对 fabfile 使用 sphinx autodoc

发布于 2024-12-26 06:59:41 字数 793 浏览 1 评论 0 原文

是否可以使用 Sphinx autodoc 从函数 docstrings 为我的 fabfile 生成文档?

例如,对于包含我尝试过的 setup_development 任务的 fabfile:

.. automodule::fabfile
   :members:
   .. autofunction:: setup_development

但没有生成任何内容。

fabfile 片段:

@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>

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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

徒留西风 2025-01-02 06:59:41

这是因为您在函数 setup_development 上应用了装饰器,

您需要使用 functools.wraps 更新您的 task 函数,如下所示,

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

如果您记录了装饰器函数或方法,请记住,autodoc 通过导入模块并检查给定函数或方法的 __doc__ 属性来检索其文档字符串。

这意味着如果装饰器用另一个装饰器替换被装饰的函数,它必须将原始的 __doc__ 复制到新函数。
Python 2.5 开始,functools.wraps() 可用于创建行为良好的装饰函数。

参考文献:

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:

掀纱窥君容 2025-01-02 06:59:41

通过使用decorator_apply配方可在 中找到rel="nofollow">装饰器模块。

""" 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

这是我使用的简单 ReST 源:

.. automodule:: myfabfile
   :members:

一些评论:

shahjapan 提交的答案解释了如何在一般情况下保留文档字符串,但它没有解决定义 @task 装饰器的事实在外部库中。

不管怎样,事实证明,用 @task 修饰的函数会自动保留文档字符串。以下内容位于 Fabric 的 tasks.WrappedCallableTask 类的 __init__ 方法中:

if hasattr(callable, '__doc__'):
    self.__doc__ = callable.__doc__

因此,它已经按原样工作(显式的 .. autofunction::是需要的)。为了确保保留函数签名,可以使用如上所示的decorator模块。


更新

decorator 模块的使用破坏了 Fabric 的工作方式(参见评论)。所以这可能终究是不可行的。作为替代方案,我建议使用以下修改后的 reST 标记:

.. automodule:: myfabfile2
   :members: 

   .. autofunction:: setup_development(remote='origin', branch='development')

也就是说,您必须包含完整的函数签名。这也是 Sphinx 文档中建议的内容(请参阅 “如果签名该方法被装饰器隐藏。")

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.").

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文