##// END OF EJS Templates
use NumericalVersion utility in external.qt
MinRK -
Show More
@@ -1,81 +1,81
1 """ A Qt API selector that can be used to switch between PyQt and PySide.
1 """ A Qt API selector that can be used to switch between PyQt and PySide.
2
2
3 This uses the ETS 4.0 selection pattern of:
3 This uses the ETS 4.0 selection pattern of:
4 PySide first, PyQt with API v2. second.
4 PySide first, PyQt with API v2. second.
5
5
6 Do not use this if you need PyQt with the old QString/QVariant API.
6 Do not use this if you need PyQt with the old QString/QVariant API.
7 """
7 """
8
8
9 import os
9 import os
10 from distutils.version import LooseVersion as V
10 from IPython.utils.version import NumericalVersion as V
11 # Available APIs.
11 # Available APIs.
12 QT_API_PYQT = 'pyqt'
12 QT_API_PYQT = 'pyqt'
13 QT_API_PYSIDE = 'pyside'
13 QT_API_PYSIDE = 'pyside'
14
14
15 def prepare_pyqt4():
15 def prepare_pyqt4():
16 # For PySide compatibility, use the new-style string API that automatically
16 # For PySide compatibility, use the new-style string API that automatically
17 # converts QStrings to Unicode Python strings. Also, automatically unpack
17 # converts QStrings to Unicode Python strings. Also, automatically unpack
18 # QVariants to their underlying objects.
18 # QVariants to their underlying objects.
19 import sip
19 import sip
20 sip.setapi('QString', 2)
20 sip.setapi('QString', 2)
21 sip.setapi('QVariant', 2)
21 sip.setapi('QVariant', 2)
22
22
23 # Select Qt binding, using the QT_API environment variable if available.
23 # Select Qt binding, using the QT_API environment variable if available.
24 QT_API = os.environ.get('QT_API')
24 QT_API = os.environ.get('QT_API')
25 if QT_API is None:
25 if QT_API is None:
26 pyside_found = False
26 pyside_found = False
27 try:
27 try:
28 import PySide
28 import PySide
29 if V(PySide.__version__) < V('1.0.3'):
29 if V(PySide.__version__) < V('1.0.3'):
30 # old PySide, fallback on PyQt
30 # old PySide, fallback on PyQt
31 raise ImportError
31 raise ImportError
32 # we can't import an incomplete pyside and pyqt4
32 # we can't import an incomplete pyside and pyqt4
33 # this will cause a crash in sip (#1431)
33 # this will cause a crash in sip (#1431)
34 # check for complete presence before importing
34 # check for complete presence before importing
35 import imp
35 import imp
36 imp.find_module("QtCore", PySide.__path__)
36 imp.find_module("QtCore", PySide.__path__)
37 imp.find_module("QtGui", PySide.__path__)
37 imp.find_module("QtGui", PySide.__path__)
38 imp.find_module("QtSvg", PySide.__path__)
38 imp.find_module("QtSvg", PySide.__path__)
39 pyside_found = True
39 pyside_found = True
40 from PySide import QtCore, QtGui, QtSvg
40 from PySide import QtCore, QtGui, QtSvg
41 QT_API = QT_API_PYSIDE
41 QT_API = QT_API_PYSIDE
42 except ImportError:
42 except ImportError:
43 try:
43 try:
44 prepare_pyqt4()
44 prepare_pyqt4()
45 import PyQt4
45 import PyQt4
46 from PyQt4 import QtCore, QtGui, QtSvg
46 from PyQt4 import QtCore, QtGui, QtSvg
47 if pyside_found:
47 if pyside_found:
48 print "WARNING: PySide installation incomplete and PyQt4 " \
48 print "WARNING: PySide installation incomplete and PyQt4 " \
49 "present.\nThis will likely crash, please install " \
49 "present.\nThis will likely crash, please install " \
50 "PySide completely, remove PySide or PyQt4 or set " \
50 "PySide completely, remove PySide or PyQt4 or set " \
51 "the QT_API environment variable to pyqt or pyside"
51 "the QT_API environment variable to pyqt or pyside"
52 if V(QtCore.PYQT_VERSION_STR) < V('4.7'):
52 if V(QtCore.PYQT_VERSION_STR) < V('4.7'):
53 # PyQt 4.6 has issues with null strings returning as None
53 # PyQt 4.6 has issues with null strings returning as None
54 raise ImportError
54 raise ImportError
55 QT_API = QT_API_PYQT
55 QT_API = QT_API_PYQT
56 except ImportError:
56 except ImportError:
57 raise ImportError('Cannot import PySide >= 1.0.3 or PyQt4 >= 4.7')
57 raise ImportError('Cannot import PySide >= 1.0.3 or PyQt4 >= 4.7')
58
58
59 elif QT_API == QT_API_PYQT:
59 elif QT_API == QT_API_PYQT:
60 # Note: This must be called *before* PyQt4 is imported.
60 # Note: This must be called *before* PyQt4 is imported.
61 prepare_pyqt4()
61 prepare_pyqt4()
62
62
63 # Now peform the imports.
63 # Now peform the imports.
64 if QT_API == QT_API_PYQT:
64 if QT_API == QT_API_PYQT:
65 from PyQt4 import QtCore, QtGui, QtSvg
65 from PyQt4 import QtCore, QtGui, QtSvg
66 if V(QtCore.PYQT_VERSION_STR) < V('4.7'):
66 if V(QtCore.PYQT_VERSION_STR) < V('4.7'):
67 raise ImportError("IPython requires PyQt4 >= 4.7, found %s"%QtCore.PYQT_VERSION_STR)
67 raise ImportError("IPython requires PyQt4 >= 4.7, found %s"%QtCore.PYQT_VERSION_STR)
68
68
69 # Alias PyQt-specific functions for PySide compatibility.
69 # Alias PyQt-specific functions for PySide compatibility.
70 QtCore.Signal = QtCore.pyqtSignal
70 QtCore.Signal = QtCore.pyqtSignal
71 QtCore.Slot = QtCore.pyqtSlot
71 QtCore.Slot = QtCore.pyqtSlot
72
72
73 elif QT_API == QT_API_PYSIDE:
73 elif QT_API == QT_API_PYSIDE:
74 import PySide
74 import PySide
75 if V(PySide.__version__) < V('1.0.3'):
75 if V(PySide.__version__) < V('1.0.3'):
76 raise ImportError("IPython requires PySide >= 1.0.3, found %s"%PySide.__version__)
76 raise ImportError("IPython requires PySide >= 1.0.3, found %s"%PySide.__version__)
77 from PySide import QtCore, QtGui, QtSvg
77 from PySide import QtCore, QtGui, QtSvg
78
78
79 else:
79 else:
80 raise RuntimeError('Invalid Qt API %r, valid values are: %r or %r' %
80 raise RuntimeError('Invalid Qt API %r, valid values are: %r or %r' %
81 (QT_API, QT_API_PYQT, QT_API_PYSIDE))
81 (QT_API, QT_API_PYQT, QT_API_PYSIDE))
@@ -1,87 +1,88
1 """ Import Qt in a manner suitable for an IPython kernel.
1 """ Import Qt in a manner suitable for an IPython kernel.
2
2
3 This is the import used for the `gui=qt` or `pylab=qt` initialization.
3 This is the import used for the `gui=qt` or `pylab=qt` initialization.
4
4
5 Import Priority:
5 Import Priority:
6
6
7 if matplotlib has been imported and doesn't support v2 (<= 1.0.1):
7 if matplotlib has been imported and doesn't support v2 (<= 1.0.1):
8 use PyQt4 @v1
8 use PyQt4 @v1
9
9
10 Next, ask ETS' QT_API env variable
10 Next, ask ETS' QT_API env variable
11
11
12 if QT_API not set:
12 if QT_API not set:
13 ask matplotlib via rcParams['backend.qt4']
13 ask matplotlib via rcParams['backend.qt4']
14 if it said PyQt:
14 if it said PyQt:
15 use PyQt4 @v1
15 use PyQt4 @v1
16 elif it said PySide:
16 elif it said PySide:
17 use PySide
17 use PySide
18
18
19 else: (matplotlib said nothing)
19 else: (matplotlib said nothing)
20 # this is the default path - nobody told us anything
20 # this is the default path - nobody told us anything
21 try:
21 try:
22 PyQt @v1
22 PyQt @v1
23 except:
23 except:
24 fallback on PySide
24 fallback on PySide
25 else:
25 else:
26 use PyQt @v2 or PySide, depending on QT_API
26 use PyQt @v2 or PySide, depending on QT_API
27 because ETS doesn't work with PyQt @v1.
27 because ETS doesn't work with PyQt @v1.
28
28
29 """
29 """
30
30
31 import os
31 import os
32 import sys
32 import sys
33
33
34 from IPython.utils.warn import warn
34 from IPython.utils.warn import warn
35 from IPython.utils.version import NumericalVersion as V
35
36
36 matplotlib = sys.modules.get('matplotlib')
37 matplotlib = sys.modules.get('matplotlib')
37 if matplotlib and matplotlib.__version__ <= '1.0.1':
38 if matplotlib and V(matplotlib.__version__) <= V('1.0.1'):
38 # 1.0.1 doesn't support pyside or v2, so stick with PyQt @v1,
39 # 1.0.1 doesn't support pyside or v2, so stick with PyQt @v1,
39 # and ignore everything else
40 # and ignore everything else
40 from PyQt4 import QtCore, QtGui
41 from PyQt4 import QtCore, QtGui
41 else:
42 else:
42 # ask QT_API ETS variable *first*
43 # ask QT_API ETS variable *first*
43 QT_API = os.environ.get('QT_API', None)
44 QT_API = os.environ.get('QT_API', None)
44 if QT_API is None:
45 if QT_API is None:
45 # QT_API not set, ask matplotlib if it was imported (e.g. `pylab=qt`)
46 # QT_API not set, ask matplotlib if it was imported (e.g. `pylab=qt`)
46 if matplotlib:
47 if matplotlib:
47 mpqt = matplotlib.rcParams.get('backend.qt4', None)
48 mpqt = matplotlib.rcParams.get('backend.qt4', None)
48 else:
49 else:
49 mpqt = None
50 mpqt = None
50 if mpqt is None:
51 if mpqt is None:
51 # matplotlib not imported or had nothing to say.
52 # matplotlib not imported or had nothing to say.
52 try:
53 try:
53 # default to unconfigured PyQt4
54 # default to unconfigured PyQt4
54 from PyQt4 import QtCore, QtGui
55 from PyQt4 import QtCore, QtGui
55 except ImportError:
56 except ImportError:
56 # fallback on PySide
57 # fallback on PySide
57 try:
58 try:
58 from PySide import QtCore, QtGui
59 from PySide import QtCore, QtGui
59 except ImportError:
60 except ImportError:
60 raise ImportError('Cannot import PySide or PyQt4')
61 raise ImportError('Cannot import PySide or PyQt4')
61 elif mpqt.lower() == 'pyqt4':
62 elif mpqt.lower() == 'pyqt4':
62 # import PyQt4 unconfigured
63 # import PyQt4 unconfigured
63 from PyQt4 import QtCore, QtGui
64 from PyQt4 import QtCore, QtGui
64 elif mpqt.lower() == 'pyside':
65 elif mpqt.lower() == 'pyside':
65 from PySide import QtCore, QtGui
66 from PySide import QtCore, QtGui
66 else:
67 else:
67 raise ImportError("unhandled value for backend.qt4 from matplotlib: %r"%mpqt)
68 raise ImportError("unhandled value for backend.qt4 from matplotlib: %r"%mpqt)
68 else:
69 else:
69 # QT_API specified, use PySide or PyQt+v2 API from external.qt
70 # QT_API specified, use PySide or PyQt+v2 API from external.qt
70 # this means ETS is likely to be used, which requires v2
71 # this means ETS is likely to be used, which requires v2
71 try:
72 try:
72 from IPython.external.qt import QtCore, QtGui
73 from IPython.external.qt import QtCore, QtGui
73 except ValueError as e:
74 except ValueError as e:
74 if 'API' in str(e):
75 if 'API' in str(e):
75 # PyQt4 already imported, and APIv2 couldn't be set
76 # PyQt4 already imported, and APIv2 couldn't be set
76 # Give more meaningful message, and warn instead of raising
77 # Give more meaningful message, and warn instead of raising
77 warn("""
78 warn("""
78 Assigning the ETS variable `QT_API=pyqt` implies PyQt's v2 API for
79 Assigning the ETS variable `QT_API=pyqt` implies PyQt's v2 API for
79 QString and QVariant, but PyQt has already been imported
80 QString and QVariant, but PyQt has already been imported
80 with v1 APIs. You should unset QT_API to work with PyQt4
81 with v1 APIs. You should unset QT_API to work with PyQt4
81 in its default mode.
82 in its default mode.
82 """)
83 """)
83 # allow it to still work
84 # allow it to still work
84 from PyQt4 import QtCore, QtGui
85 from PyQt4 import QtCore, QtGui
85 else:
86 else:
86 raise
87 raise
87
88
General Comments 0
You need to be logged in to leave comments. Login now