Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit55a9d88

Browse files
committed
Rewrite and greatly simplify qt_compat.py.
The selection logic is now described in the module's docstring. Theonly changes is that the QT_ENV_MAJOR_VERSION global, which wouldsometimes be defined (depending on the state of the import cache, theQT_API environment variable, and the requested backend) is never definedanymore.
1 parentcfb648f commit55a9d88

File tree

4 files changed

+123
-199
lines changed

4 files changed

+123
-199
lines changed

‎INSTALL.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,8 +189,9 @@ interface toolkits. See :ref:`what-is-a-backend` for more details on the
189189
optional Matplotlib backends and the capabilities they provide.
190190

191191
*:term:`tk` (>= 8.3, != 8.6.0 or 8.6.1): for the TkAgg backend;
192-
* `PyQt4<https://pypi.python.org/pypi/PyQt4>`_ (>= 4.4) or
193-
`PySide<https://pypi.python.org/pypi/PySide>`_: for the Qt4Agg backend;
192+
* `PyQt4<https://pypi.python.org/pypi/PyQt4>`_ (>= 4.6) or
193+
`PySide<https://pypi.python.org/pypi/PySide>`_ (>= 1.0.3): for the Qt4Agg
194+
backend;
194195
* `PyQt5<https://pypi.python.org/pypi/PyQt5>`_: for the Qt5Agg backend;
195196
*:term:`pygtk` (>= 2.4): for the GTK and the GTKAgg backend;
196197
*:term:`wxpython` (>= 2.9 or later): for the WX or WXAgg backend;

‎doc/conf.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,9 @@ class Frame(object):
355355

356356

357357
classMyPyQt4(MagicMock):
358+
classQtCore(MagicMock):
359+
PYQT_VERSION_STR="4.6"
360+
358361
classQtGui(object):
359362
# PyQt4.QtGui public classes.
360363
# Generated with
@@ -450,6 +453,9 @@ class QtGui(object):
450453
locals()[_name]=type(_name, (), {})
451454
del_name
452455

456+
QtCore=QtCore()
457+
QtGui=QtGui()
458+
453459

454460
classMySip(MagicMock):
455461
defgetapi(*args):

‎lib/matplotlib/backends/qt_compat.py

