You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
plt.axes should return Axes and not matplotlib.axes.Axes
Code for reproduction
@_docstring.dedent_interpddefaxes(
arg: None|tuple[float, float, float, float] =None,
**kwargs
) ->matplotlib.axes.Axes: #axes is not a known member of module 'matplotlib' #type of axes is unknown #type of Axes is unknown
The technical location of the class is matplotlib.axes._axes.Axes but it's re-imported in matplotlib.axes, which is our canonical public point of contact. Maybe pyright is stumbling over that?
Pyright understands matplotlib and goes under __init__.py but cannot find any source of axes there.
Why not use Axes as the return type instead? It is imported in pyplot.py too. The same is used for functions returning Figure. I can make a PR if this is the intended direction.
Short version is that sphinx had trouble resolving some things, so I resorted to the fully specified names in some cases. I think this particular example should be fine to be shortened, but the other places in pyplot.py where Axes was referred to as a union type broke sphinx in ways that I could not at the time figure out how to resolve.
It is possible sphinx has changed how it resolves links in type hints since then, I have not checked.
That said, this reference should work for type checkers, I'm pretty sure (and does work for mypy for instance, which is what we use for our CI).
It is true that matplotlib.axes is not imported by default:
Adding the explicit imports (I just did it in the if TYPE_CHECKING: block since its working around type checker limitations) appears to fix the problems (for some reason did not fix one of the backend_bases flags, not sure why):
diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py
index 2376c62439..426892afca 100644
--- a/lib/matplotlib/pyplot.py+++ b/lib/matplotlib/pyplot.py@@ -90,6 +90,9 @@ if TYPE_CHECKING:
import PIL.Image
from numpy.typing import ArrayLike
+ import matplotlib.axes+ import matplotlib.artist+ import matplotlib.backend_bases
from matplotlib.axis import Tick
from matplotlib.axes._base import _AxesBase
from matplotlib.backend_bases import RendererBase, Event
The remaining flags I see from pyright in pyplot.py are largely due to either:
a) types are narrowed in ways pyright doesn't (or can't) know e.g.:
we looked up an rcParam, so we know the type narrowed
we do a hasattr check before accessing an optional attribute
b) a small handful of artist functions that do not get type hints because of the complexity of doing so (its not impossible, just never got around to it and didn't hold the rest of the work on it)
I have no issue with paring down the number of flags we get with pyright, though mypy remains my preference for CI purposes for now (not totally opposed to both, but did not optimize for pyright). There were ~3000 flags from pyright that mypy did not flag when we first added type hints (10k if you include tests), so not trivial.
I do use a pyright-based LSP/editor integration, but it doesn't play well with editable meson installs, so mostly don't get mpl flags unless I go looking for them.
I like the if TYPE_CHECKING solution better. It works for now and would not bother sphinx as well.
Let me know if you want a PR for that.
Off topic: I prefer pyright for now as it does not hang up once an error is encountered unlike pyright. Also it seems to have support for PEP 695 generics, and it has some strong arguments in its comparison to mypy. I would prefer mypy but it automatically skips if a type cannot be inferred and that to me is a big bummer. Pyright on the other hand does not need to append None on functions that do not return anything which is a bit less clutter imo.
Activity
timhoffm commentedon Apr 4, 2024
The technical location of the class is
matplotlib.axes._axes.Axesbut it's re-imported inmatplotlib.axes, which is our canonical public point of contact. Maybe pyright is stumbling over that?haarisr commentedon Apr 4, 2024
Pyright understands matplotlib and goes under
__init__.pybut cannot find any source of axes there.Why not use
Axesas the return type instead? It is imported inpyplot.pytoo. The same is used for functions returningFigure. I can make a PR if this is the intended direction.timhoffm commentedon Apr 4, 2024
Yes, changing
matplotlib.axes.AxestoAxesin type annotations in pyplot seems the right thing to do. ping @ksunden do you agree? A PR is welcome!ksunden commentedon Apr 4, 2024
See full explanations here:
Short version is that sphinx had trouble resolving some things, so I resorted to the fully specified names in some cases. I think this particular example should be fine to be shortened, but the other places in
pyplot.pywhereAxeswas referred to as a union type broke sphinx in ways that I could not at the time figure out how to resolve.It is possible sphinx has changed how it resolves links in type hints since then, I have not checked.
That said, this reference should work for type checkers, I'm pretty sure (and does work for mypy for instance, which is what we use for our CI).
It is true that
matplotlib.axesis not imported by default:Adding the explicit imports (I just did it in the
if TYPE_CHECKING:block since its working around type checker limitations) appears to fix the problems (for some reason did not fix one of thebackend_basesflags, not sure why):The remaining flags I see from pyright in pyplot.py are largely due to either:
a) types are narrowed in ways pyright doesn't (or can't) know e.g.:
hasattrcheck before accessing an optional attributeb) a small handful of artist functions that do not get type hints because of the complexity of doing so (its not impossible, just never got around to it and didn't hold the rest of the work on it)
I have no issue with paring down the number of flags we get with pyright, though mypy remains my preference for CI purposes for now (not totally opposed to both, but did not optimize for pyright). There were ~3000 flags from pyright that mypy did not flag when we first added type hints (10k if you include tests), so not trivial.
I do use a pyright-based LSP/editor integration, but it doesn't play well with editable meson installs, so mostly don't get mpl flags unless I go looking for them.
haarisr commentedon Apr 5, 2024
I like the
if TYPE_CHECKINGsolution better. It works for now and would not bother sphinx as well.Let me know if you want a PR for that.
Off topic: I prefer pyright for now as it does not hang up once an error is encountered unlike pyright. Also it seems to have support for PEP 695 generics, and it has some strong arguments in its comparison to mypy. I would prefer mypy but it automatically skips if a type cannot be inferred and that to me is a big bummer. Pyright on the other hand does not need to append
Noneon functions that do not return anything which is a bit less clutter imo.