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