Lines changed: 113 additions & 196 deletions
Original file line numberDiff line numberDiff line change
@@ -1,227 +1,144 @@
1-
""" A Qt API selector that can be used to switch between PyQt and PySide.
21
"""
2+
Qt binding and backend selector.
3+
4+
The selection logic is as follows:
5+
- if any of PyQt5, PySide2, PyQt4 or PySide have already been imported (checked
6+
in that order), use it;
7+
- otherwise, if the QT_API environment variable (used by Enthought) is
8+
set, use it to determine which binding to use (but do not change the
9+
backend based on it; i.e. if the Qt4Agg backend is requested but QT_API
10+
is set to "pyqt5", then actually use Qt4 with the binding specified by
11+
``rcParams["backend.qt4"]``;
12+
- otherwise, use whatever the rcParams indicate.
13+
"""
14+
315
from __future__import (absolute_import,division,print_function,
416
unicode_literals)
517

618
importsix
719

20+
fromdistutils.versionimportLooseVersion
821
importos
9-
importlogging
1022
importsys
11-
frommatplotlibimportrcParams
1223

13-
_log=logging.getLogger(__name__)
14-
15-
# Available APIs.
16-
QT_API_PYQT='PyQt4'# API is not set here; Python 2.x default is V 1
17-
QT_API_PYQTv2='PyQt4v2'# forced to Version 2 API
18-
QT_API_PYSIDE='PySide'# only supports Version 2 API
19-
QT_API_PYQT5='PyQt5'# use PyQt5 API; Version 2 with module shim
20-
QT_API_PYSIDE2='PySide2'# Version 2 API with module shim
24+
frommatplotlibimportrcParams
2125

22-
ETS=dict(pyqt=(QT_API_PYQTv2,4),pyside=(QT_API_PYSIDE,4),
23-
pyqt5=(QT_API_PYQT5,5),pyside2=(QT_API_PYSIDE2,5))
24-
# ETS is a dict of env variable to (QT_API, QT_MAJOR_VERSION)
25-
# If the ETS QT_API environment variable is set, use it, but only
26-
# if the varible if of the same major QT version. Note that
27-
# ETS requires the version 2 of PyQt4, which is not the platform
28-
# default for Python 2.x.
2926

27+
QT_API_PYQT="PyQt4"
28+
QT_API_PYQTv2="PyQt4v2"
29+
QT_API_PYSIDE="PySide"
30+
QT_API_PYQT5="PyQt5"
31+
QT_API_PYSIDE2="PySide2"
3032
QT_API_ENV=os.environ.get('QT_API')
31-
32-
ifrcParams['backend']=='Qt5Agg':
33-
QT_RC_MAJOR_VERSION=5
34-
elifrcParams['backend']=='Qt4Agg':
35-
QT_RC_MAJOR_VERSION=4
33+
# First, check if anything is already imported.
34+
if"PyQt5"insys.modules:
35+
QT_API=rcParams["backend.qt5"]=QT_API_PYQT5
36+
elif"PySide2"insys.modules:
37+
QT_API=rcParams["backend.qt5"]=QT_API_PYSIDE2
38+
elif"PyQt4"insys.modules:
39+
QT_API=rcParams["backend.qt4"]=QT_API_PYQTv2
40+
elif"PySide"insys.modules:
41+
QT_API=rcParams["backend.qt4"]=QT_API_PYSIDE
42+
# Otherwise, check the QT_API environment variable (from Enthought). This can
43+
# only override the binding, not the backend (in other words, we check that the
44+
# requested backend actually matches).
45+
elifrcParams["backend"]=="Qt5Agg":
46+
ifQT_API_ENV=="pyqt5":
47+
rcParams["backend.qt5"]=QT_API_PYQT5
48+
elifQT_API_ENV=="pyside2":
49+
rcParams["backend.qt5"]=QT_API_PYSIDE2
50+
QT_API=rcParams["backend.qt5"]
51+
elifrcParams["backend"]=="Qt4Agg":
52+
ifQT_API_ENV=="pyqt4":
53+
rcParams["backend.qt4"]=QT_API_PYQTv2
54+
elifQT_API_ENV=="pyside":
55+
rcParams["backend.qt4"]=QT_API_PYSIDE
56+
QT_API=rcParams["backend.qt5"]
57+
# A non-Qt backend was selected but we still got there (possible, e.g., when
58+
# fully manually embedding Matplotlib in a Qt app without using pyplot).
3659
else:
37-
# A different backend was specified, but we still got here because a Qt
38-
# related file was imported. This is allowed, so lets try and guess
39-
# what we should be using.
40-
if"PyQt4"insys.modulesor"PySide"insys.modules:
41-
# PyQt4 or PySide is actually used.
42-
QT_RC_MAJOR_VERSION=4
43-
else:
44-
# This is a fallback: PyQt5
45-
QT_RC_MAJOR_VERSION=5
46-
47-
QT_API=None
48-
49-
# check if any binding is already imported, if so silently ignore the
50-
# rcparams/ENV settings and use what ever is already imported.
51-
if'PySide'insys.modules:
52-
# user has imported PySide before importing mpl
53-
QT_API=QT_API_PYSIDE
54-
55-
if'PySide2'insys.modules:
56-
# user has imported PySide before importing mpl
57-
QT_API=QT_API_PYSIDE2
60+
QT_API=None
5861

59-
if'PyQt4'insys.modules:
60-
# user has imported PyQt4 before importing mpl
61-
# this case also handles the PyQt4v2 case as once sip is imported
62-
# the API versions can not be changed so do not try
63-
QT_API=QT_API_PYQT
6462

65-
if'PyQt5'insys.modules:
66-
# the user has imported PyQt5 before importing mpl
67-
QT_API=QT_API_PYQT5
63+
def_setup_pyqt4():
64+
globalQtCore,QtGui,QtWidgets,__version__,is_pyqt5,_getSaveFileName
6865

69-
if (QT_API_ENVisnotNone)andQT_APIisNone:
70-
try:
71-
QT_ENV_MAJOR_VERSION=ETS[QT_API_ENV][1]
72-
exceptKeyError:
73-
raiseRuntimeError(
74-
('Unrecognized environment variable %r, valid values are:'
75-
' %r, %r, %r or %r'
76-
% (QT_API_ENV,'pyqt','pyside','pyqt5','pyside2')))
77-
ifQT_ENV_MAJOR_VERSION==QT_RC_MAJOR_VERSION:
78-
# Only if backend and env qt major version are
79-
# compatible use the env variable.
80-
QT_API=ETS[QT_API_ENV][0]
81-
82-
_fallback_to_qt4=False
83-
ifQT_APIisNone:
84-
# No ETS environment or incompatible so use rcParams.
85-
ifrcParams['backend']=='Qt5Agg':
86-
QT_API=rcParams['backend.qt5']
87-
elifrcParams['backend']=='Qt4Agg':
88-
QT_API=rcParams['backend.qt4']
89-
else:
90-
# A non-Qt backend was specified, no version of the Qt
91-
# bindings is imported, but we still got here because a Qt
92-
# related file was imported. This is allowed, fall back to Qt5
93-
# using which ever binding the rparams ask for.
94-
_fallback_to_qt4=True
95-
QT_API=rcParams['backend.qt5']
96-
97-
# We will define an appropriate wrapper for the differing versions
98-
# of file dialog.
99-
_getSaveFileName=None
100-
101-
# Flag to check if sip could be imported
102-
_sip_imported=False
103-
104-
# Now perform the imports.
105-
ifQT_APIin (QT_API_PYQT,QT_API_PYQTv2,QT_API_PYQT5):
106-
try:
66+
def_setup_pyqt4(api):
67+
globalQtCore,QtGui,QtWidgets, \
68+
__version__,is_pyqt5,_getSaveFileName
69+
# List of incompatible APIs:
70+
# http://pyqt.sourceforge.net/Docs/PyQt4/incompatible_apis.html
71+
_sip_apis= ["QDate","QDateTime","QString","QTextStream","QTime",
72+
"QUrl","QVariant"]
10773
importsip
108-
_sip_imported=True
109-
exceptImportError:
110-
# Try using PySide
111-
ifQT_RC_MAJOR_VERSION==5:
112-
QT_API=QT_API_PYSIDE2
113-
else:
114-
QT_API=QT_API_PYSIDE
115-
cond= ("Could not import sip; falling back on PySide\n"
116-
"in place of PyQt4 or PyQt5.\n")
117-
_log.info(cond)
118-
119-
if_sip_imported:
120-
ifQT_API==QT_API_PYQTv2:
121-
ifQT_API_ENV=='pyqt':
122-
cond= ("Found 'QT_API=pyqt' environment variable. "
123-
"Setting PyQt4 API accordingly.\n")
124-
else:
125-
cond="PyQt API v2 specified."
126-
try:
127-
sip.setapi('QString',2)
128-
except:
129-
res='QString API v2 specification failed. Defaulting to v1.'
130-
_log.info(cond+res)
131-
# condition has now been reported, no need to repeat it:
132-
cond=""
133-
try:
134-
sip.setapi('QVariant',2)
135-
except:
136-
res='QVariant API v2 specification failed. Defaulting to v1.'
137-
_log.info(cond+res)
138-
ifQT_API==QT_API_PYQT5:
139-
try:
140-
fromPyQt5importQtCore,QtGui,QtWidgets
141-
_getSaveFileName=QtWidgets.QFileDialog.getSaveFileName
142-
exceptImportError:
143-
if_fallback_to_qt4:
144-
# fell through, tried PyQt5, failed fall back to PyQt4
145-
QT_API=rcParams['backend.qt4']
146-
QT_RC_MAJOR_VERSION=4
147-
else:
148-
raise
149-
150-
# needs to be if so we can re-test the value of QT_API which may
151-
# have been changed in the above if block
152-
ifQT_APIin [QT_API_PYQT,QT_API_PYQTv2]:# PyQt4 API
74+
for_sip_apiin_sip_apis:
75+
try:
76+
sip.setapi(_sip_api,api)
77+
exceptValueError:
78+
pass
15379
fromPyQt4importQtCore,QtGui
80+
__version__=QtCore.PYQT_VERSION_STR
81+
# PyQt 4.6 introduced getSaveFileNameAndFilter:
82+
# https://riverbankcomputing.com/news/pyqt-46
83+
if__version__<LooseVersion(str("4.6")):
84+
raiseImportError("PyQt<4.6 is not supported")
85+
QtCore.Signal=QtCore.pyqtSignal
86+
QtCore.Slot=QtCore.pyqtSlot
87+
QtCore.Property=QtCore.pyqtProperty
88+
_getSaveFileName=QtGui.QFileDialog.getSaveFileNameAndFilter
15489

155-
try:
156-
ifsip.getapi("QString")>1:
157-
# Use new getSaveFileNameAndFilter()
158-
_getSaveFileName=QtGui.QFileDialog.getSaveFileNameAndFilter
159-
else:
90+
ifQT_API==QT_API_PYQT:
91+
_setup_pyqt4(api=1)
92+
elifQT_API==QT_API_PYQTv2:
93+
_setup_pyqt4(api=2)
94+
elifQT_API==QT_API_PYSIDE:
95+
fromPySideimportQtCore,QtGui,__version__,__version_info__
96+
# PySide 1.0.3 fixed the following:
97+
# https://srinikom.github.io/pyside-bz-archive/809.html
98+
if__version_info__< (1,0,3):
99+
raiseImportError("PySide<1.0.3 is not supported")
100+
_getSaveFileName=QtGui.QFileDialog.getSaveFileName
101+
else:
102+
raiseValueError('Unexpected value for the "backend.qt4" rcparam')
103+
QtWidgets=QtGui
160104

161-
# Use old getSaveFileName()
162-
def_getSaveFileName(*args,**kwargs):
163-
return (QtGui.QFileDialog.getSaveFileName(*args,**kwargs),
164-
None)
105+
defis_pyqt5():
106+
returnFalse
165107

166-
except (AttributeError,KeyError):
167108

168-
# call to getapi() can fail in older versions of sip
169-
def_getSaveFileName(*args,**kwargs):
170-
returnQtGui.QFileDialog.getSaveFileName(*args,**kwargs),None
171-
try:
172-
# Alias PyQt-specific functions for PySide compatibility.
173-
QtCore.Signal=QtCore.pyqtSignal
174-
try:
175-
QtCore.Slot=QtCore.pyqtSlot
176-
exceptAttributeError:
177-
# Not a perfect match but works in simple cases
178-
QtCore.Slot=QtCore.pyqtSignature
109+
def_setup_pyqt5():
110+
globalQtCore,QtGui,QtWidgets,__version__,is_pyqt5,_getSaveFileName
179111

180-
QtCore.Property=QtCore.pyqtProperty
112+
ifQT_API==QT_API_PYQT5:
113+
fromPyQt5importQtCore,QtGui,QtWidgets
181114
__version__=QtCore.PYQT_VERSION_STR
182-
exceptNameError:
183-
# QtCore did not get imported, fall back to pyside
184-
ifQT_RC_MAJOR_VERSION==5:
185-
QT_API=QT_API_PYSIDE2
186-
else:
187-
QT_API=QT_API_PYSIDE
115+
QtCore.Signal=QtCore.pyqtSignal
116+
QtCore.Slot=QtCore.pyqtSlot
117+
QtCore.Property=QtCore.pyqtProperty
118+
elifQT_API==QT_API_PYSIDE2:
119+
fromPySide2importQtCore,QtGui,QtWidgets,__version__
120+
else:
121+
raiseValueError('Unexpected value for the "backend.qt5" rcparam')
122+
_getSaveFileName=QtWidgets.QFileDialog.getSaveFileName
188123

124+
defis_pyqt5():
125+
returnTrue
189126

190-
ifQT_API==QT_API_PYSIDE2:
191-
try:
192-
fromPySide2importQtCore,QtGui,QtWidgets,__version__
193-
_getSaveFileName=QtWidgets.QFileDialog.getSaveFileName
194-
exceptImportError:
195-
# tried PySide2, failed, fall back to PySide
196-
QT_RC_MAJOR_VERSION=4
197-
QT_API=QT_API_PYSIDE
198127

199-
ifQT_API==QT_API_PYSIDE:# try importing pyside
128+
ifQT_APIin [QT_API_PYQT5,QT_API_PYSIDE2]:
129+
_setup_pyqt5()
130+
elifQT_APIin [QT_API_PYQT,QT_API_PYQTv2,QT_API_PYSIDE]:
131+
_setup_pyqt4()
132+
elifQT_APIisNone:
200133
try:
201-
fromPySideimportQtCore,QtGui,__version__,__version_info__
134+
_setup_pyqt5()
202135
exceptImportError:
203-
raiseImportError(
204-
"Matplotlib qt-based backends require an external PyQt4, PyQt5,\n"
205-
"PySide or PySide2 package to be installed, but it was not found.")
206-
207-
if__version_info__< (1,0,3):
208-
raiseImportError(
209-
"Matplotlib backend_qt4 and backend_qt4agg require PySide >=1.0.3")
210-
211-
_getSaveFileName=QtGui.QFileDialog.getSaveFileName
212-
213-
214-
# Apply shim to Qt4 APIs to make them look like Qt5
215-
ifQT_APIin (QT_API_PYQT,QT_API_PYQTv2,QT_API_PYSIDE):
216-
'''Import all used QtGui objects into QtWidgets
217-
218-
Here I've opted to simple copy QtGui into QtWidgets as that
219-
achieves the same result as copying over the objects, and will
220-
continue to work if other objects are used.
221-
222-
'''
223-
QtWidgets=QtGui
136+
_setup_pyqt4()
137+
else:
138+
raiseRuntimeError# We should not get there.
224139

225140

226-
defis_pyqt5():
227-
returnQT_API==QT_API_PYQT5
141+
# These globals are only defined for backcompatibilty purposes.
142+
ETS=dict(pyqt=(QT_API_PYQTv2,4),pyside=(QT_API_PYSIDE,4),
143+
pyqt5=(QT_API_PYQT5,5),pyside2=(QT_API_PYSIDE2,5))
144+
QT_RC_MAJOR_VERSION=5ifis_pyqt5()else4

‎lib/matplotlib/backends/qt_editor/formlayout.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
importsix
5454

5555
frommatplotlibimportcolorsasmcolors
56-
frommatplotlib.backends.qt_compatimportQtGui,QtWidgets,QtCore
56+
from..qt_compatimportQtCore,QtGui,QtWidgets
5757

5858

5959
BLACKLIST= {"title","label"}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp