qtpy: update to spider-ide/qtpy v1.11.2
[git-cola.git] / qtpy / __init__.py
blobccb7d417e06abcc3c212a200a38ead37ad9bc992
1 # -*- coding: utf-8 -*-
3 # Copyright © 2009- The Spyder Development Team
4 # Copyright © 2014-2015 Colin Duquesnoy
6 # Licensed under the terms of the MIT License
7 # (see LICENSE.txt for details)
9 """
10 **QtPy** is a shim over the various Python Qt bindings. It is used to write
11 Qt binding independent libraries or applications.
13 If one of the APIs has already been imported, then it will be used.
15 Otherwise, the shim will automatically select the first available API (PyQt5,
16 PySide2, PyQt4 and finally PySide); in that case, you can force the use of one
17 specific bindings (e.g. if your application is using one specific bindings and
18 you need to use library that use QtPy) by setting up the ``QT_API`` environment
19 variable.
21 PyQt5
22 =====
24 For PyQt5, you don't have to set anything as it will be used automatically::
26 >>> from qtpy import QtGui, QtWidgets, QtCore
27 >>> print(QtWidgets.QWidget)
30 PySide2
31 ======
33 Set the QT_API environment variable to 'pyside2' before importing other
34 packages::
36 >>> import os
37 >>> os.environ['QT_API'] = 'pyside2'
38 >>> from qtpy import QtGui, QtWidgets, QtCore
39 >>> print(QtWidgets.QWidget)
41 PyQt4
42 =====
44 Set the ``QT_API`` environment variable to 'pyqt' before importing any python
45 package::
47 >>> import os
48 >>> os.environ['QT_API'] = 'pyqt'
49 >>> from qtpy import QtGui, QtWidgets, QtCore
50 >>> print(QtWidgets.QWidget)
52 PySide
53 ======
55 Set the QT_API environment variable to 'pyside' before importing other
56 packages::
58 >>> import os
59 >>> os.environ['QT_API'] = 'pyside'
60 >>> from qtpy import QtGui, QtWidgets, QtCore
61 >>> print(QtWidgets.QWidget)
63 """
65 from distutils.version import LooseVersion
66 import os
67 import platform
68 import sys
69 import warnings
71 # Version of QtPy
72 from ._version import __version__
73 from .py3compat import PY2
76 class PythonQtError(RuntimeError):
77 """Error raise if no bindings could be selected."""
78 pass
81 class PythonQtWarning(Warning):
82 """Warning if some features are not implemented in a binding."""
83 pass
86 # Qt API environment variable name
87 QT_API = 'QT_API'
89 # Names of the expected PyQt5 api
90 PYQT5_API = ['pyqt5']
92 # Names of the expected PyQt4 api
93 PYQT4_API = [
94 'pyqt', # name used in IPython.qt
95 'pyqt4' # pyqode.qt original name
98 # Names of the expected PySide api
99 PYSIDE_API = ['pyside']
101 # Names of the expected PySide2 api
102 PYSIDE2_API = ['pyside2']
104 # Detecting if a binding was specified by the user
105 binding_specified = QT_API in os.environ
107 # Setting a default value for QT_API
108 os.environ.setdefault(QT_API, 'pyqt5')
110 API = os.environ[QT_API].lower()
111 initial_api = API
112 assert API in (PYQT5_API + PYQT4_API + PYSIDE_API + PYSIDE2_API)
114 is_old_pyqt = is_pyqt46 = False
115 PYQT5 = True
116 PYQT4 = PYSIDE = PYSIDE2 = False
118 # When `FORCE_QT_API` is set, we disregard
119 # any previously imported python bindings.
120 if not os.environ.get('FORCE_QT_API'):
121 if 'PyQt5' in sys.modules:
122 API = initial_api if initial_api in PYQT5_API else 'pyqt5'
123 elif 'PySide2' in sys.modules:
124 API = initial_api if initial_api in PYSIDE2_API else 'pyside2'
125 elif 'PyQt4' in sys.modules:
126 API = initial_api if initial_api in PYQT4_API else 'pyqt4'
127 elif 'PySide' in sys.modules:
128 API = initial_api if initial_api in PYSIDE_API else 'pyside'
131 if API in PYQT5_API:
132 try:
133 from PyQt5.QtCore import PYQT_VERSION_STR as PYQT_VERSION # analysis:ignore
134 from PyQt5.QtCore import QT_VERSION_STR as QT_VERSION # analysis:ignore
135 PYSIDE_VERSION = None
137 if sys.platform == 'darwin':
138 macos_version = LooseVersion(platform.mac_ver()[0])
139 if macos_version < LooseVersion('10.10'):
140 if LooseVersion(QT_VERSION) >= LooseVersion('5.9'):
141 raise PythonQtError("Qt 5.9 or higher only works in "
142 "macOS 10.10 or higher. Your "
143 "program will fail in this "
144 "system.")
145 elif macos_version < LooseVersion('10.11'):
146 if LooseVersion(QT_VERSION) >= LooseVersion('5.11'):
147 raise PythonQtError("Qt 5.11 or higher only works in "
148 "macOS 10.11 or higher. Your "
149 "program will fail in this "
150 "system.")
152 del macos_version
153 except ImportError:
154 API = os.environ['QT_API'] = 'pyside2'
156 if API in PYSIDE2_API:
157 try:
158 from PySide2 import __version__ as PYSIDE_VERSION # analysis:ignore
159 from PySide2.QtCore import __version__ as QT_VERSION # analysis:ignore
161 PYQT_VERSION = None
162 PYQT5 = False
163 PYSIDE2 = True
165 if sys.platform == 'darwin':
166 macos_version = LooseVersion(platform.mac_ver()[0])
167 if macos_version < LooseVersion('10.11'):
168 if LooseVersion(QT_VERSION) >= LooseVersion('5.11'):
169 raise PythonQtError("Qt 5.11 or higher only works in "
170 "macOS 10.11 or higher. Your "
171 "program will fail in this "
172 "system.")
174 del macos_version
175 except ImportError:
176 API = os.environ['QT_API'] = 'pyqt'
178 if API in PYQT4_API:
179 try:
180 import sip
181 try:
182 sip.setapi('QString', 2)
183 sip.setapi('QVariant', 2)
184 sip.setapi('QDate', 2)
185 sip.setapi('QDateTime', 2)
186 sip.setapi('QTextStream', 2)
187 sip.setapi('QTime', 2)
188 sip.setapi('QUrl', 2)
189 except (AttributeError, ValueError):
190 # PyQt < v4.6
191 pass
192 try:
193 from PyQt4.Qt import PYQT_VERSION_STR as PYQT_VERSION # analysis:ignore
194 from PyQt4.Qt import QT_VERSION_STR as QT_VERSION # analysis:ignore
195 except ImportError:
196 # In PyQt4-sip 4.19.13 PYQT_VERSION_STR and QT_VERSION_STR are in PyQt4.QtCore
197 from PyQt4.QtCore import PYQT_VERSION_STR as PYQT_VERSION # analysis:ignore
198 from PyQt4.QtCore import QT_VERSION_STR as QT_VERSION # analysis:ignore
199 PYSIDE_VERSION = None
200 PYQT5 = False
201 PYQT4 = True
202 except ImportError:
203 API = os.environ['QT_API'] = 'pyside'
204 else:
205 is_old_pyqt = PYQT_VERSION.startswith(('4.4', '4.5', '4.6', '4.7'))
206 is_pyqt46 = PYQT_VERSION.startswith('4.6')
208 if API in PYSIDE_API:
209 try:
210 from PySide import __version__ as PYSIDE_VERSION # analysis:ignore
211 from PySide.QtCore import __version__ as QT_VERSION # analysis:ignore
212 PYQT_VERSION = None
213 PYQT5 = PYSIDE2 = False
214 PYSIDE = True
215 except ImportError:
216 raise PythonQtError('No Qt bindings could be found')
218 # If a correct API name is passed to QT_API and it could not be found,
219 # switches to another and informs through the warning
220 if API != initial_api and binding_specified:
221 warnings.warn('Selected binding "{}" could not be found, '
222 'using "{}"'.format(initial_api, API), RuntimeWarning)
224 API_NAME = {'pyqt5': 'PyQt5', 'pyqt': 'PyQt4', 'pyqt4': 'PyQt4',
225 'pyside': 'PySide', 'pyside2':'PySide2'}[API]
227 if PYQT4:
228 import sip
229 try:
230 API_NAME += (" (API v{0})".format(sip.getapi('QString')))
231 except AttributeError:
232 pass
234 try:
235 # QtDataVisualization backward compatibility (QtDataVisualization vs. QtDatavisualization)
236 # Only available for Qt5 bindings > 5.9 on Windows
237 from . import QtDataVisualization as QtDatavisualization
238 except ImportError:
239 pass