GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — FIX: Handle AxesWidget cleanup after failed init by larrybradley · Pull Request #30935 · matplotlib/matplotlib

Conversation

@larrybradley

@larrybradley larrybradley commented Jan 6, 2026

Copy link
Copy Markdown
Contributor

PR summary

In 3.11.0.dev, AxesWidget.__del__ is called on partially constructed selectors when __init__ raises early (e.g., EllipseSelector(ax, foo="bar") with an invalid kwarg). Because __init__ never runs, attributes like _blit_background_id and canvas are not set, so __del__ gives Exception ignored while calling deallocator <function AxesWidget.__del__ at 0x108598b40>: and raises an AttributeError during garbage collection. This surfaces as PytestUnraisableExceptionWarning in tests in downstream packages.
See, e.g., https://github.com/astropy/regions/actions/runs/20730257507/job/59516157314

This bug was introduced in #30591.

Minimal example (also added as a regression test):

import matplotlib.pyplot as plt
from matplotlib.widgets import EllipseSelector
fig, ax = plt.subplots()
try:
    EllipseSelector(ax, foo="bar")
except TypeError:
    pass
plt.close(fig)

PR checklist

  • "closes #0000" is in the body of the PR description to link the related issue
  • new and changed code is tested
  • Plotting related features are demonstrated in an example
  • New Features and API Changes are noted with a directive and release note
  • Documentation complies with general and docstring guidelines

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@github-actions github-actions Bot added the topic: widgets/UI label Jan 6, 2026
@larrybradley larrybradley mentioned this pull request Jan 6, 2026
devdeps CI tests failing for ellipse and rectangle selectors astropy/regions#640
Closed
QuLogic
QuLogic reviewed Jan 6, 2026
View reviewed changes
Comment thread lib/matplotlib/tests/test_widgets.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

@larrybradley
FIX: Handle AxesWidget cleanup after failed init
5bc69c9
@larrybradley
larrybradley force-pushed the fix-axeswidget-del branch from d65638e to 5bc69c9 Compare January 7, 2026 22:34
timhoffm
timhoffm reviewed Jan 7, 2026
View reviewed changes
Comment thread lib/matplotlib/widgets.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread lib/matplotlib/tests/test_widgets.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

@larrybradley
Apply code review suggestions
4963e01
timhoffm
timhoffm reviewed Jan 8, 2026
View reviewed changes
Comment thread lib/matplotlib/tests/test_widgets.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

@larrybradley @timhoffm
Update lib/matplotlib/tests/test_widgets.py
adfd6bb
Co-authored-by: Tim Hoffmann <[email protected]>
timhoffm
timhoffm approved these changes Jan 8, 2026
View reviewed changes
@anntzer

anntzer commented Jan 12, 2026

Copy link
Copy Markdown
Contributor

Maybe instead of defining AxesWidget.__del__ at all it would be simpler to just register the necessary finalizer when the blitbackgroundid is first requested, i.e.

diff --git i/lib/matplotlib/widgets.py w/lib/matplotlib/widgets.py
index 5e87abe08d..9418794dcf 100644
--- i/lib/matplotlib/widgets.py
+++ w/lib/matplotlib/widgets.py
@@ -120,16 +120,6 @@ class AxesWidget(Widget):
         self._cids = []
         self._blit_background_id = None
 
-    def __del__(self):
-        blit_background_id = getattr(self, '_blit_background_id', None)
-        # __del__ may be called on a partially initialized object, e.g.,
-        # when __init__ raises. Therefore, we handle missing attributes
-        # gracefully.
-        if blit_background_id is not None:
-            canvas = getattr(self, 'canvas', None)
-            if canvas is not None:
-                canvas._release_blit_background_id(blit_background_id)
-
     canvas = property(
         lambda self: getattr(self.ax.get_figure(root=True), 'canvas', None)
     )
