Thanks to visit codestin.com
Credit goes to github.com

Skip to content

MNT: when clearing an Axes via clear/cla fully detach children #24627

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

Merged
merged 3 commits into from
Dec 7, 2022

Conversation

tacaswell
Copy link
Member

Reset the Axes and Figure of the children to None to help break cycles.

Closes #6982

PR Summary

PR Checklist

Documentation and Tests

  • Has pytest style unit tests (and pytest passes)

I do not think this needs any additional documentation.

@tacaswell tacaswell added this to the v3.7.0 milestone Dec 5, 2022
Reset the Axes and Figure of the children to None to help break cycles.

Closes matplotlib#6982
@tacaswell tacaswell force-pushed the mnt/cla_clear_chlildren branch from c68d4de to ffcc8d3 Compare December 5, 2022 00:06
self._children = []
for chld in old_children:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason for not doing for chld in getattr(self, "_children", []): ... before resetting _children?

Copy link
Member Author

@tacaswell tacaswell Dec 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am more worried about the state where the Axes thinks the Artist is in the draw list rather than the case where the Artist still thinks it is in the Axes (which has been the status quo).

My first attempt was

old_children, self._children = self._children, []

but that had issues where either you check self._children before it exists or you get other attribute errors because other parts of the code are using the existence of self._children to determine if we are still in the init method or not.

I also thought about doing for chld in self._chidren: chld.remove() but was trying to avoid a lot of thrashing / maybe some premature optimization.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure if compressing to one line is better or worse ....

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps a good idea to first get rid of this "not having _children" problem by pre-initing it early in __init__? e.g. something like

diff --git i/lib/matplotlib/axes/_base.py w/lib/matplotlib/axes/_base.py
index 3e665cda42..9eb65d3fc4 100644
--- i/lib/matplotlib/axes/_base.py
+++ w/lib/matplotlib/axes/_base.py
@@ -665,6 +665,8 @@ class _AxesBase(martist.Artist):
         self.set_box_aspect(box_aspect)
         self._axes_locator = None  # Optionally set via update(kwargs).
 
+        self._children = []
+
         # placeholder for any colorbars added that use this Axes.
         # (see colorbar.py):
         self._colorbars = []
@@ -1078,7 +1080,7 @@ class _AxesBase(martist.Artist):
         self.transScale.set(
             mtransforms.blended_transform_factory(
                 self.xaxis.get_transform(), self.yaxis.get_transform()))
-        for line in getattr(self, "_children", []):  # Not set during init.
+        for line in self._children:
             if not isinstance(line, mlines.Line2D):
                 continue
             try:
@@ -2936,22 +2938,15 @@ class _AxesBase(martist.Artist):
 
         x_stickies = y_stickies = np.array([])
         if self.use_sticky_edges:
-            # Only iterate over Axes and artists if needed.  The check for
-            # ``hasattr(ax, "_children")`` is necessary because this can be
-            # called very early in the Axes init process (e.g., for twin Axes)
-            # when these attributes don't even exist yet, in which case
-            # `get_children` would raise an AttributeError.
             if self._xmargin and scalex and self.get_autoscalex_on():
                 x_stickies = np.sort(np.concatenate([
                     artist.sticky_edges.x
                     for ax in self._shared_axes["x"].get_siblings(self)
-                    if hasattr(ax, "_children")
                     for artist in ax.get_children()]))
             if self._ymargin and scaley and self.get_autoscaley_on():
                 y_stickies = np.sort(np.concatenate([
                     artist.sticky_edges.y
                     for ax in self._shared_axes["y"].get_siblings(self)
-                    if hasattr(ax, "_children")
                     for artist in ax.get_children()]))
         if self.get_xscale() == 'log':
             x_stickies = x_stickies[x_stickies > 0]

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That will lead to AttributeErrors related to the Axes title attributes (and that was the point where I stopped debugging and used getattr) 🤣

I think the choice is either accept getattr or start pulling this string and see what we have to unravel which might spin out to "re-do all of the init logic in the Axes family".

@QuLogic
Copy link
Member

QuLogic commented Dec 6, 2022

Does this need some refactor now after #24634?

@tacaswell tacaswell force-pushed the mnt/cla_clear_chlildren branch from 522cc01 to 146b478 Compare December 6, 2022 03:28
@tacaswell
Copy link
Member Author

dropped the getattr logic.

Co-authored-by: Elliott Sales de Andrade <[email protected]>
@anntzer anntzer merged commit b2e8434 into matplotlib:main Dec 7, 2022
@tacaswell tacaswell deleted the mnt/cla_clear_chlildren branch December 7, 2022 22:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

cla(), clf() should unset the .axes and .figure attributes of deparented artists
4 participants