Merge {Pastebin,PyPIVersion}Client into HTTPClient.

This commit is contained in:
Florian Bruhin 2015-04-13 20:42:28 +02:00
parent e5d33a6706
commit 9381aac501
3 changed files with 133 additions and 60 deletions

View File

@ -19,21 +19,19 @@
"""Client for the pastebin."""
import functools
import urllib.request
import urllib.parse
from PyQt5.QtCore import pyqtSignal, QObject, QUrl
from PyQt5.QtNetwork import (QNetworkAccessManager, QNetworkRequest,
QNetworkReply)
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, QUrl
from qutebrowser.misc import httpclient
class PastebinClient(QObject):
"""A client for http://p.cmpl.cc/ using QNetworkAccessManager.
"""A client for http://p.cmpl.cc/ using HTTPClient.
Attributes:
_nam: The QNetworkAccessManager used.
_client: The HTTPClient used.
Class attributes:
API_URL: The base API URL.
@ -51,7 +49,9 @@ class PastebinClient(QObject):
def __init__(self, parent=None):
super().__init__(parent)
self._nam = QNetworkAccessManager(self)
self._client = httpclient.HTTPClient(self)
self._client.error.connect(self.error)
self._client.success.connect(self.on_client_success)
def paste(self, name, title, text, parent=None):
"""Paste the text into a pastebin and return the URL.
@ -69,33 +69,17 @@ class PastebinClient(QObject):
}
if parent is not None:
data['reply'] = parent
encoded_data = urllib.parse.urlencode(data).encode('utf-8')
create_url = urllib.parse.urljoin(self.API_URL, 'create')
request = QNetworkRequest(QUrl(create_url))
request.setHeader(QNetworkRequest.ContentTypeHeader,
'application/x-www-form-urlencoded;charset=utf-8')
reply = self._nam.post(request, encoded_data)
if reply.isFinished():
self.on_reply_finished(reply)
else:
reply.finished.connect(functools.partial(
self.on_reply_finished, reply))
url = QUrl(urllib.parse.urljoin(self.API_URL, 'create'))
self._client.post(url, data)
def on_reply_finished(self, reply):
"""Read the data and finish when the reply finished.
@pyqtSlot(str)
def on_client_success(self, data):
"""Process the data and finish when the client finished.
Args:
reply: The QNetworkReply which finished.
data: A string with the received data.
"""
if reply.error() != QNetworkReply.NoError:
self.error.emit(reply.errorString())
return
try:
url = bytes(reply.readAll()).decode('utf-8')
except UnicodeDecodeError:
self.error.emit("Invalid UTF-8 data received in reply!")
return
if url.startswith('http://'):
self.success.emit(url)
if data.startswith('http://'):
self.success.emit(data)
else:
self.error.emit("Invalid data received in reply!")

View File

@ -20,21 +20,20 @@
"""Classes related to auto-updating and getting the latest version."""
import json
import functools
from PyQt5.QtCore import pyqtSignal, QObject, QUrl
from PyQt5.QtNetwork import (QNetworkAccessManager, QNetworkRequest,
QNetworkReply)
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, QUrl
from qutebrowser.misc import httpclient
class PyPIVersionClient(QObject):
"""A client for the PyPI API using QNetworkAccessManager.
"""A client for the PyPI API using HTTPClient.
It gets the latest version of qutebrowser from PyPI.
Attributes:
_nam: The QNetworkAccessManager used.
_client: The HTTPClient used.
Class attributes:
API_URL: The base API URL.
@ -52,7 +51,9 @@ class PyPIVersionClient(QObject):
def __init__(self, parent=None):
super().__init__(parent)
self._nam = QNetworkAccessManager(self)
self._client = httpclient.HTTPClient(self)
self._client.error.connect(self.error)
self._client.success.connect(self.on_client_success)
def get_version(self, package='qutebrowser'):
"""Get the newest version of a given package.
@ -63,31 +64,15 @@ class PyPIVersionClient(QObject):
package: The name of the package to check.
"""
url = QUrl(self.API_URL.format(package))
request = QNetworkRequest(url)
reply = self._nam.get(request)
if reply.isFinished():
self.on_reply_finished(reply)
else:
reply.finished.connect(functools.partial(
self.on_reply_finished, reply))
self._client.get(url)
def on_reply_finished(self, reply):
"""When the reply finished, load and parse the json data.
Then emits error/success.
@pyqtSlot(str)
def on_client_success(self, data):
"""Process the data and finish when the client finished.
Args:
reply: The QNetworkReply which finished.
data: A string with the received data.
"""
if reply.error() != QNetworkReply.NoError:
self.error.emit(reply.errorString())
return
try:
data = bytes(reply.readAll()).decode('utf-8')
except UnicodeDecodeError as e:
self.error.emit("Invalid UTF-8 data received in reply: "
"{}!".format(e))
return
try:
json_data = json.loads(data)
except ValueError as e:

View File

@ -0,0 +1,104 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2014-2015 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# 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/>.
"""A HTTP client based on QNetworkAccessManager."""
import functools
import urllib.request
import urllib.parse
from PyQt5.QtCore import pyqtSignal, QObject
from PyQt5.QtNetwork import (QNetworkAccessManager, QNetworkRequest,
QNetworkReply)
class HTTPClient(QObject):
"""A HTTP client based on QNetworkAccessManager.
Intended for APIs, automatically decodes data.
Attributes:
_nam: The QNetworkAccessManager used.
Signals:
success: Emitted when the operation succeeded.
arg: The recieved data.
error: Emitted when the request failed.
arg: The error message, as string.
"""
success = pyqtSignal(str)
error = pyqtSignal(str)
def __init__(self, parent=None):
super().__init__(parent)
self._nam = QNetworkAccessManager(self)
def post(self, url, data=None):
"""Create a new POST request.
Args:
url: The URL to post to, as QUrl.
data: A dict of data to send.
"""
if data is None:
data = {}
encoded_data = urllib.parse.urlencode(data).encode('utf-8')
request = QNetworkRequest(url)
request.setHeader(QNetworkRequest.ContentTypeHeader,
'application/x-www-form-urlencoded;charset=utf-8')
reply = self._nam.post(request, encoded_data)
if reply.isFinished():
self.on_reply_finished(reply)
else:
reply.finished.connect(functools.partial(
self.on_reply_finished, reply))
def get(self, url):
"""Create a new GET request.
Emits success/error when done.
Args:
url: The URL to access, as QUrl.
"""
request = QNetworkRequest(url)
reply = self._nam.get(request)
if reply.isFinished():
self.on_reply_finished(reply)
else:
reply.finished.connect(functools.partial(
self.on_reply_finished, reply))
def on_reply_finished(self, reply):
"""Read the data and finish when the reply finished.
Args:
reply: The QNetworkReply which finished.
"""
if reply.error() != QNetworkReply.NoError:
self.error.emit(reply.errorString())
return
try:
data = bytes(reply.readAll()).decode('utf-8')
except UnicodeDecodeError:
self.error.emit("Invalid UTF-8 data received in reply!")
return
self.success.emit(data)