繁体   English   中英

使用 Sphinx autodoc 记录 Python 协程

[英]Documenting Python coroutines with Sphinx autodoc

我开始用 Sphinx 记录我的第一个基于 asyncio 的项目。 我注意到有些项目在某些方法之前有这个“协程”前缀,我想在我的项目文档中做同样的事情,但我不知道如何做。

例如, aiohttp 的 HTTP 客户端参考显示:

aiohttp.ClientSession (...):

协程request (...)

该项目似乎使用coroutinemethod指令来实现这一点,但我使用文档字符串内联记录了我的所有函数和类,并且该指令仅在您将文档写入 reStructuredText 文档时才有效。

有人知道如何使用 autodoc 实现此结果吗?

编辑:如果 Sphinx 不支持,我也将接受解释如何制作 Sphinx 扩展来执行此操作的答案。 如果有人可以指出我使用inspect.iscoroutinefunction()自动检测该方法是否为协程的某种方式,则奖励积分。

编辑:我正在查看 CPython 项目中的“pyspecific”Sphinx 扩展以获得灵感。 但是,我需要更改 autodoc 的行为,而不是添加新指令。 经过一番研究,看起来 autodoc 有一个autodoc-process-signature 事件,可用于自定义函数签名,但它似乎没有“pyspecific”扩展使用的对象。

此功能尚未内置到 Sphinx 中。 然而, pull request #1826添加了对生成器、协程函数、协程方法的支持,在 autodoc 的autofunctionautomethod指令中内置了协程检测。

这是我在本地应用的一个补丁,用于在 Sphinx 1.4 中启用此功能(需要禁用sphinx-build-W “将警告转换为错误”选项):

# Recipe stolen from open PR (https://github.com/sphinx-doc/sphinx/pull/1826).


from inspect import iscoroutinefunction

from sphinx import addnodes
from sphinx.domains.python import (
    PyClassmember,
    PyModulelevel,
)
from sphinx.ext.autodoc import FunctionDocumenter as _FunctionDocumenter
from sphinx.ext.autodoc import MethodDocumenter as _MethodDocumenter


class PyCoroutineMixin(object):
    """Helper for coroutine-related Sphinx custom directives."""

    def handle_signature(self, sig, signode):
        ret = super(PyCoroutineMixin, self).handle_signature(sig, signode)
        signode.insert(0, addnodes.desc_annotation('coroutine ', 'coroutine '))
        return ret


class PyCoroutineFunction(PyCoroutineMixin, PyModulelevel):
    """Sphinx directive for coroutine functions."""

    def run(self):
        self.name = 'py:function'
        return PyModulelevel.run(self)


class PyCoroutineMethod(PyCoroutineMixin, PyClassmember):
    """Sphinx directive for coroutine methods."""

    def run(self):
        self.name = 'py:method'
        return PyClassmember.run(self)


class FunctionDocumenter(_FunctionDocumenter):
    """Automatically detect coroutine functions."""

    def import_object(self):
        ret = _FunctionDocumenter.import_object(self)
        if not ret:
            return ret

        obj = self.parent.__dict__.get(self.object_name)
        if iscoroutinefunction(obj):
            self.directivetype = 'coroutine'
            self.member_order = _FunctionDocumenter.member_order + 2
        return ret


class MethodDocumenter(_MethodDocumenter):
    """Automatically detect coroutine methods."""

    def import_object(self):
        ret = _MethodDocumenter.import_object(self)
        if not ret:
            return ret

        obj = self.parent.__dict__.get(self.object_name)
        if iscoroutinefunction(obj):
            self.directivetype = 'coroutinemethod'
            self.member_order = _MethodDocumenter.member_order + 2
        return ret


def setup(app):
    """Sphinx extension entry point."""

    # Add new directives.
    app.add_directive_to_domain('py', 'coroutine', PyCoroutineFunction)
    app.add_directive_to_domain('py', 'coroutinemethod', PyCoroutineMethod)

    # Customize annotations for anything that looks like a coroutine.
    app.add_autodocumenter(FunctionDocumenter)
    app.add_autodocumenter(MethodDocumenter)

    # Return extension meta data.
    return {
        'version': '1.0',
        'parallel_read_safe': True,
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM