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

Skip to content

Commit 281814d

Browse files
committed
Run setupext qt checks in a subprocess rather than with multiprocessing.
1 parent c29d9b2 commit 281814d

File tree

1 file changed

+62
-133
lines changed

1 file changed

+62
-133
lines changed

setupext.py

Lines changed: 62 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -1613,155 +1613,84 @@ def get_extension(self):
16131613
return ext
16141614

16151615

1616-
class BackendQtBase(OptionalBackendPackage):
1617-
1618-
def convert_qt_version(self, version):
1619-
version = '%x' % version
1620-
temp = []
1621-
while len(version) > 0:
1622-
version, chunk = version[:-2], version[-2:]
1623-
temp.insert(0, str(int(chunk, 16)))
1624-
return '.'.join(temp)
1625-
1626-
def check_requirements(self):
1627-
"""
1628-
If PyQt4/PyQt5 is already imported, importing PyQt5/PyQt4 will fail
1629-
so we need to test in a subprocess (as for Gtk3).
1630-
"""
1631-
try:
1632-
p = multiprocessing.Pool()
1633-
1634-
except:
1635-
# Can't do multiprocessing, fall back to normal approach
1636-
# (this will fail if importing both PyQt4 and PyQt5).
1637-
try:
1638-
# Try in-process
1639-
msg = self.callback(self)
1640-
except RuntimeError:
1641-
raise CheckFailed(
1642-
"Could not import: are PyQt4 & PyQt5 both installed?")
1643-
1644-
else:
1645-
# Multiprocessing OK
1646-
try:
1647-
res = p.map_async(self.callback, [self])
1648-
msg = res.get(timeout=10)[0]
1649-
except multiprocessing.TimeoutError:
1650-
p.terminate()
1651-
# No result returned. Probably hanging, terminate the process.
1652-
raise CheckFailed("Check timed out")
1653-
except:
1654-
# Some other error.
1655-
p.close()
1656-
raise
1657-
else:
1658-
# Clean exit
1659-
p.close()
1660-
finally:
1661-
# Tidy up multiprocessing
1662-
p.join()
1663-
1664-
return msg
1665-
1666-
1667-
def backend_pyside_internal_check(self):
1668-
try:
1669-
from PySide import __version__
1670-
from PySide import QtCore
1671-
except ImportError:
1672-
raise CheckFailed("PySide not found")
1673-
else:
1674-
return ("Qt: %s, PySide: %s" %
1675-
(QtCore.__version__, __version__))
1616+
def _run_check_script(script):
1617+
"""
1618+
Run given script in a subprocess.
16761619
1620+
If the subprocess returns successfully, return the subprocess' stdout.
1621+
Otherwise, raise a `CheckFailed` with the subprocess' stderr.
16771622
1678-
def backend_pyqt4_internal_check(self):
1679-
try:
1680-
from PyQt4 import QtCore
1681-
except ImportError:
1682-
raise CheckFailed("PyQt4 not found")
1683-
1623+
The use of a subprocess is needed to avoid importing both Qt4 and Qt5 in
1624+
the same process (which causes a RuntimeError).
1625+
"""
16841626
try:
1685-
qt_version = QtCore.QT_VERSION
1686-
pyqt_version_str = QtCore.PYQT_VERSION_STR
1687-
except AttributeError:
1688-
raise CheckFailed('PyQt4 not correctly imported')
1627+
proc = subprocess.run([sys.executable, "-c", script],
1628+
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
1629+
universal_newlines=True, timeout=10)
1630+
except subprocess.TimeoutExpired:
1631+
raise CheckFailed("Check timed out")
1632+
if proc.returncode:
1633+
raise CheckFailed(proc.stderr)
16891634
else:
1690-
return ("Qt: %s, PyQt: %s" % (self.convert_qt_version(qt_version), pyqt_version_str))
1691-
1692-
1693-
def backend_qt4_internal_check(self):
1694-
successes = []
1695-
failures = []
1696-
try:
1697-
successes.append(backend_pyside_internal_check(self))
1698-
except CheckFailed as e:
1699-
failures.append(str(e))
1700-
1701-
try:
1702-
successes.append(backend_pyqt4_internal_check(self))
1703-
except CheckFailed as e:
1704-
failures.append(str(e))
1705-
1706-
if len(successes) == 0:
1707-
raise CheckFailed('; '.join(failures))
1708-
return '; '.join(successes + failures)
1635+
return proc.stdout
17091636

17101637

1711-
class BackendQt4(BackendQtBase):
1638+
class BackendQt4(OptionalBackendPackage):
17121639
name = "qt4agg"
17131640

1714-
def __init__(self, *args, **kwargs):
1715-
BackendQtBase.__init__(self, *args, **kwargs)
1716-
self.callback = backend_qt4_internal_check
1641+
def check_requirements(self):
1642+
return _run_check_script("""\
1643+
import sys
1644+
found = []
17171645
1718-
def backend_pyside2_internal_check(self):
1719-
try:
1720-
from PySide2 import __version__
1721-
from PySide2 import QtCore
1722-
except ImportError:
1723-
raise CheckFailed("PySide2 not found")
1724-
else:
1725-
return ("Qt: %s, PySide2: %s" %
1726-
(QtCore.__version__, __version__))
1646+
try:
1647+
from PyQt4.QtCore import QT_VERSION_STR, PYQT_VERSION_STR
1648+
except ImportError:
1649+
pass
1650+
else:
1651+
found.append("Qt: {}, PyQt: {}".format(QT_VERSION_STR, PYQT_VERSION_STR))
17271652
1728-
def backend_pyqt5_internal_check(self):
1729-
try:
1730-
from PyQt5 import QtCore
1731-
except ImportError:
1732-
raise CheckFailed("PyQt5 not found")
1653+
try:
1654+
from PySide import __version__, QtCore
1655+
except ImportError:
1656+
pass
1657+
else:
1658+
found.append("Qt: {}, PySide: {}".format(QtCore.__version__, __version__))
17331659
1734-
try:
1735-
qt_version = QtCore.QT_VERSION
1736-
pyqt_version_str = QtCore.PYQT_VERSION_STR
1737-
except AttributeError:
1738-
raise CheckFailed('PyQt5 not correctly imported')
1739-
else:
1740-
return ("Qt: %s, PyQt: %s" % (self.convert_qt_version(qt_version), pyqt_version_str))
1660+
if found:
1661+
print("; ".join(found), end="")
1662+
else:
1663+
sys.exit("Found neither PyQt4 nor PySide.")
1664+
""")
17411665

1742-
def backend_qt5_internal_check(self):
1743-
successes = []
1744-
failures = []
1745-
try:
1746-
successes.append(backend_pyside2_internal_check(self))
1747-
except CheckFailed as e:
1748-
failures.append(str(e))
17491666

1750-
try:
1751-
successes.append(backend_pyqt5_internal_check(self))
1752-
except CheckFailed as e:
1753-
failures.append(str(e))
1667+
class BackendQt5(OptionalBackendPackage):
1668+
name = "qt5agg"
17541669

1755-
if len(successes) == 0:
1756-
raise CheckFailed('; '.join(failures))
1757-
return '; '.join(successes + failures)
1670+
def check_requirements(self):
1671+
return _run_check_script("""\
1672+
import sys
1673+
found = []
17581674
1759-
class BackendQt5(BackendQtBase):
1760-
name = "qt5agg"
1675+
try:
1676+
from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR
1677+
except ImportError:
1678+
pass
1679+
else:
1680+
found.append("Qt: {}, PyQt: {}".format(QT_VERSION_STR, PYQT_VERSION_STR))
17611681
1762-
def __init__(self, *args, **kwargs):
1763-
BackendQtBase.__init__(self, *args, **kwargs)
1764-
self.callback = backend_qt5_internal_check
1682+
try:
1683+
from PySide2 import __version__, QtCore
1684+
except ImportError:
1685+
pass
1686+
else:
1687+
found.append("Qt: {}, PySide: {}".format(QtCore.__version__, __version__))
1688+
1689+
if found:
1690+
print("; ".join(found), end="")
1691+
else:
1692+
sys.exit("Found neither PyQt5 nor PySide2.")
1693+
""")
17651694

17661695

17671696
class BackendCairo(OptionalBackendPackage):

0 commit comments

Comments
 (0)