sphinx
sphinx copied to clipboard
Shortening long intersphinx cross-references while keeping library explicit
I'm working with some external libraries which have most of their common classes defined in modules nested two layers deep, so I'm repeatedly having to write things like sympy.core.symbol.Symbol everywhere instead of the simpler sympy.Symbol, which is where you can actually import the class from. I know you can prepend ~ to the reference which shortens the link text but it still keeps the docstrings very verbose. Just typing Symbol (and I'm assuming .Symbol and .symbol.Symbol, etc.) works but it is no longer explicit that the reference is to an external library.
Intersphinx appears to support a special (undocumented?) syntax where the intersphinx_mapping key is prepended to the reference along with a colon, like sympy:Symbol, but after it splits off the first part it seems to expect the remaining part to match the inventory key exactly, which makes it somewhat useless. It would be great if this would use the same searching logic as regular references do, just restricting them to the given external inventory.
I'm happy to try to implement this myself and submit a PR if necessary.
Hi @jlumpe, did you manage to make some progress on this? Also, you mentioned:
Just typing
Symbol(and I'm assuming.Symboland.symbol.Symbol, etc.) works but it is no longer explicit that the reference is to an external library.
This does not work in my case. What i do is:
from external.lib.long.path import AClass
def my_method(input_class):
"""
Reference to :class:`AClass` <- does not create a link
Reference to :class:`external.lib.long.path.AClass` <- this one works
"""
Should it work like this?
Would it be somehow possible to use default_role for this purpose? I would absolutely love it if one could somehow achieve the following behaviour:
- Check if object exists in
autodoc_type_aliases/napoleon_type_aliases, if so, replace with the definition provided there - If not, then replace with the "default"
default_role
So for instance, if we had
default_role = "py:obj"
napoleon_type_aliases = {
"Tensor" : "~torch.Tensor",
}
Then the docstring
"Takes as input an `array_like` and outputs a `Tensor`."
Should be translated to
"Takes as input an :py:obj:`array_like` and outputs a :py:class:`~torch.Tensor`."
Another big advantage of this would be that help() strings would no longer be cluttered with formatting commands for sphinx!
The solution I found for this was to create replace directives in rst_epilog within conf.py, as demonstrated in this conf.py from one of my projects. One example:
.. |Inventory| replace:: :class:`~sphobjinv.inventory.Inventory`
Then, in doc source (including docstrings), cross-references to Inventory can be made simply by inserting |Inventory| into the source:
class SourceTypes(Enum):
"""|Enum| for the import mode used in instantiating an |Inventory|.
...
"""
While I'm sure it would be possible to add logic to intersphinx to, e.g., tell it to match against the tails of the object name values, instead of requiring an exact match on the full name, any solution like that would probably be brittle and hard to make general. This replace based solution can be made bespoke for each project that needs it, and has the added advantage of being even more concise and readable.