Skip to content
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

error with pyside6 6.4.0 backend on macOS arm64 #2407

Closed
psobolewskiPhD opened this issue Oct 16, 2022 · 20 comments · Fixed by #2411
Closed

error with pyside6 6.4.0 backend on macOS arm64 #2407

psobolewskiPhD opened this issue Oct 16, 2022 · 20 comments · Fixed by #2411

Comments

@psobolewskiPhD
Copy link
Contributor

psobolewskiPhD commented Oct 16, 2022

Making a fresh env, python 3.9 or python 3.10, then installing pyside6 pip install pyside6 and vispy (0.11.0) works, but running
https://vispy.org/gallery/scene/turntable_box.html#sphx-glr-gallery-scene-turntable-box-py
fails with error:

╰─ python turntable_box.py                                        (test-env3) ─╯
Traceback (most recent call last):
  File "/Users/piotrsobolewski/Downloads/turntable_box.py", line 17, in <module>
    canvas = scene.SceneCanvas(keys='interactive', size=(800, 600), show=True)
  File "/Users/piotrsobolewski/Dev/miniforge3/envs/test-env3/lib/python3.9/site-packages/vispy/scene/canvas.py", line 135, in __init__
    super(SceneCanvas, self).__init__(
  File "/Users/piotrsobolewski/Dev/miniforge3/envs/test-env3/lib/python3.9/site-packages/vispy/app/canvas.py", line 211, in __init__
    self.create_native()
  File "/Users/piotrsobolewski/Dev/miniforge3/envs/test-env3/lib/python3.9/site-packages/vispy/app/canvas.py", line 228, in create_native
    self._app.backend_module.CanvasBackend(self, **self._backend_kwargs)
  File "/Users/piotrsobolewski/Dev/miniforge3/envs/test-env3/lib/python3.9/site-packages/vispy/app/backends/_qt.py", line 372, in __init__
    self._init_specific(p, kwargs)
  File "/Users/piotrsobolewski/Dev/miniforge3/envs/test-env3/lib/python3.9/site-packages/vispy/app/backends/_qt.py", line 791, in _init_specific
    glformat = _set_config(p.context.config)
  File "/Users/piotrsobolewski/Dev/miniforge3/envs/test-env3/lib/python3.9/site-packages/vispy/app/backends/_qt.py", line 283, in _set_config
    glformat.setSwapBehavior(glformat.DoubleBuffer if c['double_buffer']
AttributeError: 'PySide6.QtGui.QSurfaceFormat' object has no attribute 'DoubleBuffer'

(by comparison the same but with pip install pyqt6 works fine.)

@djhoese
Copy link
Member

djhoese commented Oct 17, 2022

Just so we keep a record: see related #2335 and #2406.

It seems like we might need to add yet another test environment for pyside2 (based on #2406). For this PySide6 stuff I'm hoping we can just live with user testing for now. I can't find it right now but I believe there was another issue around with someone getting a seg fault on macOS with Qt6 installed. That might have been specific to their environment though.

@psobolewskiPhD do you or someone on the napari team (@brisvag?) think you could add a new CI environment to vispy that uses pyside2 to run the examples? Or if you want pyside6 instead?

@psobolewskiPhD
Copy link
Contributor Author

Just so we keep a record: see related #2335 and #2406.

It seems like we might need to add yet another test environment for pyside2 (based on #2406). For this PySide6 stuff I'm hoping we can just live with user testing for now. I can't find it right now but I believe there was another issue around with someone getting a seg fault on macOS with Qt6 installed. That might have been specific to their environment though.

@psobolewskiPhD do you or someone on the napari team (@brisvag?) think you could add a new CI environment to vispy that uses pyside2 to run the examples? Or if you want pyside6 instead?

At least from a napari PoV Qt6 (so pyside6) is really experimental and not officially supported. But pyside2 is supported and maybe even cleaner from a licensing PoV, so I think CI tests with it would be a good idea. napari tests windows and ubuntu with PySide2==5.15.2.1 and ubuntu with pyside6, so this issue could be mac specific or conda-forge specific or version specific.

@psobolewskiPhD psobolewskiPhD changed the title error with pyside6 backend on macOS arm64 error with pyside6 6.4.0 backend on macOS arm64 Oct 19, 2022
@psobolewskiPhD
Copy link
Contributor Author

psobolewskiPhD commented Oct 19, 2022

Based on some sleuthing by @Czaki I tried python 3.10 and pyside6 (latest, 6.4.0) but it still gave the same error. However! Using pyside6 6.3.0 and 6.3.2 was fine, so this issue is specific to something that's changed in pyside 6 6.4.0 . I've edited the title.

@Czaki
Copy link
Contributor

Czaki commented Oct 19, 2022

Yes. This is pyside 6.4.0 proble and requires a new qtpy release
spyder-ide/qtpy#374

@psobolewskiPhD
Copy link
Contributor Author

Yes. Phis is pyside 6.4.0 proble and requires a new qtpy release
spyder-ide/qtpy#374

Unfortunately installing that PR doesn't solve this issue. Again it's puzzling because it's in the docs:
https://doc.qt.io/qtforpython/PySide6/QtGui/QSurfaceFormat.html#PySide6.QtGui.PySide6.QtGui.QSurfaceFormat.SwapBehavior

@Czaki
Copy link
Contributor

Czaki commented Oct 20, 2022

could you show traceback?
Is the code working with 6.3.1 and/or 6.3.2.

@psobolewskiPhD
Copy link
Contributor Author

Traceback is in the OP and yes both 6.3.0 and 6.3.2 work (#2407 (comment))

@Czaki
Copy link
Contributor

Czaki commented Oct 20, 2022

Could you report it to vispy?

@psobolewskiPhD
Copy link
Contributor Author

Could you report it to vispy?

How? This is a vispy issue... Sorry if i'm missing something, it's been a long day.

@Czaki
Copy link
Contributor

Czaki commented Oct 20, 2022

It is a long day, and this is the proper diagnosis for me. I war pretty sure that I'm in napari repository.

@djhoese
Copy link
Member

djhoese commented Oct 20, 2022

@psobolewskiPhD I'm trying to look through pyside6 source code, but their git web UI is not helpful. Since I don't see it defined here, what are the minimal number of steps to reproduce this (what commands create the environment)? Are you able to do an import of the exact PySide6 module and access this attribute it is failing on?

from PySide6.QtGui import QSurfaceFormat
print(hasattr(QSurfaceFormat, "DoubleBuffer"))

@djhoese
Copy link
Member

djhoese commented Oct 20, 2022

Scratch that code, try this:

from PySide6.QtGui import QSurfaceFormat
qsf = QSurfaceFormat()
print(hasattr(qsf, "DoubleBuffer"))
print(hasattr(qsf.SwapBehavior, "DoubleBuffer"))

This "SwapBehavior" version matches what vispy is doing for PyQt6 so maybe PySide6 6.4.0+ is matching PyQt6 for this interface...or something similar.

@psobolewskiPhD
Copy link
Contributor Author

Replicating the env:

mamba create -n vispy-clean -c conda-forge python=3.9 
conda activate wispy-clean
pip install pyside6
pip install vispy

Here's the output I get on my arm64 macOS 12.6:

>>> from PySide6.QtGui import QSurfaceFormat
>>> qsf = QSurfaceFormat()
>>> print(hasattr(qsf, "DoubleBuffer"))
False
>>> print(hasattr(qsf.SwapBehavior, "DoubleBuffer"))
True
>>> 

@djhoese
Copy link
Member

djhoese commented Oct 20, 2022

Great! I see the same thing on my Ubuntu system. Note that the vispy installation isn't actually necessary for this simple test.

So it looks like PySide6 6.4.0 uses the same interfaces as PyQt6. This should be a simple but yet another version check we need to do in _qt.py. @psobolewskiPhD or @Czaki would you be willing and have the time to make a PR for this?

I think the main change is here:

if QT5_NEW_API or PYSIDE6_API:
# Qt5 >= 5.4.0 - below options automatically enabled if nonzero.
glformat.setSwapBehavior(glformat.DoubleBuffer if c['double_buffer']
else glformat.SingleBuffer)
elif PYQT6_API:
glformat.setSwapBehavior(glformat.SwapBehavior.DoubleBuffer if c['double_buffer']
else glformat.SwapBehavior.SingleBuffer)

I'm not sure if this is the only change. We may need to rename PYSIDE6_API to PYSIDE6_LEGACY_API and create a new PYSIDE6_API that is used in the same locations as PYQT6_API. If there are more name changes that effect vispy then it may be that PyQt6 and PySide6 now have equivalent interfaces. In that case importing PySide6 6.4+ could just set PYQT6_API to True.

@psobolewskiPhD
Copy link
Contributor Author

Awesome 👏
I can try to take a look over the weekend.
❤️

@psobolewskiPhD
Copy link
Contributor Author

psobolewskiPhD commented Oct 22, 2022

@djhoese I ran your tests on PySide6 6.3.2:

>>> from PySide6.QtGui import QSurfaceFormat
>>> qsf = QSurfaceFormat()
>>> print(hasattr(qsf, "DoubleBuffer"))
True
>>> print(hasattr(qsf.SwapBehavior, "DoubleBuffer"))
True

So if I'm understanding correctly, so it looks like DoubleBuffer was removed in 6.4, but SwapBehavior was already changed in 6.3—I can't test older, due to lack of arm64 binaries.
I also can't figure out how to check when the change was made via pyside6 docs.

Edit: will make a different issue for the test_context

@psobolewskiPhD
Copy link
Contributor Author

I've used both approaches:
using PYSIDE6_LEGACY_API vs. PYSIDE6_API:
https://github.com/psobolewskiPhD/vispy/tree/use_pyside6_legacy

    if QT5_NEW_API or PYSIDE6_LEGACY_API:
        # Qt5 >= 5.4.0 - below options automatically enabled if nonzero.
        glformat.setSwapBehavior(glformat.DoubleBuffer if c['double_buffer']
                                 else glformat.SingleBuffer)
    elif PYQT6_API or PYSIDE6_API:
        glformat.setSwapBehavior(glformat.SwapBehavior.DoubleBuffer if c['double_buffer']
                                 else glformat.SwapBehavior.SingleBuffer)

Or just using PYSIDE6_API along side PYQT6 for the SwapBehavior related to DoubleBuffer:
https://github.com/psobolewskiPhD/vispy/tree/use_pyqt6

    if QT5_NEW_API:
        # Qt5 >= 5.4.0 - below options automatically enabled if nonzero.
        glformat.setSwapBehavior(glformat.DoubleBuffer if c['double_buffer']
                                 else glformat.SingleBuffer)
    elif PYQT6_API or PYSIDE6_API:
        glformat.setSwapBehavior(glformat.SwapBehavior.DoubleBuffer if c['double_buffer']
                                 else glformat.SwapBehavior.SingleBuffer)

I will try and figure out when the change was made in pyside6.

@psobolewskiPhD
Copy link
Contributor Author

psobolewskiPhD commented Oct 22, 2022

Edit: made issue #2410

@psobolewskiPhD
Copy link
Contributor Author

psobolewskiPhD commented Oct 22, 2022

Edit: issue #2410

@psobolewskiPhD
Copy link
Contributor Author

So if I'm understanding correctly, so it looks like DoubleBuffer was removed in 6.4, but SwapBehavior was already changed in 6.3—I can't test older, due to lack of arm64 binaries.
I also can't figure out how to check when the change was made via pyside6 docs.

I found the Qt 6.2 (LTS) docs. The swap behavior was already present.
https://doc.qt.io/qt-6.2/qsurfaceformat.html#SwapBehavior-enum
https://doc.qt.io/qtforpython-6.2/PySide6/QtGui/QSurfaceFormat.html#PySide6.QtGui.PySide6.QtGui.QSurfaceFormat.SwapBehavior

So I think the 2nd option above is better—I'll make a PR with that. There's a chance somehow pyside6 6.0 or 6.1 won't work, but it seems slim.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants