2015-08-03 42 views
13

我想用Sphinx记录Python对象属性。我明白我应该使用狮身人面像:ivar标签去寻找交叉引用

:ivar varname: description 
:ivar type varname: description 

但是我看到一个奇怪的现象,那就是狮身人面像搜索我的项目为变量名,并试图创建符号链接。 例如验证码:

class A(object): 
    """ 
    :ivar x: some description 
    """ 
    def __init__(self, x): 
     self.x = x 

class B(object): 
    def x(self): 
     return 1 

class C(object): 
    def x(self): 
     return 2 

将导致此错误:

module1.py:docstring of mylibrary.module1.A:None: WARNING: more than one target found for cross-reference u'x': mylibrary.module1.C.x, mylibrary.module1.B.x

我才明白正确的目的或用途:伊娃?

+0

所以,如果你删除':ivar x:一些描述',错误消失? – mzjn

+0

是的,错误是由:伊娃,如果我删除类C,然后我得到没有错误,但在HTML中,我得到一个不需要的符号链接从A.x到B.x – crusaderky

+0

我有同样的问题。它不会发生所有事件:ivar,只有在其他类/模块使用实例变量的名称的情况下。有关的事情是:伊娃不应(根据我的理解)创建一个交叉引用 – stochastic

回答

1

由于mzjn这里提到的是open issue for this SO post。在该主题中,已经发布了针对该问题的解决方法。总之,您使用内嵌注释#:而不是文档字符串。

查看用户here引用的提交中的python.py文件。文档字符串条目被删除(红线),并且他在构造函数中添加了内联注释(绿线)。

我一直在找这方面的文档,但找不到它。 例如:

(...) 
def __init__(self, function, fixtureinfo, config, cls=None, module=None): 
    #: access to the :class:`_pytest.config.Config` object for the test session 
    self.config = config 
    (...) 

正如尼克·巴斯汀该注意变通呈现从:ivar:完全不同。没有类型支持,并且它总是呈现默认值。

+0

问题是那个'#:'完全不同于':ivar:'(和它的同类)。没有类型支持,它总是呈现默认值,并且不是紧凑的。 –

+0

我觉得你,这不是一个解决方案,只是一个解决方法。我只是在这里添加了信息来完成线程,因为问题源于此处。我也会添加你的笔记。 – rll

3

这是一个猴子补丁(基于Sphinx 1.5.1),禁用ivar交叉引用。我不确定最佳解决方案是什么,因此请考虑修补程序作为实验性建议。要尝试它,请将以下代码添加到conf.py.

from docutils import nodes 
from sphinx.util.docfields import TypedField 
from sphinx import addnodes 

def patched_make_field(self, types, domain, items): 
    # type: (List, unicode, Tuple) -> nodes.field 
    def handle_item(fieldarg, content): 
     par = nodes.paragraph() 
     par += addnodes.literal_strong('', fieldarg) # Patch: this line added 
     #par.extend(self.make_xrefs(self.rolename, domain, fieldarg, 
     #       addnodes.literal_strong)) 
     if fieldarg in types: 
      par += nodes.Text(' (') 
      # NOTE: using .pop() here to prevent a single type node to be 
      # inserted twice into the doctree, which leads to 
      # inconsistencies later when references are resolved 
      fieldtype = types.pop(fieldarg) 
      if len(fieldtype) == 1 and isinstance(fieldtype[0], nodes.Text): 
       typename = u''.join(n.astext() for n in fieldtype) 
       par.extend(self.make_xrefs(self.typerolename, domain, typename, 
              addnodes.literal_emphasis)) 
      else: 
       par += fieldtype 
      par += nodes.Text(')') 
     par += nodes.Text(' -- ') 
     par += content 
     return par 

    fieldname = nodes.field_name('', self.label) 
    if len(items) == 1 and self.can_collapse: 
     fieldarg, content = items[0] 
     bodynode = handle_item(fieldarg, content) 
    else: 
     bodynode = self.list_type() 
     for fieldarg, content in items: 
      bodynode += nodes.list_item('', handle_item(fieldarg, content)) 
    fieldbody = nodes.field_body('', bodynode) 
    return nodes.field('', fieldname, fieldbody) 

TypedField.make_field = patched_make_field 

原来TypedField.make_field方法是在这里:https://github.com/sphinx-doc/sphinx/blob/master/sphinx/util/docfields.py

+0

这是行不通的!当然,这感觉有点不顺利,我不知道它是否适用于RTD,但是因为它满足了请求的参数而给予赏金(并且希望有人会在某个时候修正狮身人面像票,但这会起作用同时)。 –

+0

至少实际变化很小;一行代码替代另一行。这个补丁也可以应用到Sphinx的早期版本,顺便说一句。 – mzjn

1

有其他优点的替代方案。只需在类作用域中定义成员变量并使用纯文档字符串将其文档化即可。稍后,您可以使用py:attr:角色引用它们。这是更可读,自我记录(是的,我知道这是在,但无论如何)和反思友好的方法。

module.py

class A: 

    x = None 
    '''This way there's no issue. It is more readable and friendly 
    for class member introspection.''' 


    def __init__(self, x): 
     self.x = x 

class B: 
    '''Something about :py:attr:`.A.x`''' 

    def x(self): 
     '''Method x of B''' 
     return 1 

的README.txt

**** 
Test 
**** 

.. autoclass:: module.A 
    :members: 

.. autoclass:: module.B 
    :members: 

conf.py

extensions = ['sphinx.ext.autodoc'] 

source_suffix = '.txt' 

master_doc = 'README' 

project = 'Test' 

pygments_style = 'sphinx' 

html_theme = 'alabaster' 

html_use_index  = False 
html_show_sourcelink = False 
html_show_copyright = False 

html_sidebars = {'**': ['localtoc.html']} 

样订做PYTHONPATH=. sphinx-build . html

+0

这从根本上改变了可以用你的代码完成的事情 - 类属性与实例属性完全不同。另外,你可以在不使用':py:attr:'的情况下使用':py:attr:',但它也不以相同的方式呈现(作为类或实例属性)。 –

+0

@NickBastin我没有看到任何“根本改变”,以这种方式“定义”其成员的类。我只看到了好处。你能详细说明你的意思吗? – saaj

+0

最简单的例子是你的改变允许'A.x'有一个值,而在正确的代码中,只有'A()。x'有一个值(并且试图访问'A.x'会给你一个例外)。这很容易导致微妙的错误,或更糟。无论如何,文档不应该要求改变实际代码的行为。 –