Search code examples
python-sphinxrestructuredtextautodoccross-reference

How to reference a dict with sphinx-autodoc?


:data:`~package._module._DICT_NAME`

Doesn't work, _DICT_NAME is rendered as if referenced, but with no hyperlink. Same with :obj:. Putting it in a function isn't an acceptable workaround.


Minimal conf.py:

extensions = ['sphinx.ext.autodoc']
templates_path = ['_templates']
exclude_patterns = []
html_static_path = ['_static']

def skip(app, what, name, obj, would_skip, options):
    if name.startswith('_'):  # include private methods
        return False
    return would_skip

def setup(app):
    app.connect("autodoc-skip-member", skip)

(Actual context: conf.py, attempted cross-reference, the dict, rendered docs (scroll up a little))


Solution

  • Before trying to reference _DICT_NAME verify it's been put in the general index (and thus became cross-referenceable!!). If using an autodoc directive without :undoc-members: option the dictionary won't be include if it doesn't have a comment. Variables can't have docstrings, so you need to use a comment #: before or """ immediately after, in the py for autodoc to pick it up.

    Unless you are explicitly including the dictionary in the .rst with py:data:, using Domains and roles. Or, by including it in the .rst (using autodata or autoattribute, in case your automodule or autoclass doesn't pick it up and you're using directives of the autodoc extension.

    Then your _DICT_NAME is also a private variable, so you need to check the conf.py settings to see if it's included like napoleon_include_private_with_doc = True, if you're using Sphinx Napoleon extension.

    _DICT_NAME is rendered as if referenced, but no hyperlink.

    First check that it shows up documented in the final rendering of you documentation be it HTML or other. If it is included and has a comment it can be then be cross-referenced and the link will be generated.

    How to reference a dict with sphinx-autodoc?

    Notice you aren't referencing with autodoc. Autodoc is extracting the docstring where you write its directive in your .rst. Your :data: cross-referencing is done by domain and roles. Although you can have referencing inside your docstring that is afterwards extracted by autodoc and finally rendered, altogether, by the Sphinx tool.

    EDIT after OP added MCVE:

    First problem I see is this, your dictionary _DEFAULT_TRAINGEN_CFG is in module _default_configs.py...

    So, the cross-reference you wrote should be right :data:~deeptrain.util._default_configs._DEFAULT_TRAINGEN_CFG\....BUT, did you actually include this module in any .rst file? I don't think so, looking at deeptrain.util.rst the _default_configs.py module is not present in any automodule directive, so there's nothing to reference (that's why the hyperlink isn't generated)...

    Three examples of cross-references:

    A module level dictionary, dict_document.py

    #: a comment on your dictionary
    _DEFAULT_TRAINGEN_CFG = dict(
        dynamic_predict_threshold_min_max = None,
        checkpoints_overwrite_duplicates  = True,
    )
    
    1. One possible dict_document.rst
    dic_document module
    ===================
    
    .. automodule:: dict_document
    
    some text to break, lets reference:
    
    :data:`_DEFAULT_TRAINGEN_CFG` WORKS !!
    

    The result:

    enter image description here

    1. Another possible dict_document.rst
    dic_document module
    ===================
    Lets try a more explicit apporach:
    
    .. automodule:: dict_document
        :exclude-members: _DEFAULT_TRAINGEN_CFG
    
        .. autodata:: _DEFAULT_TRAINGEN_CFG
    
    some text to break, lets reference:
    
    :data:`_DEFAULT_TRAINGEN_CFG` WORKS !!
    

    The result:

    enter image description here

    1. One more possible dict_document.rst
    dic_document module
    ===================
    
    Lets try without using autodoc:
    
    .. py:module:: Sphinx_test.dict_document
    
    .. py:data:: _DEFAULT_TRAINGEN_CFG
        :type: dict[str, Any]
    
    Notice the docstring wasn't extracted from .py and included here because autodoc directives weren't used.
    
    some text to break, lets reference:
    
    :py:data:`~._DEFAULT_TRAINGEN_CFG` WORKS !!
    

    The result:

    enter image description here


    Minimal example, without modifying .rst, in module.py; note that the comment can be empty:

    #:
    some_dict = {"a": 1}
    

    Some docstring:

    """
    :data:module.some_dict
    """