Skip to content

Commit e34ee8c

Browse files
committed
MAINT: Fix PySide6 and PyVista compat (#11721)
1 parent e596fae commit e34ee8c

File tree

6 files changed

+52
-15
lines changed

6 files changed

+52
-15
lines changed

azure-pipelines.yml

+5-3
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ stages:
8080
jobs:
8181
- job: Ultraslow_PG
8282
pool:
83-
vmImage: 'ubuntu-20.04'
83+
vmImage: 'ubuntu-22.04'
8484
variables:
8585
DISPLAY: ':99'
8686
OPENBLAS_NUM_THREADS: '1'
@@ -107,7 +107,7 @@ stages:
107107
- bash: |
108108
set -e
109109
python -m pip install --progress-bar off --upgrade pip setuptools wheel
110-
python -m pip install --progress-bar off mne-qt-browser[opengl] pyvista scikit-learn pytest-error-for-skips python-picard "PySide6!=6.3.0,!=6.4.0,!=6.4.0.1,!=6.5.0" qtpy
110+
python -m pip install --progress-bar off mne-qt-browser[opengl] pyvista scikit-learn pytest-error-for-skips python-picard "PySide6!=6.5.1" qtpy
111111
python -m pip uninstall -yq mne
112112
python -m pip install --progress-bar off --upgrade -e .[test]
113113
displayName: 'Install dependencies with pip'
@@ -149,7 +149,7 @@ stages:
149149

150150
- job: Qt
151151
pool:
152-
vmImage: 'ubuntu-20.04'
152+
vmImage: 'ubuntu-22.04'
153153
variables:
154154
DISPLAY: ':99'
155155
OPENBLAS_NUM_THREADS: '1'
@@ -196,6 +196,8 @@ stages:
196196
- bash: |
197197
set -e
198198
python -m pip install PyQt6
199+
# Uncomment if "xcb not found" Qt errors/segfaults come up again
200+
# LD_DEBUG=libs python -c "from PyQt6.QtWidgets import QApplication, QWidget; app = QApplication([]); import matplotlib; matplotlib.use('QtAgg'); import matplotlib.pyplot as plt; plt.figure()"
199201
mne sys_info -pd
200202
mne sys_info -pd | grep "qtpy .* (PyQt6=.*)$"
201203
pytest -m "not slowtest" ${TEST_OPTIONS}

doc/changes/1.4.inc

+10
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
.. _changes_1_4_2:
2+
3+
Version 1.4.2 (2023-06-06)
4+
--------------------------
5+
6+
Bugs
7+
~~~~
8+
9+
- Fix bug with PySide6 compatibility (:gh:`11721` by `Eric Larson`_)
10+
111
.. _changes_1_4_1:
212

313
Version 1.4.1 (2023-06-05)

mne/viz/backends/_pyvista.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,11 @@
4343
import pyvista
4444
from pyvista import Plotter, PolyData, Line, close_all, UnstructuredGrid
4545
from pyvistaqt import BackgroundPlotter
46-
from pyvista.plotting.plotting import _ALL_PLOTTERS
46+
47+
try:
48+
from pyvista.plotting.plotter import _ALL_PLOTTERS
49+
except Exception: # PV < 0.40
50+
from pyvista.plotting.plotting import _ALL_PLOTTERS
4751

4852
from vtkmodules.vtkCommonCore import vtkCommand, vtkLookupTable, VTK_UNSIGNED_CHAR
4953
from vtkmodules.vtkCommonDataModel import VTK_VERTEX, vtkPiecewiseFunction

mne/viz/backends/_qt.py

+30-9
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,8 @@ class _Button(QPushButton, _AbstractButton, _Widget, metaclass=_BaseWidget):
269269
def __init__(self, value, callback, icon=None):
270270
_AbstractButton.__init__(value=value, callback=callback)
271271
_Widget.__init__(self)
272-
QPushButton.__init__(self)
272+
with _disabled_init(_AbstractButton):
273+
QPushButton.__init__(self)
273274
self.setText(value)
274275
self.released.connect(callback)
275276
if icon:
@@ -288,7 +289,8 @@ def __init__(self, value, rng, callback, horizontal=True):
288289
value=value, rng=rng, callback=callback, horizontal=horizontal
289290
)
290291
_Widget.__init__(self)
291-
QSlider.__init__(self, Qt.Horizontal if horizontal else Qt.Vertical)
292+
with _disabled_init(_AbstractSlider):
293+
QSlider.__init__(self, Qt.Horizontal if horizontal else Qt.Vertical)
292294
self.setMinimum(rng[0])
293295
self.setMaximum(rng[1])
294296
self.setValue(value)
@@ -322,7 +324,8 @@ class _CheckBox(QCheckBox, _AbstractCheckBox, _Widget, metaclass=_BaseWidget):
322324
def __init__(self, value, callback):
323325
_AbstractCheckBox.__init__(value=value, callback=callback)
324326
_Widget.__init__(self)
325-
QCheckBox.__init__(self)
327+
with _disabled_init(_AbstractCheckBox):
328+
QCheckBox.__init__(self)
326329
self.setChecked(value)
327330
self.stateChanged.connect(lambda x: callback(bool(x)))
328331

@@ -337,7 +340,8 @@ class _SpinBox(QDoubleSpinBox, _AbstractSpinBox, _Widget, metaclass=_BaseWidget)
337340
def __init__(self, value, rng, callback, step=None):
338341
_AbstractSpinBox.__init__(value=value, rng=rng, callback=callback, step=step)
339342
_Widget.__init__(self)
340-
QDoubleSpinBox.__init__(self)
343+
with _disabled_init(_AbstractSpinBox):
344+
QDoubleSpinBox.__init__(self)
341345
self.setAlignment(Qt.AlignCenter)
342346
self.setMinimum(rng[0])
343347
self.setMaximum(rng[1])
@@ -360,7 +364,8 @@ class _ComboBox(QComboBox, _AbstractComboBox, _Widget, metaclass=_BaseWidget):
360364
def __init__(self, value, items, callback):
361365
_AbstractComboBox.__init__(value=value, items=items, callback=callback)
362366
_Widget.__init__(self)
363-
QComboBox.__init__(self)
367+
with _disabled_init(_AbstractComboBox):
368+
QComboBox.__init__(self)
364369
self.addItems(items)
365370
self.setCurrentText(value)
366371
self.currentTextChanged.connect(callback)
@@ -377,7 +382,8 @@ class _RadioButtons(QVBoxLayout, _AbstractRadioButtons, _Widget, metaclass=_Base
377382
def __init__(self, value, items, callback):
378383
_AbstractRadioButtons.__init__(value=value, items=items, callback=callback)
379384
_Widget.__init__(self)
380-
QVBoxLayout.__init__(self)
385+
with _disabled_init(_AbstractRadioButtons):
386+
QVBoxLayout.__init__(self)
381387
self._button_group = QButtonGroup()
382388
self._button_group.setExclusive(True)
383389
for val in items:
@@ -455,7 +461,8 @@ class _PlayMenu(QVBoxLayout, _AbstractPlayMenu, _Widget, metaclass=_BaseWidget):
455461
def __init__(self, value, rng, callback):
456462
_AbstractPlayMenu.__init__(value=value, rng=rng, callback=callback)
457463
_Widget.__init__(self)
458-
QVBoxLayout.__init__(self)
464+
with _disabled_init(_AbstractPlayMenu):
465+
QVBoxLayout.__init__(self)
459466
self._slider = QSlider(Qt.Horizontal)
460467
self._slider.setMinimum(rng[0])
461468
self._slider.setMaximum(rng[1])
@@ -540,7 +547,8 @@ def __init__(
540547
window=window,
541548
)
542549
_Widget.__init__(self)
543-
QMessageBox.__init__(self, parent=window)
550+
with _disabled_init(_AbstractPopup):
551+
QMessageBox.__init__(self, parent=window)
544552
self.setWindowTitle(title)
545553
self.setText(text)
546554
# icon is one of _Dialog.supported_icon_names
@@ -693,9 +701,22 @@ def _set_size(self, width=None, height=None):
693701
# https://github.com/mne-tools/mne-python/issues/9182
694702

695703

704+
# This is necessary to make PySide6 happy -- something weird with the
705+
# __init__ calling causes the _AbstractXYZ class __init__ to be called twice
706+
@contextmanager
707+
def _disabled_init(klass):
708+
orig = klass.__init__
709+
klass.__init__ = lambda *args, **kwargs: None
710+
try:
711+
yield
712+
finally:
713+
klass.__init__ = orig
714+
715+
696716
class _MNEMainWindow(MainWindow):
697717
def __init__(self, parent=None, title=None, size=None):
698-
MainWindow.__init__(self, parent=parent, title=title, size=size)
718+
with _disabled_init(_Widget):
719+
MainWindow.__init__(self, parent=parent, title=title, size=size)
699720
self.setAttribute(Qt.WA_ShowWithoutActivating, True)
700721
self.setAttribute(Qt.WA_DeleteOnClose, True)
701722

requirements.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ h5io
99
packaging
1010
pymatreader
1111
qtpy
12-
PySide6!=6.3.0,!=6.4.0,!=6.4.0.1,!=6.5.0 # incompat with Matplotlib 3.6.1 and qtpy
12+
PySide6!=6.5.1
1313
pyobjc-framework-Cocoa>=5.2.0; platform_system=="Darwin"
1414
sip
1515
scikit-learn

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111

1212
if "SETUPTOOLS_SCM_PRETEND_VERSION" not in os.environ:
13-
os.environ["SETUPTOOLS_SCM_PRETEND_VERSION"] = "1.4.1"
13+
os.environ["SETUPTOOLS_SCM_PRETEND_VERSION"] = "1.4.2"
1414

1515

1616
def parse_requirements_file(fname):

0 commit comments

Comments
 (0)