2015-08-03 63 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'會給你一個例外)。這很容易導致微妙的錯誤,或更糟。無論如何,文檔不應該要求改變實際代碼的行爲。 –