Sphinx :ivar tag goes looking for cross-references

前端 未结 4 698
粉色の甜心
粉色の甜心 2021-01-07 22:35

I want to document Python object attributes with Sphinx. I understand I should use

:ivar varname: description
:ivar type varname: description
相关标签:
4条回答
  • 2021-01-07 23:09

    Here is a workaround provided by @acrisci on github: prefix your variable name with ~.. For example replace

    :ivar float bandwidth: blah
    

    with this:

    :ivar float ~.bandwidth: blah
    

    Source: https://github.com/sphinx-doc/sphinx/issues/2549#issuecomment-488896939

    0 讨论(0)
  • 2021-01-07 23:11

    As mzjn referred there is an open issue for this SO post. In that thread there is also already a work-around for the issue posted. In sum, you use inline comments #: instead of the docstring.

    Take a look at the python.py file in the commit referred by the user here. The docstring entries were removed (red lines), and he added inline comments in the constructor (green lines).

    I have been looking for documentation on this but could not find it. For instance:

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

    As noted by Nick Bastin this work-around renders completely differently from :ivar:. There is no type support, and it always renders the default value.

    0 讨论(0)
  • 2021-01-07 23:28

    Here is a monkey patch (based on Sphinx 1.5.1) that disables ivar cross-references. I'm not sure what the best solution is, so consider the patch an experimental suggestion. To try it out, add the code below to 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
    

    The original TypedField.make_field method is here: https://github.com/sphinx-doc/sphinx/blob/master/sphinx/util/docfields.py.

    0 讨论(0)
  • 2021-01-07 23:34

    There's an alternative with other advantages. Just define you member variables at class scope and document them with plain docstring. Later you can reference them with py:attr: role. It's more readable, self-documented (yeah, I know this is under python-sphinx, but anyway) and introspection-friendly approach.

    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']}
    

    Build like PYTHONPATH=. sphinx-build . html.

    0 讨论(0)
提交回复
热议问题