enthought / pyface

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

Update of PyQt5 imports needed. #418

Open capn-freako opened 5 years ago

capn-freako commented 5 years ago

In recent PyQt5 releases, the QtWebKit module has been replaced by QtWebEngine. This causes the following error to occur when attempting to use the most recent PyQt5 release:

  File "/Users/dbanas/Documents/Projects/PyBERT/pyface/pyface/qt/QtWebKit.py", line 18, in <module>
    from PyQt5.QtWebKit import *
ModuleNotFoundError: No module named 'PyQt5.QtWebKit'

So, 2 questions:

  1. Are there plans to update PyFace to use QtWebEngine, instead of QtWebKit?

  2. Do you happen to know in which release of PyQt5 this change first occurred?

Thanks!

corranwebster commented 5 years ago

The answers are:

1) Definitely yes - if you look at the relevant file (here https://github.com/enthought/pyface/blob/master/pyface/qt/QtWebKit.py#L9) you can see that we only hit that line after we have tried to use QtWebEngine and failed to import it for some reason. I can't say what went wrong without more information about your system and which import statement failed (some strategic print statements might help).

2) Not sure - it should be in the Qt release notes - by I know 5.6 uses QtWebKit and 5.11 does not.

kitchoi commented 3 years ago

For reference, if I try to change the code to get more information from the error:

    try:
        from PyQt5.QtWebEngine import *
        from PyQt5.QtWebEngineWidgets import (
            QWebEngineHistory as QWebHistory,
            QWebEngineHistoryItem as QWebHistoryItem,
            QWebEnginePage as QWebPage,
            QWebEngineView as QWebView,
            QWebEngineSettings as QWebSettings,
        )
    except ImportError as original_error:
        try:
            from PyQt5.QtWebKit import *
            from PyQt5.QtWebKitWidgets import *
        except ImportError as fallback_error:
            raise fallback_error from original_error

I get more information from the traceback:

>>> from pyface.qt import QtWebKit
Traceback (most recent call last):
  File "/Users/kchoi/Work/ETS/py39-venv/traitsui-env/lib/python3.9/site-packages/pyface/qt/QtWebKit.py", line 19, in <module>
    from PyQt5.QtWebEngine import *
ModuleNotFoundError: No module named 'PyQt5.QtWebEngine'

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

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/kchoi/Work/ETS/py39-venv/traitsui-env/lib/python3.9/site-packages/pyface/qt/QtWebKit.py", line 32, in <module>
    raise fallback_error from original_error
  File "/Users/kchoi/Work/ETS/py39-venv/traitsui-env/lib/python3.9/site-packages/pyface/qt/QtWebKit.py", line 29, in <module>
    from PyQt5.QtWebKit import *
ModuleNotFoundError: No module named 'PyQt5.QtWebKit'

If I then do this on the command line:

pip install PyQtWebEngine

then the import works.

However, when I run a set of integration tests where an import of PyQtWebEngine happens later (e.g. when the HTML editor is required), I also get the following error:

>>> from pyface.ui.qt4 import init
>>> from pyface.qt import QtWebKit
Qt WebEngine seems to be initialized from a plugin. Please set Qt::AA_ShareOpenGLContexts using QCoreApplication::setAttribute before constructing QGuiApplication.
Traceback (most recent call last):
  File "/Users/kchoi/Work/ETS/py39-venv/traitsui-env/lib/python3.9/site-packages/pyface/qt/QtWebKit.py", line 20, in <module>
    from PyQt5.QtWebEngineWidgets import (
ImportError: QtWebEngineWidgets must be imported before a QCoreApplication instance is created

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

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/kchoi/Work/ETS/py39-venv/traitsui-env/lib/python3.9/site-packages/pyface/qt/QtWebKit.py", line 32, in <module>
    raise fallback_error from original_error
  File "/Users/kchoi/Work/ETS/py39-venv/traitsui-env/lib/python3.9/site-packages/pyface/qt/QtWebKit.py", line 29, in <module>
    from PyQt5.QtWebKit import *
ModuleNotFoundError: No module named 'PyQt5.QtWebKit'

Looks like we need to fix pyface.ui.qt4.init to make sure it tries to import QtWebKit first before initializing the QCoreApplication.

kitchoi commented 3 years ago

To add more context to the import error observed, if I run the HTMLEditor example from TraitsUI:

If I also apply the raise fallback_error from original_error patch in https://github.com/enthought/pyface/issues/418#issuecomment-738798017 to get more information...

Without having pip install PyQtWebEngine, I get the following error traceback:

Traceback (most recent call last):
  File "/Users/kchoi/Work/ETS/py39-venv/env/lib/python3.9/site-packages/pyface/qt/QtWebKit.py", line 19, in <module>
    from PyQt5.QtWebEngine import *
ModuleNotFoundError: No module named 'PyQt5.QtWebEngine'

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

Traceback (most recent call last):
...
  File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
  File "/Users/kchoi/Work/ETS/py39-venv/env/lib/python3.9/site-packages/traitsui/qt4/html_editor.py", line 23, in <module>
    from pyface.qt import QtCore, QtGui, QtWebKit
  File "/Users/kchoi/Work/ETS/py39-venv/env/lib/python3.9/site-packages/pyface/qt/QtWebKit.py", line 32, in <module>
    raise fallback_error from original_error
  File "/Users/kchoi/Work/ETS/py39-venv/env/lib/python3.9/site-packages/pyface/qt/QtWebKit.py", line 29, in <module>
    from PyQt5.QtWebKit import *
ModuleNotFoundError: No module named 'PyQt5.QtWebKit'

After pip install PyQtWebEngine, I get this traceback:

Traceback (most recent call last):
  File "/Users/kchoi/Work/ETS/py39-venv/enable-env/lib/python3.9/site-packages/pyface/qt/QtWebKit.py", line 20, in <module>
    from PyQt5.QtWebEngineWidgets import (
ImportError: QtWebEngineWidgets must be imported before a QCoreApplication instance is created
The above exception was the direct cause of the following exception:

Traceback (most recent call last):
...
  File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
  File "/Users/kchoi/Work/ETS/py39-venv/env/lib/python3.9/site-packages/traitsui/qt4/html_editor.py", line 23, in <module>
    from pyface.qt import QtCore, QtGui, QtWebKit
  File "/Users/kchoi/Work/ETS/py39-venv/env/lib/python3.9/site-packages/pyface/qt/QtWebKit.py", line 32, in <module>
    raise fallback_error from original_error
  File "/Users/kchoi/Work/ETS/py39-venv/env/lib/python3.9/site-packages/pyface/qt/QtWebKit.py", line 29, in <module>
    from PyQt5.QtWebKit import *
ModuleNotFoundError: No module named 'PyQt5.QtWebKit'

Adding this block:

    try:
        from pyface.qt import QtWebKit
    except ImportError:
        pass

before this line: https://github.com/enthought/pyface/blob/4a991afb5eb243af5d303b7281b906f6bf24e109/pyface/ui/qt4/init.py#L37 resolves the error and I was able to launch the HTMLEditor (I still need to have PyQtWebEngine in my environment, though!).

Edited with platform and Python environment information:

Steps to create an environment On OSX 10.15: ``` $ python3.9 -m venv py39-venv/webkit-env $ source py39-venv/webkit-env/bin/activate $ pip install traitsui[pyqt5] ```
Packages before installing PyQtWebEngine ``` $ pip list Package Version ------------------- ------- importlib-metadata 3.3.0 importlib-resources 3.3.0 pip 20.2.3 pyface 7.2.0 Pygments 2.7.3 PyQt5 5.15.2 PyQt5-sip 12.8.1 setuptools 49.2.1 traits 6.1.1 traitsui 7.1.1 zipp 3.4.0 ```
Packages after installing PyQtWebEngine ``` $ pip install PyQtWebEngine $ pip list Package Version ------------------- ------- importlib-metadata 3.3.0 importlib-resources 3.3.0 pip 20.2.3 pyface 7.2.0 Pygments 2.7.3 PyQt5 5.15.2 PyQt5-sip 12.8.1 PyQtWebEngine 5.15.2 setuptools 49.2.1 traits 6.1.1 traitsui 7.1.1 zipp 3.4.0 ```