Skip to content

Commit ace106e

Browse files
committed
PyQt5 Compatibility: Use "pyqt5" QT_API value to decide when to run under this toolkit
- This is the same behavior adopted by IPython
1 parent 5822ca6 commit ace106e

File tree

9 files changed

+97
-186
lines changed

9 files changed

+97
-186
lines changed

bootstrap.py

+13-7
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@
3232
Type `python bootstrap.py -- --help` to read about Spyder
3333
options.""")
3434
parser.add_option('--gui', default=None,
35-
help="GUI toolkit: pyqt (for PyQt4/PyQt5) or pyside (for PySide)")
35+
help="GUI toolkit: pyqt5 (for PyQt5), pyqt (for PyQt4) or "
36+
"pyside (for PySide)")
3637
parser.add_option('--hide-console', action='store_true',
3738
default=False, help="Hide parent console window (Windows only)")
3839
parser.add_option('--test', dest="test", action='store_true', default=False,
@@ -43,7 +44,7 @@
4344
default=False, help="Run Spyder in debug mode")
4445
options, args = parser.parse_args()
4546

46-
assert options.gui in (None, 'pyqt', 'pyside'), \
47+
assert options.gui in (None, 'pyqt5', 'pyqt', 'pyside'), \
4748
"Invalid GUI toolkit option '%s'" % options.gui
4849

4950
# For testing purposes
@@ -108,11 +109,16 @@
108109
# (Note: PyQt4 is still the officially supported GUI toolkit for Spyder)
109110
if options.gui is None:
110111
try:
111-
import PySide # analysis:ignore
112-
print("02. PySide is detected, selecting (experimental)")
113-
os.environ['QT_API'] = 'pyside'
114-
except:
115-
print("02. No PySide detected, using PyQt4 or PyQt5 if available")
112+
import PyQt5 # analysis:ignore
113+
print("02. PyQt5 is detected, selecting (experimental)")
114+
os.environ['QT_API'] = 'pyqt5'
115+
except ImportError:
116+
try:
117+
import PySide # analysis:ignore
118+
print("02. PySide is detected, selecting")
119+
os.environ['QT_API'] = 'pyside'
120+
except ImportError:
121+
print("02. No PyQt5 or PySide detected, using PyQt4 if available")
116122
else:
117123
print ("02. Skipping GUI toolkit detection")
118124
os.environ['QT_API'] = options.gui

spyderlib/qt/QtCore.py

+17-43
Original file line numberDiff line numberDiff line change
@@ -5,49 +5,23 @@
55
# (see spyderlib/__init__.py for details)
66

77
import os
8-
import sys
9-
10-
11-
if os.environ['QT_API'] == 'pyqt':
12-
if "PyQt4" in sys.modules:
13-
from PyQt4.Qt import QSize, QByteArray, QUrl, QThread
14-
from PyQt4.Qt import QAbstractTableModel, QModelIndex
15-
from PyQt4.Qt import QObject, Qt, QLocale, QTranslator
16-
from PyQt4.Qt import QProcess, QTimer, QTextCodec
17-
from PyQt4.Qt import QEventLoop, QEvent, QPoint, QRect
18-
from PyQt4.Qt import QRegExp, QFileInfo, QMimeData, QDir
19-
from PyQt4.Qt import QMutexLocker, QMutex, QCoreApplication, QDateTime
20-
from PyQt4.Qt import QBasicTimer
21-
from PyQt4.QtCore import QLibraryInfo
22-
from PyQt4.QtCore import pyqtSignal as Signal
23-
from PyQt4.QtCore import pyqtSlot as Slot
24-
from PyQt4.QtCore import pyqtProperty as Property
25-
from PyQt4.QtCore import QT_VERSION_STR as __version__
26-
from PyQt4.QtCore import QProcessEnvironment
27-
try:
28-
# PyQt <v4.6 (API #1)
29-
from PyQt4.Qt import QString
30-
except ImportError:
31-
# PyQt >=v4.6
32-
QString = None
33-
elif "PyQt5" in sys.modules:
34-
from PyQt5.QtCore import QSize, QByteArray, QUrl, QThread
35-
from PyQt5.QtCore import QAbstractTableModel, QModelIndex
36-
from PyQt5.QtCore import QObject, Qt, QLocale, QTranslator
37-
from PyQt5.QtCore import QProcess, QTimer, QTextCodec
38-
from PyQt5.QtCore import QEventLoop, QEvent, QPoint, QRect
39-
from PyQt5.QtCore import QRegExp, QFileInfo, QMimeData, QDir
40-
from PyQt5.QtCore import QMutexLocker, QMutex, QCoreApplication, QDateTime
41-
from PyQt5.QtCore import QBasicTimer, QLibraryInfo
42-
from PyQt5.QtCore import pyqtSignal as Signal
43-
from PyQt5.QtCore import pyqtSlot as Slot
44-
from PyQt5.QtCore import pyqtProperty as Property
45-
from PyQt5.QtCore import QT_VERSION_STR as __version__
46-
from PyQt5.QtCore import QProcessEnvironment
47-
48-
498

9+
if os.environ['QT_API'] == 'pyqt5':
10+
from PyQt5.QtCore import * # analysis:ignore
11+
from PyQt5.QtCore import QCoreApplication
12+
from PyQt5.QtCore import pyqtSignal as Signal
13+
from PyQt5.QtCore import pyqtSlot as Slot
14+
from PyQt5.QtCore import pyqtProperty as Property
15+
from PyQt5.QtCore import QT_VERSION_STR as __version__
16+
elif os.environ['QT_API'] == 'pyqt':
17+
from PyQt4.QtCore import * # analysis:ignore
18+
from PyQt4.Qt import QCoreApplication # analysis:ignore
19+
from PyQt4.Qt import Qt # analysis:ignore
20+
from PyQt4.QtCore import pyqtSignal as Signal # analysis:ignore
21+
from PyQt4.QtCore import pyqtSlot as Slot # analysis:ignore
22+
from PyQt4.QtCore import pyqtProperty as Property # analysis:ignore
23+
from PyQt4.QtCore import QT_VERSION_STR as __version__ # analysis:ignore
5024
else:
5125
import PySide.QtCore
52-
__version__ = PySide.QtCore.__version__
53-
from PySide.QtCore import *
26+
__version__ = PySide.QtCore.__version__ # analysis:ignore
27+
from PySide.QtCore import * # analysis:ignore

spyderlib/qt/QtGui.py

+11-72
Original file line numberDiff line numberDiff line change
@@ -5,77 +5,16 @@
55
# (see spyderlib/__init__.py for details)
66

77
import os
8-
import sys
9-
10-
if os.environ['QT_API'] == 'pyqt':
11-
if "PyQt4" in sys.modules:
12-
from PyQt4.QtGui import QApplication, QMainWindow, QWidget, QLabel
13-
from PyQt4.QtGui import QDockWidget, QShortcut, QCursor, QDialog, QListWidget
14-
from PyQt4.QtGui import QListWidgetItem, QVBoxLayout, QStackedWidget, QListView
15-
from PyQt4.QtGui import QHBoxLayout, QDialogButtonBox, QCheckBox, QMessageBox
16-
from PyQt4.QtGui import QLabel, QLineEdit, QSpinBox, QPushButton
17-
from PyQt4.QtGui import QFontComboBox, QGroupBox, QComboBox, QColor, QGridLayout
18-
from PyQt4.QtGui import QTabWidget, QRadioButton, QButtonGroup, QSplitter
19-
from PyQt4.QtGui import QStyleFactory, QScrollArea, QAction, QPrinter
20-
from PyQt4.QtGui import QPrintDialog, QToolBar, QActionGroup
21-
from PyQt4.QtGui import QInputDialog, QMenu, QAbstractPrintDialog, QKeySequence
22-
from PyQt4.QtGui import QPrintPreviewDialog, QFontDialog, QSizePolicy, QToolButton
23-
from PyQt4.QtGui import QFormLayout, QStackedWidget, QFrame, QItemDelegate
24-
from PyQt4.QtGui import QTableView, QStackedWidget, QDesktopServices, QStyle
25-
from PyQt4.QtGui import QIcon, QKeyEvent, QPixmap, QFont
26-
from PyQt4.QtGui import QCursor, QTextCursor, QTextEdit, QTextCharFormat
27-
from PyQt4.QtGui import QToolTip, QPlainTextEdit, QPalette, QTextOption
28-
from PyQt4.QtGui import QMouseEvent, QTextFormat, QClipboard, QPainter
29-
from PyQt4.QtGui import QBrush, QTextDocument, QTextBlockUserData, QIntValidator
30-
from PyQt4.QtGui import QSyntaxHighlighter, QDoubleValidator, QAbstractItemDelegate, QProgressBar
31-
from PyQt4.QtGui import QColorDialog, QCompleter, QDateEdit, QDateTimeEdit
32-
from PyQt4.QtGui import QTreeWidgetItem, QFileSystemModel, QDrag, QSortFilterProxyModel
33-
from PyQt4.QtGui import QSpacerItem, QFileIconProvider, QHeaderView, QAbstractItemView
34-
from PyQt4.QtGui import QTabBar, QFontDatabase, QSplashScreen
35-
from PyQt4.QtGui import QFileDialog, QTreeWidget, QTreeView
36-
from PyQt4.QtGui import QStylePainter, QStyleOptionFrame,QPaintEvent
37-
elif "PyQt5" in sys.modules:
38-
from PyQt5.QtGui import QCursor
39-
from PyQt5.QtGui import QColor
40-
from PyQt5.QtGui import QKeySequence
41-
from PyQt5.QtGui import QDesktopServices
42-
from PyQt5.QtGui import QIcon, QKeyEvent, QPixmap, QFont
43-
from PyQt5.QtGui import QCursor, QTextCursor
44-
from PyQt5.QtGui import QTextCharFormat
45-
from PyQt5.QtGui import QPalette, QTextOption
46-
from PyQt5.QtGui import QMouseEvent, QTextFormat, QClipboard, QPainter
47-
from PyQt5.QtGui import QBrush, QTextDocument, QTextBlockUserData, QIntValidator
48-
from PyQt5.QtGui import QSyntaxHighlighter, QDoubleValidator
49-
from PyQt5.QtGui import QDrag
50-
from PyQt5.QtGui import QFontDatabase, QPaintEvent
51-
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QLabel
52-
from PyQt5.QtWidgets import QDockWidget, QShortcut
53-
from PyQt5.QtWidgets import QDialog, QListWidget
54-
from PyQt5.QtWidgets import QListWidgetItem, QVBoxLayout, QStackedWidget, QListView
55-
from PyQt5.QtWidgets import QHBoxLayout, QDialogButtonBox, QCheckBox, QMessageBox
56-
from PyQt5.QtWidgets import QLabel, QLineEdit, QSpinBox, QPushButton
57-
from PyQt5.QtWidgets import QFontComboBox, QGroupBox, QComboBox
58-
from PyQt5.QtWidgets import QGridLayout
59-
from PyQt5.QtWidgets import QTabWidget, QRadioButton, QButtonGroup, QSplitter
60-
from PyQt5.QtWidgets import QStyleFactory, QScrollArea, QAction
61-
from PyQt5.QtWidgets import QToolBar, QActionGroup
62-
from PyQt5.QtWidgets import QInputDialog, QMenu
63-
from PyQt5.QtWidgets import QFontDialog, QSizePolicy, QToolButton
64-
from PyQt5.QtWidgets import QFormLayout, QStackedWidget, QFrame, QItemDelegate
65-
from PyQt5.QtWidgets import QTableView, QStackedWidget
66-
from PyQt5.QtWidgets import QStyle
67-
from PyQt5.QtWidgets import QTextEdit
68-
from PyQt5.QtWidgets import QToolTip, QPlainTextEdit
69-
from PyQt5.QtWidgets import QProgressBar, QAbstractItemDelegate
70-
from PyQt5.QtWidgets import QColorDialog, QCompleter, QDateEdit, QDateTimeEdit
71-
from PyQt5.QtWidgets import QTreeWidgetItem, QFileSystemModel
72-
from PyQt5.QtWidgets import QSpacerItem, QFileIconProvider, QHeaderView, QAbstractItemView
73-
from PyQt5.QtWidgets import QTabBar, QSplashScreen
74-
from PyQt5.QtWidgets import QFileDialog, QTreeWidget, QTreeView
75-
from PyQt5.QtWidgets import QStylePainter, QStyleOptionFrame
76-
from PyQt5.QtCore import QSortFilterProxyModel
77-
from PyQt5.QtPrintSupport import QPrinter, QPrintDialog, QAbstractPrintDialog
78-
from PyQt5.QtPrintSupport import QPrintPreviewDialog
798

9+
if os.environ['QT_API'] == 'pyqt5':
10+
from PyQt5.QtCore import QSortFilterProxyModel # analysis:ignore
11+
from PyQt5.QtPrintSupport import (QPrinter, QPrintDialog, # analysis:ignore
12+
QAbstractPrintDialog)
13+
from PyQt5.QtPrintSupport import QPrintPreviewDialog # analysis:ignore
14+
from PyQt5.QtGui import * # analysis:ignore
15+
from PyQt5.QtWidgets import * # analysis:ignore
16+
elif os.environ['QT_API'] == 'pyqt':
17+
from PyQt4.Qt import QKeySequence, QTextCursor # analysis:ignore
18+
from PyQt4.QtGui import * # analysis:ignore
8019
else:
81-
from PySide.QtGui import * # analysis:ignore
20+
from PySide.QtGui import * # analysis:ignore

spyderlib/qt/QtSvg.py

+5-8
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,10 @@
55
# (see spyderlib/__init__.py for details)
66

77
import os
8-
import sys
9-
10-
if os.environ['QT_API'] == 'pyqt':
11-
if "PyQt4" in sys.modules:
12-
from PyQt4.QtSvg import * # analysis:ignore
13-
elif "PyQt5" in sys.modules:
14-
from PyQt5.QtSvg import * # analysis:ignore
158

9+
if os.environ['QT_API'] == 'pyqt5':
10+
from PyQt5.QtSvg import * # analysis:ignore
11+
elif os.environ['QT_API'] == 'pyqt':
12+
from PyQt4.QtSvg import * # analysis:ignore
1613
else:
17-
from PySide.QtSvg import * # analysis:ignore
14+
from PySide.QtSvg import * # analysis:ignore

spyderlib/qt/QtWebKit.py

+7-9
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,12 @@
55
# (see spyderlib/__init__.py for details)
66

77
import os
8-
import sys
9-
10-
if os.environ['QT_API'] == 'pyqt':
11-
if "PyQt4" in sys.modules:
12-
from PyQt4.QtWebKit import QWebPage, QWebView, QWebSettings
13-
elif "PyQt5" in sys.modules:
14-
from PyQt5.QtWebKitWidgets import QWebPage, QWebView
15-
from PyQt5.QtWebKit import QWebSettings
168

9+
if os.environ['QT_API'] == 'pyqt5':
10+
from PyQt5.QtWebKitWidgets import QWebPage, QWebView # analysis:ignore
11+
from PyQt5.QtWebKit import QWebSettings # analysis:ignore
12+
elif os.environ['QT_API'] == 'pyqt':
13+
from PyQt4.QtWebKit import (QWebPage, QWebView, # analysis:ignore
14+
QWebSettings)
1715
else:
18-
from PySide.QtWebKit import * # analysis:ignore
16+
from PySide.QtWebKit import * # analysis:ignore

spyderlib/qt/__init__.py

+17-17
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,22 @@
1010
import os
1111

1212
os.environ.setdefault('QT_API', 'pyqt')
13-
assert os.environ['QT_API'] in ('pyqt', 'pyside')
13+
assert os.environ['QT_API'] in ('pyqt5', 'pyqt', 'pyside')
1414

1515
API = os.environ['QT_API']
16-
#API_NAME = {'pyqt': 'PyQt4', 'pyside': 'PySide'}[API]
16+
API_NAME = {'pyqt5': 'PyQt5', 'pyqt': 'PyQt4', 'pyside': 'PySide'}[API]
1717

1818
PYQT5 = False
1919

20-
21-
if API == 'pyqt':
20+
if API == 'pyqt5':
21+
try:
22+
from PyQt5.QtCore import PYQT_VERSION_STR as __version__
23+
is_old_pyqt = False
24+
is_pyqt46 = False
25+
PYQT5 = True
26+
except ImportError:
27+
pass
28+
elif API == 'pyqt':
2229
# Spyder 2.3 is compatible with both #1 and #2 PyQt API,
2330
# but to avoid issues with IPython and other Qt plugins
2431
# we choose to support only API #2 for 2.4+
@@ -32,27 +39,20 @@
3239
pass
3340

3441
try:
35-
from PyQt4.QtCore import PYQT_VERSION_STR as __version__
42+
from PyQt4.QtCore import PYQT_VERSION_STR as __version__ # analysis:ignore
43+
except ImportError:
44+
# Switching to PySide
45+
API = os.environ['QT_API'] = 'pyside'
46+
API_NAME = 'PySide'
47+
else:
3648
is_old_pyqt = __version__.startswith(('4.4', '4.5', '4.6', '4.7'))
3749
is_pyqt46 = __version__.startswith('4.6')
38-
API_NAME = 'PyQt4'
3950
import sip
4051
try:
41-
4252
API_NAME += (" (API v%d)" % sip.getapi('QString'))
4353
except AttributeError:
4454
pass
4555

46-
except ImportError:
47-
try:
48-
from PyQt5.QtCore import PYQT_VERSION_STR as __version__
49-
is_pyqt46 = False
50-
API_NAME = 'PyQt5'
51-
PYQT5 = True
52-
except:
53-
# Switching to PySide
54-
API = os.environ['QT_API'] = 'pyside'
55-
API_NAME = 'PySide'
5656

5757
if API == 'pyside':
5858
try:

spyderlib/qt/compat.py

+6-7
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,12 @@
3333

3434
PYQT_API_1 = False
3535
if os.environ['QT_API'] == 'pyqt':
36-
if 'PyQt4' in sys.modules:
37-
import sip
38-
try:
39-
PYQT_API_1 = sip.getapi('QVariant') == 1 # PyQt API #1
40-
except AttributeError:
41-
# PyQt <v4.6
42-
PYQT_API_1 = True
36+
import sip
37+
try:
38+
PYQT_API_1 = sip.getapi('QVariant') == 1 # PyQt API #1
39+
except AttributeError:
40+
# PyQt <v4.6
41+
PYQT_API_1 = True
4342
def to_qvariant(pyobj=None):
4443
"""Convert Python object to QVariant
4544
This is a transitional function from PyQt API #1 (QVariant exist)

spyderlib/requirements.py

+13-13
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,17 @@ def check_path():
3535

3636
def check_qt():
3737
"""Check Qt binding requirements"""
38-
if "PyQt4" in sys.modules:
39-
qt_infos = dict(pyqt=("PyQt4", "4.6"), pyside=("PySide", "1.2.0"))
40-
try:
41-
from spyderlib import qt
42-
package_name, required_ver = qt_infos[qt.API]
43-
actual_ver = qt.__version__
44-
if LooseVersion(actual_ver) < LooseVersion(required_ver):
45-
show_warning("Please check Spyder installation requirements:\n"
46-
"%s %s+ is required (found v%s)."
47-
% (package_name, required_ver, actual_ver))
48-
except ImportError:
38+
qt_infos = dict(pyqt5=("PyQt5", "5.2"), pyqt=("PyQt4", "4.6"),
39+
pyside=("PySide", "1.2.0"))
40+
try:
41+
from spyderlib import qt
42+
package_name, required_ver = qt_infos[qt.API]
43+
actual_ver = qt.__version__
44+
if LooseVersion(actual_ver) < LooseVersion(required_ver):
4945
show_warning("Please check Spyder installation requirements:\n"
50-
"%s %s+ (or %s %s+) is required."
51-
% (qt_infos['pyqt']+qt_infos['pyside']))
46+
"%s %s+ is required (found v%s)."
47+
% (package_name, required_ver, actual_ver))
48+
except ImportError:
49+
show_warning("Please check Spyder installation requirements:\n"
50+
"%s %s+ (or %s %s+) is required."
51+
% (qt_infos['pyqt']+qt_infos['pyside']))

spyderlib/widgets/externalshell/sitecustomize.py

+8-10
Original file line numberDiff line numberDiff line change
@@ -263,16 +263,14 @@ def open_in_spyder(source, lineno=1):
263263
# * Installing an input hook: this feature is not yet supported
264264
# natively by PySide
265265
if os.environ.get("INSTALL_QT_INPUTHOOK", "").lower() == "true":
266-
if os.environ["QT_API"] == 'pyqt':
267-
if 'PyQt4' in sys.modules:
268-
from PyQt4 import QtCore
269-
# Removing PyQt's PyOS_InputHook implementation:
270-
QtCore.pyqtRemoveInputHook()
271-
elif 'PyQt5' in sys.modules:
272-
from PyQt5 import QtCore
273-
# Removing PyQt's PyOS_InputHook implementation:
274-
QtCore.pyqtRemoveInputHook()
275-
266+
if os.environ["QT_API"] == 'pyqt5':
267+
from PyQt5 import QtCore
268+
# Removing PyQt's PyOS_InputHook implementation:
269+
QtCore.pyqtRemoveInputHook()
270+
elif os.environ["QT_API"] == 'pyqt':
271+
from PyQt4 import QtCore
272+
# Removing PyQt's PyOS_InputHook implementation:
273+
QtCore.pyqtRemoveInputHook()
276274
elif os.environ["QT_API"] == 'pyside':
277275
from PySide import QtCore
278276
# XXX: when PySide will implement an input hook, we will have to

0 commit comments

Comments
 (0)