Подтвердить что ты не робот

Sphinx: тег ivar ищет перекрестные ссылки

Я хочу документировать атрибуты объекта Python с помощью Sphinx. Я понимаю, что я должен использовать

:ivar varname: description
:ivar type varname: description

Однако я вижу странное поведение, то есть Sphinx ищет мой проект для имени переменной и пытается создать символические ссылки. Например. этот код:

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 mylibrary.module1.A: Нет: ПРЕДУПРЕЖДЕНИЕ: для перекрестной ссылки u'x 'найдено более одной цели: mylibrary.module1.C.x, mylibrary.module1.B.x

Я неправильно понял цель или использование: ivar?

4b9b3361

Ответ 1

Вот патч обезьяны (на основе 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 метод TypedField.make_field находится здесь: https://github.com/sphinx-doc/sphinx/blob/master/sphinx/util/docfields.py.

Ответ 2

В качестве mzjn существует открытая проблема для этого сообщения SO. В этой теме также есть проблема с размещенной проблемой. В общем, вы используете встроенные комментарии #: вместо docstring.

Взгляните на файл python.py в комманде, указанном пользователем здесь. Записи docstring были удалены (красные строки), и он добавил встроенные комментарии в конструктор (зеленые линии).

Я искал документацию по этому вопросу, но не смог найти его. Например:

(...)
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
    (...)

Как отмечено Nick Bastin, эта обходная работа совершенно отличается от :ivar:. Нет поддержки типа, и она всегда отображает значение по умолчанию.

Ответ 3

Есть альтернатива другим преимуществам. Просто определите переменные-члены в классе и документируйте их с помощью простой docstring. Позже вы можете ссылаться на них с помощью py:attr:. Это более читаемое, самодокументированное (да, я знаю, что это находится под , но в любом случае) и удобный подход к интроспекции.

module.py

class A:

    x = None
    '''This way there 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.

Ответ 4

Вот обходной путь, предоставленный @acrisci для github: добавьте префикс имени вашей переменной к ~.. Например, заменить

:ivar float bandwidth: blah

с этим:

:ivar float ~.bandwidth: blah

Источник: https://github.com/sphinx-doc/sphinx/issues/2549#issuecomment-488896939