Move special network replies to their own file.

This commit is contained in:
Florian Bruhin 2014-11-14 08:34:01 +01:00
parent c4da44e90c
commit 142e90cdd3
4 changed files with 135 additions and 110 deletions

View File

@ -31,7 +31,7 @@ else:
from qutebrowser.config import config from qutebrowser.config import config
from qutebrowser.utils import message, log, usertypes, utils, objreg from qutebrowser.utils import message, log, usertypes, utils, objreg
from qutebrowser.network import qutescheme, schemehandler from qutebrowser.network import qutescheme, networkreply
class NetworkManager(QNetworkAccessManager): class NetworkManager(QNetworkAccessManager):
@ -148,7 +148,7 @@ class NetworkManager(QNetworkAccessManager):
""" """
scheme = req.url().scheme() scheme = req.url().scheme()
if scheme == 'https' and not SSL_AVAILABLE: if scheme == 'https' and not SSL_AVAILABLE:
return schemehandler.ErrorNetworkReply( return networkreply.ErrorNetworkReply(
req, "SSL is not supported by the installed Qt library!", req, "SSL is not supported by the installed Qt library!",
QNetworkReply.ProtocolUnknownError) QNetworkReply.ProtocolUnknownError)
elif scheme in self._scheme_handlers: elif scheme in self._scheme_handlers:

View File

@ -0,0 +1,128 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# Based on the Eric5 helpviewer,
# Copyright (c) 2009 - 2014 Detlev Offenbach <detlev@die-offenbachs.de>
#
# 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 <http://www.gnu.org/licenses/>.
"""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()

View File

@ -30,7 +30,7 @@ Module attributes:
from PyQt5.QtNetwork import QNetworkReply from PyQt5.QtNetwork import QNetworkReply
import qutebrowser import qutebrowser
from qutebrowser.network import schemehandler from qutebrowser.network import schemehandler, networkreply
from qutebrowser.utils import version, utils, jinja, log, message, docutils from qutebrowser.utils import version, utils, jinja, log, message, docutils
@ -65,16 +65,16 @@ class QuteSchemeHandler(schemehandler.SchemeHandler):
except KeyError: except KeyError:
errorstr = "No handler found for {}!".format( errorstr = "No handler found for {}!".format(
request.url().toDisplayString()) request.url().toDisplayString())
return schemehandler.ErrorNetworkReply( return networkreply.ErrorNetworkReply(
request, errorstr, QNetworkReply.ContentNotFoundError, request, errorstr, QNetworkReply.ContentNotFoundError,
self.parent()) self.parent())
try: try:
data = handler(self._win_id, request) data = handler(self._win_id, request)
except IOError as e: except IOError as e:
return schemehandler.ErrorNetworkReply( return networkreply.ErrorNetworkReply(
request, str(e), QNetworkReply.ContentNotFoundError, request, str(e), QNetworkReply.ContentNotFoundError,
self.parent()) self.parent())
return schemehandler.SpecialNetworkReply( return networkreply.FixedDataNetworkReply(
request, data, 'text/html', self.parent()) request, data, 'text/html', self.parent())

View File

@ -22,8 +22,7 @@
"""Base class for custom scheme handlers.""" """Base class for custom scheme handlers."""
from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest from PyQt5.QtCore import QObject
from PyQt5.QtCore import pyqtSlot, QObject, QIODevice, QByteArray, QTimer
class SchemeHandler(QObject): class SchemeHandler(QObject):
@ -50,105 +49,3 @@ class SchemeHandler(QObject):
A QNetworkReply. A QNetworkReply.
""" """
raise NotImplementedError 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()