diff --git a/newsfragments/3565.minor b/newsfragments/3565.minor new file mode 100644 index 000000000..e69de29bb 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/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/test/web/test_common.py b/src/allmydata/test/web/test_common.py index 5261c412f..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 @@ -163,7 +173,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/test/web/test_status.py b/src/allmydata/test/web/test_status.py index 5685a3938..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 @@ -143,12 +153,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_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/test/web/test_web.py b/src/allmydata/test/web/test_web.py index 326569a26..1908afdeb 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, @@ -127,12 +127,12 @@ 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("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 @@ -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( diff --git a/src/allmydata/util/_python3.py b/src/allmydata/util/_python3.py index c29217912..af771cd5a 100644 --- a/src/allmydata/util/_python3.py +++ b/src/allmydata/util/_python3.py @@ -154,6 +154,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", @@ -178,4 +179,7 @@ PORTED_TEST_MODULES = [ "allmydata.test.test_upload", "allmydata.test.test_uri", "allmydata.test.test_util", + "allmydata.test.web.test_common", + "allmydata.test.web.test_util", + "allmydata.test.web.test_status", ] diff --git a/src/allmydata/web/common.py b/src/allmydata/web/common.py index d970cc918..929db4f6e 100644 --- a/src/allmydata/web/common.py +++ b/src/allmydata/web/common.py @@ -208,28 +208,44 @@ 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 "" + 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 + """ + 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 "" + 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): @@ -562,7 +578,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", diff --git a/src/allmydata/web/common_py3.py b/src/allmydata/web/common_py3.py index 22f235790..41b6939f3 100644 --- a/src/allmydata/web/common_py3.py +++ b/src/allmydata/web/common_py3.py @@ -95,16 +95,23 @@ 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 "" + 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) 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)"