【问题标题】:How do I reference a documented Python function parameter using Sphinx markup?如何使用 Sphinx 标记引用记录在案的 Python 函数参数?
【发布时间】:2012-06-23 08:58:10
【问题描述】:

我想在 Python 文档字符串的其他地方引用以前记录的函数参数。考虑以下(诚然完全人为的)示例:

def foo(bar):
    """Perform foo action
    :param bar: The bar parameter
    """

    def nested():
        """Some nested function that depends on enclosing scope's bar parameter.
        I'd like to reference function foo's bar parameter here
        with a link, is that possible?"""
        return bar * bar

    # ...
    return nested()

有没有一种使用 Sphinx 标记嵌入参数引用的简单方法,或者这会自动发生吗?

(我是一个完整的 Sphinx 新手。我一直在扫描 Sphinx 文档,但没有找到这个问题的答案,也没有找到演示正确标记的示例。)

【问题讨论】:

    标签: python python-sphinx docstring


    【解决方案1】:

    没有简单的方法可以使用sphinx 直接引用函数的参数,而且我不知道这个问题的扩展。

    documentation of the python domain 解释了哪些对象可以交叉引用。

    为用户提供对函数foo 的参数bar 的引用的一种可能方法是

    See parameter ``bar`` in :func:`foo`.
    

    也许可以通过编写扩展来直接引用。

    【讨论】:

      【解决方案2】:

      我刚刚构建了一个扩展来完成这项任务。到目前为止,它似乎正在使用独立的 HTML 构建,另外还有 readthedocs(经过更多调整)。

      扩展程序位于:https://pypi.python.org/pypi/sphinx-paramlinks/

      我现在正在为 Alembic 和 SQLAlchemy 项目推出它。 (sample)。

      我不同意链接到参数意味着文档太长的建议。 Python 标准库在这里是一个糟糕的例子,因为 stdlib 函数必须是细粒度和简单的。完成更粗粒度任务的软件,其中单个函数骑在要解决的复杂问题之上,通常会有需要更多解释的参数;这种解释通常非常有价值,因为它可以解决其他地方的特定问题,因此能够链接到它非常重要。

      【讨论】:

      • 这很好,但似乎不适用于 Googly 文档字符串(例如与 sphinxcontrib.napoleon 一起使用的文档字符串)。那是可以工作的东西吗?
      • 取决于它的工作方式。如果它将参数直接重写为重组后的文本,sphinx-paramlinks 并没有太多开箱即用的功能,因为它依赖于在 sphinx 控制它之前解析原始 RST。这主要是为了避免不得不操纵狮身人面像的内部结构。如果 Sphinx 只是在此时本地实现此功能,那会好多了。我希望我的扩展能够清楚地表明这个功能是多么迫切需要。
      • 谢谢。我期待这样的事情(这是有道理的)。我同意你的观点,这是一个迫切需要的功能。
      • 我使用 pip 安装,并尝试它,我从 Sphinx 收到此错误:Could not import extension sphinx-paramlinks (exception: No module named 'sphinx-paramlinks'),而pip list 表示已安装。我正在使用 Python 3.4。
      • 好的,我明白了。包的名称是 sphinx-paramlinks,但要添加到 conf.py 的扩展名是 sphinx_paramlinks(下划线与 dahs)。
      【解决方案3】:

      对于那些想要使用sphinx-paramlinkssphinx.ext.napoleon 的人,这里有一个补丁。只需在sphinx-paramlinks 源代码(sphinx_paramlinks\sphinx_paramlinks.py,第 50 行左右)中找到正确的片段并将其替换为:

      def cvt(m):
          directive, modifier, objname, paramname = (
              m.group(1), m.group(2) or '', name, m.group(3))
          if directive == 'param':
              refname = _refname_from_paramname(paramname, strip_markup=True)
              item = ('single', '%s (%s parameter)' % (refname, objname),
                      '%s.params.%s' % (objname, refname), '')
              if LooseVersion(__version__) >= LooseVersion('1.4.0'):
                  item += (None,)
              doc_idx.append(item)
          return ":%s %s_sphinx_paramlinks_%s.%s:" % (
              directive, modifier, objname, paramname)
      return re.sub(r'^:(param|type) ([^:]+? )?([^:]+?):', cvt, line)
      

      注意:记住正确的缩进。

      我不是 Sphinx 专家,但这似乎可以完成工作。

      【讨论】:

        【解决方案4】:

        不是说sphinx-paramlinks不是很好的解决方案,而是我有点 固执地向我的项目添加更多个扩展。

        您不会获得视觉突出显示或锚图标的好处,这很糟糕,但在该部分之前的 reStructuredText hyperlink target 至少可以让您接近:

            def from_existing_id(cls, jobid, **kwargs):
                """Instantiates a new :class:`Job` object from an existing job ID.
        
                :param jobid: the ID of the previous job
                :param kwargs: keyword arguments supported by :meth:`deserialize`,
                    *e.g.*, :ref:`ignore_missing <deserialize_params>`.
                """
                ⋮
        
            # elsewhere
            def deserialize(self, filename, copy_inputs=False, ignore_missing=False):
                """Reads a disk file into the current :class:`Job` object's config.
            
                .. _deserialize_params:
        
                :param filename: the filename to read from to disk
                :param copy_inputs: copy input files to output directory
                :param ignore_missing: don't bail if input files are missing
                """
                ⋮
        

        不过,参数列表越长,它的用处就越小。

        【讨论】:

          【解决方案5】:

          如果您正在寻找一种直接链接到bar 定义foo 的方法,那么您的文档太长,或者您要求您的读者忽略一棵树或两者的某种组合的森林。

          defaultdict Examples为例:

          Setting the :attr:`default_factory` to :class:`int` makes the
          :class:`defaultdict` useful for counting (like a bag or multiset in other
          languages):
          

          如果我懒得把五个句子读入collections.defaultdict 以找到default_factory 的含义,我可能不配被引导到那里。

          请注意,属性引用语法与上一节中的相同:

          The first argument provides the initial value for the :attr:`default_factory`
          attribute; it defaults to ``None``.
          

          但看起来 Sphinx 没有超出当前部分范围,因此将后面的引用呈现为样式文本而不是锚点。如果这是故意的,我不会感到惊讶。

          【讨论】:

          • 也许我最初的问题/示例过于简单化了。 (当我在睡眠不足的状态下发布问题时会发生这种情况:D)我更新了问题和代码示例以帮助阐明我的动机。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-12-03
          • 1970-01-01
          • 2016-07-24
          • 2018-07-15
          • 1970-01-01
          相关资源
          最近更新 更多