maint: flake8/pylint fixes
[git-cola.git] / qtpy / __init__.py
blobddbe452910678933f70d28aa6c0e4b2b138145b1
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 indenpendent 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__
75 class PythonQtError(RuntimeError):
76 """Error raise if no bindings could be selected."""
77 pass
80 class PythonQtWarning(Warning):
81 """Warning if some features are not implemented in a binding."""
82 pass
85 # Qt API environment variable name
86 QT_API = 'QT_API'
88 # Names of the expected PyQt5 api
89 PYQT5_API = ['pyqt5']
91 # Names of the expected PyQt4 api
92 PYQT4_API = [
93 'pyqt', # name used in IPython.qt
94 'pyqt4' # pyqode.qt original name
97 # Names of the expected PySide api
98 PYSIDE_API = ['pyside']
100 # Names of the expected PySide2 api
101 PYSIDE2_API = ['pyside2']
103 # Detecting if a binding was specified by the user
104 binding_specified = QT_API in os.environ
106 # Setting a default value for QT_API
107 os.environ.setdefault(QT_API, 'pyqt5')
109 API = os.environ[QT_API].lower()
110 initial_api = API
111 assert API in (PYQT5_API + PYQT4_API + PYSIDE_API + PYSIDE2_API)
113 is_old_pyqt = is_pyqt46 = False
114 PYQT5 = True
115 PYQT4 = PYSIDE = PYSIDE2 = False
117 # When `FORCE_QT_API` is set, we disregard
118 # any previously imported python bindings.
119 if os.environ.get('FORCE_QT_API') is not None:
120 if 'PyQt5' in sys.modules:
121 API = initial_api if initial_api in PYQT5_API else 'pyqt5'
122 elif 'PySide2' in sys.modules:
123 API = initial_api if initial_api in PYSIDE2_API else 'pyside2'
124 elif 'PyQt4' in sys.modules:
125 API = initial_api if initial_api in PYQT4_API else 'pyqt4'
126 elif 'PySide' in sys.modules:
127 API = initial_api if initial_api in PYSIDE_API else 'pyside'
130 if API in PYQT5_API:
131 try:
132 from PyQt5.QtCore import PYQT_VERSION_STR as PYQT_VERSION # analysis:ignore
133 from PyQt5.QtCore import QT_VERSION_STR as QT_VERSION # analysis:ignore
134 PYSIDE_VERSION = None
136 if sys.platform == 'darwin':
137 macos_version = LooseVersion(platform.mac_ver()[0])
138 if macos_version < LooseVersion('10.10'):
139 if LooseVersion(QT_VERSION) >= LooseVersion('5.9'):
140 raise PythonQtError("Qt 5.9 or higher only works in "
141 "macOS 10.10 or higher. Your "
142 "program will fail in this "
143 "system.")
144 elif macos_version < LooseVersion('10.11'):
145 if LooseVersion(QT_VERSION) >= LooseVersion('5.11'):
146 raise PythonQtError("Qt 5.11 or higher only works in "
147 "macOS 10.11 or higher. Your "
148 "program will fail in this "
149 "system.")
151 del macos_version
152 except ImportError:
153 API = os.environ['QT_API'] = 'pyside2'
155 if API in PYSIDE2_API:
156 try:
157 from PySide2 import __version__ as PYSIDE_VERSION # analysis:ignore
158 from PySide2.QtCore import __version__ as QT_VERSION # analysis:ignore
160 PYQT_VERSION = None
161 PYQT5 = False
162 PYSIDE2 = True
164 if sys.platform == 'darwin':
165 macos_version = LooseVersion(platform.mac_ver()[0])
166 if macos_version < LooseVersion('10.11'):
167 if LooseVersion(QT_VERSION) >= LooseVersion('5.11'):
168 raise PythonQtError("Qt 5.11 or higher only works in "
169 "macOS 10.11 or higher. Your "
170 "program will fail in this "
171 "system.")
173 del macos_version
174 except ImportError:
175 API = os.environ['QT_API'] = 'pyqt'
177 if API in PYQT4_API:
178 try:
179 import sip
180 try:
181 sip.setapi('QString', 2)
182 sip.setapi('QVariant', 2)
183 sip.setapi('QDate', 2)
184 sip.setapi('QDateTime', 2)
185 sip.setapi('QTextStream', 2)
186 sip.setapi('QTime', 2)
187 sip.setapi('QUrl', 2)
188 except (AttributeError, ValueError):
189 # PyQt < v4.6
190 pass
191 from PyQt4.Qt import PYQT_VERSION_STR as PYQT_VERSION # analysis:ignore
192 from PyQt4.Qt import QT_VERSION_STR as QT_VERSION # analysis:ignore
193 PYSIDE_VERSION = None
194 PYQT5 = False
195 PYQT4 = True
196 except ImportError:
197 API = os.environ['QT_API'] = 'pyside'
198 else:
199 is_old_pyqt = PYQT_VERSION.startswith(('4.4', '4.5', '4.6', '4.7'))
200 is_pyqt46 = PYQT_VERSION.startswith('4.6')
202 if API in PYSIDE_API:
203 try:
204 from PySide import __version__ as PYSIDE_VERSION # analysis:ignore
205 from PySide.QtCore import __version__ as QT_VERSION # analysis:ignore
206 PYQT_VERSION = None
207 PYQT5 = PYSIDE2 = False
208 PYSIDE = True
209 except ImportError:
210 raise PythonQtError('No Qt bindings could be found')
212 # If a correct API name is passed to QT_API and it could not be found,
213 # switches to another and informs through the warning
214 if API != initial_api and binding_specified:
215 warnings.warn('Selected binding "{}" could not be found, '
216 'using "{}"'.format(initial_api, API), RuntimeWarning)
218 API_NAME = {'pyqt5': 'PyQt5', 'pyqt': 'PyQt4', 'pyqt4': 'PyQt4',
219 'pyside': 'PySide', 'pyside2':'PySide2'}[API]
221 if PYQT4:
222 import sip
223 try:
224 API_NAME += (" (API v{0})".format(sip.getapi('QString')))
225 except AttributeError:
226 pass