test: deterministically tear down example widgets - #743
Conversation
|
... let me know if you want me to add a "open an issue when the scheduled one fails, if one doesn't already exist" here or in another PR. I find them useful in other repos, otherwise I miss scheduled run failures (but not sure if it would help here, depends on maintainer availability etc.) |
The namespace from runpy.run_path is discarded, so widgets created by
an example are garbage-collected at an arbitrary later point during
event processing. A still-visible widget whose C++ side is deleted
mid-event-loop can receive a paintEvent during deletion, which PyQt5
escalates to a process abort:
RuntimeError: wrapped C/C++ object of type QRangeSlider has been
deleted
as seen intermittently on the windows-latest (3.12) pyqt5 job in
test_example[demo_widgets/range_slider.py] (e.g. the scheduled main
run on 2026-08-22, and both pyapp-kit#741 and pyapp-kit#742).
Close (hide) all top-level widgets first so nothing can paint, then
deleteLater() + sendPostedEvents(None, DeferredDelete) to destroy the
native widgets (and stop their timers) while hidden -- note that
processEvents() alone does NOT dispatch DeferredDelete events -- then
gc.collect() for anything left over.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pytest-qt 4.4.0 is incompatible with recent PySide6: qtbot.waitSignal fails with 'SystemError: <method disconnect of SignalInstance> returned a result with an exception set' and a TimeoutError in test_parent_changed (reproduced locally with PySide6 6.11.2 + pytest-qt 4.4.0; fixed by pytest-qt 4.5.0, see pytest-dev/pytest-qt#552). This is what has been failing every pyside6 CI job (and the scheduled runs on main) since at least mid-July. pytest-qt 4.5 dropped PySide2, so the pyside2 dependency group keeps the 4.4.0 pin via a separate test-qt-legacy group, declared as a uv conflict so universal resolution still succeeds. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
hatchling 1.32.0 (2026-08-11) bumped the default core metadata version
to 2.5, which the twine run by build-and-inspect-python-package rejects
('InvalidDistribution: 2.5 is not a valid metadata version'). Nobody
noticed because build-and-inspect needs the test job, which has been
red since mid-July (see previous commit). Verified locally: with this
setting both the wheel and sdist emit Metadata-Version 2.4 and pass
'twine check --strict'.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ad0b40f to
e0a9da5
Compare
|
Rebased this onto current Confirmed your pytest-qt diagnosis independently before touching anything: the failure is Verified locally with I left the hatchling core-metadata commit in. Worth noting it hasn't actually been exercised yet: Thanks for chasing this one down. |
|
You still have 3.9 tests... want to bump to 3.10 (or if you're bold, 3.11)? Happy to do this in another maintainability PR |
|
i can bump min python elsewhere. thanks. and as for the "open an issue when the scheduled one fails", I too use/like that elsewhere, but i fear I'm the only one listening here at the moment, and I'm feeling pretty buried recently (and likely wouldn't take action on it until i had to anyway) |
CIs seem to be failing in all PRs. Based on (painful) experience with PyVistaQt, mne-qt-browser, etc. a reasonable fix is to make sure windows are closed and torn down at the end of every test (rather than "whenever gc.collect() decides to run"). Otherwise, a still-visible widget whose C++ side is deleted mid-event-loop can receive a paintEvent during deletion, which leads to a segfault.
This should hopefully fix CIs. Changes drafted by Claude Fable 5 but reviewed / iterated / understood be me.