[PyQt] QNetworkReply and PyQt 4.7.3-2

Tiago Rezende tiagosr at gmail.com
Mon May 3 19:52:30 BST 2010


Hi,

I was using PyQt 4.7.1 for developing an app using QWebView as the
main interface, and was coding a scheme not unlike that of Firefox
with it's "chrome:" protocol, following some pointers from
http://www.mail-archive.com/python-list@python.org/msg247104.html
(which, with some slight changes, got me to where I wanted).
Trouble is, when I updated to PyQt 4.7.3-2 on saturday, my program
just stopped working, throwing a segfault on Python 2.6.5 (and even on
IDLE, which to the extent that I know is in a separate instance) on
Windows XP SP2 and Windows 7 x64 both (32bit Python on Windows 7,
though), and isolating the cause, it happens to be exactly after I set
up my custom QNetworkReply class to deliver the response my QWebView.
Has anything changed with the QNetworkReply interface inbetween these
versions? Here follows the minimal code needed to reproduce the bug,
hope it helps.

# ---- start code here

import sys
from PyQt4.QtCore import QTimer, QVariant, SIGNAL, QUrl, QBuffer
from PyQt4.QtGui import *
from PyQt4.QtNetwork import QNetworkAccessManager, QNetworkRequest,
QNetworkReply
from PyQt4.QtWebKit import QWebView

class ProtocolReply(QNetworkReply):
    def __init__(self, operation, request, data):
        QNetworkReply.__init__(self)
        print "hi new ProtocolReply"
        self.setRequest(request)
        self.request = request
        self.setOperation(operation)
        self.offset = 0
        self.content = u"""
<html>
    <head><title>Hi!</title></head>
    <body>It worked!</body>
</html>
"""
        self.setHeader(QNetworkRequest.ContentTypeHeader,
QVariant("text/html; charset=UTF-8"))
        self.setHeader(QNetworkRequest.ContentLengthHeader,
QVariant(len(self.content)))
        QTimer.singleShot(0, self.emitSignals)
        self.open(self.ReadOnly | self.Unbuffered)
        self.setUrl(request.url())

    def emitSignals(self):
        print "hi emitSignals()"
        self.readyRead.emit()
        self.finished.emit()

    def abort(self):
        pass

    def bytesAvailable(self):
        return len(self.content) - self.offset

    def isSequential(self):
        return True

    def readData(self, maxsize):
        print "hi readData()"
        if self.offset < len(self.content):
            end = min(self.offset + maxsize, len(self.content))
            data = self.content[self.offset:end]
            self.offset = end
            return str(data)

class NetworkAccessManager(QNetworkAccessManager):
    def __init__(self, old_manager):
        QNetworkAccessManager.__init__(self)
        self.old_manager = old_manager
        self.setCache(old_manager.cache())
        self.setCookieJar(old_manager.cookieJar())
        self.setProxy(old_manager.proxy())
        self.setProxyFactory(old_manager.proxyFactory())

    def requestProtocol(self, operation, request, data):
        return ProtocolReply(operation, request, data)


    def createRequest(self, operation, request, data):
        scheme_map = {"protocol": self.requestProtocol}
        if str(request.url().scheme()) in scheme_map:
            print "mapped scheme " + request.url().scheme()
            return scheme_map[str(request.url().scheme())](operation,
request, data)
        else:
            return QNetworkAccessManager.createRequest(self,
operation, request, data)

class ProtocolView(QWebView):
    def __init__(self,parent = None):
        QWebView.__init__(self,parent)
        old_manager = self.page().networkAccessManager()
        self.old_manager = old_manager
        self.new_manager = NetworkAccessManager(old_manager)
        self.page().setNetworkAccessManager(self.new_manager)
        #self.page().setForwardUnsupportedContent(True)
        self.setStartContent()
    def setStartContent(self):
        self.setHtml("""
<html><head><title>QNetworkReply Test</title></head>
    <body>
        <h1>QNetworkReply Test</h1>
        <p><a href="protocol:hi">This crashes PyQt 4.7.3-2</a></p>
        <p><a href="http://www.google.com/">This is a normal web link</a></p>
    </body>
</html>
""")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = QMainWindow()
    view = ProtocolView(window)
    window.setCentralWidget(view)
    window.show()
    app.exit(app.exec_())

# ---- end code here

I put some debugging prints. On all interpreters I could get my code
on, all but the readData() one are printed before the crash.

Thanks in advance,
Tiago Rezende


More information about the PyQt mailing list