From ff6cec251a17a0d8ef9193ebc7dbc43e1cd866c3 Mon Sep 17 00:00:00 2001 From: Calum Lind Date: Sun, 12 Feb 2017 11:26:31 +0000 Subject: [PATCH] [Core] Markup byte-strings to fix httpdownloader and core tests * Twisted methods require byte-string arguments. * The headers str conversion in httpdownloader _download_file was incorrent and left the dict key still as unicode so replaced with a dict comprehension (py2.7 requirement). --- DEPENDS | 2 +- deluge/core/core.py | 2 +- deluge/core/rpcserver.py | 2 +- deluge/httpdownloader.py | 14 ++++++------ deluge/tests/common.py | 2 +- deluge/tests/test_core.py | 17 ++++++++++----- deluge/tests/test_httpdownloader.py | 33 +++++++++++++++++------------ deluge/transfer.py | 8 +++---- deluge/ui/web/common.py | 2 +- 9 files changed, 49 insertions(+), 33 deletions(-) diff --git a/DEPENDS b/DEPENDS index 43a955d68..795a995ff 100644 --- a/DEPENDS +++ b/DEPENDS @@ -1,6 +1,6 @@ === Core === * libtorrent (rasterbar) >= 1.1.1 - * python >= 2.6 + * python >= 2.7.7 * setuptools * twisted >= 11.1 * pyopenssl diff --git a/deluge/core/core.py b/deluge/core/core.py index 7c860eb42..f0d2eb523 100644 --- a/deluge/core/core.py +++ b/deluge/core/core.py @@ -985,7 +985,7 @@ class Core(component.Component): :rtype: bool """ - d = getPage('http://deluge-torrent.org/test_port.php?port=%s' % + d = getPage(b'http://deluge-torrent.org/test_port.php?port=%s' % self.get_listen_port(), timeout=30) def on_get_page(result): diff --git a/deluge/core/rpcserver.py b/deluge/core/rpcserver.py index 2ab7af86f..563c5e9ce 100644 --- a/deluge/core/rpcserver.py +++ b/deluge/core/rpcserver.py @@ -556,7 +556,7 @@ def generate_ssl_keys(): """ This method generates a new SSL key/cert. """ - digest = 'sha256' + digest = b'sha256' # Generate key pair pkey = crypto.PKey() pkey.generate_key(crypto.TYPE_RSA, 2048) diff --git a/deluge/httpdownloader.py b/deluge/httpdownloader.py index 672b97ac8..7d094c837 100644 --- a/deluge/httpdownloader.py +++ b/deluge/httpdownloader.py @@ -43,6 +43,7 @@ class HTTPDownloader(client.HTTPDownloader): :param headers: any optional headers to send :type headers: dictionary """ + self.part_callback = part_callback self.current_length = 0 self.total_length = 0 @@ -51,7 +52,8 @@ class HTTPDownloader(client.HTTPDownloader): self.force_filename = force_filename self.allow_compression = allow_compression self.code = None - agent = 'Deluge/%s (http://deluge-torrent.org)' % get_version() + agent = b'Deluge/%s (http://deluge-torrent.org)' % get_version() + client.HTTPDownloader.__init__(self, url, filename, headers=headers, agent=agent) def gotStatus(self, version, status, message): # NOQA: N802 @@ -165,17 +167,17 @@ def _download_file(url, filename, callback=None, headers=None, force_filename=Fa t.w.e.Error: for all other HTTP response errors """ - url = str(url) - filename = str(filename) - if headers: - for key, value in headers.items(): - headers[str(key)] = str(value) if allow_compression: if not headers: headers = {} headers['accept-encoding'] = 'deflate, gzip, x-gzip' + url = url.encode('utf8') + filename = filename.encode('utf8') + if headers: + headers = {k.encode('utf8'): v.encode('utf8') for k, v in headers.items()} + # In Twisted 13.1.0 _parse() function replaced by _URI class. # In Twisted 15.0.0 _URI class renamed to URI. if hasattr(client, '_parse'): diff --git a/deluge/tests/common.py b/deluge/tests/common.py index c9de2967f..b81edd5b2 100644 --- a/deluge/tests/common.py +++ b/deluge/tests/common.py @@ -287,7 +287,7 @@ def start_process(script, callbacks, logfile=None, print_stderr=True): """ cwd = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) - process_protocol = ProcessOutputHandler(script, callbacks, logfile, print_stderr) + process_protocol = ProcessOutputHandler(script.encode('utf8'), callbacks, logfile, print_stderr) # Add timeouts to deferreds for c in callbacks: diff --git a/deluge/tests/test_core.py b/deluge/tests/test_core.py index 2bc0d8d23..f2870d522 100644 --- a/deluge/tests/test_core.py +++ b/deluge/tests/test_core.py @@ -1,3 +1,10 @@ +# -*- coding: utf-8 -*- +# +# This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with +# the additional special exception to link portions of this program with the OpenSSL library. +# See LICENSE for more details. +# + from __future__ import unicode_literals import base64 @@ -34,7 +41,7 @@ class CookieResource(Resource): request.setResponseCode(FORBIDDEN) return - request.setHeader('Content-Type', 'application/x-bittorrent') + request.setHeader(b'Content-Type', b'application/x-bittorrent') with open(common.get_test_data_file('ubuntu-9.04-desktop-i386.iso.torrent')) as _file: data = _file.read() return data @@ -45,8 +52,8 @@ class PartialDownload(Resource): def render(self, request): with open(common.get_test_data_file('ubuntu-9.04-desktop-i386.iso.torrent')) as _file: data = _file.read() - request.setHeader('Content-Type', len(data)) - request.setHeader('Content-Type', 'application/x-bittorrent') + request.setHeader(b'Content-Type', len(data)) + request.setHeader(b'Content-Type', b'application/x-bittorrent') if request.requestHeaders.hasHeader('accept-encoding'): return compress(data, request) return data @@ -55,8 +62,8 @@ class PartialDownload(Resource): class RedirectResource(Resource): def render(self, request): - request.redirect('/ubuntu-9.04-desktop-i386.iso.torrent') - return '' + request.redirect(b'/ubuntu-9.04-desktop-i386.iso.torrent') + return b'' class TopLevelResource(Resource): diff --git a/deluge/tests/test_httpdownloader.py b/deluge/tests/test_httpdownloader.py index 00484681b..a5cc3d27e 100644 --- a/deluge/tests/test_httpdownloader.py +++ b/deluge/tests/test_httpdownloader.py @@ -1,3 +1,10 @@ +# -*- coding: utf-8 -*- +# +# This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with +# the additional special exception to link portions of this program with the OpenSSL library. +# See LICENSE for more details. +# + from __future__ import unicode_literals import tempfile @@ -27,7 +34,7 @@ def fname(name): class RedirectResource(Resource): def render(self, request): - url = self.get_url() + url = self.get_url().encode('utf8') return redirectTo(url, request) @@ -35,21 +42,21 @@ class RenameResource(Resource): def render(self, request): filename = request.args.get('filename', ['renamed_file'])[0] - request.setHeader('Content-Type', 'text/plain') - request.setHeader('Content-Disposition', 'attachment; filename=' + + request.setHeader(b'Content-Type', b'text/plain') + request.setHeader(b'Content-Disposition', b'attachment; filename=' + filename) - return 'This file should be called ' + filename + return b'This file should be called ' + filename class CookieResource(Resource): def render(self, request): - request.setHeader('Content-Type', 'text/plain') + request.setHeader(b'Content-Type', b'text/plain') if request.getCookie('password') is None: - return 'Password cookie not set!' + return b'Password cookie not set!' if request.getCookie('password') == 'deluge': - return 'COOKIE MONSTER!' + return b'COOKIE MONSTER!' return request.getCookie('password') @@ -58,7 +65,7 @@ class GzipResource(Resource): def render(self, request): message = request.args.get('msg', ['EFFICIENCY!'])[0] - request.setHeader('Content-Type', 'text/plain') + request.setHeader(b'Content-Type', b'text/plain') return compress(message, request) @@ -71,9 +78,9 @@ class PartialDownloadResource(Resource): def render(self, request): # encoding = request.requestHeaders._rawHeaders.get('accept-encoding', None) if self.render_count == 0: - request.setHeader('content-length', '5') + request.setHeader(b'content-length', b'5') else: - request.setHeader('content-length', '3') + request.setHeader(b'content-length', b'3') # if encoding == "deflate, gzip, x-gzip": request.write('abc') @@ -103,7 +110,7 @@ class TopLevelResource(Resource): def render(self, request): if request.getHeader('If-Modified-Since'): request.setResponseCode(NOT_MODIFIED) - return '

Deluge HTTP Downloader tests webserver here

' + return b'

Deluge HTTP Downloader tests webserver here

' class DownloadFileTestCase(unittest.TestCase): @@ -198,13 +205,13 @@ class DownloadFileTestCase(unittest.TestCase): def test_download_with_gzip_encoding(self): url = self.get_url('gzip?msg=success') d = download_file(url, fname('gzip_encoded')) - d.addCallback(self.assertContains, 'success') + d.addCallback(self.assertContains, b'success') return d def test_download_with_gzip_encoding_disabled(self): url = self.get_url('gzip?msg=fail') d = download_file(url, fname('gzip_encoded'), allow_compression=False) - d.addCallback(self.failIfContains, 'fail') + d.addCallback(self.failIfContains, b'fail') return d def test_page_redirect_unhandled(self): diff --git a/deluge/transfer.py b/deluge/transfer.py index 442d71446..c276df440 100644 --- a/deluge/transfer.py +++ b/deluge/transfer.py @@ -33,7 +33,7 @@ class DelugeTransferProtocol(Protocol, object): """ def __init__(self): - self._buffer = '' + self._buffer = b'' # TODO: Look into using bytearray instead of byte string. self._message_length = 0 self._bytes_received = 0 self._bytes_sent = 0 @@ -53,7 +53,7 @@ class DelugeTransferProtocol(Protocol, object): size_data = len(compressed) # Store length as a signed integer (using 4 bytes). "!" denotes network byte order. payload_len = struct.pack('!i', size_data) - header = 'D' + payload_len + header = b'D' + payload_len self._bytes_sent += len(header) + len(compressed) self.transport.write(header) self.transport.write(compressed) @@ -95,7 +95,7 @@ class DelugeTransferProtocol(Protocol, object): # Read the first bytes of the message (MESSAGE_HEADER_SIZE bytes) header = self._buffer[:MESSAGE_HEADER_SIZE] payload_len = header[1:MESSAGE_HEADER_SIZE] - if header[0] != 'D': + if header[0] != b'D': raise Exception('Invalid header format. First byte is %d' % ord(header[0])) # Extract the length stored as a signed integer (using 4 bytes) self._message_length = struct.unpack('!i', payload_len)[0] @@ -107,7 +107,7 @@ class DelugeTransferProtocol(Protocol, object): log.warn('Error occurred when parsing message header: %s.', ex) log.warn('This version of Deluge cannot communicate with the sender of this data.') self._message_length = 0 - self._buffer = '' + self._buffer = b'' def _handle_complete_message(self, data): """ diff --git a/deluge/ui/web/common.py b/deluge/ui/web/common.py index 0aa14014b..688e9361e 100644 --- a/deluge/ui/web/common.py +++ b/deluge/ui/web/common.py @@ -32,7 +32,7 @@ def escape(text): def compress(contents, request): - request.setHeader('content-encoding', 'gzip') + request.setHeader(b'content-encoding', b'gzip') compress_zlib = zlib.compressobj(6, zlib.DEFLATED, zlib.MAX_WBITS + 16, zlib.DEF_MEM_LEVEL, 0) contents = compress_zlib.compress(contents) contents += compress_zlib.flush()