@@ -170,7 +160,10 @@ class AxesWidget(Widget):
         good enough for all existing widgets.
         """
         if self._blit_background_id is None:
-            self._blit_background_id = self.canvas._get_blit_background_id()
+            bbid = self.canvas._get_blit_background_id()
+            import weakref
+            weakref.finalize(self, self.canvas._release_blit_background_id, bbid)
+            self._blit_background_id = bbid
         self.canvas._blit_backgrounds[self._blit_background_id] = background
 
     def _load_blit_background(self):

?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@larrybradley

larrybradley commented Jan 21, 2026

Copy link
Copy Markdown
Contributor Author

@anntzer Do you want me to implement your suggestion or was that a question for @timhoffm ?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@anntzer

anntzer commented Jan 22, 2026

Copy link
Copy Markdown
Contributor

If my patch works as is (well, moving the import to where it should be) I'd rather have that in directly, otherwise it can be punted.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@larrybradley

larrybradley commented Jan 23, 2026

Copy link
Copy Markdown
Contributor Author

@anntzer OK, thanks. I've updated this PR with your suggested fix. The test passes.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@larrybradley
larrybradley force-pushed the fix-axeswidget-del branch from 668304d to eeb61a5 Compare January 23, 2026 21:26
@larrybradley
larrybradley requested a review from timhoffm January 23, 2026 21:28
@larrybradley
Remove __del__ method
b60db73
@larrybradley
larrybradley force-pushed the fix-axeswidget-del branch from eeb61a5 to b60db73 Compare January 23, 2026 21:29
@anntzer

anntzer commented Jan 23, 2026

Copy link
Copy Markdown
Contributor

Looks like the pyi file needs to be updated for the removal of __del__.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@larrybradley
Remove AxesWidget.__del__ from widgets.pyi
d725b13
@larrybradley

larrybradley commented Jan 23, 2026

Copy link
Copy Markdown
Contributor Author

@anntzer Fixed, thanks!

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

timhoffm
timhoffm approved these changes Jan 24, 2026
View reviewed changes
@QuLogic QuLogic added this to the v3.11.0 milestone Jan 24, 2026
QuLogic
QuLogic approved these changes Jan 24, 2026
View reviewed changes
@timhoffm
timhoffm merged commit 74aa9ab into matplotlib:main Jan 24, 2026
37 of 40 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@larrybradley
larrybradley deleted the fix-axeswidget-del branch January 24, 2026 14:45
llohse pushed a commit to llohse/matplotlib that referenced this pull request Feb 3, 2026
@larrybradley @timhoffm @llohse
FIX: Handle AxesWidget cleanup after failed init (matplotlib#30935)
608ae27
* FIX: Handle AxesWidget cleanup after failed init

* Apply code review suggestions

* Update lib/matplotlib/tests/test_widgets.py

Co-authored-by: Tim Hoffmann <[email protected]>

* Remove __del__ method

* Remove AxesWidget.__del__ from widgets.pyi

---------

Co-authored-by: Tim Hoffmann <[email protected]>
llohse pushed a commit to llohse/matplotlib that referenced this pull request Feb 3, 2026
@larrybradley @timhoffm @llohse
FIX: Handle AxesWidget cleanup after failed init (matplotlib#30935)
2ae379a
* FIX: Handle AxesWidget cleanup after failed init

* Apply code review suggestions

* Update lib/matplotlib/tests/test_widgets.py

Co-authored-by: Tim Hoffmann <[email protected]>

* Remove __del__ method

* Remove AxesWidget.__del__ from widgets.pyi

---------

Co-authored-by: Tim Hoffmann <[email protected]>
llohse pushed a commit to llohse/matplotlib that referenced this pull request Feb 3, 2026
@larrybradley @timhoffm @llohse
FIX: Handle AxesWidget cleanup after failed init (matplotlib#30935)
deec641
* FIX: Handle AxesWidget cleanup after failed init

* Apply code review suggestions

* Update lib/matplotlib/tests/test_widgets.py

Co-authored-by: Tim Hoffmann <[email protected]>

* Remove __del__ method

* Remove AxesWidget.__del__ from widgets.pyi

---------

Co-authored-by: Tim Hoffmann <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@QuLogic QuLogic QuLogic approved these changes
@timhoffm timhoffm timhoffm approved these changes

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

topic: widgets/UI

Projects

None yet

Milestone

v3.11.0

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

4 participants

@larrybradley @anntzer @QuLogic @timhoffm
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.
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.