[PyQt] Behavior of QWebEngineUrlRequestJob
Jérôme Laheurte
jerome at jeromelaheurte.net
Tue Feb 7 09:15:21 GMT 2017
Hello. I’m trying to implement a custom URI scheme handler, in a context where the underlying data will actually be fetched asynchronously. I reduced the problem to the « minimal » code pasted below (python 3.5, PyQt 5.7.1). Basically the problem is that when I call QWebEngineUrlRequestJob.reply() with an instance of my custom QIODevice, I expect the following:
1. bytesAvailable() is called, returns 0 (no data available yet)
2. The request job waits for readyRead to be emitted
3. The proceeds with bytesAvailable() / readData() until data is exhausted
4. Goto 2, until readChannelFinished is emitted
What actually happens:
1. bytesAvailable() is called, returns 0
2. The request job tries to read 32 Kb nonetheless
3. It gets no data, closes the QIODevice
Did I miss something here ? This happens on both mac OS and Linux.
TIA
Jérôme Laheurte
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtWebEngineCore import QWebEngineUrlSchemeHandler
class TestIODevice(QtCore.QIODevice):
def __init__(self):
super().__init__()
self.open(self.ReadOnly | self.Unbuffered)
self._data = b''
QtCore.QTimer.singleShot(1000, self._dataReceived)
def _dataReceived(self):
print('== RECV')
self._data = b'foo'
self.readyRead.emit()
def bytesAvailable(self):
count = len(self._data) + super().bytesAvailable()
print('== AVAIL', count)
return count
def isSequential(self):
return True
def readData(self, maxSize):
print('== READ', maxSize)
data, self._data = self._data[:maxSize], self._data[maxSize:]
return data
def close(self):
print('== CLOSE')
super().close()
class TestHandler(QWebEngineUrlSchemeHandler):
def requestStarted(self, request):
self._dev = TestIODevice() # Must keep ref
request.reply(b'text/plain', self._dev)
class TestWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self._view = QWebEngineView(self)
self._handler = TestHandler() # Must keep ref
self._view.page().profile().installUrlSchemeHandler(b'spam', self._handler)
self._view.setHtml('<html><head><title>Test</title></head><body><img src="spam:eggs" /></body></html>')
self.setCentralWidget(self._view)
self.show()
self.raise_()
if __name__ == '__main__':
app = QtWidgets.QApplication([])
win = TestWindow()
app.exec_()
More information about the PyQt
mailing list