enthought / enable

Enable: low-level drawing and interaction
Other
91 stars 45 forks source link

ModuleNotFoundError: No module named 'enable.savage.trait_defs.ui.qt' when running python3.11 enable/examples/demo/savage/button_demo.py #1026

Closed homosapien-lcy closed 1 year ago

homosapien-lcy commented 1 year ago

Problem:

When running many demos in enable/examples/demo/savage/, a ModuleNotFoundError will be resulted. For instance:

python3.11 enable/examples/demo/savage/button_demo.py
Traceback (most recent call last):
  File "/Users/cyliu/.venvs/py311_test_2/lib/python3.11/site-packages/enable/savage/trait_defs/ui/toolkit.py", line 30, in _init_toolkit
    __import__(backend)
ModuleNotFoundError: No module named 'enable.savage.trait_defs.ui.qt'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/cyliu/Documents/3.11_test_2/enable/enable/examples/demo/savage/button_demo.py", line 16, in <module>
    from enable.savage.trait_defs.ui.svg_button import SVGButton
  File "/Users/cyliu/.venvs/py311_test_2/lib/python3.11/site-packages/enable/savage/trait_defs/ui/svg_button.py", line 15, in <module>
    from .svg_button_editor import SVGButtonEditor
  File "/Users/cyliu/.venvs/py311_test_2/lib/python3.11/site-packages/enable/savage/trait_defs/ui/svg_button_editor.py", line 17, in <module>
    from enable.savage.trait_defs.ui.toolkit import toolkit_object
  File "/Users/cyliu/.venvs/py311_test_2/lib/python3.11/site-packages/enable/savage/trait_defs/ui/toolkit.py", line 43, in <module>
    _init_toolkit()
  File "/Users/cyliu/.venvs/py311_test_2/lib/python3.11/site-packages/enable/savage/trait_defs/ui/toolkit.py", line 32, in _init_toolkit
    raise ImportError(
ImportError: Unable to import a Savage backend for the qt toolkit.

How to replicate: python enable/examples/demo/savage/button_demo.py

Environment: MacOS, python3.11

Packages: Package Version


chaco 5.1.1 enable 5.4.0.dev25 fonttools 4.39.3 kiwisolver 1.4.4 numpy 1.24.2 Pillow 9.5.0 pip 22.3.1 pyface 8.0.0 pygarrayimage 1.0 pyglet 2.0.5 pyparsing 3.0.9 PySide6 6.5.0 PySide6-Addons 6.5.0 PySide6-Essentials 6.5.0 reportlab 3.6.12 scipy 1.10.1 setuptools 65.6.3 shiboken6 6.5.0 traits 6.4.1 traitsui 7.4.3

homosapien-lcy commented 1 year ago

After some research, the source of the error is _init_toolkit(), line 27-39

    # Import the selected backend
    backend = "enable.savage.trait_defs.ui.%s" % ETSConfig.toolkit
    try:
        __import__(backend)
    except (ImportError, SystemExit):
        raise ImportError(
            "Unable to import a Savage backend for the %s "
            "toolkit." % ETSConfig.toolkit
        )

    # Save the imported toolkit module.
    global _toolkit_backend
    _toolkit_backend = backend

The ETSConfi.toolkit (from traits.etsconfig.api) uses 'qt' now, this makes the backend enable.savage.trait_defs.ui.qt which doesn't exist

dpinte commented 1 year ago

@homosapien-lcy There are two valid subpackage in savage: wx and qt4. So the question is what is the expected values for the backend names. If the new official backend name is qt, then we need to rename "enable.savage.trait_defs.ui.qt4" -> "enable.savage.trait_defs.ui.qt". That decision must be backed by information about ETSConfig.

homosapien-lcy commented 1 year ago

After some investigation: 1 there is no code in traits that specify what the ETSConfig.toolkit should be 2 if we change toolkit to qt4 (either in _init_toolkit() or specify ETS_TOOLKIT=qt4 python3.11 enable/examples/demo/savage/button_demo.py), line 27-39 the demo will run successfully. If we directly echo $ETS_TOOLKIT it will return nothing, same do os.environ.get("ETS_TOOLKIT", ""). Suggesting qt is a default option setup. Further studies points to traitsui.toolkit -> pyface.base_toolkit. The pyface.base_toolkit contains the likely cause (line 84) TOOLKIT_PRIORITIES = {"qt": -2, "wx": -1, "null": float("inf")} To solve this problem, I think we should rename the enable.savage.trait_defs.ui.qt4 to enable.savage.trait_defs.ui.qt. Since this renaming is consistent with the recent renaming in pyface and traitsui (https://github.com/enthought/traitsui) as well. Qt4 naming has caused confusion since it is outdated and Qt5 and Qt6 are more popular now (https://github.com/enthought/pyface/releases/tag/8.0.0)

dpinte commented 1 year ago

Pyface 8.0 release has some specific in the changelog (https://github.com/enthought/pyface/blob/main/CHANGES.txt#L5).
Let's get a similar implementation in enable to the backend selection.