Move special network replies to their own file.
This commit is contained in:
parent
c4da44e90c
commit
142e90cdd3
@ -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:
|
||||
|
128
qutebrowser/network/networkreply.py
Normal file
128
qutebrowser/network/networkreply.py
Normal 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()
|
@ -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())
|
||||
|
||||
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user