Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Intersphinx Mapping link not working with Plotly objects in signature #12360

Closed
jeertmans opened this issue May 7, 2024 · 4 comments
Closed
Labels

Comments

@jeertmans
Copy link

Describe the bug

Hello,

Note: I am not sure if I should rather report that to Plotly, but could literaly not find any information on the internet. There is one question on StackOverflow, but this has not received any answer in years, and I cannot "up" or comment this question just because I do not have enough reputation...

For some (unknown) reasons, it appears that Sphinx does not correctly link to the objects if they were defined in the signature. I would love to have all my external references actually work.

The following code

def process_plotly_kwargs(
    kwargs: MutableMapping[str, Any],
) -> Figure:
    """
    Process keyword arguments passed to some Plotly plotting utility.

    Args:
        kwargs: A mutable mapping of keyword arguments passed to
            Plotly plotting.

            .. warning::

                The keys specified below will be removed from the mapping.

    Keyword Args:
        figure (:py:class:`Figure<plotly.graph_objects.Figure>`):
            The figure that draws contents of the scene.

    Return:
        The figure used to display contents.
    """

produces:

image

As you can see, the handwritten reference to Figure is clickable, but not the one from the signature.

This is also in other online documentation, see plot_terminator_improvement from the Neptuna Python package:

image

In this function, I return one of three possible plot types, and we can clearly see that the only one failing is the Ploty one:

@contextmanager
def reuse(**kwargs: Any) -> Iterator[SceneCanvas | MplFigure | Figure]:
    """Create a context manager that will automatically reuse the current canvas / figure.

    Args:
        args: Positional arguments passed to
            :py:func:`set_defaults`.
        kwargs: Keywords arguments passed to
            :py:func:`set_defaults`.

    Return:
        The canvas or figure that is reused for this context.
    """
    ...

image

How to Reproduce

I don't have much time to build a minimal example, but I can link to my docs: https://differt.eertmans.be/v0.0.12/reference/differt.plotting.html#differt.plotting.process_plotly_kwargs.

Environment Information

Platform:              linux; (Linux-6.5.0-21-generic-x86_64-with-glibc2.35)
Python version:        3.9.19 (main, Apr 15 2024, 18:26:57) 
[Clang 17.0.6 ])
Python implementation: CPython
Sphinx version:        7.3.7
Docutils version:      0.21.2
Jinja2 version:        3.1.3
Pygments version:      2.17.2

Sphinx extensions

extensions = [
    # Built-in
    "sphinx.ext.autodoc",
    "sphinx.ext.autosummary",
    "sphinx.ext.intersphinx",
    "sphinx.ext.githubpages",
    "sphinx.ext.mathjax",
    "sphinx.ext.napoleon",
    "sphinx.ext.viewcode",
    # Additional
    "differt_dev.sphinxext.apidoc",
    "matplotlib.sphinxext.plot_directive",
    "myst_nb",
    "sphinxcontrib.bibtex",
    "sphinxext.opengraph",
    "sphinx_autodoc_typehints",
    "sphinx_copybutton",
    "sphinx_design",
    "sphinx_plotly_directive",
    "sphinx_remove_toctrees",
]


### Additional context

_No response_
@electric-coder
Copy link

electric-coder commented May 9, 2024

The example you're showing is convoluted to say the least, i.e:

    Keyword Args:
        figure (:py:class:`Figure<plotly.graph_objects.Figure>`):
            The figure that draws contents of the scene.

Here, unless I'm mistaken, you're not "declaring" but inserting an explicit cross-reference in the type field. So Figure is your shortened alias for the link to plotly.graph_objects.Figure. (Needless to say for this to work properly you'll need intersphinx correctly setup for plotly).

The usual way of writing these links would be using the shortened ~ syntax, so you'd write ~plotly.graph_objects.Figure or just .Figure - note that on occasion Sphinx won't be able to resolve all links depending on the context and if the referenced class is affected by one of the bugs listed in #11991

The surest way to get this working, currently, is to explicitly write the return type into the docstring (notice that the one field/link you're complaining about is the one you're not writing out explicitly but instead expect Sphinx to extract&link automatically from the signature, so instead of:

    Return:
        The canvas or figure that is reused for this context.

try writing the type explicitly:

    Returns:
        Figure: Description of return value

or with the path as specified in the docs in the link until you find what works:

    Returns:
        ~.plotly.graph_objects.Figure: Description of return value

@jeertmans
Copy link
Author

The example you're showing is convoluted to say the least, i.e:

    Keyword Args:
        figure (:py:class:`Figure<plotly.graph_objects.Figure>`):
            The figure that draws contents of the scene.

Here, unless I'm mistaken, you're not "declaring" but inserting an explicit cross-reference in the type field. So Figure is your shortened alias for the link to plotly.graph_objects.Figure. (Needless to say for this to work properly you'll need intersphinx correctly setup for plotly).

The usual way of writing these links would be using the shortened ~ syntax, so you'd write ~plotly.graph_objects.Figure or just .Figure - note that on occasion Sphinx won't be able to resolve all links depending on the context and if the referenced class is affected by one of the bugs listed in #11991

The surest way to get this working, currently, is to explicitly write the return type into the docstring (notice that the one field/link you're complaining about is the one you're not writing out explicitly but instead expect Sphinx to extract&link automatically from the signature, so instead of:

    Return:
        The canvas or figure that is reused for this context.

try writing the type explicitly:

    Returns:
        Figure: Description of return value

or with the path as specified in the docs in the link until you find what works:

    Returns:
        ~.plotly.graph_objects.Figure: Description of return value

I think you misunderstood my problem.

This example you cite works properly (i.e., where I put figure (:py:class:Figure<plotly.graph_objects.Figure>)), because the link is actually clickable.

The issue comes from the return type, that is obtained from the type signature (using "sphinx_autodoc_typehints" extension).

For all return values, I get a clickable link, except from Figure objects from Plotly (in the code, from plotly.graph_objects import Figure.).

@electric-coder
Copy link

The issue comes from ... (using "sphinx_autodoc_typehints" extension).

Exactly! You should post this issue at their repository since it's their extension that proposes to extract the type from the signature.

I think you misunderstood my problem.

I understood it perfectly fine!

@jeertmans
Copy link
Author

Ok, will do that then :-)

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 11, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants