From 142e90cdd3c4270ef5a74fa108d4cc5c990e342d Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 14 Nov 2014 08:34:01 +0100 Subject: [PATCH] Move special network replies to their own file. --- qutebrowser/network/networkmanager.py | 4 +- qutebrowser/network/networkreply.py | 128 ++++++++++++++++++++++++++ qutebrowser/network/qutescheme.py | 8 +- qutebrowser/network/schemehandler.py | 105 +-------------------- 4 files changed, 135 insertions(+), 110 deletions(-) create mode 100644 qutebrowser/network/networkreply.py diff --git a/qutebrowser/network/networkmanager.py b/qutebrowser/network/networkmanager.py index a56c30003..4e57d5211 100644 --- a/qutebrowser/network/networkmanager.py +++ b/qutebrowser/network/networkmanager.py @@ -31,7 +31,7 @@ else: from qutebrowser.config import config from qutebrowser.utils import message, log, usertypes, utils, objreg -from qutebrowser.network import qutescheme, schemehandler +from qutebrowser.network import qutescheme, networkreply class NetworkManager(QNetworkAccessManager): @@ -148,7 +148,7 @@ class NetworkManager(QNetworkAccessManager): """ scheme = req.url().scheme() if scheme == 'https' and not SSL_AVAILABLE: - return schemehandler.ErrorNetworkReply( + return networkreply.ErrorNetworkReply( req, "SSL is not supported by the installed Qt library!", QNetworkReply.ProtocolUnknownError) elif scheme in self._scheme_handlers: diff --git a/qutebrowser/network/networkreply.py b/qutebrowser/network/networkreply.py new file mode 100644 index 000000000..b47b117d3 --- /dev/null +++ b/qutebrowser/network/networkreply.py @@ -0,0 +1,128 @@ +# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et: + +# Copyright 2014 Florian Bruhin (The Compiler) +# +# Based on the Eric5 helpviewer, +# Copyright (c) 2009 - 2014 Detlev Offenbach +# +# This file is part of qutebrowser. +# +# qutebrowser is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# qutebrowser is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with qutebrowser. If not, see . + +"""Special network replies..""" + +from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest +from PyQt5.QtCore import pyqtSlot, QIODevice, QByteArray, QTimer + + +class FixedDataNetworkReply(QNetworkReply): + + """QNetworkReply subclass for fixed data.""" + + def __init__(self, request, fileData, mimeType, parent=None): + """Constructor. + + Args: + request: reference to the request object (QNetworkRequest) + fileData: reference to the data buffer (QByteArray) + mimeType: for the reply (string) + parent: reference to the parent object (QObject) + """ + super().__init__(parent) + + self._data = fileData + + self.setRequest(request) + self.setUrl(request.url()) + self.setOpenMode(QIODevice.ReadOnly) + + self.setHeader(QNetworkRequest.ContentTypeHeader, mimeType) + self.setHeader(QNetworkRequest.ContentLengthHeader, + QByteArray.number(len(fileData))) + self.setAttribute(QNetworkRequest.HttpStatusCodeAttribute, 200) + self.setAttribute(QNetworkRequest.HttpReasonPhraseAttribute, 'OK') + # For some reason, a segfault will be triggered if these lambdas aren't + # there. + QTimer.singleShot(0, lambda: self.metaDataChanged.emit()) + QTimer.singleShot(0, lambda: self.readyRead.emit()) + QTimer.singleShot(0, lambda: self.finished.emit()) + + @pyqtSlot() + def abort(self): + """Abort the operation.""" + pass + + def bytesAvailable(self): + """Determine the bytes available for being read. + + Return: + bytes available (int) + """ + return len(self._data) + super().bytesAvailable() + + def readData(self, maxlen): + """Retrieve data from the reply object. + + Args: + maxlen maximum number of bytes to read (int) + + Return: + bytestring containing the data + """ + len_ = min(maxlen, len(self._data)) + buf = bytes(self._data[:len_]) + self._data = self._data[len_:] + return buf + + def isFinished(self): + """Check if the reply is finished.""" + return True + + +class ErrorNetworkReply(QNetworkReply): + + """QNetworkReply which always returns an error.""" + + def __init__(self, req, errorstring, error, parent=None): + """Constructor. + + Args: + req: The QNetworkRequest associated with this reply. + errorstring: The error string to print. + error: The numerical error value. + parent: The parent to pass to QNetworkReply. + """ + super().__init__(parent) + self.setRequest(req) + self.setUrl(req.url()) + # We don't actually want to read anything, but we still need to open + # the device to avoid getting a warning. + self.setOpenMode(QIODevice.ReadOnly) + self.setError(error, errorstring) + # For some reason, a segfault will be triggered if these lambdas aren't + # there. + QTimer.singleShot(0, lambda: self.error.emit(error)) + QTimer.singleShot(0, lambda: self.finished.emit()) + + def abort(self): + """Do nothing since it's a fake reply.""" + pass + + def bytesAvailable(self): + """We always have 0 bytes available.""" + return 0 + + def readData(self): + """No data available.""" + return bytes() diff --git a/qutebrowser/network/qutescheme.py b/qutebrowser/network/qutescheme.py index 54298efe2..a9695be8e 100644 --- a/qutebrowser/network/qutescheme.py +++ b/qutebrowser/network/qutescheme.py @@ -30,7 +30,7 @@ Module attributes: from PyQt5.QtNetwork import QNetworkReply import qutebrowser -from qutebrowser.network import schemehandler +from qutebrowser.network import schemehandler, networkreply from qutebrowser.utils import version, utils, jinja, log, message, docutils @@ -65,16 +65,16 @@ class QuteSchemeHandler(schemehandler.SchemeHandler): except KeyError: errorstr = "No handler found for {}!".format( request.url().toDisplayString()) - return schemehandler.ErrorNetworkReply( + return networkreply.ErrorNetworkReply( request, errorstr, QNetworkReply.ContentNotFoundError, self.parent()) try: data = handler(self._win_id, request) except IOError as e: - return schemehandler.ErrorNetworkReply( + return networkreply.ErrorNetworkReply( request, str(e), QNetworkReply.ContentNotFoundError, self.parent()) - return schemehandler.SpecialNetworkReply( + return networkreply.FixedDataNetworkReply( request, data, 'text/html', self.parent()) diff --git a/qutebrowser/network/schemehandler.py b/qutebrowser/network/schemehandler.py index d309fed7b..8fa90764f 100644 --- a/qutebrowser/network/schemehandler.py +++ b/qutebrowser/network/schemehandler.py @@ -22,8 +22,7 @@ """Base class for custom scheme handlers.""" -from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest -from PyQt5.QtCore import pyqtSlot, QObject, QIODevice, QByteArray, QTimer +from PyQt5.QtCore import QObject class SchemeHandler(QObject): @@ -50,105 +49,3 @@ class SchemeHandler(QObject): A QNetworkReply. """ raise NotImplementedError - - -class SpecialNetworkReply(QNetworkReply): - - """QNetworkReply subclass for special data.""" - - def __init__(self, request, fileData, mimeType, parent=None): - """Constructor. - - Args: - request: reference to the request object (QNetworkRequest) - fileData: reference to the data buffer (QByteArray) - mimeType: for the reply (string) - parent: reference to the parent object (QObject) - """ - super().__init__(parent) - - self._data = fileData - - self.setRequest(request) - self.setUrl(request.url()) - self.setOpenMode(QIODevice.ReadOnly) - - self.setHeader(QNetworkRequest.ContentTypeHeader, mimeType) - self.setHeader(QNetworkRequest.ContentLengthHeader, - QByteArray.number(len(fileData))) - self.setAttribute(QNetworkRequest.HttpStatusCodeAttribute, 200) - self.setAttribute(QNetworkRequest.HttpReasonPhraseAttribute, 'OK') - # For some reason, a segfault will be triggered if these lambdas aren't - # there. - QTimer.singleShot(0, lambda: self.metaDataChanged.emit()) - QTimer.singleShot(0, lambda: self.readyRead.emit()) - QTimer.singleShot(0, lambda: self.finished.emit()) - - @pyqtSlot() - def abort(self): - """Abort the operation.""" - pass - - def bytesAvailable(self): - """Determine the bytes available for being read. - - Return: - bytes available (int) - """ - return len(self._data) + super().bytesAvailable() - - def readData(self, maxlen): - """Retrieve data from the reply object. - - Args: - maxlen maximum number of bytes to read (int) - - Return: - bytestring containing the data - """ - len_ = min(maxlen, len(self._data)) - buf = bytes(self._data[:len_]) - self._data = self._data[len_:] - return buf - - def isFinished(self): - """Check if the reply is finished.""" - return True - - -class ErrorNetworkReply(QNetworkReply): - - """QNetworkReply which always returns an error.""" - - def __init__(self, req, errorstring, error, parent=None): - """Constructor. - - Args: - req: The QNetworkRequest associated with this reply. - errorstring: The error string to print. - error: The numerical error value. - parent: The parent to pass to QNetworkReply. - """ - super().__init__(parent) - self.setRequest(req) - self.setUrl(req.url()) - # We don't actually want to read anything, but we still need to open - # the device to avoid getting a warning. - self.setOpenMode(QIODevice.ReadOnly) - self.setError(error, errorstring) - # For some reason, a segfault will be triggered if these lambdas aren't - # there. - QTimer.singleShot(0, lambda: self.error.emit(error)) - QTimer.singleShot(0, lambda: self.finished.emit()) - - def abort(self): - """Do nothing since it's a fake reply.""" - pass - - def bytesAvailable(self): - """We always have 0 bytes available.""" - return 0 - - def readData(self): - """No data available.""" - return bytes()