patrick-kidger / jaxtyping

Type annotations and runtime checking for shape and dtype of JAX/NumPy/PyTorch/etc. arrays. https://docs.kidger.site/jaxtyping/
Other
1.04k stars 49 forks source link

How to properly escape `*` and `_` when rendering docs with Sphinx #203

Open jeertmans opened 2 months ago

jeertmans commented 2 months ago

Hello,

I use your great package to annotate all my functions, both for type checking and documentation purposes.

However, most Python package rely on .rst formatting, and do I, as a result of using Sphinx when generating the docs (I know I could opt for a Markdown parser, but not sure if that would solve my problem).

Stars * are very common in my type annotation and some (not all, ?) signatures emit this warning when I build the docs: :1: (WARNING/2) Inline emphasis start-string without end-string.

This is because, I think, RST tries to interpret * as the start of some markup, see result below.

image

Above, the * links to some non-existing id.

I have tried to define a custom Sphinx pre-processor to escape * to \*, but it seems quite complex for such a seemingly stupid problem...

Have you already encountered this problem and, if so, do you have any suggestion on how to solve this?

jeertmans commented 2 months ago

Ok, nevermind, the not all was caused by the fact that I use from __future__ import annotations in my plotting module. In module where I do not import from __future__ import annotations, it renders nicely.

patrick-kidger commented 1 month ago

Ah, that's good to know! For what it's worth from __future__ import annotations will often break runtime type checkers in unpredictable ways (resolving the stringified annotations correctly is intractable in general), so I'm afraid this should be avoided anyway.

(That aside, if this is a greenfield project then having tried both Sphinx and MkDocs, I've come to really enjoy the greater simplicity of the latter, and would recommend it!)

jeertmans commented 1 month ago

I actually run in a problem where not solution is optimal because of that.

Because I use this library, I cannot use from __future__ import annotations.

When Sphinx's autodoc tries to import the module, it first tries with typing.TYPE_CHECKING=True, so I could do that:

if TYPE_CHECKING:
    from some_optioal_deps import ReturnType
else:
    ReturnType = Any

but will fail (Any will be displayed in the docs) because your module depends on numpy, which cannot be imported with TYPE_CHECKING set to True. It then fallsback to ReturnType = Any.

So the solution I came up with is

try:
    from some_optioal_deps import ReturnType
except ImportError:
    ReturnType = Any

which renders correctly in the docs (because I installed the optional deps to build the docs).

However, tools like Pyright will complain because ReturnType can be Any, which is often a bad practice.

My current solution was to annotate each return type with # type: ignore.

I think you could "fix" this issue by removing imports to NumPy load, and only import this when needed.

Anything, I thought it was interesting to document this here!