# HG changeset patch
# User Matt Harbison <
matt_h...@yahoo.com>
# Date 1736567816 18000
# Fri Jan 10 22:56:56 2025 -0500
# Branch stable
# Node ID 67f679f133d9d2d5b1c724cdc4bc977f6a9b278d
# Parent 14f6de8168615bdd98db8b8e3589b2dc17d5650d
cmdcore: work around a possible QBuffer.readLine() bug on PyQt6
The modified test worked with PyQt5, but failed with PyQt6 by returning None
from `sess.readLine()`, and printing "QIODevice::readLine (QBuffer): Called with
maxSize < 2" on stderr. The previous code was returning QByteArray with PyQt5
(which isn't what the type annotation says it would). Instead, try to call the
no-arg overload that definitely returns a QByteArray[1]. This method may include
'\r\n', unlike the other overload[2] that replaces EOL with '\\n'. That's
probably not a big deal, since hg normally prints '\n' regardless of platform.
Also ensure that whatever path is taken return bytes, to agree with the type
annotation.
Somehow with PyQt5, the assertion that is changed in the test here passed, even
though QByteArray and str have different types, so they shouldn't have. But
that assertion failed with PyQt6 when a QByteArray was returned. Either way, it
needs to be modified to handle bytes now. The good news is this method doesn't
seem to be called outside of tests.
[1]
https://codebrowser.dev/qt6/qtbase/src/corelib/io/qiodevice.cpp.html#_ZN9QIODevice8readLineEx
[2]
https://codebrowser.dev/qt6/qtbase/src/corelib/io/qiodevice.cpp.html#_ZN9QIODevice8readLineEPcx
diff --git a/tests/qt_cmdagent_test.py b/tests/qt_cmdagent_test.py
--- a/tests/qt_cmdagent_test.py
+++ b/tests/qt_cmdagent_test.py
@@ -145,7 +145,7 @@
self.assertTrue('no such file' in sess.warningString()) # not captured
self.assertTrue(readyRead.called)
self.assertTrue(sess.canReadLine())
- self.assertEqual(self._strhgpath() + '\n', sess.readLine())
+ self.assertEqual(self.hg.path + b'\n', sess.readLine())
self.assertEqual(b'5', sess.read(1))
self.assertEqual(b'3', sess.peek(1))
self.assertEqual(b'3245c60e682\n',
diff --git a/tortoisehg/hgqt/cmdcore.py b/tortoisehg/hgqt/cmdcore.py
--- a/tortoisehg/hgqt/cmdcore.py
+++ b/tortoisehg/hgqt/cmdcore.py
@@ -738,7 +738,15 @@
return self._dataoutrbuf.readAll()
def readLine(self, maxlen: int = 0) -> bytes:
- return self._dataoutrbuf.readLine(maxlen)
+ buf = self._dataoutrbuf
+ # There's possibly a bug in PyQt 6.8.1 or Qt 6.8.0 where passing 0 fails
+ # and prints "QIODevice::readLine (QBuffer): Called with maxSize < 2" to
+ # stderr.
+ if maxlen == 0:
+ line = buf.readLine()
+ else:
+ line = buf.readLine(maxlen)
+ return qtlib.qbytearray_or_bytes_to_bytes(line)
def canReadLine(self) -> bool:
return self._dataoutrbuf.canReadLine()