Support for `numpy.typing`
Hey guys. Hope you're well.
I was adding a type annotation to a function that is npt.DTypeLike, see here. However, when displayed with sphinx-immaterial the underlying Union is unpacked. Is there a way to only display npt.DTypeLike in our API docs?
from typing import Optional
import numpy as np
import numpy.typing as npt
def pack(x: np.ndarray, bpe: int, dtype: Optional[npt.DTypeLike] = None) -> np.ndarray:
return x
I found this https://stackoverflow.com/a/67483317/11694321. It says to add from __future__ import annotations to the top of the module to add this to conf.py.
autodoc_type_aliases = {
"npt.DTypeLike": "~numpy.typing.DTypeLike",
}
This now give me the following. It is almost perfect. It is succinct, but the pink DTypeLike doesn't hyperlink (even though the yellow one below does, using :obj:numpy.typing.DTypeLike).
Do you get any warnings?
I would expect this to work. This theme also has its own type alias mechanism that applies to the Python domain generally (not just to autodoc-generated things):
https://jbms.github.io/sphinx-immaterial/apidoc/python/index.html#confval-python_type_aliases
You could try using that instead. I believe the autodoc_type_aliases only apply in certain cases (and not, for example, when using text signatures as obtained from things defined by C extensions), but I would expect them to apply in this case.
If you don't specify the autodoc_type_aliases, do you get the same thing except it shows npt.DTypeLike?
I got no warnings. I'm including a reproducible example. foo-270.zip
- With no
from __future__ import annotationsand nothing special inconf.pyI get the expanded Union. - Adding
from __future__ import annotationsdoesn't help. - Adding just
autodoc_type_aliases = {"npt.DTypeLike": "~numpy.typing.DTypeLike"}displays the hint asDTypeLike, but it doesn't hyperlink. - Adding just
python_type_aliases = {"npt.DTypeLike": "~numpy.typing.DTypeLike"}displays the expanded Union. - Adding both
autodoc_type_aliases = {"npt.DTypeLike": "~numpy.typing.DTypeLike"}andpython_type_aliases = {"npt.DTypeLike": "~numpy.typing.DTypeLike"}displays the hint asDTypeLike, but it doesn't hyperlink.
I'm using Sphinx v5.3.0 and Sphinx Immaterial v0.11.5 in Python 3.8.10.
This may be another clue... Using the autodoc_type_aliases trick above, the following give these outputs.
Acceptable
def unpack(x: np.ndarray, bpe: int, dtype: npt.DTypeLike) -> np.ndarray:
Something's wrong
def unpack(x: np.ndarray, bpe: int, dtype: npt.DTypeLike = np.uint8) -> np.ndarray:
And I now get these warnings.
/mnt/c/Users/matth/repos/sdr/<python_apigen_rst_epilog>:2: WARNING: Parameter name 'x' does not match any of the parameters defined in the signature: ['x: ~numpy.ndarray', 'bpe: int', "dtype: ~numpy.typing.DTypeLike = <class 'numpy.uint8'>"]
/mnt/c/Users/matth/repos/sdr/<python_apigen_rst_epilog>:2: WARNING: Parameter name 'bpe' does not match any of the parameters defined in the signature: ['x: ~numpy.ndarray', 'bpe: int', "dtype: ~numpy.typing.DTypeLike = <class 'numpy.uint8'>"]
/mnt/c/Users/matth/repos/sdr/<python_apigen_rst_epilog>:2: WARNING: Parameter name 'dtype' does not match any of the parameters defined in the signature: ['x: ~numpy.ndarray', 'bpe: int', "dtype: ~numpy.typing.DTypeLike = <class 'numpy.uint8'>"]
The default value issue is the same as https://github.com/jbms/sphinx-immaterial/issues/140. That makes the signature unparsable as an ast, which causes sphinx to fall back to a more heuristic parsing which prevents a lot of things from working.
I looked into this --- the issue is that numpy.typing.DTypeLike is not a class object but a data object, but Sphinx has hardcoded that the type annotation xrefs use the class role:
https://github.com/sphinx-doc/sphinx/blob/d3c91f951255c6729a53e38c895ddc0af036b5b9/sphinx/domains/python.py#L100
There is room for a lot of improvement in that function.
Separately, I'd suggest always building with nitpicky = True in your config, otherwise it is too easy to miss invalid references. You can silence expected missing references with nitpick_ignore.
I'm running into this again. This function (no from __future__ import annotations)
def db(
x: npt.ArrayLike,
type: Literal["value", "power", "voltage"] = "value",
) -> npt.NDArray[np.float_]:
is rendered like this, which is borderline unreadable.
Any thoughts on ways to work around this? I'd really like to use native NumPy types, where possible. Thanks again for all the great work on this theme!