简体   繁体   English

sphinx 可以忽略 python 文档字符串中的某些标签吗?

[英]Can sphinx ignore certain tags in python docstrings?

I'm documenting my project with sphinx and using the sphinxcontrib.napoleon extension which lets me use google style docstrings.我正在使用 sphinx 记录我的项目,并使用 sphinxcontrib.napoleon 扩展,这让我可以使用谷歌风格的文档字符串。

Here is a function from my project这是我项目中的 function

def nn_normalized_weight(normweight_fn, qaid2_nns, qreq_):
    """
    Weights nearest neighbors using the chosen function

    Args:
        normweight_fn (func): chosen weight function e.g. lnbnn
        qaid2_nns (dict): query descriptor nearest neighbors and distances. qaid -> (qfx2_nnx, qfx2_dist)
        qreq_ (QueryRequest): hyper-parameters

    Returns:
        tuple(dict, dict) : (qaid2_weight, qaid2_selnorms)

    Example:
        >>> from ibeis.model.hots.nn_weights import *
        >>> from ibeis.model.hots import nn_weights
        >>> ibs, daid_list, qaid_list, qaid2_nns, qreq_ = nn_weights.testdata_nn_weights()
        >>> qaid = qaid_list[0]
        >>> #----
        >>> normweight_fn = lnbnn_fn
        >>> tup1 = nn_weights.nn_normalized_weight(normweight_fn, qaid2_nns, qreq_)
        >>> (qaid2_weight1, qaid2_selnorms1) = tup1
        >>> weights1 = qaid2_weight1[qaid]
        >>> selnorms1 = qaid2_selnorms1[qaid]
        >>> #---
        >>> # test NN_WEIGHT_FUNC_DICT
        >>> #---
        >>> nn_normonly_weight = nn_weights.NN_WEIGHT_FUNC_DICT['lnbnn']
        >>> tup2 = nn_normonly_weight(qaid2_nns, qreq_)
        >>> (qaid2_weight2, qaid2_selnorms2) = tup2
        >>> selnorms2 = qaid2_selnorms2[qaid]
        >>> weights2 = qaid2_weight2[qaid]
        >>> assert np.all(weights1 == weights2)
        >>> assert np.all(selnorms1 == selnorms2)

    Ignore:
        #from ibeis.model.hots import neighbor_index as hsnbrx
        #nnindexer = hsnbrx.new_ibeis_nnindexer(ibs, daid_list)
    """
    #utool.stash_testdata('qaid2_nns')
    #
    K = qreq_.qparams.K

    Knorm = qreq_.qparams.Knorm
    rule  = qreq_.qparams.normalizer_rule
    # Prealloc output
    qaid2_weight = {qaid: None for qaid in six.iterkeys(qaid2_nns)}
    qaid2_selnorms = {qaid: None for qaid in six.iterkeys(qaid2_nns)}
    # Database feature index to chip index
    for qaid in six.iterkeys(qaid2_nns):
        (qfx2_idx, qfx2_dist) = qaid2_nns[qaid]
        # Apply normalized weights
        (qfx2_normweight, qfx2_normmeta) = apply_normweight(
            normweight_fn, qaid, qfx2_idx, qfx2_dist, rule, K, Knorm, qreq_)
        # Output
        qaid2_weight[qaid]   = qfx2_normweight
        qaid2_selnorms[qaid] = qfx2_normmeta
    return (qaid2_weight, qaid2_selnorms)

When I parse this with sphinx-apidoc It parses the args, returns, and example section correctly, but then it tags on the ignore section as well.当我用 sphinx-apidoc 解析它时,它正确地解析了 args、返回和示例部分,但随后它也在忽略部分标记。

The ignore section looks very ugly as it has had all its formating stripped away.忽略部分看起来非常难看,因为它的所有格式都被剥离了。 I would like to remove it.我想删除它。 Is there any way to configure sphinx to ignore certain tags like Ignore:?有什么方法可以配置 sphinx 忽略某些标签,如忽略:?

I'm aware I could take it out of the docstr, but this is very inconvient as I'd like to have a place without leading # sybmols where I can copy and paste test code to and from ipython.我知道我可以将它从 docstr 中取出,但这非常不方便,因为我希望有一个没有前导 #sybmols 的地方,我可以在 ipython 中复制和粘贴测试代码。

Ok, I think I've got a solution for you: 好的,我想我有一个解决方案:

sphinx.ext.autodoc offers a listener sphinx.ext.autodoc.between that can be used to determine what parts of the docstrings autodoc collects should be kept or discarded: sphinx.ext.autodoc提供了一个监听器sphinx.ext.autodoc.between ,可用于确定应保留或丢弃autodoc收集的docstrings的哪些部分:

sphinx.ext.autodoc.between(marker, what=None, keepempty=False, exclude=False)

Return a listener that either keeps, or if exclude is True excludes, lines between lines that match the marker regular expression. 返回一个侦听器,该侦听器保留,或者如果excludeTrue ,则排除标记正则表达式匹配的行之间的行。 If no line matches, the resulting docstring would be empty, so no change will be made unless keepempty is true. 如果没有行匹配,则生成的docstring将为空,因此除非keepempty为true,否则不会进行任何更改。

