From acc36c34d05f53f2bc7fc61ccdf9ef859c7e0e03 Mon Sep 17 00:00:00 2001 From: Itamar Turner-Trauring Date: Wed, 16 Dec 2020 11:13:32 -0500 Subject: [PATCH 01/10] Tests pass on Python 2 and Python 3. --- src/allmydata/test/web/test_common.py | 2 +- src/allmydata/web/common.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/allmydata/test/web/test_common.py b/src/allmydata/test/web/test_common.py index 5261c412f..6f0d51d5a 100644 --- a/src/allmydata/test/web/test_common.py +++ b/src/allmydata/test/web/test_common.py @@ -163,7 +163,7 @@ class RenderExceptionTests(SyncTestCase): BeautifulSoup(value, 'html5lib'), "meta", {"http-equiv": "refresh", - "content": "0;URL={}".format(loc.encode("ascii")), + "content": "0;URL={}".format(loc), }, ) # The assertion will raise if it has a problem, otherwise diff --git a/src/allmydata/web/common.py b/src/allmydata/web/common.py index d970cc918..a1fd06c1c 100644 --- a/src/allmydata/web/common.py +++ b/src/allmydata/web/common.py @@ -562,7 +562,7 @@ def _finish(result, render, request): Message.log( message_type=u"allmydata:web:common-render:DecodedURL", ) - _finish(redirectTo(str(result), request), render, request) + _finish(redirectTo(result.to_text().encode("utf-8"), request), render, request) elif result is None: Message.log( message_type=u"allmydata:web:common-render:None", From f7362dc1efb8cf6cf0f0857f696dc8241ca40717 Mon Sep 17 00:00:00 2001 From: Itamar Turner-Trauring Date: Wed, 16 Dec 2020 11:14:55 -0500 Subject: [PATCH 02/10] Port to Python 3. --- src/allmydata/test/web/test_common.py | 10 ++++++++++ src/allmydata/util/_python3.py | 1 + 2 files changed, 11 insertions(+) diff --git a/src/allmydata/test/web/test_common.py b/src/allmydata/test/web/test_common.py index 6f0d51d5a..84ab5cab2 100644 --- a/src/allmydata/test/web/test_common.py +++ b/src/allmydata/test/web/test_common.py @@ -1,6 +1,16 @@ """ Tests for ``allmydata.web.common``. + +Ported to Python 3. """ +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +from future.utils import PY2 +if PY2: + from future.builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, dict, list, object, range, str, max, min # noqa: F401 import gc diff --git a/src/allmydata/util/_python3.py b/src/allmydata/util/_python3.py index 903567983..169c7b413 100644 --- a/src/allmydata/util/_python3.py +++ b/src/allmydata/util/_python3.py @@ -171,4 +171,5 @@ PORTED_TEST_MODULES = [ "allmydata.test.test_upload", "allmydata.test.test_uri", "allmydata.test.test_util", + "allmydata.test.web.test_common", ] From 61c76902cae05a19e484a8119a4ca236382b46aa Mon Sep 17 00:00:00 2001 From: Itamar Turner-Trauring Date: Wed, 16 Dec 2020 11:16:34 -0500 Subject: [PATCH 03/10] Port to Python 3. --- src/allmydata/test/test_json_metadata.py | 11 +++++++++++ src/allmydata/util/_python3.py | 1 + 2 files changed, 12 insertions(+) diff --git a/src/allmydata/test/test_json_metadata.py b/src/allmydata/test/test_json_metadata.py index 75d4e1567..a0cb9c142 100644 --- a/src/allmydata/test/test_json_metadata.py +++ b/src/allmydata/test/test_json_metadata.py @@ -1,3 +1,14 @@ +""" +Ported to Python 3. +""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +from future.utils import PY2 +if PY2: + from future.builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, dict, list, object, range, str, max, min # noqa: F401 from twisted.trial.unittest import TestCase diff --git a/src/allmydata/util/_python3.py b/src/allmydata/util/_python3.py index 169c7b413..98e8568e2 100644 --- a/src/allmydata/util/_python3.py +++ b/src/allmydata/util/_python3.py @@ -153,6 +153,7 @@ PORTED_TEST_MODULES = [ "allmydata.test.test_immutable", "allmydata.test.test_introducer", "allmydata.test.test_iputil", + "allmydata.test.test_json_metadata", "allmydata.test.test_log", "allmydata.test.test_monitor", "allmydata.test.test_netstring", From 67c0a4ac8430ff96fd4526a969cb9575c1cf9005 Mon Sep 17 00:00:00 2001 From: Itamar Turner-Trauring Date: Wed, 16 Dec 2020 13:53:49 -0500 Subject: [PATCH 04/10] Port another test module to Python 3. --- src/allmydata/test/web/test_util.py | 12 ++++++++++++ src/allmydata/util/_python3.py | 1 + src/allmydata/web/common.py | 18 +++++++++--------- src/allmydata/web/common_py3.py | 10 +++++----- 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/allmydata/test/web/test_util.py b/src/allmydata/test/web/test_util.py index 24f865ebc..5f4d6bb88 100644 --- a/src/allmydata/test/web/test_util.py +++ b/src/allmydata/test/web/test_util.py @@ -1,3 +1,15 @@ +""" +Ported to Python 3. +""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +from future.utils import PY2 +if PY2: + from future.builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, dict, list, object, range, str, max, min # noqa: F401 + from twisted.trial import unittest from allmydata.web import status, common from ..common import ShouldFailMixin diff --git a/src/allmydata/util/_python3.py b/src/allmydata/util/_python3.py index 98e8568e2..31796a71b 100644 --- a/src/allmydata/util/_python3.py +++ b/src/allmydata/util/_python3.py @@ -173,4 +173,5 @@ PORTED_TEST_MODULES = [ "allmydata.test.test_uri", "allmydata.test.test_util", "allmydata.test.web.test_common", + "allmydata.test.web.test_util", ] diff --git a/src/allmydata/web/common.py b/src/allmydata/web/common.py index a1fd06c1c..4e8cab89d 100644 --- a/src/allmydata/web/common.py +++ b/src/allmydata/web/common.py @@ -210,26 +210,26 @@ def compute_rate(bytes, seconds): def abbreviate_rate(data): # 21.8kBps, 554.4kBps 4.37MBps if data is None: - return "" + return u"" r = float(data) if r > 1000000: - return "%1.2fMBps" % (r/1000000) + return u"%1.2fMBps" % (r/1000000) if r > 1000: - return "%.1fkBps" % (r/1000) - return "%.0fBps" % r + return u"%.1fkBps" % (r/1000) + return u"%.0fBps" % r def abbreviate_size(data): # 21.8kB, 554.4kB 4.37MB if data is None: - return "" + return u"" r = float(data) if r > 1000000000: - return "%1.2fGB" % (r/1000000000) + return u"%1.2fGB" % (r/1000000000) if r > 1000000: - return "%1.2fMB" % (r/1000000) + return u"%1.2fMB" % (r/1000000) if r > 1000: - return "%.1fkB" % (r/1000) - return "%.0fB" % r + return u"%.1fkB" % (r/1000) + return u"%.0fB" % r def plural(sequence_or_length): if isinstance(sequence_or_length, int): diff --git a/src/allmydata/web/common_py3.py b/src/allmydata/web/common_py3.py index 22f235790..89efd4d5d 100644 --- a/src/allmydata/web/common_py3.py +++ b/src/allmydata/web/common_py3.py @@ -97,14 +97,14 @@ class MultiFormatResource(resource.Resource, object): def abbreviate_time(data): # 1.23s, 790ms, 132us if data is None: - return "" + return u"" s = float(data) if s >= 10: return abbreviate.abbreviate_time(data) if s >= 1.0: - return "%.2fs" % s + return u"%.2fs" % s if s >= 0.01: - return "%.0fms" % (1000*s) + return u"%.0fms" % (1000*s) if s >= 0.001: - return "%.1fms" % (1000*s) - return "%.0fus" % (1000000*s) + return u"%.1fms" % (1000*s) + return u"%.0fus" % (1000000*s) From b5f2afe39cce90d3863934f1756336399be7fd75 Mon Sep 17 00:00:00 2001 From: Itamar Turner-Trauring Date: Wed, 16 Dec 2020 14:13:46 -0500 Subject: [PATCH 05/10] WIP porting test_status.py. --- src/allmydata/test/web/test_web.py | 10 +++++----- src/allmydata/web/status.py | 7 ++++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/allmydata/test/web/test_web.py b/src/allmydata/test/web/test_web.py index 326569a26..f2b6d8f13 100644 --- a/src/allmydata/test/web/test_web.py +++ b/src/allmydata/test/web/test_web.py @@ -90,7 +90,7 @@ class FakeNodeMaker(NodeMaker): return FakeMutableFileNode(None, None, self.encoding_params, None, self.all_contents).init_from_cap(cap) - def create_mutable_file(self, contents="", keysize=None, + def create_mutable_file(self, contents=b"", keysize=None, version=SDMF_VERSION): n = FakeMutableFileNode(None, None, self.encoding_params, None, self.all_contents) @@ -105,7 +105,7 @@ class FakeUploader(service.Service): d = uploadable.get_size() d.addCallback(lambda size: uploadable.read(size)) def _got_data(datav): - data = "".join(datav) + data = b"".join(datav) n = create_chk_filenode(data, self.all_contents) ur = upload.UploadResults(file_size=len(data), ciphertext_fetched=0, @@ -130,9 +130,9 @@ def build_one_ds(): ds = DownloadStatus("storage_index", 1234) now = time.time() - serverA = StubServer(hashutil.tagged_hash("foo", "serverid_a")[:20]) - serverB = StubServer(hashutil.tagged_hash("foo", "serverid_b")[:20]) - storage_index = hashutil.storage_index_hash("SI") + serverA = StubServer(hashutil.tagged_hash(b"foo", b"serverid_a")[:20]) + serverB = StubServer(hashutil.tagged_hash(b"foo", b"serverid_b")[:20]) + storage_index = hashutil.storage_index_hash(b"SI") e0 = ds.add_segment_request(0, now) e0.activate(now+0.5) e0.deliver(now+1, 0, 100, 0.5) # when, start,len, decodetime diff --git a/src/allmydata/web/status.py b/src/allmydata/web/status.py index ec55b73eb..3284dfda6 100644 --- a/src/allmydata/web/status.py +++ b/src/allmydata/web/status.py @@ -1,3 +1,4 @@ +from past.builtins import long, unicode import pprint import itertools @@ -1297,6 +1298,7 @@ class Status(MultiFormatResource): except ValueError: raise WebError("no '-' in '{}'".format(path)) count = int(count_s) + stype = unicode(stype, "ascii") if stype == "up": for s in itertools.chain(h.list_all_upload_statuses(), h.list_all_helper_statuses()): @@ -1335,7 +1337,7 @@ class Status(MultiFormatResource): active = [s for s in self._get_all_statuses() if s.get_active()] - active.sort(lambda a, b: cmp(a.get_started(), b.get_started())) + active.sort(key=lambda a: a.get_started()) active.reverse() return active @@ -1343,7 +1345,7 @@ class Status(MultiFormatResource): recent = [s for s in self._get_all_statuses() if not s.get_active()] - recent.sort(lambda a, b: cmp(a.get_started(), b.get_started())) + recent.sort(key=lambda a: a.get_started()) recent.reverse() return recent @@ -1373,7 +1375,6 @@ class StatusElement(Element): started_s = render_time(op.get_started()) result["started"] = started_s - si_s = base32.b2a_or_none(op.get_storage_index()) if si_s is None: si_s = "(None)" From 33392502d3e1e96a27fa187f39d076feadecdb87 Mon Sep 17 00:00:00 2001 From: Itamar Turner-Trauring Date: Thu, 17 Dec 2020 09:41:14 -0500 Subject: [PATCH 06/10] server IDs/node IDS should be bytes. --- src/allmydata/storage_client.py | 1 + src/allmydata/test/web/test_status.py | 10 +++++----- src/allmydata/test/web/test_web.py | 4 ++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/allmydata/storage_client.py b/src/allmydata/storage_client.py index 294a2d215..eb1572dcb 100644 --- a/src/allmydata/storage_client.py +++ b/src/allmydata/storage_client.py @@ -464,6 +464,7 @@ class StorageFarmBroker(service.MultiService): @implementer(IDisplayableServer) class StubServer(object): def __init__(self, serverid): + assert isinstance(serverid, bytes) self.serverid = serverid # binary tubid def get_serverid(self): return self.serverid diff --git a/src/allmydata/test/web/test_status.py b/src/allmydata/test/web/test_status.py index 5685a3938..d2ab5a606 100644 --- a/src/allmydata/test/web/test_status.py +++ b/src/allmydata/test/web/test_status.py @@ -143,12 +143,12 @@ class DownloadStatusElementTests(TrialTestCase): See if we can render the page almost fully. """ status = FakeDownloadStatus( - "si-1", 123, - ["s-1", "s-2", "s-3"], - {"s-1": "unknown problem"}, - {"s-1": [1], "s-2": [1,2], "s-3": [2,3]}, + b"si-1", 123, + [b"s-1", b"s-2", b"s-3"], + {b"s-1": "unknown problem"}, + {b"s-1": [1], b"s-2": [1,2], b"s-3": [2,3]}, {"fetch_per_server": - {"s-1": [1], "s-2": [2,3], "s-3": [3,2]}} + {b"s-1": [1], b"s-2": [2,3], b"s-3": [3,2]}} ) result = self._render_download_status_element(status) diff --git a/src/allmydata/test/web/test_web.py b/src/allmydata/test/web/test_web.py index f2b6d8f13..48c477a47 100644 --- a/src/allmydata/test/web/test_web.py +++ b/src/allmydata/test/web/test_web.py @@ -261,7 +261,7 @@ class FakeClient(_Client): # minimal subset service.MultiService.__init__(self) self.all_contents = {} - self.nodeid = "fake_nodeid" + self.nodeid = b"fake_nodeid" self.nickname = u"fake_nickname \u263A" self.introducer_furls = [] self.introducer_clients = [] @@ -277,7 +277,7 @@ class FakeClient(_Client): # fake knowledge of another server self.storage_broker.test_add_server("other_nodeid", FakeDisplayableServer( - serverid="other_nodeid", nickname=u"other_nickname \u263B", connected = True, + serverid=b"other_nodeid", nickname=u"other_nickname \u263B", connected = True, last_connect_time = 10, last_loss_time = 20, last_rx_time = 30)) self.storage_broker.test_add_server("disconnected_nodeid", FakeDisplayableServer( From 3ac64e42f71355aafb6ceb97720eec5303522f7d Mon Sep 17 00:00:00 2001 From: Itamar Turner-Trauring Date: Thu, 17 Dec 2020 09:54:04 -0500 Subject: [PATCH 07/10] Web test_status tests pass on Python 3. --- src/allmydata/test/web/test_web.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/allmydata/test/web/test_web.py b/src/allmydata/test/web/test_web.py index 48c477a47..1908afdeb 100644 --- a/src/allmydata/test/web/test_web.py +++ b/src/allmydata/test/web/test_web.py @@ -127,7 +127,7 @@ class FakeUploader(service.Service): def build_one_ds(): - ds = DownloadStatus("storage_index", 1234) + ds = DownloadStatus(b"storage_index", 1234) now = time.time() serverA = StubServer(hashutil.tagged_hash(b"foo", b"serverid_a")[:20]) From 6e12cce1e49ac90f2925ed53953c24c8751d908e Mon Sep 17 00:00:00 2001 From: Itamar Turner-Trauring Date: Thu, 17 Dec 2020 09:55:35 -0500 Subject: [PATCH 08/10] Port to Python 3. --- src/allmydata/test/web/test_status.py | 10 ++++++++++ src/allmydata/util/_python3.py | 1 + 2 files changed, 11 insertions(+) diff --git a/src/allmydata/test/web/test_status.py b/src/allmydata/test/web/test_status.py index d2ab5a606..414925446 100644 --- a/src/allmydata/test/web/test_status.py +++ b/src/allmydata/test/web/test_status.py @@ -1,6 +1,16 @@ """ Tests for ```allmydata.web.status```. + +Ported to Python 3. """ +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +from future.utils import PY2 +if PY2: + from future.builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, dict, list, object, range, str, max, min # noqa: F401 from bs4 import BeautifulSoup from twisted.web.template import flattenString diff --git a/src/allmydata/util/_python3.py b/src/allmydata/util/_python3.py index 803835fae..af771cd5a 100644 --- a/src/allmydata/util/_python3.py +++ b/src/allmydata/util/_python3.py @@ -181,4 +181,5 @@ PORTED_TEST_MODULES = [ "allmydata.test.test_util", "allmydata.test.web.test_common", "allmydata.test.web.test_util", + "allmydata.test.web.test_status", ] From 48b9ffe2a5985691e56ecb78cdef56b20eba7c2c Mon Sep 17 00:00:00 2001 From: Itamar Turner-Trauring Date: Thu, 17 Dec 2020 09:55:48 -0500 Subject: [PATCH 09/10] News file. --- newsfragments/3565.minor | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 newsfragments/3565.minor diff --git a/newsfragments/3565.minor b/newsfragments/3565.minor new file mode 100644 index 000000000..e69de29bb From f964ae1782076dcb99aaad886393bbddb416ecbf Mon Sep 17 00:00:00 2001 From: Itamar Turner-Trauring Date: Fri, 18 Dec 2020 15:43:27 -0500 Subject: [PATCH 10/10] Docstrings. --- src/allmydata/web/common.py | 20 ++++++++++++++++++-- src/allmydata/web/common_py3.py | 7 +++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/allmydata/web/common.py b/src/allmydata/web/common.py index 4e8cab89d..929db4f6e 100644 --- a/src/allmydata/web/common.py +++ b/src/allmydata/web/common.py @@ -208,7 +208,15 @@ def compute_rate(bytes, seconds): return 1.0 * bytes / seconds def abbreviate_rate(data): - # 21.8kBps, 554.4kBps 4.37MBps + """ + Convert number of bytes/second into human readable strings (unicode). + + Uses metric measures, so 1000 not 1024, e.g. 21.8kBps, 554.4kBps, 4.37MBps. + + :param data: Either ``None`` or integer. + + :return: Unicode string. + """ if data is None: return u"" r = float(data) @@ -219,7 +227,15 @@ def abbreviate_rate(data): return u"%.0fBps" % r def abbreviate_size(data): - # 21.8kB, 554.4kB 4.37MB + """ + Convert number of bytes into human readable strings (unicode). + + Uses metric measures, so 1000 not 1024, e.g. 21.8kB, 554.4kB, 4.37MB. + + :param data: Either ``None`` or integer. + + :return: Unicode string. + """ if data is None: return u"" r = float(data) diff --git a/src/allmydata/web/common_py3.py b/src/allmydata/web/common_py3.py index 89efd4d5d..41b6939f3 100644 --- a/src/allmydata/web/common_py3.py +++ b/src/allmydata/web/common_py3.py @@ -95,6 +95,13 @@ class MultiFormatResource(resource.Resource, object): def abbreviate_time(data): + """ + Convert number of seconds into human readable string. + + :param data: Either ``None`` or integer or float, seconds. + + :return: Unicode string. + """ # 1.23s, 790ms, 132us if data is None: return u""