Guidedog 手册 0.2.0
语言
本页内容
Guidedog / 文档 0.2.0

用 autodoc 编写 Python 文档

Guidedog 通过读取源代码生成 Python 文档,不会导入软件包。docstring 和函数签名成为文档图的一部分。仅在运行时创建的对象需要显式说明。这是有意划定的边界。

配置方法

列出扩展,并告诉 Guidedog 软件包相对于源目录的位置,就像 sys.path 告诉 Python 那样:

extensions = ["sphinx.ext.autodoc"]
autodoc_source_paths = ["../src"]

guidedog migrate 会读取 conf.py 中用于定位软件包的语句,例如 sys.path.insert(0, os.path.abspath('..')),并为你生成 autodoc_source_paths。对于安装在其他位置的软件包,必须添加其所在目录,例如依赖项的源代码检出目录;Guidedog 不会搜索 Python 自己的 site-packages。

接下来,这些指令的用法与 Sphinx 相同:

.. automodule:: shop.cart
   :members:
   :show-inheritance:

.. autoclass:: shop.Cart
   :members: add, remove
   :inherited-members:

支持 Sphinx 9.1 的全部选项,含义也相同::members:、:undoc-members:、:private-members:、:special-members:、:inherited-members:、:exclude-members:、:member-order:、:show-inheritance:、:imported-members:、:ignore-module-all:、:class-doc-from:、:no-value:、:annotation:、:no-index:、:no-index-entry:、:synopsis:、:platform:、:deprecated:,以及取消 autodoc_default_options 的 no- 形式。

设置

这些 conf.toml 设置沿用 Sphinx 的名称、取值和默认值。

autodoc_source_paths

Guidedog 专用设置:按顺序列出查找 Python 模块的目录,路径相对于源文件目录。只读取这些目录下的文件;若符号链接指向目录外部,则拒绝访问。

autoclass_content

指定用于描述类的文档字符串:"class"(默认)、"init" 或 "both"。

autodoc_class_signature

"mixed"(默认)或 "separated";后者将 __init__ 单独作为方法记入文档。

autodoc_default_options

为所有指令设置默认选项的表,例如 members = true 或 member-order = "bysource"。值为 false 时不添加该选项。

autodoc_docstring_signature

true(默认):若文档字符串首行为 name(args) -> result 这样的形式,则将其作为签名。

autodoc_inherit_docstrings

true(默认):没有文档字符串的成员继承基类的文档字符串。

autodoc_member_order

"alphabetical"(默认)、"groupwise" 或 "bysource"。

autodoc_preserve_defaults

false(默认):按 repr() 的表示方式显示默认值;true 则保留源码中的写法。

autodoc_typehints

"signature"(默认)、"description"(使用 :type: 和 :rtype: 字段)、"both" 或 "none"。

autodoc_typehints_description_target

"all"(默认)、"documented" 或 "documented_params"。

autodoc_typehints_format

"short"(默认)或 "fully-qualified"。

autodoc_use_type_comments

true(默认):将 # type: 注释作为类型注解。

strip_signature_backslash

与 Sphinx 一样,将签名中的反斜杠加倍。

autodoc_mock_imports, autodoc_type_aliases, autodoc_warningiserror

接受这些设置。由于不会导入模块,因此无需模拟导入;不应用类型别名。

Guidedog 如何推断 Python 的行为

名称按照 Python 的绑定规则解析。例如,在包的 __init__.py 中写入 from .app import Flask,flask.Flask 就指向 flask/app.py 中定义的类,autodoc 会标注 :canonical: flask.app.Flask。基类也按相同方式解析;方法解析顺序按 Python 的规则计算,继承的成员从基类源码中读取。仅在 if TYPE_CHECKING: 下导入的名称在运行时不存在,因此引用这些名称的注解会保留原样,与 Sphinx 一致。

文档字符串与 Python 实际存储的内容一致:处理转义,并按 Python 3.13 编译器的规则去除缩进。属性文档来自 Sphinx 分析器读取的位置:赋值行末尾或上方的 #: 注释,以及赋值后紧接的字符串字面量。函数签名来自 def。类的签名按照 Python 的查找规则来自元类的 __call__、__new__ 或 __init__;dataclass 或 NamedTuple 的签名来自字段。@overload 变体会替代实现本身的签名。

不运行 Python 就无法获知的内容

如果源码无法揭示 Python 的实际行为,Guidedog 会明确指出涉及的对象。无法生成文档时给出警告;能生成文档但信息少于 Sphinx 时给出说明,使用 -v 可查看。

  • 编译后的模块(.so、.pyd)没有可读取的源码,因此找不到其中的对象。
  • 运行代码得到的值(app = Flask(__name__)、now = datetime.now())不会生成 :value:;需要计算的默认值保留源码写法。
  • 由源码搜索路径之外的装饰器(@click.command())生成的函数,按被装饰的原函数生成文档。
  • 源码搜索路径之外的包中的类,使用导入时的路径命名;该路径可能与定义类的模块不同。它的成员、构造函数签名以及可继承的文档字符串都无法确定。
  • 无法读取内置类型的文档字符串。因此,如果某个方法没有自己的文档字符串,只能从 dict 继承,就不将它列入文档。
  • 不会执行处理 autodoc 事件(autodoc-process-docstring、autodoc-skip-member 等)的 Python 扩展。
  • 嵌套深度远超正常代码的模块不会进行分析,并给出 autodoc.too_deep 警告。Python 本身拒绝 200 层嵌套括号;Guidedog 也拒绝含数百个操作数的 + 链。
  • 会产生倍增的工作量都有上限。沿导入和别名查找名称时,单条路径最多 48 步,总计最多 100,000 步。类型别名或常量展开最多 10,000 步,超过后保留源码写法。类的 MRO 最多追踪 100 层;单条指令最多生成 10,000 条指令,超过时给出 autodoc.limit 警告。只有以自身名称包含自身的类才会达到最后这一上限。

将缺失包的源码目录加入 autodoc_source_paths,即可解决上述大部分限制。

重新构建

autodoc 指令读取的每个 Python 文件都是该页面的依赖项。修改文件后,下次构建会重新读取页面。未找到对象的页面会在每次构建时重读,因此源码中出现该对象后即可识别。

安全性

构建文档绝不运行项目代码。Guidedog 将 Python 源码作为文本读取,并使用与 include 相同的路径限制:仅访问 autodoc_source_paths 下的文件,不通过链接访问外部路径。