If what is a sequence of strings, only docstrings of a type in what will be processed. 如果有什么串序列,在什么将只处理一种类型的文档字符串。

sphinxcontrib.napoleon works on the docstrings that autodoc collects , so this should work for napoleon as well. sphinxcontrib.napoleon autodoc收集的文档字符串 ,因此这对napoleon也适用。

Usage example 用法示例

Change your docstring like this: 像这样更改你的文档字符串:

"""
Args:
    ...

Returns:
    ...

IGNORE:
    #from ibeis.model.hots import neighbor_index as hsnbrx
    #nnindexer = hsnbrx.new_ibeis_nnindexer(ibs, daid_list)
IGNORE
"""

So make sure to surround the part you want to exclude with two lines that contain a unique marker (in this example the uppercase word IGNORE ). 因此,请确保使用包含唯一标记的两行(在此示例中为大写单词IGNORE )围绕要排除的部分。

Add the following to your Sphinx project's conf.py (I'd probably append it all at the bottom as one block, but that's your call): 将以下内容添加到您的Sphinx项目的conf.py (我可能会将其全部添加到底部作为一个块,但这是您的调用):

from sphinx.ext.autodoc import between

def setup(app):
    # Register a sphinx.ext.autodoc.between listener to ignore everything
    # between lines that contain the word IGNORE
    app.connect('autodoc-process-docstring', between('^.*IGNORE.*$', exclude=True))
    return app

(If your conf.py already contains a setup() function, just extend it accordingly). (如果你的conf.py已经包含setup()函数,只需相应地扩展它)。

This will create and register a listener that gets called everytime autodoc processes a docstring. 这将创建并注册一个每次autodoc处理文档字符串时调用的侦听器。 The listener then gets the chance to filter the docstring. 然后,监听器有机会过滤docstring。 In this example, the listener will discard everything between lines that match the regular expression ^.*IGNORE.*$ - so it's up to you to choose this expression so that it's specific enough for your project, but doesn't require a marker that adds too much noise. 在此示例中,侦听器将丢弃与正则表达式匹配的行之间的所有内容^.*IGNORE.*$ - 因此,您可以选择此表达式,以便它对您的项目足够具体,但不需要标记增加了太多的噪音。

( Note : If all you change is your conf.py , Sphinx won't pick up that change because the doctree didn't change. So make sure you run make clean (or rm -rf _build/* ) before building your docs again). 注意 :如果你改变的只是你的conf.py ,那么Sphinx不会接受这个改变,因为doctree没有改变。所以确保你在再次构建你的文档之前运行make clean (或rm -rf _build/* ) )。

I stumbled upon this question I wrote 7 years ago today.我偶然发现了我 7 年前的今天写的这个问题。

At the time I thought Lukas Graf's answer would be fine, but being forced to have and open and close Ignore tag was too much overhead (espeically in Python), so I stopped doing it and I forgot about it.当时我认为 Lukas Graf 的回答会很好,但被迫打开和关闭 Ignore 标签的开销太大(特别是在 Python 中),所以我停止这样做并且忘记了它。 Fast forward, my API docs are littered with ignores, and I really want to get rid of them.快进,我的 API 文档到处都是忽略,我真的很想摆脱它们。 I looked at the answer with older and wiser eyes, and I have an actual solution that isn't hacky.我用更年长、更睿智的眼光审视了答案,并且我有一个不老套的实际解决方案。 This actually solves the problem.这实际上解决了问题。

def setup(app):
    # https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html
    from sphinx.application import Sphinx
    from typing import Any, List

    what = None
    # Custom process to transform docstring lines
    # Remove "Ignore" blocks
    def process(app: Sphinx, what_: str, name: str, obj: Any, options: Any, lines: List[str]
                ) -> None:
        if what and what_ not in what:
            return
        orig_lines = lines[:]

        ignoring = False
        new_lines = []
        for i, line in enumerate(orig_lines):
            if line.startswith('Ignore'):
                # We will start ignoring everything indented after this
                ignoring = True
            else:
                # if the line startswith anything but a space stop
                # ignoring the indented region.
                if ignoring and line and not line.startswith(' '):
                    ignoring = False

            if not ignoring:
                new_lines.append(line)

        lines[:] = new_lines
        # make sure there is a blank line at the end
        if lines and lines[-1]:
            lines.append('')

    app.connect('autodoc-process-docstring', process)
    return app

The idea is very similar, except I looked at the source code of what "between" does, and it is possible to just write your own custom function that processes your docstring in whatever way you want (although it is postprocessed by neopoleon, but that doesn't matter in this case).这个想法非常相似,只是我查看了“between”的源代码,并且可以编写自己的自定义 function 以您想要的任何方式处理您的文档字符串(尽管它是由 neopoleon 进行后处理的,但是在这种情况下无关紧要)。

Given the lines of each processsed docstring I can check to see if it starts with Ignore, then ignore everything until the indendation scope ends.给定每个已处理文档字符串的行,我可以检查它是否以忽略开头,然后忽略所有内容,直到缩进 scope 结束。 No regex "between" tags needed.不需要正则表达式“之间”标签。

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

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