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
{{ message }}
Repository navigation
[Bug]: Type checkers not finding Axes, Figure in matplotlib.pyplot #26812
The classes Axes and Figure are not meant to be public from pyplot. Their existence is an implementation detail. Unfortunately, python does reasonably support private use of classes within modules. There's only a rather crude recommended convention in PEP-8:
Documented interfaces are considered public, unless the documentation explicitly declares them to be provisional or internal interfaces exempt from the usual backwards compatibility guarantees. All undocumented interfaces should be assumed to be internal.
As far as I'm aware, we have not documented Axes and Figure to be public interfaces of pyplot.
Type hints are new in Matplotlib 3.8.0, so previously type checkers would ignore (or rather, warn on import without the --ignore-missing-imports flag), but now that we have type hints, it will see more.
That said, pyplot is not the canonical import location for Axes (matplotlib.axes.Axes) and Figure (matplotlib.figure.Figure). The fact that they are importable there at run-time is to some degree an implementation detail (as imports to most python modules are).
Now, it is an implementation detail that has a relatively widespread use, so I will defer to @timhoffm (in his role as API lead) for the final say on whether importing Axes and Figure from pyplot should be officially supported or not. My personal opinion is that type hints can be used as a mechanism to communicate and encourage best practices, while not breaking runtime behavior. (Note, he posted while I was writing this)
I think the only place where we depend on the behavior internally is for the (discouraged) pylab module (which just does a * import, and never usesFigure/Axes, so even there it is debatable whether Axes, Figure, etc are intended to be there).
None of our examples use these, though there are precisely two instances of plt.Axes in test code. (and none of plt.Figure (noting the capital letter))
xref #12743, which adds a __all__ to pyplot (though it far predates type hints)
That PR does include Axes and Figure, though I think partly because it affects runtime time behavior of * imports.
Now, it is an implementation detail that has a relatively widespread use,
Yes, I believe the person who wrote the testing code for pandas-stubs that used matplotlib.pyplot.Axes and matplotlib.pyplot.Figure did that based on his experience.
That PR does include Axes and Figure, though I think partly because it affects runtime time behavior of * imports.
Just to clarify: #12743 was a very first step of collection. It explicitly states "The hard-coded part of functions in __all__ needs some cleanup. Possible some are missing, while others are not neccesary. The state of the PR does not tell anything about intended public/private convention.
My (strong) opinion on Axes/Figure being available from pyplot (or pylab): These modules are function based interfaces. Users have no business in accessing the classes via them. I wish python had a reasonable way to mark them as private but there's officially only the crude "is-not-documented" convention. Given where we are, I propose no further action. In particular that means:
We continue to consider these classes private within pyplot - "communicated by not documenting"
Runtime usage will continue to work. (But you are relying on an implementation detail then).
We do not add the type information for these classes from pyplot, in line with considering them to be private.
type hints can be used as a mechanism to communicate and encourage best practices, while not breaking runtime behavior.
Before, we weren't able to communicate this reasonably. TBH this "private by not documented" claim from PEP-8 is horrific. Code and maybe convention should define the API not documentation. Unfortunately, there are no means within the Python language (except for crude import renaming like from matplotlib.axes import Axes as _Axes, which I reject for other reasons).
The best that can come off this is that people realize through the type checker that they were using the library not as intended.
The best that can come off this is that people realize through the type checker that they were using the library not as intended.
I agree with your conclusion. We've taken a similar philosophy with pandas-stubs. We are using the concept of "the typing stubs cover what is documented".
Activity
timhoffm commentedon Sep 18, 2023
Thanks for the report.
The classes
AxesandFigureare not meant to be public frompyplot. Their existence is an implementation detail. Unfortunately, python does reasonably support private use of classes within modules. There's only a rather crude recommended convention in PEP-8:As far as I'm aware, we have not documented
AxesandFigureto be public interfaces ofpyplot.ksunden commentedon Sep 18, 2023
Type hints are new in Matplotlib 3.8.0, so previously type checkers would ignore (or rather, warn on import without the
--ignore-missing-importsflag), but now that we have type hints, it will see more.That said,
pyplotis not the canonical import location forAxes(matplotlib.axes.Axes) andFigure(matplotlib.figure.Figure). The fact that they are importable there at run-time is to some degree an implementation detail (as imports to most python modules are).Now, it is an implementation detail that has a relatively widespread use, so I will defer to @timhoffm (in his role as API lead) for the final say on whether importing Axes and Figure from pyplot should be officially supported or not. My personal opinion is that type hints can be used as a mechanism to communicate and encourage best practices, while not breaking runtime behavior. (Note, he posted while I was writing this)
I think the only place where we depend on the behavior internally is for the (discouraged)
pylabmodule (which just does a*import, and never usesFigure/Axes, so even there it is debatable whetherAxes,Figure, etc are intended to be there).None of our examples use these, though there are precisely two instances of
plt.Axesin test code. (and none ofplt.Figure(noting the capital letter))xref #12743, which adds a
__all__to pyplot (though it far predates type hints)That PR does include Axes and Figure, though I think partly because it affects runtime time behavior of
*imports.Dr-Irv commentedon Sep 18, 2023
Yes, I believe the person who wrote the testing code for
pandas-stubsthat usedmatplotlib.pyplot.Axesandmatplotlib.pyplot.Figuredid that based on his experience.timhoffm commentedon Sep 18, 2023
Just to clarify: #12743 was a very first step of collection. It explicitly states "The hard-coded part of functions in
__all__needs some cleanup. Possible some are missing, while others are not neccesary. The state of the PR does not tell anything about intended public/private convention.My (strong) opinion on Axes/Figure being available from pyplot (or pylab): These modules are function based interfaces. Users have no business in accessing the classes via them. I wish python had a reasonable way to mark them as private but there's officially only the crude "is-not-documented" convention. Given where we are, I propose no further action. In particular that means:
I agree with @ksunden's statement
Before, we weren't able to communicate this reasonably. TBH this "private by not documented" claim from PEP-8 is horrific. Code and maybe convention should define the API not documentation. Unfortunately, there are no means within the Python language (except for crude import renaming like
from matplotlib.axes import Axes as _Axes, which I reject for other reasons).The best that can come off this is that people realize through the type checker that they were using the library not as intended.
Dr-Irv commentedon Sep 18, 2023
I agree with your conclusion. We've taken a similar philosophy with
pandas-stubs. We are using the concept of "the typing stubs cover what is documented".Remove usage of plt.Axes from tests
Remove usage of plt.Axes from tests
STY: STY: Ignore unsupported type hints for 3D axes and figures
Update matplotlib requirement from <=3.7.0 to <=3.8.0 (#955)
Fix mpl missing import mypy error
Use correct matplotlib public interfaces for type hints.
Use correct matplotlib public interfaces for type hints.
Use correct matplotlib public interfaces for type hints. (#595)
Import `Figure` from `matplotlib.figures` instead of `matplotlib.pypl…