-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
[Bug]: Matplotlib 3.7 has yet again changed the class returned by plt.gca()
#25228
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I think the minimal example here is import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_subplot(1, 2, 1)
ax2 = fig.add_subplot(1, 2, 2, projection="3d")
print(repr(ax1))
print(repr(ax2)) v3.6.3
v3.7.0
Though I note that you can still do isinstance(ax, matplotlib.axes.SubplotBase) to check whether your axes was added on a grid. So this possibly only affects users who specifically check the repr, e.g. in doctests. |
I do not believe that reprs should be considered as covered by any API stability unless otherwise documented (Otherwise, even adding a |
Yes, I haven't looked at your tests, but I agree with the above that testing our repr seems very fragile. We also strongly encourage developers to run CI on our release candidates when they are announced to sort out problems before they hit an actual release. We build wheels for these. We also make a nightly wheel build available https://matplotlib.org/devdocs/users/installing/index.html#installing-a-nightly-build that you could incorporate into your CI (probably as a different run than against released versions) - we have such a run and it is extremely useful to catch numpy changes before they hit a release, and we have been alerted to issues with downstream libraries because they run our nightly's. I think astropy or sunpy do this with our nightlies, and it has caught some potential snafus. |
As others have pointed out, we do not consider In fact, adding a The fact of the matter is Python is a dynamically typed/duck-typed language, and what matters as a library is that users of the public api are as minimally affected by API changes as possible. In fact, AxesSubplot was an undocumented subclass of Axes. In my opinion at least, return types are very much allowed to change, as long as behavior remains consistent. (Especially if the new return type was always a documented possible return type) (See also the ArrayList class that was introduced in order to warn that that return would become immutable... trying to mutate the result is at least one additional cause of failures you linked, though that very much did have warnings, but doctests don't surface such deprecation warnings... even Numpy was caught by that one)
Strict SemVer is not actually used by any general purpose, popular scientific Python library, to my knowledge. Numpy, Scipy, Pandas, etc (including Python the language itself) all have deprecation policies that include a best effort to retain backwards compatibility, where possible for minor releases. Some use date-based versioning (which I have a personal affinity towards, but I think mpl has good reason to use the scheme we currently use), most use something more "Major changes"."Feature releases, breaking changes allowed"."bugfix patch". If we were to adopt a strict semver, I don't think it would actually be any different as to when we do releases or what goes in them... we would just bump the first number of the release instead of the second. (If anything, I think we would be more willing to make breaking changes) Instead, we use the first number to indicate large changes that will break the majority of users (e.g. default style changes, as was the case for 2 -> 3). If you truly want the SemVer like experience (and I don't think you do, long term), you can treat the "Minor" releases as the version that can contain some backwards incompatibilities. |
I don't have much to add, other than while I appreciate your appeal to SemVer, this is precisely one of those cases that argues against SemVer being practical. Most devs would not have considered these (changing a repr or changing a return to an API-compatible type) to be breaking changes. Therefore, no one would have bumped the version for that change. This leads many to the end conclusion that the only way to be completely SemVer "pure" is to consider every change to be a breaking change. |
Hello, Given the issue title and description I wrote, I would hope that it is clear that I understood that the class type/name itself changed. I haven't compared the code between 3.7 and < 3.7 so I don't know what happened under the hood and there are no mention about it in the release notes. Now please consider it from my vantage point: the Class name/type has (possibly) changed, it means that not only my doctests are breaking but also that my static typing annotations are now possibly wrong. Another relevant one pertaining to the discussion is that the way the Artists, e.g. Lines are accessed for an Cheers, Thomas |
In point of fact, the Your tests from before our release have 1426 warnings, some of those are likely our deprecation warnings for this and possibly other pending deprecations. As for typing annotations, until #24976 is complete (and even then will probably be documented as provisional and thus liable to change without warning for a release cycle or two) it is not recommended to type hint matplotlib code. While we are working towards the goal of being typed, it is simply not ready yet, and if you are overspecifing, you can expect that changes will be required once we do have type hints. The returned type is the documented type still, so if you are going to type hint, it must include The diff you show for the The following should suffice if equivalent code is desired: axes.lines[0].remove() We thank you for the report, but have discussed this and believe the changes are in line with our balancing of api stability/documented behavior vs making the code on our end better. As such I'm going to close this issue as we do not have any action to take on our end. |
For completeness, directly mutating the child lists was deprecated in 3.5 ( https://matplotlib.org/stable/api/prev_api_changes/api_changes_3.5.0.html#axes-children-are-no-longer-separated-by-type) and warned in both the 3.5 and 3.6 series. Looking at #23573 we did not consider this an API change because you can still import If you find any differences in behavior (other than repr) please report those as bugs! |
Thanks you all for the details. |
@KelSolaar, going back to your doctests, I looked at some of your rendered docs and I have the impression that what you really want is the example, and the check on the >>> plot_planckian_locus(planckian_locus_colours="RGB"); which should suppress that text output and you never need to worry about whether the |
Hi @rcomer, The text output serves two purposes for us: Understanding the return type when you read the docstrings, and also that it matches expectations. People will often read the usage example first in the docs and then take a look at the definition signature if they need more info. Cheers, Thomas |
Bug summary
Hello,
It is the second time in 2.5 years that a Matplotlib release breaks all our doctests because
plt.gca()
returns a different type. It also happened around July 2020: colour-science/colour@d5f6800There is no notice in the release notes and it is kind of wrecking havoc on our end. I will be using longer ellipsis from now on but I was wondering if you guys had considered using SemVER?
Code for reproduction
Actual outcome
Colour's doctests are sad! :(
Expected outcome
Happy doctests!
Additional information
No response
Operating system
No response
Matplotlib Version
3.7
Matplotlib Backend
No response
Python version
No response
Jupyter version
No response
Installation
None
The text was updated successfully, but these errors were encountered: