简体   繁体   中英

How to link typing-like nested classes and other urls with Sphinx and RST

Using intersphinx and autodoc , having:

:param stores: Array of objects
:type stores: list[dict[str,int]]

Would result in an entry like:

Is there a way to convert list[dict[str,int]] outside of the autodoc :param: derivative (or others like :rtype: ) with raw RST (within the docstring) or programatically given a 'list[dict[str,int]]' string?

Additionally, is it possible to use external links within the aforementioned example?

Example

Consider a script.py file:

def some_func(arg1):
  """
  This is a head description.

  :param arg1: The type of this param is hyperlinked.
  :type arg1: list[dict[str,int]]

  Is it possible to hyperlink this, here: dict[str,list[int]]

  Or even add custom references amongst the classes: dict[int,ref]

  Where *ref* links to a foreign, external source.
  """ 

Now in the Sphinx conf.py file add:

extensions = [
    'sphinx.ext.autodoc',
    'sphinx.ext.intersphinx'
]

intersphinx_mapping = {
  'py': ('https://docs.python.org/3', None),
}

In your index.rst , add:

Title
=====

.. toctree::
  :maxdepth: 2

.. autofunction:: script.some_func

And now simply make the html for the page.

The list[dict[str,int]] next to :type arg1: will be hyperlinked as shown at the beginning of this question, but dict[str,list[int]] obviously won't. Is there a way to make the latter behave like the former?

I reached a solution after digging around sphinx's code.

Injecting External References (:param:)

I created a custom extension that connects to the missing-reference event and attempts to resolve unknown references.

Code of reflinks.py :

import docutils.nodes as nodes

_cache = {}

def fill_cache(app):
    _cache.update(app.config.reflinks)

def missing_reference(app, env, node, contnode):
    target = node['reftarget']
    try:
        uri = _cache[target]
    except KeyError:
        return
    newnode = nodes.reference('', '', internal = False, refuri = uri)
    if not node.get('refexplicit'):
        name = target.replace('_', ' ') # style
        contnode = contnode.__class__(name, name)
    newnode.append(contnode)
    return newnode

def setup(app):
    app.add_config_value('reflinks', None, False)
    app.connect('builder-inited', fill_cache)
    app.connect('missing-reference', missing_reference, priority = 1000)

Explanation

I consulted intersphinx 's methodology for resolving unknown references and connected the function with high priority so it's hopefully only consulted as a last result.

Followup

Include the extenion.

Adding to conf.py :

reflinks = {'google': 'https://google.com'}

Allowed for script.py :

def some_func(arg1):
    """
    :param arg1: Google homepages.
    :type arg1: dict[str, google]
    """

Where dict[str, google] are now all hyperlinks.

Formatting Nested Types

There were instances where I wanted to use type structures like list[dict[str,myref]] outside of fields like :param: , :rtype: , etc. Another short extension did the trick.

Code of nestlinks.py :

import sphinx.domains.python as domain
import docutils.parsers.rst.roles as roles

_field = domain.PyTypedField('class')

def handle(name, rawtext, text, lineno, inliner, options = {}, content = []):
    refs = _field.make_xrefs('class', 'py', text)
    return (refs, [])

def setup(app):
    roles.register_local_role('nref', handle)

Explanation

After reading this guide on roles, and digging here and here I realised that all I needed was a dummy field to handle the whole reference-making work and pretend like it's trying to reference classes.

Followup

Include the extension.

Now script.py :

def some_func(arg1):
    """
    :param arg1: Google homepages.
    :type arg1: dict[str, google]

    Now this :nref:`list[dict[str,google]]` is hyperlinked!
    """

Notes

  • I am using intersphinx and autodoc to link to python's types and document my function's docstrings.
  • I am not well-versed in Sphinx's underlying mechanisms so take my methodology with a grain of salt.
  • The examples are provided are adjusted for the sake of being re-usable and generic and have not been tested.
  • The usability of such features is obviously questionable and only necessary when libraries like extlinks don't cover your needs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM