Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c98406d

Browse files
author
Martin Fitzpatrick
committed
Fix setupext.py for the case where both PyQt4 and PyQt5 are installed
If both PyQt4 and PyQt5 are installed in the same Python the setup check for the modules will cause a RuntimeError as they are both imported. The Gtk module uses a multiprocessing pool to perform the imports, and this approach is used here. However, if we import PyQt4 normally, then PyQt5 using multiprocessing the import is incomplete (no version information). Instead, we default to multiprocessing for both PyQt4 and PyQt5 and only fall to normal imports if that is not available. In the case of a RuntimeError on a normal-style import the error is raised as `CheckFailed("Could not import: are PyQt4 & PyQt5 both installed?")` to give a hint as to the problem.
1 parent c9bf9ec commit c98406d

1 file changed

Lines changed: 75 additions & 30 deletions

File tree

setupext.py

Lines changed: 75 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1852,8 +1852,7 @@ def get_extension(self):
18521852
return ext
18531853

18541854

1855-
class BackendQt4(OptionalBackendPackage):
1856-
name = "qt4agg"
1855+
class BackendQtBase(OptionalBackendPackage):
18571856

18581857
def convert_qt_version(self, version):
18591858
version = '%x' % version
@@ -1864,38 +1863,84 @@ def convert_qt_version(self, version):
18641863
return '.'.join(temp)
18651864

18661865
def check_requirements(self):
1866+
'''
1867+
If PyQt4/PyQt5 is already imported, importing PyQt5/PyQt4 will fail
1868+
so we need to test in a subprocess (as for Gtk3).
1869+
'''
18671870
try:
1868-
from PyQt4 import QtCore
1869-
except ImportError:
1870-
raise CheckFailed("PyQt4 not found")
1871-
# Import may still be broken for our python
1872-
try:
1873-
qt_version = QtCore.QT_VERSION
1874-
pyqt_version_str = QtCore.PYQT_VERSION_STR
1875-
except AttributeError:
1876-
raise CheckFailed('PyQt4 not correctly imported')
1877-
BackendAgg.force = True
1878-
return ("Qt: %s, PyQt4: %s" %
1879-
(self.convert_qt_version(
1880-
qt_version),
1881-
pyqt_version_str))
1871+
p = multiprocessing.Pool()
1872+
1873+
except:
1874+
# Can't do multiprocessing, fall back to normal approach ( this will fail if importing both PyQt4 and PyQt5 )
1875+
try:
1876+
# Try in-process
1877+
msg = self.callback(self)
1878+
1879+
except RuntimeError:
1880+
raise CheckFailed("Could not import: are PyQt4 & PyQt5 both installed?")
1881+
1882+
except:
1883+
# Raise any other exceptions
1884+
raise
1885+
1886+
else:
1887+
# Multiprocessing OK
1888+
try:
1889+
msg = p.map(self.callback, [self])[0]
1890+
except:
1891+
# If we hit an error on multiprocessing raise it
1892+
raise
1893+
finally:
1894+
# Tidy up multiprocessing
1895+
p.close()
1896+
p.join()
1897+
1898+
return msg
1899+
1900+
1901+
def backend_qt4_internal_check(self):
1902+
try:
1903+
from PyQt4 import QtCore
1904+
except ImportError:
1905+
raise CheckFailed("PyQt4 not found")
1906+
try:
1907+
qt_version = QtCore.QT_VERSION
1908+
pyqt_version_str = QtCore.QT_VERSION_STR
1909+
except AttributeError:
1910+
raise CheckFailed('PyQt4 not correctly imported')
1911+
1912+
return ("Qt: %s, PyQt: %s" % (self.convert_qt_version(qt_version), pyqt_version_str))
1913+
18821914

1883-
class BackendQt5(BackendQt4):
1915+
class BackendQt4(BackendQtBase):
1916+
name = "qt4agg"
1917+
1918+
def __init__(self, *args, **kwargs):
1919+
BackendQtBase.__init__(self, *args, **kwargs)
1920+
self.callback = backend_qt4_internal_check
1921+
1922+
1923+
def backend_qt5_internal_check(self):
1924+
try:
1925+
from PyQt5 import QtCore
1926+
except ImportError:
1927+
raise CheckFailed("PyQt5 not found")
1928+
try:
1929+
qt_version = QtCore.QT_VERSION
1930+
pyqt_version_str = QtCore.QT_VERSION_STR
1931+
except AttributeError:
1932+
raise CheckFailed('PyQt5 not correctly imported')
1933+
1934+
return ("Qt: %s, PyQt: %s" % (self.convert_qt_version(qt_version), pyqt_version_str))
1935+
1936+
1937+
class BackendQt5(BackendQtBase):
18841938
name = "qt5agg"
18851939

1886-
def check_requirements(self):
1887-
try:
1888-
from PyQt5 import QtCore
1889-
except ImportError:
1890-
raise CheckFailed("PyQt5 not found")
1891-
# Import may still be broken for our python
1892-
try:
1893-
qtconfig = QtCore.PYQT_CONFIGURATION
1894-
except AttributeError:
1895-
raise CheckFailed('PyQt5 not correctly imported')
1896-
BackendAgg.force = True
1897-
# FIXME: How to return correct version information?
1898-
return ("Qt: 5, PyQt5: %s" % (QtCore.PYQT_VERSION_STR) )
1940+
def __init__(self, *args, **kwargs):
1941+
BackendQtBase.__init__(self, *args, **kwargs)
1942+
self.callback = backend_qt5_internal_check
1943+
18991944

19001945
class BackendPySide(OptionalBackendPackage):
19011946
name = "pyside"

0 commit comments

Comments
 (0)