如何使用intersphinx正确编写对外部文档的交叉引用?

时间:2015-06-19 13:50:27

标签: python opencv documentation python-sphinx autodoc

我正在尝试将外部API的交叉引用添加到我的文档中,但我面临三种不同的行为。

我正在使用sphinx(1.3.1)和Python(2.7.3),我的intersphinx映射配置为:

{
'python': ('https://docs.python.org/2.7', None),
'numpy': ('http://docs.scipy.org/doc/numpy/', None),
'cv2' : ('http://docs.opencv.org/2.4/', None),
'h5py' : ('http://docs.h5py.org/en/latest/', None)
}

使用:class:`numpy.ndarray`:func:`numpy.array`编写对numpy API的交叉引用并没有问题,正如预期的那样,我可以使用numpy.ndarray

但是,使用h5py,我可以生成链接的唯一方法是省略模块名称。例如,:class:`Group`(或:class:`h5py:Group`)为我提供Group,但:class:`h5py.Group`无法生成链接。

最后,我找不到一种方法来编写一个有效的交叉引用OpenCV API,这些似乎都不起作用:

:func:`cv2.convertScaleAbs`
:func:`cv2:cv2.convertScaleAbs`
:func:`cv2:convertScaleAbs`
:func:`convertScaleAbs`

如何正确编写对外部API的交叉引用,或配置intersphinx,以便在numpy情况下生成链接?

7 个答案:

答案 0 :(得分:22)

我尝试了解class PlanetEdge < ActiveRecord::Base belongs_to :first_planet, class_name: 'Planet' belongs_to :second_planet, class_name: 'Planet' accepts_nested_attributes_for :first_planet accepts_nested_attributes_for :second_planet end PlanetEdge.create( first_planet_attributes: { type: 'mars' }, second_planet_attributes: { type: 'jupiter' } ) 文件的内容,并希望这次我检查numpy和h5py而不是OpenCV的文件。

如何阅读intersphinx清单文件

尽管我无法找到有关阅读objects.inv文件内容的任何内容,但实际上使用intersphinx模块非常简单。

object.inv

文件结构(numpy)

在检查了numpy之后,您可以看到密钥是域:

from sphinx.ext import intersphinx
import warnings


def fetch_inventory(uri):
    """Read a Sphinx inventory file into a dictionary."""
    class MockConfig(object):
        intersphinx_timeout = None  # type: int
        tls_verify = False

    class MockApp(object):
        srcdir = ''
        config = MockConfig()

        def warn(self, msg):
            warnings.warn(msg)

    return intersphinx.fetch_inventory(MockApp(), '', uri)


uri = 'http://docs.python.org/2.7/objects.inv'

# Read inventory into a dictionary
inv = fetch_inventory(uri)
# Or just print it
intersphinx.debug(['', uri])

当您查看特定域的内容时,您可以看到如何编写交叉引用。例如,[u'np-c:function', u'std:label', u'c:member', u'np:classmethod', u'np:data', u'py:class', u'np-c:member', u'c:var', u'np:class', u'np:function', u'py:module', u'np-c:macro', u'np:exception', u'py:method', u'np:method', u'np-c:var', u'py:exception', u'np:staticmethod', u'py:staticmethod', u'c:type', u'np-c:type', u'c:macro', u'c:function', u'np:module', u'py:data', u'np:attribute', u'std:term', u'py:function', u'py:classmethod', u'py:attribute']

py:class

所以在这里,{u'numpy.DataSource': (u'NumPy', u'1.9', u'http://docs.scipy.org/doc/numpy/reference/generated/numpy.DataSource.html#numpy.DataSource', u'-'), u'numpy.MachAr': (u'NumPy', u'1.9', u'http://docs.scipy.org/doc/numpy/reference/generated/numpy.MachAr.html#numpy.MachAr', u'-'), u'numpy.broadcast': (u'NumPy', u'1.9', u'http://docs.scipy.org/doc/numpy/reference/generated/numpy.broadcast.html#numpy.broadcast', u'-'), ...} 将按预期工作。

h5py

对于h5py,域名为:

:class:`numpy.DataSource`

如果您查看[u'py:attribute', u'std:label', u'py:method', u'py:function', u'py:class'] 域名:

py:class

这就是为什么我无法将其作为numpy引用工作的原因。因此,格式化它们的好方法是{u'AttributeManager': (u'h5py', u'2.5', u'http://docs.h5py.org/en/latest/high/attr.html#AttributeManager', u'-'), u'Dataset': (u'h5py', u'2.5', u'http://docs.h5py.org/en/latest/high/dataset.html#Dataset', u'-'), u'ExternalLink': (u'h5py', u'2.5', u'http://docs.h5py.org/en/latest/high/group.html#ExternalLink', u'-'), ...}

的OpenCV

OpenCV的广告资源对象似乎格式不正确。在我希望找到域名的地方,实际上有902个功能签名:

:class:`h5py:Dataset`

如果我们取第一个值:

[u':',
 u'AdjusterAdapter::create(const',
 u'AdjusterAdapter::good()',
 u'AdjusterAdapter::tooFew(int',
 u'AdjusterAdapter::tooMany(int',
 u'Algorithm::create(const',
 u'Algorithm::getList(vector<string>&',
 u'Algorithm::name()',
 u'Algorithm::read(const',
 u'Algorithm::set(const'
 ...]

我很确定用这个文件编写OpenCV交叉引用是不可能的......

结论

我认为intersphinx以标准方式基于文档项目的内容生成{u'Ptr<AdjusterAdapter>': (u'OpenCV', u'2.4', u'http://docs.opencv.org/2.4/detectorType)', u'ocv:function 1 modules/features2d/doc/common_interfaces_of_feature_detectors.html#$ -')} ,但似乎并非如此。 因此,编写交叉引用的正确方法似乎取决于API,应该检查特定的库存对象以实际查看可用的内容。

答案 1 :(得分:18)

除了@gall的详细解答外,我还发现intersphinx也可以作为模块运行:

python -m sphinx.ext.intersphinx 'http://python-eve.org/objects.inv'

这会输出格式正确的信息。供参考:https://github.com/sphinx-doc/sphinx/blob/master/sphinx/ext/intersphinx.py#L390

答案 2 :(得分:2)

如何使用OpenCV 2.4(cv2)intersphinx

受到@Gall答案的启发,我想比较一下OpenCV和Open的内容。 numpy库存文件。我无法让sphinx.ext.intersphinx.fetch_inventory从ipython开始工作,但以下工作正常:

curl http://docs.opencv.org/2.4/objects.inv | tail -n +5 | zlib-flate -uncompress > cv2.inv
curl https://docs.scipy.org/doc/numpy/objects.inv | tail -n +5 | zlib-flate -uncompress > numpy.inv

numpy.inv有这样的行:

numpy.ndarray py:class 1 reference/generated/numpy.ndarray.html#$ -

而cv2.inv有这样的行:

cv2.imread ocv:pyfunction 1 modules/highgui/doc/reading_and_writing_images_and_video.html#$ -

因此,您可能会使用:ocv:pyfunction:`cv2.imread`而不是:py:function:`cv2.imread`链接到OpenCV文档。斯芬克斯不喜欢它:

  

警告:未知的解释文本角色“ocv:pyfunction”。

一些谷歌搜索显示OpenCV项目有自己的“ocv”sphinx域:https://github.com/opencv/opencv/blob/2.4/doc/ocv.py - 可能是因为他们需要同时记录C,C ++和Python API。

要使用它,请将ocv.py保存在狮身人面像conf.py旁边,然后修改conf.py

sys.path.insert(0, os.path.abspath('.'))
import ocv
extensions = [
    'ocv',
]
intersphinx_mapping = {
    'cv2': ('http://docs.opencv.org/2.4/', None),
}

在您的第一个文件中,您需要说:ocv:pyfunc:`cv2.imread`(不是:ocv:pyfunction:)。

Sphinx打印一些警告(unparseable C++ definition: u'cv2.imread'),但生成的html文档实际上看起来没问题,链接指向http://docs.opencv.org/2.4/modules/highgui/doc/reading_and_writing_images_and_video.html#cv2.imread。您可以编辑ocv.py并删除打印该警告的行。

答案 3 :(得分:2)

我是个固执的傻瓜,我使用了2to3Sphinx deprecated APIs chart来复兴@david-röthlisberger's ocv.py-based answer,因此它可以在Python 3.5上的Sphinx 2.3中使用。

固定版本在这里:

https://gist.github.com/ssokolow/a230b27b7ea4a31f7fb40621e6461f9a

...而我所做的快速版本是:

  1. 运行2to3 -w ocv.py && rm ocv.py.bak
  2. 在运行Sphinx和将功能重命名为其图表中的替换项之间来回循环。我相信这些是我在此步骤中唯一要做的更改:
    1. Directive现在必须从docutils.parsers.rst导入
    2. 将对l_(...)的调用替换为对_(...)的调用,并删除l_导入。
  3. 将对env.warn的呼叫替换为对log.warn的呼叫,其中log = sphinx.util.logging.getLogger(__name__)

然后,只需将其与此狮身人面像定义配对即可,获得的新内容足以与大多数用例相关:

'cv2': ('https://docs.opencv.org/3.0-last-rst/', None)

答案 4 :(得分:1)

接受的答案在新版本(1.5.x)中不再有用......

import requests
import posixpath
from sphinx.ext.intersphinx import read_inventory

uri = 'http://docs.python.org/2.7/'

r = requests.get(uri + 'objects.inv', stream=True)
r.raise_for_status()

inv = read_inventory(r.raw, uri, posixpath.join)

答案 5 :(得分:1)

为方便起见,我做了一个小的扩展,以别名化sphinx交叉引用。这很有用,因为有时当从包的__init__.py导入子模块中的对象时,对象清单会变得混乱。

另请参阅https://github.com/sphinx-doc/sphinx/issues/5603

###
# Workaround of
# Intersphinx references to objects imported at package level can"t be mapped.
#
# See https://github.com/sphinx-doc/sphinx/issues/5603

intersphinx_aliases = {
    ("py:class", "click.core.Group"):
        ("py:class", "click.Group"),
    ("py:class", "click.core.Command"):
        ("py:class", "click.Command"),
}


def add_intersphinx_aliases_to_inv(app):
    from sphinx.ext.intersphinx import InventoryAdapter
    inventories = InventoryAdapter(app.builder.env)

    for alias, target in app.config.intersphinx_aliases.items():
        alias_domain, alias_name = alias
        target_domain, target_name = target
        try:
            found = inventories.main_inventory[target_domain][target_name]
            try:
                inventories.main_inventory[alias_domain][alias_name] = found
            except KeyError:
                print("could not add to inv")
                continue
        except KeyError:
            print("missed :(")
            continue


def setup(app):
    app.add_config_value("intersphinx_aliases", {}, "env")
    app.connect("builder-inited", add_intersphinx_aliases_to_inv)

要使用此功能,我将上面的代码粘贴到conf.py中,并将别名添加到intersphinx_aliases字典中。

答案 6 :(得分:0)

检查objects.inv文件的另一种方法是使用sphobjinv模块。

您可以搜索本地或什至远程清单文件(具有模糊匹配)。例如,使用scipy:

$ sphobjinv suggest -t 90 -u https://docs.scipy.org/doc/scipy/reference/objects.inv "signal.convolve2d"

Remote inventory found.

:py:function:`scipy.signal.convolve2d`
:std:doc:`generated/scipy.signal.convolve2d`

请注意,您可能需要使用:py:func:而不是:py:function:(我很高兴知道原因)。

相关问题