jbms / sphinx-immaterial

Adaptation of the popular mkdocs-material material design theme to the sphinx documentation system
https://jbms.github.io/sphinx-immaterial/
Other
177 stars 28 forks source link

Referenced targets defined in docstrings are unresolved in summaries #293

Open funkyfuture opened 9 months ago

funkyfuture commented 9 months ago

assuming that a documented docstring contains a hyperlink in this form:

def foo():
    """
    See this_ for more.

    .. _this: https://this.net
    """

the build doesn't find that target: ERROR: Unknown target name: "this".

a workaround is to define the targets in the text document that includes the automodule directive which eventually includes the function.

2bndy5 commented 9 months ago

I think you're just fighting scoping. What happens if you define the URL first, then refer to it after it is defined?

funkyfuture commented 9 months ago

thanks for the hint, that works. but i'd consider that a workaround as well as it deviates from the common behaviour. and the source code's contents are rather weird, it's like starting a text with end notes.

funkyfuture commented 9 months ago

it may be worth mentioning that this only affects HTML pages with summaries, for the individual page that documents foo everything is fine. setting the generate_synopses option to None doesn't change the results.

2bndy5 commented 9 months ago

As for being specific to this theme, I don't know where to fix that; the "pages with summaries" tidbit sounds like a lead. The stuff you put in docstrings gets parsed "separately" from rst file content; this is due to using the sphinx.ext.autodoc extension's API. Some of that API maybe monkey-patched by this theme to implement certain features. @funkyfuture Can you disclose more detail like a sample project (in a .zip file) that can reproduce this?


I don't think of it as a workaround; it's just more declarative writing to me.

If I reference a substitution more than once in multiple docstrings of a module, then I'd put the definition in either the

Both of which use the define-substitution first approach. If I need to use the same substitution multiple times in the same docstring, then I still put it before the first reference. It may look like "starting a text with end notes", but I see it as a rst comment or rst metadata (and my eyes skim past it).

Although I do see that the docutils example does not define the substitution first.

funkyfuture commented 9 months ago

thanks for the feedback.

i meanwhile found out that my initial description doesn't cover all. i found one case where the mentioned workaround doesn't help and also the references to sections with :ref:`Section Title` can be affected.

i'm occasionaly working on migrating / evaluating an existing, not too uncomplex documentation to this theme; i can provide an archive, but would like to progress a little more before i share it.


it's just more declarative writing to me.

but should the usage of a theme require a specific style for docstrings?

If I reference a substitution more than once in multiple docstrings

i may have several references to the same external target all across the general prose and docstrings of a documentation. particularly within docstrings the possible redundancy is useful as the docstrings are self-contained and complete for readers of the source code.

but I see it as a rst comment or rst metadata (and my eyes skim past it).

as a human reader whose first impulse is not to parse the text into abstract categories, i don't agree. neither have i ever seen that form in the wild. functionally the foot-/endnote allegory works for me.

jbms commented 9 months ago

The summary is currently generated by first applying any text transformations to the docstring (e.g. sphinx.ext.napoleon) and then extracting the first paragraph (by presence of newline characters) textually, then parsing it as rST within the context of the summary document.

https://github.com/jbms/sphinx-immaterial/blob/52384ce01d95151d65d1b865dd7e73ad5a4d6e00/sphinx_immaterial/apidoc/python/apigen.py#L584C35-L584C35

https://github.com/jbms/sphinx-immaterial/blob/52384ce01d95151d65d1b865dd7e73ad5a4d6e00/sphinx_immaterial/apidoc/python/apigen.py#L1401

This saves the cost of parsing an entire long docstring only to throw away most of the result, and also avoids other issues that might occur such as duplicate labels, assuming no labels are defined in the first paragraph.

However, it doesn't work with the footnote hyperlink syntax. A different strategy would be needed to support that.

funkyfuture commented 9 months ago

thanks for the explanation. without knowledge of the overall build process; wouldn't it be best to produce (and cache) all the HTML output and derive the summaries from that?

or what about dismissing links to other resources in the summaries altogether? atm i think that is a proper result, in any case it's preferable to broken links.

jbms commented 9 months ago

The document is built by first parsing each rST document into an intermediate document tree, performing a number of transformations on all of the document trees, and then converting each document tree to html.

I think the footnote-type references are resolved as an early transformation right after parsing the rST.

Extracting summaries from the html is problematic because the document trees are all built before any html is generated. In principle the summary could be extracted from the document tree of the one document that contains the full version of the description, and then substituted like a resolved reference where the summary is required.

Not sure if that would be the best solution, though.