1

I can't get the example from the PySide6 documentation working on my system. I am running PySide-6.2 on Ubuntu.

toUtf16 = QStringDecoder(QStringConverter.Utf8)
toUtf16('test')

Result:

TypeError: 'PySide6.QtCore.QStringDecoder' object is not callable
ekhumoro
  • 115,249
  • 20
  • 229
  • 336
Aaron
  • 759
  • 1
  • 7
  • 15

1 Answers1

4

It looks like a bug in PySide6. The returned object only has the inherited methods from QStringConverter, as can be seen by using dir:

>>> dec = QtCore.QStringDecoder(QtCore.QStringConverter.Encoding.Utf16)
>>> for x in dir(dec):
...     if x[0].islower(): print(x)
...
hasError
isValid
name
nameForEncoding
requiredSpace
resetState
state

So the decode methods are missing, and the TypeError indicates that the ()-operator overload is missing as well. The QStringEncoder class has similar problems.

In PyQt6, everything works as expected:

>>> enc = QtCore.QStringEncoder(QtCore.QStringConverter.Encoding.Utf16)
>>> dec = QtCore.QStringDecoder(QtCore.QStringConverter.Encoding.Utf16)
>>> x = enc('text')
>>> x
PyQt6.QtCore.QByteArray(b't\x00e\x00x\x00t\x00')
>>> dec(x)
'text'

Of course, you don't really need to use these Qt classes, since the equivalent functionality already exists in Python:

>>> x = 'text'.encode('utf-16')
>>> x
b'\xff\xfet\x00e\x00x\x00t\x00'
>>> x.decode('utf-16')
'text'

Note that Python automatically prepends a BOM, whereas Qt requires an additional flag to get the same behaviour. To get a Qt-style callable object in Python, you can either use functools.partial or a lambda:

>>> from functools import partial
>>> enc = partial(str.encode, encoding='utf-16')
>>> # or enc = lambda s: s.encode('utf-16')
>>> dec = partial(bytes.decode, encoding='utf-16')
>>> # or dec = lambda b: b.decode('utf-16')
>>> x = enc('text')
b'\xff\xfet\x00e\x00x\x00t\x00'
>>> dec(x)
'text'

NB: to convert a QByteArray to a Python bytes object, use bytes(qtbytearray) or qtbytearray.data() (see also: How to convert a QByteArray to a python string).

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
  • Thanks can you tell me how to do the equivalent in Python? – Aaron Jan 19 '22 at 16:10
  • 1
    @Aaron See my updated answer. – ekhumoro Jan 19 '22 at 17:50
  • I am getting an error when using your Python method of decoding an actual QByteArray: TypeError: descriptor 'decode' for 'bytes' objects doesn't apply to a 'PySide6.QtCore.QByteArray' object – Aaron Jan 19 '22 at 20:36
  • 1
    @Aaron Yes, you just need to convert it to python bytes object first, using either `bytes(qtbytearray)` or `qtbytearray.data()`. I will update my answer accordingly. – ekhumoro Jan 19 '22 at 21:40
  • thanks it works :) – Aaron Jan 21 '22 at 21:11