feat(py3): Convert unicode-only modules to str

Modules that reference `unicode` but do *not* reference `str` can safely be converted to
use `str` in a way that's closest to the way it should be done under Python 3 but that
is still Python 2 compatible [per
`python-future`](https://python-future.org/compatible_idioms.html?highlight=unicode#unicode).

This change results in 4 additional tests passing under Python 3 that weren't before,
one previous test error is now a failure, and more coverage in a few modules.  Here's
the diff of the output from running all tests under Python 3 before these changes and
after.  I've elided the irrelevant changes (time stamps, object ids, etc.):

```diff
--- .tox/make-test-py3-all-old.log	2020-09-27 20:56:55.761691130 -0700
+++ .tox/make-test-py3-all-new.log	2020-09-27 20:58:16.242075678 -0700
@@ -1,6 +1,6 @@
...
@@ -4218,7 +4218,7 @@
 [ERROR]
 (#.### secs)
 allmydata.test.mutable.test_version.Version.test_download_version ... Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/mutable/test_version.py", line 274, in test_download_version
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/mutable/test_version.py", line 279, in test_download_version
     d = self.publish_multiple()
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/mutable/util.py", line 372, in publish_multiple
     self._nodemaker = make_nodemaker(self._storage)
@@ -4438,40 +4438,26 @@
 allmydata.test.test_abbreviate.Abbreviate.test_time ... [OK]
 (#.### secs)
 allmydata.test.test_auth.AccountFileCheckerKeyTests.test_authenticated ... Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_auth.py", line 42, in setUp
-    abspath = abspath_expanduser_unicode(unicode(self.account_file.path))
-builtins.NameError: name 'unicode' is not defined
+Failure: twisted.cred.error.UnauthorizedLogin:
 [ERROR]
 (#.### secs)
 allmydata.test.test_auth.AccountFileCheckerKeyTests.test_missing_signature ... Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_auth.py", line 42, in setUp
-    abspath = abspath_expanduser_unicode(unicode(self.account_file.path))
-builtins.NameError: name 'unicode' is not defined
-[ERROR]
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/trial/_asynctest.py", line 75, in _eb
+    raise self.failureException(output)
+twisted.trial.unittest.FailTest:
+Expected: (<class 'twisted.conch.error.ValidPublicKey'>,)
+Got:
+[Failure instance: Traceback (failure with no frames): <class 'twisted.cred.error.UnauthorizedLogin'>:
+]
+[FAILURE]
 (#.### secs)
-allmydata.test.test_auth.AccountFileCheckerKeyTests.test_password_auth_user ... Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_auth.py", line 42, in setUp
-    abspath = abspath_expanduser_unicode(unicode(self.account_file.path))
-builtins.NameError: name 'unicode' is not defined
-[ERROR]
+allmydata.test.test_auth.AccountFileCheckerKeyTests.test_password_auth_user ... [OK]
 (#.### secs)
-allmydata.test.test_auth.AccountFileCheckerKeyTests.test_unknown_user ... Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_auth.py", line 42, in setUp
-    abspath = abspath_expanduser_unicode(unicode(self.account_file.path))
-builtins.NameError: name 'unicode' is not defined
-[ERROR]
+allmydata.test.test_auth.AccountFileCheckerKeyTests.test_unknown_user ... [OK]
 (#.### secs)
-allmydata.test.test_auth.AccountFileCheckerKeyTests.test_unrecognized_key ... Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_auth.py", line 42, in setUp
-    abspath = abspath_expanduser_unicode(unicode(self.account_file.path))
-builtins.NameError: name 'unicode' is not defined
-[ERROR]
+allmydata.test.test_auth.AccountFileCheckerKeyTests.test_unrecognized_key ... [OK]
 (#.### secs)
-allmydata.test.test_auth.AccountFileCheckerKeyTests.test_wrong_signature ... Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_auth.py", line 42, in setUp
-    abspath = abspath_expanduser_unicode(unicode(self.account_file.path))
-builtins.NameError: name 'unicode' is not defined
-[ERROR]
+allmydata.test.test_auth.AccountFileCheckerKeyTests.test_wrong_signature ... [OK]
 (#.### secs)
 allmydata.test.test_backupdb.BackupDB.test_basic ... [OK]
 (#.### secs)
@@ -4615,7 +4601,7 @@
 src/allmydata/crypto/util.py                            12      2      4      2    75%   13, 32, 12->13, 30->32
 src/allmydata/deep_stats.py                             83     63     26      0    18%   27-52, 56-58, 62-82, 86-91, 94, 97, 103-114, 117-121, 125-131, 135
 src/allmydata/dirnode.py                               525    420    178      0    15%   70-103, 112-116, 119-135, 140-143, 146-160, 165-173, 176-177, 180-205, 208-217, 223-229, 248-286, 293-299, 302, 310, 315, 318-324, 327-332, 336-340, 344-346, 355-406, 410, 413, 416, 419, 422, 425, 428, 431-433, 436, 439, 442, 445, 448-450, 453, 457, 459, 464, 469-472, 475-478, 481-484, 489-492, 498-501, 504-507, 510-518, 530-532, 539-555, 558-566, 570-589, 600-610, 613-620, 628-641, 646-652, 657-678, 693-714, 752-761, 765-770, 774-812, 819-820, 825, 828, 831, 836-839, 842-849, 852-853, 862-877, 880-881, 884-891, 894, 897-899
-src/allmydata/frontends/auth.py                        100     71     28      0    26%   21-22, 30-48, 51, 54-56, 59-70, 80-87, 100-110, 117-118, 121, 124-142, 147-150, 156-159
+src/allmydata/frontends/auth.py                        100     52     28      4    47%   21-22, 38, 41-44, 51, 54-56, 65-70, 80-87, 106-108, 117-118, 121, 124-142, 147-150, 156-159, 37->38, 40->41, 59->65, 101->106
 src/allmydata/frontends/ftpd.py                        255    254     84      0     1%   4-337
 src/allmydata/frontends/sftpd.py                      1211   1208    488      0     1%   4-2014
 src/allmydata/hashtree.py                              174    135     72      1    16%   59, 75-78, 106-108, 114-117, 123-126, 132-136, 142-149, 152-162, 165-169, 172, 175, 180, 183, 186, 218-232, 259-262, 295-306, 320-323, 326-331, 384-484, 58->59
@@ -4653,7 +4639,7 @@
 src/allmydata/scripts/admin.py                          51     31      2      0    38%   9-14, 17-21, 25, 28, 31-37, 40-46, 56-57, 59, 61-66, 74-78
 src/allmydata/scripts/backupdb.py                      146     91     14      1    36%   84-91, 94-96, 99, 103, 106, 111-114, 117-119, 122, 125, 128, 176-221, 231-242, 245-263, 266-272, 308-324, 327-333, 336-341, 306->308
 src/allmydata/scripts/cli.py                           259    124     46      6    46%   25-49, 69-72, 79-81, 103, 142-146, 175, 221-222, 258, 265-266, 284-285, 330-331, 338-341, 346-355, 361-362, 366-373, 388, 405, 417, 432, 449, 479-481, 484-486, 489-491, 494-496, 499-501, 504-515, 518-520, 523-525, 528-530, 533, 536-538, 541-543, 546-548, 551-553, 556-558, 561-563, 566-568, 571-573, 576-577, 60->exit, 61->exit, 174->175, 180->exit, 181->exit, 219->221
-src/allmydata/scripts/common.py                        153     74     60      4    48%   64, 82, 88, 100, 114-126, 130-152, 159-163, 168-169, 172, 177, 191-236, 240-241, 47->49, 63->64, 79->82, 87->88
+src/allmydata/scripts/common.py                        154     74     60      4    49%   69, 87, 93, 105, 119-131, 135-157, 164-168, 173-174, 177, 182, 196-241, 245-246, 52->54, 68->69, 84->87, 92->93
 src/allmydata/scripts/common_http.py                    77     58     20      0    20%   15-30, 34-36, 38, 42-83, 87, 90, 94-96, 101
 src/allmydata/scripts/create_node.py                   302    185    114      8    30%   24, 61-96, 99-111, 114-128, 136-139, 169-174, 191-194, 205-208, 224-229, 235, 242, 256-278, 289-292, 295-298, 329, 339, 347-380, 385-445, 448-450, 455-477, 223->224, 234->235, 241->242, 252->256, 288->289, 294->295, 328->329, 338->339
 src/allmydata/scripts/debug.py                         719    638    202      0     9%   14, 31-32, 35-49, 52-60, 63-142, 146-154, 157-164, 168-217, 220-304, 307-401, 407, 417, 437-465, 468-485, 488-602, 606, 609-611, 637-648, 653-656, 659, 683-689, 692-810, 813-842, 845-848, 851-865, 869, 888, 891-940, 946, 949-950, 957, 960-961, 967-972, 984-985, 999-1000, 1003-1004, 1020-1021, 1025-1031, 1046-1050
@@ -4661,10 +4647,10 @@
 src/allmydata/scripts/run_common.py                    135     18     24      6    85%   37, 41-46, 59-60, 149, 158, 192-193, 216-220, 226-227, 55->62, 135->exit, 135->exit, 148->149, 191->192, 225->226
 src/allmydata/scripts/runner.py                        138     53     42     11    56%   84-85, 91, 97-99, 104, 114, 123-132, 140, 146, 149-160, 174-181, 186, 189-190, 204-232, 248, 255, 31->36, 103->104, 113->114, 139->140, 145->146, 147->149, 185->186, 188->189, 202->204, 247->248, 254->255
 src/allmydata/scripts/slow_operation.py                 69     56     22      0    14%   15-44, 47-52, 55-61, 64-83
-src/allmydata/scripts/stats_gatherer.py                 41     25     10      0    31%   20-25, 62-86
+src/allmydata/scripts/stats_gatherer.py                 42     25     10      0    33%   25-30, 67-91
 src/allmydata/scripts/tahoe_add_alias.py               106     91     30      0    11%   20-32, 35-59, 63-98, 102-111, 115-144
 src/allmydata/scripts/tahoe_backup.py                  331    267     85      0    15%   20-35, 38-51, 54-58, 71-73, 76-152, 155-157, 160-161, 164-174, 178-209, 212-242, 246-274, 278-279, 287-311, 322-331, 336, 339, 342-351, 356, 359, 362-367, 372-374, 379, 384, 389, 398, 417-425, 428, 431-461, 469-480, 483-486, 500-504, 511-512, 525, 538-542, 545-549, 552-555, 558-561, 564, 571, 578, 586-594
-src/allmydata/scripts/tahoe_check.py                   263    235    121      0     7%   15, 20-100, 103-112, 120-129, 132-167, 170-173, 179-192, 195-256, 259-270, 277-323, 327-336, 339
+src/allmydata/scripts/tahoe_check.py                   264    235    121      0     8%   20, 25-105, 108-117, 125-134, 137-172, 175-178, 184-197, 200-261, 264-275, 282-328, 332-341, 344
 src/allmydata/scripts/tahoe_cp.py                      602    503    226      0    12%   22, 26, 30-31, 34-37, 40-41, 44-47, 50-53, 56-60, 63-70, 75-77, 80, 83, 86, 90-91, 94, 98-99, 102, 106-111, 114, 117-134, 138-142, 145-159, 162-172, 175-177, 180, 185-189, 192, 195-197, 200-203, 206, 210-214, 218-223, 230-233, 236, 239-253, 256-263, 266-297, 303, 307-309, 316, 320-323, 326-333, 336-350, 354-358, 361-397, 403-413, 416-433, 436-437, 440-454, 465-496, 504-580, 583, 589-630, 636-689, 693-698, 701-703, 706-719, 723-762, 765-775, 778-806, 810-818, 821-838, 842, 845-857, 862-863, 867
 src/allmydata/scripts/tahoe_get.py                      37     32     12      0    10%   9-45
 src/allmydata/scripts/tahoe_invite.py                   59     41      8      0    27%   27-31, 36-71, 76-101
@@ -4679,7 +4665,7 @@
 src/allmydata/scripts/tahoe_stop.py                     60     47     10      0    19%   16, 24-84
 src/allmydata/scripts/tahoe_unlink.py                   28     23      6      0    15%   12-40
 src/allmydata/scripts/tahoe_webopen.py                  27     24     12      0     8%   7-31
-src/allmydata/stats.py                                 242    156     54      3    33%   28-34, 37-40, 43-47, 50-64, 67-72, 101, 104-110, 113-125, 144-146, 154-155, 160-163, 169-174, 178-187, 191, 200-207, 210, 213-219, 222-228, 232-234, 237, 241, 246-250, 253, 256-257, 263-278, 281-285, 288-293, 299-325, 100->101, 143->144, 153->154
+src/allmydata/stats.py                                 242    156     54      3    33%   29-35, 38-41, 44-48, 51-65, 68-73, 102, 105-111, 114-126, 145-147, 155-156, 161-164, 170-175, 179-188, 192, 201-208, 211, 214-220, 223-229, 233-235, 238, 242, 247-251, 254, 257-258, 264-279, 282-286, 289-294, 300-326, 101->102, 144->145, 154->155
 src/allmydata/storage/common.py                         24      2      4      2    86%   11, 28, 10->11, 36->39
 src/allmydata/storage/crawler.py                       222    125     64      6    37%   16, 90, 111-113, 148-178, 192-193, 231, 244, 251, 275-312, 315-363, 377-384, 393, 416, 428, 445, 453, 488-492, 495-508, 13->16, 89->90, 96->99, 228->231, 248->251, 268->271
 src/allmydata/storage/expirer.py                       240    183     81      2    21%   9, 74-79, 119, 122, 125-167, 171-233, 236-253, 256-261, 264-266, 269-274, 280-284, 288-322, 388-435, 7->9, 71->74
@@ -4748,7 +4734,7 @@
 src/allmydata/windows/fixups.py                        133    133     54      0     0%   1-237
 src/allmydata/windows/registry.py                       42     42     12      0     0%   1-77
 ------------------------------------------------------------------------------------------------
-TOTAL                                                27427  20411   8234    294    22%
+TOTAL                                                27430  20392   8234    298    22%

 18 files skipped due to complete coverage.
 + '[' '!' -z 1 ']'
```

Trac: refs #3448, https://tahoe-lafs.org/trac/tahoe-lafs/ticket/3448
This commit is contained in:
Ross Patterson 2020-09-27 13:00:19 -07:00
parent 8f7cafc877
commit 362c121426
12 changed files with 76 additions and 21 deletions

View File

@ -257,3 +257,9 @@ $(foreach side,old new,.tox/make-test-py3-all-$(side).log):
sed -E 's/\([0-9]+\.[0-9]{3} secs\)/(#.### secs)/' | tee "$(@)" sed -E 's/\([0-9]+\.[0-9]{3} secs\)/(#.### secs)/' | tee "$(@)"
.tox/make-test-py3-all.diff: .tox/make-test-py3-all-new.log .tox/make-test-py3-all.diff: .tox/make-test-py3-all-new.log
(diff -u "$(<:%-new.log=%-old.log)" "$(<)" || true) | tee "$(@)" (diff -u "$(<:%-new.log=%-old.log)" "$(<)" || true) | tee "$(@)"
# Locate modules that are candidates for naively converting `unicode` -> `str`.
# List all Python source files that reference `unicode` but don't reference `str`
.tox/py3-unicode-no-str.ls:
find src -type f -iname '*.py' -exec grep -l -E '\Wunicode\W' '{}' ';' | \
xargs grep -L '\Wstr\W' | xargs ls -ld | tee "$(@)"

1
newsfragments/3448.minor Normal file
View File

@ -0,0 +1 @@
Convert modules that only reference `unicode` to use `str`.

View File

@ -2,9 +2,14 @@ from __future__ import print_function
import os, sys, urllib, textwrap import os, sys, urllib, textwrap
import codecs import codecs
from six.moves.configparser import NoSectionError
from os.path import join from os.path import join
# BBB: Python 2 compatibility
from builtins import str
from six.moves.configparser import NoSectionError
from twisted.python import usage from twisted.python import usage
from allmydata.util.assertutil import precondition from allmydata.util.assertutil import precondition
from allmydata.util.encodingutil import unicode_to_url, quote_output, \ from allmydata.util.encodingutil import unicode_to_url, quote_output, \
quote_local_unicode_path, argv_to_abspath quote_local_unicode_path, argv_to_abspath
@ -188,7 +193,7 @@ def get_alias(aliases, path_unicode, default):
and default is not found in aliases, an UnknownAliasError is and default is not found in aliases, an UnknownAliasError is
raised. raised.
""" """
precondition(isinstance(path_unicode, unicode), path_unicode) precondition(isinstance(path_unicode, str), path_unicode)
from allmydata import uri from allmydata import uri
path = path_unicode.encode('utf-8').strip(" ") path = path_unicode.encode('utf-8').strip(" ")

View File

@ -1,7 +1,12 @@
from __future__ import print_function from __future__ import print_function
import os import os
# BBB: Python 2 compatibility
from builtins import str
from twisted.python import usage from twisted.python import usage
from allmydata.scripts.common import NoDefaultBasedirOptions from allmydata.scripts.common import NoDefaultBasedirOptions
from allmydata.scripts.create_node import write_tac from allmydata.scripts.create_node import write_tac
from allmydata.util.assertutil import precondition from allmydata.util.assertutil import precondition
@ -62,7 +67,7 @@ def create_stats_gatherer(config):
err = config.stderr err = config.stderr
basedir = config['basedir'] basedir = config['basedir']
# This should always be called with an absolute Unicode basedir. # This should always be called with an absolute Unicode basedir.
precondition(isinstance(basedir, unicode), basedir) precondition(isinstance(basedir, str), basedir)
if os.path.exists(basedir): if os.path.exists(basedir):
if listdir_unicode(basedir): if listdir_unicode(basedir):

View File

@ -2,7 +2,12 @@ from __future__ import print_function
import urllib import urllib
import json import json
# BBB: Python 2 compatibility
from builtins import str
from twisted.protocols.basic import LineOnlyReceiver from twisted.protocols.basic import LineOnlyReceiver
from allmydata.scripts.common import get_alias, DEFAULT_ALIAS, escape_path, \ from allmydata.scripts.common import get_alias, DEFAULT_ALIAS, escape_path, \
UnknownAliasError UnknownAliasError
from allmydata.scripts.common_http import do_http, format_http_error from allmydata.scripts.common_http import do_http, format_http_error
@ -101,7 +106,7 @@ def check_location(options, where):
def check(options): def check(options):
if len(options.locations) == 0: if len(options.locations) == 0:
errno = check_location(options, unicode()) errno = check_location(options, str())
if errno != 0: if errno != 0:
return errno return errno
return 0 return 0
@ -325,7 +330,7 @@ class DeepCheckStreamer(LineOnlyReceiver, object):
def run(self, options): def run(self, options):
if len(options.locations) == 0: if len(options.locations) == 0:
errno = self.deepcheck_location(options, unicode()) errno = self.deepcheck_location(options, str())
if errno != 0: if errno != 0:
return errno return errno
return 0 return 0

View File

@ -1,13 +1,14 @@
from __future__ import print_function from __future__ import print_function
from past.builtins import unicode
import json import json
import os import os
import pprint import pprint
import time import time
from collections import deque from collections import deque
# BBB: Python 2 compatibility
from builtins import str
from twisted.internet import reactor from twisted.internet import reactor
from twisted.application import service from twisted.application import service
from twisted.application.internet import TimerService from twisted.application.internet import TimerService
@ -157,7 +158,7 @@ class StatsProvider(Referenceable, service.MultiService):
service.MultiService.startService(self) service.MultiService.startService(self)
def count(self, name, delta=1): def count(self, name, delta=1):
if isinstance(name, unicode): if isinstance(name, str):
name = name.encode("utf-8") name = name.encode("utf-8")
val = self.counters.setdefault(name, 0) val = self.counters.setdefault(name, 0)
self.counters[name] = val + delta self.counters[name] = val + delta
@ -178,7 +179,7 @@ class StatsProvider(Referenceable, service.MultiService):
def to_bytes(d): def to_bytes(d):
result = {} result = {}
for (k, v) in d.items(): for (k, v) in d.items():
if isinstance(k, unicode): if isinstance(k, str):
k = k.encode("utf-8") k = k.encode("utf-8")
result[k] = v result[k] = v
return result return result

View File

@ -37,6 +37,9 @@ a mean of 10kB and a max of 100MB, so filesize=min(int(1.0/random(.0002)),1e8)
import os, sys, httplib, binascii import os, sys, httplib, binascii
import urllib, json, random, time, urlparse import urllib, json, random, time, urlparse
# BBB: Python 2 compatibility
from builtins import str
if sys.argv[1] == "--stats": if sys.argv[1] == "--stats":
statsfiles = sys.argv[2:] statsfiles = sys.argv[2:]
# gather stats every 10 seconds, do a moving-window average of the last # gather stats every 10 seconds, do a moving-window average of the last
@ -116,7 +119,7 @@ def listdir(nodeurl, root, remote_pathname):
assert nodetype == "dirnode" assert nodetype == "dirnode"
global directories_read global directories_read
directories_read += 1 directories_read += 1
children = dict( [(unicode(name),value) children = dict( [(str(name),value)
for (name,value) for (name,value)
in d["children"].iteritems()] ) in d["children"].iteritems()] )
return children return children

View File

@ -1,18 +1,23 @@
from __future__ import print_function from __future__ import print_function
import os, shutil, sys, urllib, time, stat, urlparse import os, shutil, sys, urllib, time, stat, urlparse
# BBB: Python 2 compatibility
from builtins import str
from six.moves import cStringIO as StringIO from six.moves import cStringIO as StringIO
from twisted.internet import defer, reactor, protocol, error from twisted.internet import defer, reactor, protocol, error
from twisted.application import service, internet from twisted.application import service, internet
from twisted.web import client as tw_client from twisted.web import client as tw_client
from twisted.python import log, procutils
from foolscap.api import Tub, fireEventually, flushEventualQueue
from allmydata import client, introducer from allmydata import client, introducer
from allmydata.immutable import upload from allmydata.immutable import upload
from allmydata.scripts import create_node from allmydata.scripts import create_node
from allmydata.util import fileutil, pollmixin from allmydata.util import fileutil, pollmixin
from allmydata.util.fileutil import abspath_expanduser_unicode from allmydata.util.fileutil import abspath_expanduser_unicode
from allmydata.util.encodingutil import get_filesystem_encoding from allmydata.util.encodingutil import get_filesystem_encoding
from foolscap.api import Tub, fireEventually, flushEventualQueue
from twisted.python import log, procutils
class StallableHTTPGetterDiscarder(tw_client.HTTPPageGetter, object): class StallableHTTPGetterDiscarder(tw_client.HTTPPageGetter, object):
full_speed_ahead = False full_speed_ahead = False
@ -69,7 +74,7 @@ class SystemFramework(pollmixin.PollMixin):
numnodes = 7 numnodes = 7
def __init__(self, basedir, mode): def __init__(self, basedir, mode):
self.basedir = basedir = abspath_expanduser_unicode(unicode(basedir)) self.basedir = basedir = abspath_expanduser_unicode(str(basedir))
if not (basedir + os.path.sep).startswith(abspath_expanduser_unicode(u".") + os.path.sep): if not (basedir + os.path.sep).startswith(abspath_expanduser_unicode(u".") + os.path.sep):
raise AssertionError("safety issue: basedir must be a subdir") raise AssertionError("safety issue: basedir must be a subdir")
self.testdir = testdir = os.path.join(basedir, "test") self.testdir = testdir = os.path.join(basedir, "test")

View File

@ -2,7 +2,10 @@
Tools aimed at the interaction between tests and Eliot. Tools aimed at the interaction between tests and Eliot.
""" """
from past.builtins import unicode # BBB: Python 2 compatibility
# Can't use `builtins.str` because it's not JSON encodable:
# `exceptions.TypeError: <class 'future.types.newstr.newstr'> is not JSON-encodeable`
from past.builtins import unicode as str
__all__ = [ __all__ = [
"RUN_TEST", "RUN_TEST",
@ -29,7 +32,7 @@ from twisted.internet.defer import (
_NAME = Field.for_types( _NAME = Field.for_types(
u"name", u"name",
[unicode], [str],
u"The name of the test.", u"The name of the test.",
) )

View File

@ -1,9 +1,14 @@
from __future__ import print_function from __future__ import print_function
import os import os
# BBB: Python 2 compatibility
from builtins import str
from six.moves import cStringIO as StringIO from six.moves import cStringIO as StringIO
from twisted.internet import defer from twisted.internet import defer
from twisted.trial import unittest from twisted.trial import unittest
from allmydata import uri from allmydata import uri
from allmydata.interfaces import SDMF_VERSION, MDMF_VERSION from allmydata.interfaces import SDMF_VERSION, MDMF_VERSION
from allmydata.util import base32, consumer, mathutil from allmydata.util import base32, consumer, mathutil
@ -75,7 +80,7 @@ class Version(GridTestMixin, unittest.TestCase, testutil.ShouldFailMixin, \
fso = debug.FindSharesOptions() fso = debug.FindSharesOptions()
storage_index = base32.b2a(n.get_storage_index()) storage_index = base32.b2a(n.get_storage_index())
fso.si_s = storage_index fso.si_s = storage_index
fso.nodedirs = [os.path.dirname(abspath_expanduser_unicode(unicode(storedir))) fso.nodedirs = [os.path.dirname(abspath_expanduser_unicode(str(storedir)))
for (i,ss,storedir) for (i,ss,storedir)
in self.iterate_servers()] in self.iterate_servers()]
fso.stdout = StringIO() fso.stdout = StringIO()

View File

@ -1,3 +1,6 @@
# BBB: Python 2 compatibility
from builtins import str
from twisted.trial import unittest from twisted.trial import unittest
from twisted.python import filepath from twisted.python import filepath
from twisted.cred import error, credentials from twisted.cred import error, credentials
@ -39,7 +42,7 @@ class AccountFileCheckerKeyTests(unittest.TestCase):
def setUp(self): def setUp(self):
self.account_file = filepath.FilePath(self.mktemp()) self.account_file = filepath.FilePath(self.mktemp())
self.account_file.setContent(DUMMY_ACCOUNTS) self.account_file.setContent(DUMMY_ACCOUNTS)
abspath = abspath_expanduser_unicode(unicode(self.account_file.path)) abspath = abspath_expanduser_unicode(str(self.account_file.path))
self.checker = auth.AccountFileChecker(None, abspath) self.checker = auth.AccountFileChecker(None, abspath)
def test_unknown_user(self): def test_unknown_user(self):

View File

@ -1,9 +1,22 @@
import os, json, urllib
# BBB: Python 2 compatibility
# Can't use `builtins.str` because something deep in Twisted callbacks ends up repr'ing
# a `future.types.newstr.newstr` as a *Python 3* byte string representation under
# *Python 2*:
# File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py27/lib/python2.7/site-packages/allmydata/util/netstring.py", line 43, in split_netstring
# assert data[position] == b","[0], position
# exceptions.AssertionError: 15
# ...
# (Pdb) pp data
# '334:12:b\'mutable-good\',90:URI:SSK-RO:...
from past.builtins import unicode as str
from future.utils import native_str from future.utils import native_str
import os, json, urllib
from twisted.trial import unittest from twisted.trial import unittest
from twisted.internet import defer from twisted.internet import defer
from twisted.internet.defer import inlineCallbacks, returnValue from twisted.internet.defer import inlineCallbacks, returnValue
from allmydata.immutable import upload from allmydata.immutable import upload
from allmydata.mutable.common import UnrecoverableFileError from allmydata.mutable.common import UnrecoverableFileError
from allmydata.mutable.publish import MutableData from allmydata.mutable.publish import MutableData
@ -917,13 +930,13 @@ class DeepCheckWebBad(DeepCheckBase, unittest.TestCase):
if nodetype == "mutable": if nodetype == "mutable":
mutable_uploadable = MutableData("mutable file contents") mutable_uploadable = MutableData("mutable file contents")
d = self.g.clients[0].create_mutable_file(mutable_uploadable) d = self.g.clients[0].create_mutable_file(mutable_uploadable)
d.addCallback(lambda n: self.root.set_node(unicode(name), n)) d.addCallback(lambda n: self.root.set_node(str(name), n))
elif nodetype == "large": elif nodetype == "large":
large = upload.Data("Lots of data\n" * 1000 + name + "\n", None) large = upload.Data("Lots of data\n" * 1000 + name + "\n", None)
d = self.root.add_file(unicode(name), large) d = self.root.add_file(str(name), large)
elif nodetype == "small": elif nodetype == "small":
small = upload.Data("Small enough for a LIT", None) small = upload.Data("Small enough for a LIT", None)
d = self.root.add_file(unicode(name), small) d = self.root.add_file(str(name), small)
d.addCallback(self._stash_node, name) d.addCallback(self._stash_node, name)