@@ -1613,155 +1613,84 @@ def get_extension(self):
1613
1613
return ext
1614
1614
1615
1615
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.
1676
1619
1620
+ If the subprocess returns successfully, return the subprocess' stdout.
1621
+ Otherwise, raise a `CheckFailed` with the subprocess' stderr.
1677
1622
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
+ """
1684
1626
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 )
1689
1634
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
1709
1636
1710
1637
1711
- class BackendQt4 (BackendQtBase ):
1638
+ class BackendQt4 (OptionalBackendPackage ):
1712
1639
name = "qt4agg"
1713
1640
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 = []
1717
1645
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))
1727
1652
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__))
1733
1659
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
+ """ )
1741
1665
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 ))
1749
1666
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"
1754
1669
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 = []
1758
1674
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))
1761
1681
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
+ """ )
1765
1694
1766
1695
1767
1696
class BackendCairo (OptionalBackendPackage ):