Fix Figure.clear leaving stale state and decouple ui kwarg routing#760
Merged
Conversation
Matplotlib's `clear()` detaches every axes and artist and sets `_suptitle` to None, but ultraplot kept its own bookkeeping pointing at the destroyed objects: a cleared figure went on handing out dead axes through `subplotgrid`, `_get_subplot`, `_iter_subplots` and `_iter_axes`, kept a stale gridspec and label counter, leaked figure-level panels, and raised `AttributeError` from the next `format(suptitle=...)` because the suptitle artist was gone, so this adds `SubplotManager.reset()` and overrides `Figure.clear()` to call it, empty the panel dict, reset the layout flags, and rebuild the label artists via the extracted `_init_super_labels()` (which also covers `clf()`, matplotlib's alias for `clear()`). It further removes a footgun in `ui.py`, which split figure keywords from subplot keywords by introspecting the signatures of `Figure._parse_proj` and `Figure._add_subplots` even though those are pure pass-throughs whose only remaining job was to mirror `SubplotManager`'s parameter list -- a contract nothing enforced, and one that already fired once when collapsing `_parse_proj` to `(*args, **kwargs)` made `_pop_params` see no projection parameters and silently routed `proj` to the figure, raising from `Figure.set()`; `_pop_params` now introspects `SubplotManager.parse_proj` and `.add_subplots`, which actually own those parameters, so the delegators are free to collapse back to `(*args, **kwargs)`. Closes #755, closes #756
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Matplotlib's
clear()detaches every axes and artist and sets_suptitleto None, but ultraplot kept its own bookkeeping pointing at the destroyed objects: a cleared figure went on handing out dead axes throughsubplotgrid,_get_subplot,_iter_subplotsand_iter_axes, kept a stale gridspec and label counter, leaked figure-level panels, and raisedAttributeErrorfrom the nextformat(suptitle=...)because the suptitle artist was gone, so this addsSubplotManager.reset()and overridesFigure.clear()to call it, empty the panel dict, reset the layout flags, and rebuild the label artists via the extracted_init_super_labels()(which also coversclf(), matplotlib's alias forclear()). It further removes a footgun inui.py, which split figure keywords from subplot keywords by introspecting the signatures ofFigure._parse_projandFigure._add_subplotseven though those are pure pass-throughs whose only remaining job was to mirrorSubplotManager's parameter list -- a contract nothing enforced, and one that already fired once when collapsing_parse_projto(*args, **kwargs)made_pop_paramssee no projection parameters and silently routedprojto the figure, raising fromFigure.set();_pop_paramsnow introspectsSubplotManager.parse_projand.add_subplots, which actually own those parameters, so the delegators are free to collapse back to(*args, **kwargs).Closes #755, closes #756