Skip to content

QIODevice.read and QIODevice.readLine return values of different types in PyQt5/6 and PySide6 #499

@StSav012

Description

@StSav012

The following code demonstrates the difference. It uses QBuffer, as QIODevice is an abstract class and cannot be instantiated.

from qtpy.QtCore import QBuffer

# `data` should be a variable. It has 
buffer: QBuffer = QBuffer()
buffer.open(QBuffer.OpenModeFlag.ReadWrite)
buffer.write(b"abc")
buffer.seek(0)

# `QByteArray(b'abc')` in PySide6, `b'abc'` in PyQt5/6
print(f'1. {buffer.read(3) = !r}')

# `QByteArray(b'')` in PySide6, `b''` in PyQt5/6
print(f'2. {buffer.read(3) = !r}')

buffer.close()

# `QByteArray(b'')` in PySide6, `None` in PyQt5/6. And a warning to `stderr`.
print(f'3. {buffer.read(3) = !r}')

I could write a wrapper. I'm unsure which way to make it:

  • Make PyQt5/6 behave like PySide6:
if PYQT5 or PYQT6:

    def _read_wrapper(
        self: QIODevice,
        maxLength: int,
        *,
        _old_read: Callable[[QIODevice, int], bytes | None],
    ) -> QByteArray:
        return QByteArray(_old_read(self, maxLength) or b"")

    QIODevice.read = partialmethod(_read_wrapper, _old_read=QIODevice.read)
    QIODevice.readLine = partialmethod(_read_wrapper, _old_read=QIODevice.readLine)
  • Or the other way around:
if PYSIDE2 or PYSIDE6:

    def _read_wrapper(
        self: QIODevice,
        maxLength: int,
        *,
        _old_read: Callable[[QIODevice, int], QByteArray],
    ) -> bytes | None:
        if self.isOpen():
            return _old_read(self, maxLength).data()

    QIODevice.read = partialmethod(_read_wrapper, _old_read=QIODevice.read)
    QIODevice.readLine = partialmethod(_read_wrapper, _old_read=QIODevice.readLine)

I haven't checked PySide2, having too modern Python at hand.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions