Python 重构模块并保持向后兼容性,包括intersphinx
给定一个python包Python 重构模块并保持向后兼容性,包括intersphinx,python,python-sphinx,api-design,Python,Python Sphinx,Api Design,给定一个python包pack提供pack.foo.Bar类: pack/ __init__.py # empty foo.py # content of foo.py """ This module does stuff using the :class:`pack.foo.Bar` class. """ class Bar(object): pass
pack
提供pack.foo.Bar
类:
pack/
__init__.py # empty
foo.py
# content of foo.py
"""
This module does stuff using the :class:`pack.foo.Bar` class.
"""
class Bar(object):
pass
# much more code here
我想将pack.foo
模块重构成一个包,以便Bar
类被移动到pack/foo/Bar.py
文件中。为了保持向后兼容性,我可以在pack/foo/\uuuu init\uuuu.py
文件中添加以下内容:
"""
This module does stuff using the :class:`pack.foo.Bar` class.
"""
from pack.foo.bar import Bar
__all__ = ['Bar']
API用户仍然可以使用pack.foo导入栏中的
还有一个问题:使用sphinx时的引用。sphinx在pack/foo/\uuuuu init\uuuuuu.py
中解析docstring时,找不到目标:
WARNING: py:class reference target not found pack.foo.bar.Bar
这将破坏用户在使用扩展时制作的文档
重构包结构并保持完全向后兼容性(包括sphinx对象清单)的正确方法是什么?以下是我自己的答案和一些发现
在这种情况下没有什么灵丹妙药
首先,生成的代码文档将从文件布局推断模块布局。这意味着在pack/foo.py
中定义的Bar
类将被记录为pack.foo.Bar
,无论在pack/\uuuuu init\uuuuuu.py
中发生什么导入损坏
第二,我们仍然可以使用。Autodoc只是尝试正常导入文档化符号,因为它们是在重新构造的文本中定义的。这样,您就可以使用
.. autoclass:: pack.Bar
:members:
不过有一个陷阱。任何记录的符号(以及它们的每个依赖项,以传递方式)都必须与打算记录的名称空间完全相同。考虑我们例子中的一个变体,提供一个附加类<代码> Baz < /代码>:
pack/
__init__.py
# content of __init__.py
from pack.foo.bar import Bar, Baz
__all__ = ['Bar', 'Baz']
foo.py
# content of foo.py
"""
This module does stuff using the :class:`pack.foo.Bar` class.
"""
class Bar(object):
pass
class Baz(Bar): # Here, sphinx thinks that Baz inherits from
pass # pack.foo.Bar because Bar.__module__ is
# pack.foo in this context.
Sphinx将无法导入pack.foo.Bar
,因为它只能作为pack.Bar
导入,因为pack/\uu init\uuuuuuuuuuuuupy
的内容
为了实现这一点,必须找到一种方法,在API代码本身中只使用包的API提供的精确导入布局。例如,在我们的示例中,可以通过在单独的文件中定义Bar
和Baz
类来实现这一点。祝你好运,小心循环进口