enthought / pyface

pyface: traits-capable windowing framework
Other
105 stars 55 forks source link

Bug report: latest pyqt5 from pypi breaks pyface and traitsui #1195

Closed axel-kah closed 1 year ago

axel-kah commented 1 year ago

Environment

OS: Windows/Linux Python version: 3.7/3.8/3.9/3.10 Toolkit: Qt Qt API: PyQt5

Description

The latest pyqt5 release on pypi (5.15.8) seems to have changed its API and as a result breaks pyface and as a consequence also traitsui because it relies on pyqt imports made by pyface. I don't see any mention of this in the release notes: https://www.riverbankcomputing.com/news/PyQt_v5.15.8_Released

The last known working release of pyqt5 is 5.15.7 .

Steps to Reproduce

  1. create fresh venv

  2. pip install traitsui pyface[pyqt5]

  3. Taking an example from the traitsui docs and enforcing the toolkit produces a traceback pointing at the root cause:

    if __name__ == '__main__':
    from traits.etsconfig.api import ETSConfig
    ETSConfig.toolkit = 'qt'
    
    from traits.api import HasTraits, Int, Str
    from traitsui.api import Item, View
    
    class SimpleEmployee(HasTraits):
        first_name = Str()
        last_name = Str()
        department = Str()
        employee_number = Str()
        salary = Int()
    
    view1 = View(
        Item(name='first_name'),
        Item(name='last_name'),
        Item(name='department'),
    )
    
    sam = SimpleEmployee()
    sam.configure_traits(view=view1)
  4. Results in this traceback

    
    C:\dev\.venvpyqt5\Scripts\python.exe C:\dev\pyface_issue\traitsui-issue.py 
    Traceback (most recent call last):
    File "C:\dev\.venvpyqt5\lib\site-packages\pyface\base_toolkit.py", line 219, in import_toolkit
    toolkit_object = plugin.load()
    File "C:\Python39\lib\importlib\metadata.py", line 86, in load
    module = import_module(match.group('module'))
    File "C:\Python39\lib\importlib\__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
    File "<frozen importlib._bootstrap>", line 1030, in _gcd_import
    File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
    File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
    File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
    File "<frozen importlib._bootstrap_external>", line 850, in exec_module
    File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
    File "C:\dev\.venvpyqt5\lib\site-packages\pyface\ui\qt4\init.py", line 19, in <module>
    from .gui import GUI
    File "C:\dev\.venvpyqt5\lib\site-packages\pyface\ui\qt4\gui.py", line 18, in <module>
    from pyface.qt import QtCore, QtGui
    File "C:\dev\.venvpyqt5\lib\site-packages\pyface\qt\QtCore.py", line 30, in <module>
    from PyQt5.Qt import QCoreApplication
    ImportError: cannot import name 'QCoreApplication' from 'PyQt5.Qt' (C:\dev\.venvpyqt5\lib\site-packages\PyQt5\Qt.pyd)

The above exception was the direct cause of the following exception:

Traceback (most recent call last): File "C:\dev\pyface_issue\traitsui-issue.py", line 9, in from traitsui.api import Item, View File "C:\dev.venvpyqt5\lib\site-packages\traitsui\api.py", line 257, in from .editors.api import ArrayEditor File "C:\dev.venvpyqt5\lib\site-packages\traitsui\editors__init.py", line 16, in from .api import ArrayEditor File "C:\dev.venvpyqt5\lib\site-packages\traitsui\editors\api.py", line 96, in from .code_editor import CodeEditor File "C:\dev.venvpyqt5\lib\site-packages\traitsui\editors\code_editor.py", line 21, in class CodeEditor(EditorFactory): File "C:\dev.venvpyqt5\lib\site-packages\traitsui\editors\code_editor.py", line 32, in CodeEditor mark_color = Color(0xECE9D8) File "C:\dev.venvpyqt5\lib\site-packages\traits\trait_factory.py", line 40, in call return self.maker_function(*args, *metadata) File "C:\dev.venvpyqt5\lib\site-packages\traitsui\toolkit_traits.py", line 43, in ColorTrait return toolkit().color_trait(args, **traits) File "C:\dev.venvpyqt5\lib\site-packages\traitsui\toolkit.py", line 110, in toolkit _toolkit = find_toolkit("traitsui.toolkits") File "C:\dev.venvpyqt5\lib\site-packages\pyface\base_toolkit.py", line 265, in find_toolkit return import_toolkit(ETSConfig.toolkit, entry_point) File "C:\dev.venvpyqt5\lib\site-packages\pyface\base_toolkit.py", line 219, in import_toolkit toolkit_object = plugin.load() File "C:\Python39\lib\importlib\metadata.py", line 86, in load module = import_module(match.group('module')) File "C:\Python39\lib\importlib\init.py", line 127, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "C:\dev.venvpyqt5\lib\site-packages\traitsui\qt4\init__.py", line 35, in from . import toolkit File "C:\dev.venvpyqt5\lib\site-packages\traitsui\qt4\toolkit.py", line 33, in from pyface.toolkit import toolkit_object as pyface_toolkit File "C:\dev.venvpyqt5\lib\site-packages\pyface\toolkit.py", line 23, in toolkit = toolkit_object = find_toolkit("pyface.toolkits") File "C:\dev.venvpyqt5\lib\site-packages\pyface\base_toolkit.py", line 265, in find_toolkit return import_toolkit(ETSConfig.toolkit, entry_point) File "C:\dev.venvpyqt5\lib\site-packages\pyface\base_toolkit.py", line 231, in import_toolkit raise RuntimeError(msg) from toolkit_exception RuntimeError: No pyface.toolkits plugin could be loaded for qt

5. The root cause seems to be that
```python
from PyQt5.Qt import QCoreApplication

is no longer possible. This seems to work instead:

from PyQt5.QtCore import QCoreApplication
  1. If you don't force the toolkit and instead rely on autodiscovery you get this rather unspecific traceback:
    Traceback (most recent call last):
    File "C:\dev\pyface_issue\traitsui-issue.py", line 24, in <module>
    sam.configure_traits(view=view1)
    File "C:\dev\.venvpyqt5\lib\site-packages\traits\has_traits.py", line 2164, in configure_traits
    rc = toolkit().view_application(
    File "C:\dev\.venvpyqt5\lib\site-packages\traitsui\toolkit.py", line 238, in view_application
    raise NotImplementedError(
    NotImplementedError: the 'null' toolkit does not implement this method
axel-kah commented 1 year ago

Today pyqt5 5.15.9 was released without much of a changelog, but it seems to have fixed the issue.