Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 940202 - dev-python/spyder-6.0.1 fails to start with error: "ImportError: cannot import name 'QTextCodec' from 'qtpy.QtCore'", when using pyside{2,6} as the QtPy backend.
Summary: dev-python/spyder-6.0.1 fails to start with error: "ImportError: cannot impor...
Status: CONFIRMED
Alias: None
Product: Gentoo Linux
Classification: Unclassified
Component: Current packages (show other bugs)
Hardware: All Linux
: Normal normal
Assignee: Python Gentoo Team
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-09-24 19:26 UTC by Michael Tulupov
Modified: 2024-09-25 07:39 UTC (History)
2 users (show)

See Also:
Package list:
Runtime testing required: ---


Attachments
Error log (err.log,4.39 KB, text/x-log)
2024-09-24 19:32 UTC, Michael Tulupov
Details
Error log when PySide6 is used, without unittest plugin (err_pyside6.log,2.23 KB, text/plain)
2024-09-24 21:55 UTC, Michael Tulupov
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Tulupov 2024-09-24 19:26:49 UTC
In my setup dev-python/QtPy-2.4.1-r2 is re-built with [pyside6 -pyqt5 -pyqt6 -pyside2,....] to try Qt6 in Spyder.

According to dev-python/spyder-6.0.1 depends on >=dev-python/QtPy-2.4.0[quick,svg,webengine], but either of [pyside6 pyqt5 pyqt6 pyside2] is not specified as mandatory useflag.

As a result, spyder fails to start with the following error:

/usr/lib/python3.12/site-packages/spyder/requirements.py:42: PythonQtWarning: Selected binding 'pyqt5' could not be found; falling back to 'pyside6'
  import qtpy
unittest: cannot import name 'QTextCodec' from 'qtpy.QtCore' (/usr/lib/python3.12/site-packages/qtpy/QtCore.py)
Traceback (most recent call last):
  File "/usr/lib/python3.12/site-packages/spyder/app/find_plugins.py", line 71, in find_external_plugins
    mod = importlib.import_module(entry_point.module)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/importlib/__init__.py", line 90, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1310, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
  File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 995, in exec_module
  File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
  File "/usr/lib/python3.12/site-packages/spyder_unittest/__init__.py", line 9, in <module>
    from .unittestplugin import UnitTestPlugin as PLUGIN_CLASS
  File "/usr/lib/python3.12/site-packages/spyder_unittest/unittestplugin.py", line 27, in <module>
    from spyder_unittest.widgets.unittestgui import UnitTestWidget
  File "/usr/lib/python3.12/site-packages/spyder_unittest/widgets/unittestgui.py", line 25, in <module>
    from spyder_unittest.backend.nose2runner import Nose2Runner
  File "/usr/lib/python3.12/site-packages/spyder_unittest/backend/nose2runner.py", line 18, in <module>
    from spyder_unittest.backend.runnerbase import Category, RunnerBase, TestResult
  File "/usr/lib/python3.12/site-packages/spyder_unittest/backend/runnerbase.py", line 18, in <module>
    from qtpy.QtCore import (
ImportError: cannot import name 'QTextCodec' from 'qtpy.QtCore' (/usr/lib/python3.12/site-packages/qtpy/QtCore.py)
Traceback (most recent call last):
  File "/usr/lib/python-exec/python3.12/spyder", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/usr/lib/python3.12/site-packages/spyder/app/start.py", line 285, in main
    mainwindow.main(options, args)
  File "/usr/lib/python3.12/site-packages/spyder/app/mainwindow.py", line 1425, in main
    mainwindow = create_window(MainWindow, app, splash, options, args)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/spyder/app/utils.py", line 359, in create_window
    main.setup()
  File "/usr/lib/python3.12/site-packages/spyder/app/mainwindow.py", line 747, in setup
    PLUGIN_REGISTRY.register_plugin(self, PluginClass,
  File "/usr/lib/python3.12/site-packages/spyder/api/plugin_registration/registry.py", line 344, in register_plugin
    instance = self._instantiate_spyder5_plugin(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/spyder/api/plugin_registration/registry.py", line 186, in _instantiate_spyder5_plugin
    plugin_instance = PluginClass(main_window, configuration=CONF)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/spyder/api/plugins/new_api.py", line 332, in __init__
    self._container = container = self.CONTAINER_CLASS(
                                  ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/spyder/plugins/application/container.py", line 83, in __init__
    super().__init__(name, plugin, parent)
  File "/usr/lib/python3.12/site-packages/spyder/api/widgets/main_container.py", line 119, in __init__
    QWidget.__init__(self, parent)
  File "/usr/lib/python3.12/site-packages/spyder/api/widgets/mixins.py", line 683, in __init__
    super().__init__()
  File "/usr/lib/python3.12/site-packages/spyder/api/config/mixins.py", line 228, in __init__
    f'class attribute! Hint: {self} or its parent should define '
                             ^^^^^^
RuntimeError: '__init__' method of object's base class (ApplicationContainer) not called.

Seems like Spyder depends on QTextCodec, which was part of core in Qt5 but has been moved to optional Qt module "core5compat" in Qt6. As a consequence QTextCodec is not available in PySide6 (at minimum, maybe also missing in PyQt6).

According to 1st line of the error message, Spyder requirements also do specify PyQt5 as a QtPy binding-of-choice.

After QtPy is re-merged with [-pyside6 +pyqt5 -pyqt6 -pyside2], Spyder 6.0.1 works fine.

Since QtPy have all four backends as mutually exclusive, according to QtPy pkg_postinst(), I propose to fix QtPy dependency in Spyder explicitly to:
>=dev-python/QtPy-2.4.0[${PYTHON_USEDEP},quick,svg,webengine,pyqt5,-pyside6,-pyqt6,-pyside2]
which guarantees a correct backend choice

A better future-proof solution could be:
1. In dev-python/QtPy - disable multiple backends by adding "exactly-one-of (pyqt5,pyside6,pyqt6,pyside2)
2. In Spyder - modify dependency  to:
>=dev-python/QtPy-2.4.0[${PYTHON_USEDEP},quick,svg,webengine,pyqt5]

Reproducible: Always
Comment 1 Michael Tulupov 2024-09-24 19:32:48 UTC
Created attachment 903665 [details]
Error log
Comment 2 Nowa Ammerlaan gentoo-dev 2024-09-24 19:39:58 UTC
Pyside support in Spyder is in an experimental stage, still qt6 should work via pyqt6.

> but either of [pyside6 pyqt5 pyqt6 pyside2] is not specified as mandatory useflag.

The either off requirement is part of the QtPy ebuild and does not need to be specified here.
Comment 3 Nowa Ammerlaan gentoo-dev 2024-09-24 19:45:50 UTC
The failure seems to originate specifically in the spyder-unittest plugin, please try again without this plugin installed and please also try with pyqt6 instead of pyside6.
Comment 4 Nowa Ammerlaan gentoo-dev 2024-09-24 19:51:07 UTC
Disabling multiple backends in qtpy is not an option, it defeats the entire purpose of that package and will create a dependency mess with other packages depending on it.
Comment 5 Michael Tulupov 2024-09-24 21:44:09 UTC
(In reply to Andrew Nowa Ammerlaan from comment #4)
> Disabling multiple backends in qtpy is not an option, it defeats the entire
> purpose of that package and will create a dependency mess with other
> packages depending on it.

OK, got it, my initial impression was that backend choice is baked during build time, but i found QT_API variable.
Comment 6 Michael Tulupov 2024-09-24 21:47:51 UTC
(In reply to Andrew Nowa Ammerlaan from comment #2)
> Pyside support in Spyder is in an experimental stage, still qt6 should work
> via pyqt6.

OK, clear. Do you think it is a good idea to mention in spyder's pkg_postinst that Pyside support is experimental and PyQt5 or 6 are recommended and can be forced by QT_API ?
Comment 7 Michael Tulupov 2024-09-24 21:55:50 UTC
Created attachment 903666 [details]
Error log when PySide6 is used, without unittest plugin

(In reply to Andrew Nowa Ammerlaan from comment #3)
> The failure seems to originate specifically in the spyder-unittest plugin,
> please try again without this plugin installed and please also try with
> pyqt6 instead of pyside6.

with unittest removed and PySide6 - still does not work.
Seems like a problem somewhere near legacy plugin support (from Spyder 5.x).
new log is in attachment.

PyQt6 will try later....maybe (wants too many new packages).
For now I will stay with PyQt5, which works fine for me.

Still if new suggestions/patches will come for PySide6 - I'm in to try.

Thanks for quick support !
Comment 8 Nowa Ammerlaan gentoo-dev 2024-09-25 07:39:53 UTC
(In reply to Michael Tulupov from comment #6)
> (In reply to Andrew Nowa Ammerlaan from comment #2)
> > Pyside support in Spyder is in an experimental stage, still qt6 should work
> > via pyqt6.
> 
> OK, clear. Do you think it is a good idea to mention in spyder's
> pkg_postinst that Pyside support is experimental and PyQt5 or 6 are
> recommended and can be forced by QT_API ?

I don't think this is required since QtPy already prefers PyQt* over PySide* if both are installed, and both the PyQt5 and PyQt6 flags on QtPy are enabled by default. Which means that the default configuration should work out of the box for both Qt5 and Qt6.