pythonpyqt5pyside2pyside6

QState.assignProperty not working in PySide


I saw this example using QState, which seems to work with PyQt5. However on trying to use PySide for this, I get this error;

Traceback (most recent call last):
    File ".../qstate-error.py", line 16, in <module>
        state1.assignProperty(widget, b'test', 1)
TypeError: 'PySide2.QtCore.QState.assignProperty' called with wrong argument types:
    PySide2.QtCore.QState.assignProperty(QWidget, bytes, int)
Supported signatures:
    PySide2.QtCore.QState.assignProperty(PySide2.QtCore.QObject, bytes, typing.Any)

Unfortunately I have to use PySide for work, so switching to PyQt5 is not an option. I have tried this with PySide2 and PySide6 - both are throwing this error. But then I saw this question that explicitly mentions PySide - so presumably it works. So do QState require some special setup that I am not aware of? Or is there something broken in my build? I'm working on Rocky 8, python 3.9.16

For reference, the following example works in pyqt5, but does not work in pyside2 (same result in pyside6).

try:
    from PySide2.QtWidgets import QApplication, QWidget
    from PySide2.QtCore import QState
except ImportError:
    from PyQt5.QtWidgets import QApplication, QWidget
    from PyQt5.QtCore import QState


if __name__ == '__main__':

    app = QApplication([])
    widget = QWidget()
    state1 = QState()
    state1.assignProperty(widget, b'test', 1)
    widget.show()

    app.exec_()

Solution

  • It's a bug in the signature definition, reported in PYSIDE-2444.

    Based on the PyQt/PySide convention, a C++ char should be a bytes in Python, in fact the function works as expected in PyQt5/6, and also the latest PySide6 releases (due to the fix related to the above bug).

    In reality, many functions that accept char also accept standard Python strings and are internally converted, meaning that you can just use the following:

    state1.assignProperty(widget, 'test', 1)
    

    In case you need more strict typing and always use bytes, you can eventually use a QState subclass and "override" assignProperty() by eventually converting the type and calling the base implementation. It won't be a real override (as you could just create a function with any name and call the original assignProperty()), but it would be more consistent in code reading.