Skip to content

Conversation

@TimMonko
Copy link
Contributor

@TimMonko TimMonko commented Jan 2, 2026

I noticed that in the camera popup widget in napari that the value of the label in slider labels no longer shows value outside the default range of the sliders (0,99). napari/napari#8534 (Should the decimal issue, which I proposed to fix in napari like this: https://github.com/napari/napari/pull/8535/files#diff-b7be858b0c42314c0f7fbaaa128a2e6a24822a61aa780d9374153c02a7a6b30f actually be fixed in superqt?)

I added a test here that all assertions fail on main, but pass with this PR.

I don't know if this code change is the correct fix because this is my first time looking inside superqt, but my thought process was that the label range needs to be connected to changing the slider range.

I'm only confused because this isn't how it used to work (see the screenshot in napari/napari#7626), but a quick scan of the file history isn't making anything stand out in this method as changed, so maybe this isn't the right place to fix this / the cause of the bug. It seems both the range and decimals somehow got disconnected from the label

@codecov
Copy link

codecov bot commented Jan 2, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.35%. Comparing base (8eb941e) to head (9fc143b).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #320      +/-   ##
==========================================
- Coverage   86.40%   86.35%   -0.05%     
==========================================
  Files          49       49              
  Lines        3861     3862       +1     
==========================================
- Hits         3336     3335       -1     
- Misses        525      527       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Czaki
Copy link
Contributor

Czaki commented Jan 2, 2026

pyside2 fails looks unrelated

@tlambert03
Copy link
Member

Hi @TimMonko

If something has mysteriously changed at some point, and it's not clear where the fix should go, would you be able to run git bisect with superqt installed in editable mode and narrow down exactly what superqt commit caused the change? That might help us fill in the picture a bit and make sure we're fixing the right thing for you

@TimMonko
Copy link
Contributor Author

TimMonko commented Jan 2, 2026

@tlambert03 you have no idea how much you've indirectly taught me over the years. Today was my first time using git bisect ... and it was something I thought might be a good solution, but I was too scared to try it out. Wasn't too bad 😅

I found that 55b6639 was the first bad commit. It looks like there was a switch from using a spinbox to lineedit, which makes this more confusing to understand where the change should go than I expected.

So, I connected now to rangeChanged in SliderLabel. I think it should go there because its used by both QLabeledSlider and QLabeledRangeSlider? This does at least make sense why I noticed different behavior in a QLabeledRangeSlider widget (contrast limits in napari)

I'm not sure what to do about the test, maybe keep the one I have, or make a new direct test of SliderLabel?
Part of my confusion, I think, is that its not called QSliderLabel -- so I'm not sure if that has a name of intent for its meaning/use.

@Czaki
Copy link
Contributor

Czaki commented Jan 2, 2026

I was worried that it was that commit...

@tlambert03
Copy link
Member

Yeah... I was too. That commit has definitely cropped up for me in other places as well (stuff where it's maybe not a direct bug, but it has made things more complicated). One possible solution that I'd like to consider (in parallel perhaps) is to have two versions, or a feature flag on a single version... one that reverts the changes back to the spinBox, and one that uses the line edit to support scientific notation. It's somewhat unfortunate to add the complexity and side effects for a feature that I (personally) find to be a minority use case?

@Czaki
Copy link
Contributor

Czaki commented Jan 2, 2026

We need this in napari because QSpinBox do not support values above $2^{31}$, and there are images with such brghtness.
Also it do not work well with images with low brightness (ex. $10^{-5}$).
But except contrast limit I do not see place where we need custom line edit as label.

@tlambert03
Copy link
Member

tlambert03 commented Jan 2, 2026

We need this in napari because QSpinBox do not support values above 2^31, and there are images with such brghtness.

yes, @Czaki, if you read what I said, I wasn't proposing that we remove it altogether. but propose a way such that you can have what you need for your relatively edge use case, without imposing what has turned out to be a problematic design for the common use case. (i.e. have both)

@tlambert03
Copy link
Member

In any case @Czaki can you help @TimMonko here with this PR. Are you happy with this fix and test?

@tlambert03
Copy link
Member

btw, I did just remember what the other issue with #226 was (it's in ndv, with pyapp-kit/ndv#213 ... where we've actively pinned superqt to <0.7.5, because of that PR.) so @Czaki, if you are interested in having the scientific notation feature live in superqt (and not in napari), then it would be great if you could help out both with @TimMonko's issues here, and ideally help us figure out why that PR caused us to have segfaults over in ndv too

@Czaki
Copy link
Contributor

Czaki commented Jan 27, 2026

@tlambert03 Could you show the command to reproduce segfaults from ndv?

@tlambert03
Copy link
Member

tlambert03 commented Jan 27, 2026

thanks @Czaki, I appreciate it! This works pretty consistently for me on macos:

git clone https://github.com/pyapp-kit/ndv
cd ndv
uv run -p 3.13 --exact --no-dev --group testqt --extra pyside --extra vispy pytest -W ignore 
# works

uv add --optional pyside 'superqt[iconify,pyside6]>=0.7.5'
uv run -p 3.13 --exact --no-dev --group testqt --extra pyside --extra vispy pytest -W ignore
# segfault

then, not sure if this is also useful (honestly I seem to remember the backtrace being more informative last time):

$ source .venv/bin/activate
$ lldb python -- -m pytest -W ignore -q
output
(lldb) target create "python"
Current executable set to '/Users/talley/Desktop/ndv/.venv/bin/python' (arm64).
(lldb) settings set -- target.run-args  "-m" "pytest" "-W" "ignore" "-q"
(lldb) run
Process 9896 launched: '/Users/talley/Desktop/ndv/.venv/bin/python' (arm64)
============================= test session starts ==============================
platform darwin -- Python 3.13.9, pytest-9.0.2, pluggy-1.6.0
PySide6 6.7.3 -- Qt runtime 6.7.3 -- Qt compiled 6.7.3
rootdir: /Users/talley/Desktop/ndv
configfile: pyproject.toml
testpaths: tests
plugins: qt-4.5.0, cov-7.0.0
collected 36 items / 6 skipped

tests/test_app.py ..                                                     [  5%]
tests/test_controller.py ...2026-01-27 14:46:32.945320-0500 python[9896:17331187] [Common] Unable to obtain a task name port right for pid 609: (os/kern) failure (0x5)
....2026-01-27 14:46:33.376171-0500 python[9896:17330807] [CursorUI] ViewBridge to RemoteViewService Terminated: Error Domain=com.apple.ViewBridge Code=18 "(null)" UserInfo={com.apple.ViewBridge.error.hint=this process disconnected remote view controller -- benign unless unexpected, com.apple.ViewBridge.error.description=NSViewBridgeErrorCanceled}
.Process 9896 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=257, address=0xffffffffffff0012)
    frame #0: 0x00007fffffff0012
error: memory read failed for 0x7fffffff0000
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=257, address=0xffffffffffff0012)
  * frame #0: 0x00007fffffff0012
    frame #1: 0x00000001014e906c libpython3.13.dylib`dict_dealloc + 1060
    frame #2: 0x00000001073c4700 libshiboken6.abi3.6.7.dylib`SbkObject_tp_clear(_object*) + 208
    frame #3: 0x00000001011fa0c8 libpython3.13.dylib`gc_collect_main.llvm.8586747558674143334 + 3516
    frame #4: 0x000000010134276c libpython3.13.dylib`_Py_HandlePending + 100
    frame #5: 0x000000010126175c libpython3.13.dylib`_PyEval_EvalFrameDefault + 51432
    frame #6: 0x00000001014fa974 libpython3.13.dylib`slot_tp_init + 296
    frame #7: 0x00000001014f87cc libpython3.13.dylib`type_call + 148
    frame #8: 0x0000000101267248 libpython3.13.dylib`_PyEval_EvalFrameDefault + 74708
    frame #9: 0x00000001014fa974 libpython3.13.dylib`slot_tp_init + 296
    frame #10: 0x00000001014f87cc libpython3.13.dylib`type_call + 148
    frame #11: 0x000000010125f0e4 libpython3.13.dylib`_PyEval_EvalFrameDefault + 41584
    frame #12: 0x0000000101207c14 libpython3.13.dylib`vectorcall_method + 192
    frame #13: 0x00000001014fe2e4 libpython3.13.dylib`slot_mp_ass_subscript + 60
    frame #14: 0x0000000101294de8 libpython3.13.dylib`_PyEval_EvalFrameDefault + 262004
    frame #15: 0x00000001014fa974 libpython3.13.dylib`slot_tp_init + 296
    frame #16: 0x00000001014f87cc libpython3.13.dylib`type_call + 148
    frame #17: 0x000000010125f0e4 libpython3.13.dylib`_PyEval_EvalFrameDefault + 41584
    frame #18: 0x00000001014fa974 libpython3.13.dylib`slot_tp_init + 296
    frame #19: 0x00000001014f87cc libpython3.13.dylib`type_call + 148
    frame #20: 0x000000010125f0e4 libpython3.13.dylib`_PyEval_EvalFrameDefault + 41584
    frame #21: 0x00000001014d5e9c libpython3.13.dylib`method_vectorcall.llvm.16077761963696576860 + 300
    frame #22: 0x000000010126273c libpython3.13.dylib`_PyEval_EvalFrameDefault + 55496
    frame #23: 0x00000001014faa4c libpython3.13.dylib`slot_tp_init + 512
    frame #24: 0x00000001014f87cc libpython3.13.dylib`type_call + 148
    frame #25: 0x00000001012646f8 libpython3.13.dylib`_PyEval_EvalFrameDefault + 63620
    frame #26: 0x00000001014fa974 libpython3.13.dylib`slot_tp_init + 296
    frame #27: 0x00000001014f87cc libpython3.13.dylib`type_call + 148
    frame #28: 0x0000000101267248 libpython3.13.dylib`_PyEval_EvalFrameDefault + 74708
    frame #29: 0x0000000101353404 libpython3.13.dylib`_PyObject_Call_Prepend + 296
    frame #30: 0x0000000101352e50 libpython3.13.dylib`slot_tp_call + 216
    frame #31: 0x00000001012646f8 libpython3.13.dylib`_PyEval_EvalFrameDefault + 63620
    frame #32: 0x0000000101353404 libpython3.13.dylib`_PyObject_Call_Prepend + 296
    frame #33: 0x0000000101352e50 libpython3.13.dylib`slot_tp_call + 216
    frame #34: 0x0000000101262030 libpython3.13.dylib`_PyEval_EvalFrameDefault + 53692
    frame #35: 0x0000000101353404 libpython3.13.dylib`_PyObject_Call_Prepend + 296
    frame #36: 0x0000000101352e50 libpython3.13.dylib`slot_tp_call + 216
    frame #37: 0x00000001012646f8 libpython3.13.dylib`_PyEval_EvalFrameDefault + 63620
    frame #38: 0x0000000101353404 libpython3.13.dylib`_PyObject_Call_Prepend + 296
    frame #39: 0x0000000101352e50 libpython3.13.dylib`slot_tp_call + 216
    frame #40: 0x00000001012646f8 libpython3.13.dylib`_PyEval_EvalFrameDefault + 63620
    frame #41: 0x0000000101353404 libpython3.13.dylib`_PyObject_Call_Prepend + 296
    frame #42: 0x0000000101352e50 libpython3.13.dylib`slot_tp_call + 216
    frame #43: 0x00000001012646f8 libpython3.13.dylib`_PyEval_EvalFrameDefault + 63620
    frame #44: 0x000000010121220c libpython3.13.dylib`PyEval_EvalCode + 132
    frame #45: 0x000000010146e8cc libpython3.13.dylib`builtin_exec + 436
    frame #46: 0x00000001014f0774 libpython3.13.dylib`cfunction_vectorcall_FASTCALL_KEYWORDS.llvm.18011051801772514821 + 88
    frame #47: 0x000000010125ec98 libpython3.13.dylib`_PyEval_EvalFrameDefault + 40484
    frame #48: 0x000000010143fd90 libpython3.13.dylib`pymain_run_module + 232
    frame #49: 0x00000001013d548c libpython3.13.dylib`Py_RunMain + 220
    frame #50: 0x00000001013cbebc libpython3.13.dylib`pymain_main + 468
    frame #51: 0x00000001013cbcdc libpython3.13.dylib`Py_BytesMain + 36
    frame #52: 0x000000018b139d54 dyld`start + 7184

and I think I also did install superqt locally, editable. and according to pyapp-kit/ndv#204 (comment) narrowed it down to a specific commit

@Czaki
Copy link
Contributor

Czaki commented Jan 27, 2026

Ok. I'm able to reproduce failure on Linux.
Also spot that pinning PySide6 and NumPy on Windows ends with buliding old NumPy from source by uv. So maybe you should check if you could unpin PySide6 and NumPy for Windows.

@tlambert03
Copy link
Member

thanks! and yes I would also add that if we find that pyside6 has changed anything in the meantime, and simply updating pyside6 solves everything, then I'm more than happy to just bump our pinnings

@TimMonko
Copy link
Contributor Author

This segfaults for me on Windows:

uv add --optional pyside 'superqt[iconify,pyside6]>=0.7.5'
uv run -p 3.13 --exact --no-dev --group testqt --extra pyside --extra vispy pytest -W ignore
# segfault

tests/views/_qt/test_array_view.py::test_histogram Windows fatal exception: access violation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants