Commit Graph

6421 Commits

Author SHA1 Message Date
Ross Patterson
da046108e2 feat(py3): Fix section name unicode type clash
Before this change, there was an error in the tests in python 3.  I couldn't find any
clues from the history as to why explicit byte-string literals were used here.  This
change addresses the error under Python 3 and doesn't cause any regressions under Python
2 in the test suite.  This changes two tests from failures to passing under Python 3 and
increases coverage a bit:

```diff
--- ../../.tox/make-test-py3-all-old.log	2020-10-04 21:42:22.931028265 -0700
+++ ../../.tox/make-test-py3-all-new.log	2020-10-04 21:49:19.164127097 -0700
@@ -313,7 +313,7 @@
 ####-##-##T##:##:##-###0 [twisted.scripts._twistd_unix.UnixAppLogger#info] twistd 20.3.0 (/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/bin/python 3.6.12) starting up.
 ####-##-##T##:##:##-###0 [twisted.scripts._twistd_unix.UnixAppLogger#info] reactor class: mock.mock.MagicMock.
 ####-##-##T##:##:##-###0 [twisted.scripts._twistd_unix.UnixAppLogger#info] Server Shut Down.
-                                         [FAIL]
+                                           [OK]
 allmydata.test
   cli
     test_status ...                                                     [ERROR]
@@ -1191,7 +1191,7 @@
     test_disabled_but_helper ...                                         [FAIL]
     test_disabled_but_storage ...                                        [FAIL]
   Configuration
-    test_create_client_invalid_config ...                                [FAIL]
+    test_create_client_invalid_config ...                                  [OK]
     test_read_invalid_config ...                                           [OK]
   IntroducerNotListening
     test_port_none_introducer ...                                        [FAIL]
@@ -2024,18 +2024,6 @@
 ===============================================================================
 [FAIL]
 Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/mock/mock.py", line 1369, in patched
-    return func(*newargs, **newkeywargs)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/cli/test_start.py", line 265, in test_run_invalid_config
-    output,
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/trial/_synctest.py", line 494, in assertIn
-    % (containee, container))
-twisted.trial.unittest.FailTest: 'invalid section' not in '\nUnknown error\nTraceback (most recent call last):\n  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/cli/test_start.py", line 232, in cwr\n    fn()\n  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/scripts/run_common.py", line 155, in start\n    d = service_factory()\n  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/scripts/run_common.py", line 136, in <lambda>\n    u"client": lambda: maybeDeferred(namedAny("allmydata.client.create_client"), self.basedir),\n  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/internet/defer.py", line 151, in maybeDeferred\n    result = f(*args, **kw)\n--- <exception caught here> ---\n  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/client.py", line 243, in create_client\n    config = read_config(basedir, u"client.port")\n  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/client.py", line 219, in read_config\n    _valid_config=_valid_config(),\n  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 192, in read_config\n    configutil.validate_config(config_fname, parser, _valid_config)\n  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/util/configutil.py", line 72, in validate_config\n    if not valid_config.is_valid_section(section):\n  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/util/configutil.py", line 113, in is_valid_section\n    self._is_valid_section(section_name)\n  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/util/configutil.py", line 141, in <lambda>\n    return lambda *a, **kw: f(*a, **kw) or g(*a, **kw)\n  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/client.py", line 72, in _is_valid_section\n    section_name.startswith(b"storageserver.plugins.") or\nbuiltins.TypeError: startswith first arg must be str or a tuple of str, not bytes\n'
-
-allmydata.test.cli.test_start.RunTests.test_run_invalid_config
-===============================================================================
-[FAIL]
-Traceback (most recent call last):
   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:
@@ -2222,34 +2210,6 @@
     result = result.throwExceptionIntoGenerator(g)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/python/failure.py", line 512, in throwExceptionIntoGenerator
     return g.throw(self.type, self.value, self.tb)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 741, in test_create_client_invalid_config
-    yield client.create_client(self.basedir)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/trial/_synctest.py", line 355, in __exit__
-    self._expectedName, reason.getTraceback()),
-twisted.trial.unittest.FailTest: builtins.TypeError raised instead of UnknownConfigError:
- Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/internet/defer.py", line 1529, in _cancellableInlineCallbacks
-    _inlineCallbacks(None, g, status)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/internet/defer.py", line 1416, in _inlineCallbacks
-    result = result.throwExceptionIntoGenerator(g)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/python/failure.py", line 512, in throwExceptionIntoGenerator
-    return g.throw(self.type, self.value, self.tb)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 741, in test_create_client_invalid_config
-    yield client.create_client(self.basedir)
---- <exception caught here> ---
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 741, in test_create_client_invalid_config
-    yield client.create_client(self.basedir)
-builtins.TypeError: startswith first arg must be str or a tuple of str, not bytes
-
-
-allmydata.test.test_node.Configuration.test_create_client_invalid_config
-===============================================================================
-[FAIL]
-Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/internet/defer.py", line 1416, in _inlineCallbacks
-    result = result.throwExceptionIntoGenerator(g)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/python/failure.py", line 512, in throwExceptionIntoGenerator
-    return g.throw(self.type, self.value, self.tb)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 704, in test_port_none_introducer
     yield create_introducer(basedir)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/trial/_synctest.py", line 355, in __exit__
@@ -8717,7 +8677,7 @@
 -------------------------------------------------------------------------------
 Ran 1300 tests in ###.###s

-FAILED (skips=42, expectedFailures=1, failures=35, errors=531, successes=707)
+FAILED (skips=42, expectedFailures=1, failures=33, errors=531, successes=709)

 Unknown error
 Traceback (most recent call last):
@@ -8806,7 +8766,7 @@
 src/allmydata/scripts/create_node.py                   302     98    114     10    66%   224-229, 235, 257-260, 262-265, 268-269, 289-292, 295-298, 329, 339, 347-380, 391-445, 461-477, 223->224, 234->235, 256->257, 261->262, 266->277, 267->268, 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
 src/allmydata/scripts/default_nodedir.py                15      5      6      2    57%   10-14, 9->10, 16->exit
-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/run_common.py                    135     17     24      5    86%   37, 41-46, 59-60, 158, 192-193, 216-220, 226-227, 55->62, 135->exit, 135->exit, 191->192, 225->226
 src/allmydata/scripts/runner.py                        138     49     42      5    61%   84-85, 91, 97-99, 150, 153-160, 174-181, 188-192, 202-232, 237-252, 255, 31->36, 149->150, 151->153, 185->188, 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                 44     16     12      3    59%   8, 30, 75-79, 84-93, 7->8, 29->30, 74->75
@@ -8893,7 +8853,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                                                27477  11782   8244    605    54%
+TOTAL                                                27477  11781   8244    604    54%

 18 files skipped due to complete coverage.
 + '[' '!' -z 1 ']'
```
2020-10-04 21:50:09 -07:00
Ross Patterson
a89715ebe8 feat(py3): feat(py3): Fix use of deprecated type
Python 3 did away with the unbound method type entirely, they're just functions under
Python 3, and IIUC the unbound type is just an alias for the method type in Python 2.
As such, this approach should preserve the behavior under Python 2 and should work under
Python 3.

With this change, the diff in test output shows one test error converted to a failure,
increases coverage in all the modules that have a coverage change, and reveals the next
porting bug:

```
...
  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 740, in __init__
    self.config.write_config_file("my_nodeid", b32encode(self.nodeid).lower() + "\n")
builtins.TypeError: can't concat str to bytes
```

There are no regressions I see under Python 2, so this seems like the right fix to this
particular issue AFAICT.

```diff
--- ../../.tox/make-test-py3-all-old.log	2020-10-04 15:59:59.355692613 -0700
+++ ../../.tox/make-test-py3-all-new.log	2020-10-04 16:59:27.870208496 -0700
@@ -1206,7 +1206,7 @@
     test_location2 ...                                                  [ERROR]
     test_location_auto_and_explicit ...                                 [ERROR]
     test_location_not_set ...                                           [ERROR]
-    test_logdir_is_str ...                                              [ERROR]
+    test_logdir_is_str ...                                               [FAIL]
     test_private_config ...                                             [ERROR]
     test_private_config_missing ...                                        [OK]
     test_private_config_unreadable ...                                  [ERROR]
@@ -2254,7 +2254,7 @@
     yield create_introducer(basedir)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/trial/_synctest.py", line 355, in __exit__
     self._expectedName, reason.getTraceback()),
-twisted.trial.unittest.FailTest: builtins.AttributeError raised instead of ValueError:
+twisted.trial.unittest.FailTest: builtins.TypeError raised instead of ValueError:
  Traceback (most recent call last):
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/internet/defer.py", line 1529, in _cancellableInlineCallbacks
     _inlineCallbacks(None, g, status)
@@ -2271,11 +2271,9 @@
     tor_provider,
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/introducer/server.py", line 87, in __init__
     node.Node.__init__(self, config, main_tub, control_tub, i2p_provider, tor_provider)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 734, in __init__
-    self.setup_logging()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 826, in setup_logging
-    newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__)
-builtins.AttributeError: module 'types' has no attribute 'UnboundMethodType'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 740, in __init__
+    self.config.write_config_file("my_nodeid", b32encode(self.nodeid).lower() + "\n")
+builtins.TypeError: can't concat str to bytes

 allmydata.test.test_node.IntroducerNotListening.test_port_none_introducer
@@ -2307,6 +2305,30 @@
 ===============================================================================
 [FAIL]
 Traceback (most recent call last):
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 340, in test_logdir_is_str
+    yield client.create_client(basedir)
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/internet/defer.py", line 1418, in _inlineCallbacks
+    result = g.send(result)
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/client.py", line 298, in create_client_from_config
+    storage_broker,
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/client.py", line 676, in __init__
+    node.Node.__init__(self, config, main_tub, control_tub, i2p_provider, tor_provider)
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 734, in __init__
+    self.setup_logging()
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 842, in setup_logging
+    foolscap.logging.log.setLogDir(incident_dir.encode(get_filesystem_encoding()))
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 336, in call_setLogDir
+    self.failUnless(isinstance(logdir, str), logdir)
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/trial/_synctest.py", line 397, in assertTrue
+    super(_Assertions, self).assertTrue(condition, msg)
+  File "/usr/lib/python3.6/unittest/case.py", line 682, in assertTrue
+    raise self.failureException(msg)
+twisted.trial.unittest.FailTest: False is not true : b'/home/rpatterson/src/work/sfu/tahoe-lafs/_trial_temp/test_node/test_logdir_is_str/logs/incidents'
+
+allmydata.test.test_node.TestCase.test_logdir_is_str
+===============================================================================
+[FAIL]
+Traceback (most recent call last):
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/internet/defer.py", line 1418, in _inlineCallbacks
     result = g.send(result)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_runner.py", line 192, in test_eliot_destination
@@ -5933,11 +5955,9 @@
     storage_broker,
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/client.py", line 676, in __init__
     node.Node.__init__(self, config, main_tub, control_tub, i2p_provider, tor_provider)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 734, in __init__
-    self.setup_logging()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 826, in setup_logging
-    newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__)
-builtins.AttributeError: module 'types' has no attribute 'UnboundMethodType'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 740, in __init__
+    self.config.write_config_file("my_nodeid", b32encode(self.nodeid).lower() + "\n")
+builtins.TypeError: can't concat str to bytes

 allmydata.test.test_client.Basic.test_web_apiauthtoken
 ===============================================================================
@@ -7130,8 +7150,12 @@
 ===============================================================================
 [ERROR]
 Traceback (most recent call last):
-Failure: testtools.testresult.real._StringException: Empty attachments:
-  twisted-log
+Failure: testtools.testresult.real._StringException: twisted-log: {{{
+2020-10-04 23:57:37.636Z [-] Foolscap logging initialized
+2020-10-04 23:57:37.636Z [-] Note to developers: twistd.log does not receive very much.
+2020-10-04 23:57:37.636Z [-] Use 'flogtool tail -c NODEDIR/private/logport.furl' instead
+2020-10-04 23:57:37.636Z [-] and read docs/logging.rst
+}}}

 Traceback (most recent call last):
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/internet/defer.py", line 1416, in _inlineCallbacks
@@ -7144,19 +7168,21 @@
     tor_provider,
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/introducer/server.py", line 87, in __init__
     node.Node.__init__(self, config, main_tub, control_tub, i2p_provider, tor_provider)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 734, in __init__
-    self.setup_logging()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 826, in setup_logging
-    newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__)
-AttributeError: module 'types' has no attribute 'UnboundMethodType'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 740, in __init__
+    self.config.write_config_file("my_nodeid", b32encode(self.nodeid).lower() + "\n")
+TypeError: can't concat str to bytes

 allmydata.test.test_introducer.Node.test_create
 ===============================================================================
 [ERROR]
 Traceback (most recent call last):
-Failure: testtools.testresult.real._StringException: Empty attachments:
-  twisted-log
+Failure: testtools.testresult.real._StringException: twisted-log: {{{
+2020-10-04 23:57:38.284Z [-] Foolscap logging initialized
+2020-10-04 23:57:38.284Z [-] Note to developers: twistd.log does not receive very much.
+2020-10-04 23:57:38.284Z [-] Use 'flogtool tail -c NODEDIR/private/logport.furl' instead
+2020-10-04 23:57:38.284Z [-] and read docs/logging.rst
+}}}

 Traceback (most recent call last):
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/internet/defer.py", line 1416, in _inlineCallbacks
@@ -7169,11 +7195,9 @@
     tor_provider,
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/introducer/server.py", line 87, in __init__
     node.Node.__init__(self, config, main_tub, control_tub, i2p_provider, tor_provider)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 734, in __init__
-    self.setup_logging()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 826, in setup_logging
-    newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__)
-AttributeError: module 'types' has no attribute 'UnboundMethodType'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 740, in __init__
+    self.config.write_config_file("my_nodeid", b32encode(self.nodeid).lower() + "\n")
+TypeError: can't concat str to bytes

 allmydata.test.test_introducer.Node.test_furl
@@ -7540,24 +7564,6 @@
 ===============================================================================
 [ERROR]
 Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 340, in test_logdir_is_str
-    yield client.create_client(basedir)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/internet/defer.py", line 1418, in _inlineCallbacks
-    result = g.send(result)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/client.py", line 298, in create_client_from_config
-    storage_broker,
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/client.py", line 676, in __init__
-    node.Node.__init__(self, config, main_tub, control_tub, i2p_provider, tor_provider)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 734, in __init__
-    self.setup_logging()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 826, in setup_logging
-    newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__)
-builtins.AttributeError: module 'types' has no attribute 'UnboundMethodType'
-
-allmydata.test.test_node.TestCase.test_logdir_is_str
-===============================================================================
-[ERROR]
-Traceback (most recent call last):
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 259, in test_private_config
     config = config_from_string(basedir, "", "")
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
@@ -8446,11 +8452,9 @@
     tor_provider,
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/introducer/server.py", line 87, in __init__
     node.Node.__init__(self, config, main_tub, control_tub, i2p_provider, tor_provider)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 734, in __init__
-    self.setup_logging()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 826, in setup_logging
-    newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__)
-builtins.AttributeError: module 'types' has no attribute 'UnboundMethodType'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 740, in __init__
+    self.config.write_config_file("my_nodeid", b32encode(self.nodeid).lower() + "\n")
+builtins.TypeError: can't concat str to bytes

 allmydata.test.test_system.Connections.test_rref
 allmydata.test.test_system.SystemTest.test_filesystem
@@ -8565,11 +8569,9 @@
     tor_provider,
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/introducer/server.py", line 87, in __init__
     node.Node.__init__(self, config, main_tub, control_tub, i2p_provider, tor_provider)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 734, in __init__
-    self.setup_logging()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 826, in setup_logging
-    newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__)
-builtins.AttributeError: module 'types' has no attribute 'UnboundMethodType'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 740, in __init__
+    self.config.write_config_file("my_nodeid", b32encode(self.nodeid).lower() + "\n")
+builtins.TypeError: can't concat str to bytes

 allmydata.test.web.test_introducer.IntroducerWeb.test_basic_information
 ===============================================================================
@@ -8587,11 +8589,9 @@
     tor_provider,
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/introducer/server.py", line 87, in __init__
     node.Node.__init__(self, config, main_tub, control_tub, i2p_provider, tor_provider)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 734, in __init__
-    self.setup_logging()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 826, in setup_logging
-    newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__)
-builtins.AttributeError: module 'types' has no attribute 'UnboundMethodType'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 740, in __init__
+    self.config.write_config_file("my_nodeid", b32encode(self.nodeid).lower() + "\n")
+builtins.TypeError: can't concat str to bytes

 allmydata.test.web.test_introducer.IntroducerWeb.test_json_front_page
 ===============================================================================
@@ -8609,11 +8609,9 @@
     tor_provider,
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/introducer/server.py", line 87, in __init__
     node.Node.__init__(self, config, main_tub, control_tub, i2p_provider, tor_provider)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 734, in __init__
-    self.setup_logging()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 826, in setup_logging
-    newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__)
-builtins.AttributeError: module 'types' has no attribute 'UnboundMethodType'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 740, in __init__
+    self.config.write_config_file("my_nodeid", b32encode(self.nodeid).lower() + "\n")
+builtins.TypeError: can't concat str to bytes

 allmydata.test.web.test_introducer.IntroducerWeb.test_tahoe_css
 ===============================================================================
@@ -8631,11 +8629,9 @@
     tor_provider,
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/introducer/server.py", line 87, in __init__
     node.Node.__init__(self, config, main_tub, control_tub, i2p_provider, tor_provider)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 734, in __init__
-    self.setup_logging()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 826, in setup_logging
-    newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__)
-builtins.AttributeError: module 'types' has no attribute 'UnboundMethodType'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 740, in __init__
+    self.config.write_config_file("my_nodeid", b32encode(self.nodeid).lower() + "\n")
+builtins.TypeError: can't concat str to bytes

 allmydata.test.web.test_introducer.IntroducerWeb.test_welcome
 ===============================================================================
@@ -8721,7 +8717,7 @@
 -------------------------------------------------------------------------------
 Ran 1300 tests in ###.###s

-FAILED (skips=42, expectedFailures=1, failures=34, errors=532, successes=707)
+FAILED (skips=42, expectedFailures=1, failures=35, errors=531, successes=707)

 Unknown error
 Traceback (most recent call last):
@@ -8740,11 +8736,9 @@
     storage_broker,
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/client.py", line 676, in __init__
     node.Node.__init__(self, config, main_tub, control_tub, i2p_provider, tor_provider)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 734, in __init__
-    self.setup_logging()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 826, in setup_logging
-    newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__)
-builtins.AttributeError: module 'types' has no attribute 'UnboundMethodType'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 740, in __init__
+    self.config.write_config_file("my_nodeid", b32encode(self.nodeid).lower() + "\n")
+builtins.TypeError: can't concat str to bytes
 + test_exit=1
 + ./.tox/py36-coverage/bin/coverage combine
 + ./.tox/py36-coverage/bin/coverage html
@@ -8775,11 +8769,11 @@
 src/allmydata/immutable/downloader/__init__.py           7      1      2      1    78%   12, 11->12
 src/allmydata/immutable/downloader/common.py            14      1      2      1    88%   12, 11->12
 src/allmydata/immutable/downloader/fetcher.py          147      1     56      1    99%   12, 11->12
-src/allmydata/immutable/downloader/finder.py           143     11     40      5    91%   11, 88-89, 108, 115, 170-173, 231-232, 10->11, 87->88, 107->108, 113->115, 165->exit
+src/allmydata/immutable/downloader/finder.py           143      9     40      5    92%   11, 88-89, 108, 115, 170-173, 10->11, 87->88, 107->108, 113->115, 165->exit
 src/allmydata/immutable/downloader/node.py             282      9     66      9    94%   11, 170-172, 224-235, 271, 10->11, 43->exit, 60->68, 165->169, 169->170, 256->exit, 270->271, 517->exit, 537->exit
 src/allmydata/immutable/downloader/segmentation.py     118      1     22      1    99%   11, 10->11
-src/allmydata/immutable/downloader/share.py            453     23    154     11    94%   11, 210, 239-250, 289-290, 354, 399-400, 430-437, 518, 722-725, 775, 862, 10->11, 209->210, 222->239, 288->289, 352->354, 397->399, 515->518, 660->663, 710->722, 762->exit, 774->775
-src/allmydata/immutable/downloader/status.py           154     12     36      1    93%   11, 65-67, 223, 226, 230, 232, 234, 274, 285, 287, 10->11
+src/allmydata/immutable/downloader/share.py            453     15    154      8    96%   11, 210, 248-250, 354, 430-437, 518, 722-725, 862, 10->11, 209->210, 239->248, 352->354, 515->518, 660->663, 710->722, 762->exit
+src/allmydata/immutable/downloader/status.py           154      9     36      1    95%   11, 223, 226, 230, 232, 234, 274, 285, 287, 10->11
 src/allmydata/immutable/encode.py                      421     13    124     10    95%   114, 197-200, 278-280, 405, 412, 462, 509, 562, 687, 102->104, 113->114, 195->197, 404->405, 411->412, 461->462, 499->509, 505->511, 561->562, 685->687
 src/allmydata/immutable/filenode.py                    196     48     30      5    72%   77-78, 83, 85, 88, 94-101, 104-124, 127-172, 254, 258, 315, 40->42, 224->227, 227->229, 251->254, 257->258
 src/allmydata/immutable/happiness_upload.py            214      1    132      3    99%   15, 13->15, 213->211, 280->279
@@ -8802,7 +8796,7 @@
 src/allmydata/mutable/repairer.py                       57     37     18      0    29%   13, 15, 17, 19, 29-34, 65-71, 74-126, 129-131
 src/allmydata/mutable/retrieve.py                      489    123    120     33    71%   46, 48, 50, 52, 56, 58, 60, 62, 64, 89-90, 133, 186-193, 204-208, 211-212, 224-226, 231, 240, 251, 312, 318, 344-354, 377, 385-386, 399-400, 425-434, 490, 501, 515-516, 529-540, 564-578, 591-592, 629-630, 653-654, 674-675, 681-682, 698, 712-729, 758-760, 765, 772-774, 790-792, 871, 883, 909-910, 919-941, 965-966, 981-994, 999-1005, 129->133, 167->169, 169->171, 201->204, 223->224, 230->231, 237->239, 239->240, 243->247, 249->251, 309->312, 317->318, 376->377, 381->385, 391->394, 396->399, 424->425, 489->490, 499->501, 514->515, 590->591, 628->629, 652->653, 673->674, 677->687, 680->681, 687->694, 694->698, 755->764, 764->765, 868->871, 880->883, 964->965
 src/allmydata/mutable/servermap.py                     612    240    186     26    56%   45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 74, 130-139, 142, 148, 159-161, 175, 177, 183, 186-199, 206, 213, 217-220, 231, 234-238, 243-252, 255-259, 315, 328-350, 358-363, 370-372, 379, 429, 433, 443-447, 495, 498, 506-508, 514-516, 569-570, 603-611, 623-638, 718-721, 732-741, 792, 796, 803-804, 850-851, 872-874, 911-915, 929-945, 961-975, 982-999, 1003-1013, 1043-1045, 1050-1052, 1060-1064, 1069-1070, 1093-1100, 1106-1186, 1214-1215, 1232-1233, 313->315, 427->429, 432->433, 439->443, 459->461, 493->495, 497->498, 504->506, 509->514, 566->569, 597->603, 687->exit, 702->exit, 710->exit, 717->718, 727->732, 759->exit, 791->792, 795->796, 869->872, 1039->1043, 1047->1050, 1059->1060, 1066->1069, 1092->1093, 1213->1214
-src/allmydata/node.py                                  388     82    146     33    76%   120, 132, 190, 241, 243-245, 278, 284, 294-295, 303-306, 315, 320, 339, 341, 361, 393-396, 422, 449, 453, 490, 493, 500, 511-512, 548, 566, 574, 581, 583, 590-591, 601, 612, 629-633, 679, 681, 738-741, 747, 756, 764, 792-805, 808-809, 814-815, 827-846, 189->190, 240->241, 242->243, 277->278, 314->315, 319->320, 338->339, 340->341, 360->361, 391->393, 421->422, 448->449, 451->453, 489->490, 492->493, 499->500, 510->511, 547->548, 565->566, 573->574, 580->581, 582->583, 589->590, 600->601, 611->612, 622->629, 673->679, 680->681, 737->738, 746->747, 763->764, 821->830, 823->821
+src/allmydata/node.py                                  388     66    146     33    80%   120, 132, 190, 241, 243-245, 278, 284, 294-295, 303-306, 315, 320, 339, 341, 361, 393-396, 422, 449, 453, 490, 493, 500, 511-512, 548, 566, 574, 581, 583, 590-591, 601, 612, 629-633, 679, 681, 741, 747, 756, 764, 792-805, 808-809, 814-815, 832, 837, 189->190, 240->241, 242->243, 277->278, 314->315, 319->320, 338->339, 340->341, 360->361, 391->393, 421->422, 448->449, 451->453, 489->490, 492->493, 499->500, 510->511, 547->548, 565->566, 573->574, 580->581, 582->583, 589->590, 600->601, 611->612, 622->629, 673->679, 680->681, 746->747, 763->764, 823->821, 831->832, 835->837
 src/allmydata/nodemaker.py                              97     23     38     10    70%   49, 61, 66, 70, 81, 94, 107-115, 130-138, 141-150, 57->61, 65->66, 69->70, 79->81, 86->95, 90->94, 104->107, 124->exit, 129->130, 129->133
 src/allmydata/scripts/admin.py                          51     20      2      1    60%   9-14, 25, 28, 31-37, 40-46, 57, 59, 61-66, 56->57
 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
@@ -8837,7 +8831,7 @@
 src/allmydata/storage/common.py                         24      1      4      2    89%   11, 10->11, 36->39
 src/allmydata/storage/crawler.py                       222      1     64      3    99%   16, 13->16, 96->99, 496->505
 src/allmydata/storage/expirer.py                       240      1     81      2    99%   9, 7->9, 250->exitp
-src/allmydata/storage/immutable.py                     198      2     48      6    97%   12, 101, 11->12, 100->101, 142->140, 155->160, 187->197, 273->exit
+src/allmydata/storage/immutable.py                     198      1     48      5    98%   12, 11->12, 142->140, 155->160, 187->197, 273->exit
 src/allmydata/storage/lease.py                          35      1      4      1    95%   12, 11->12
 src/allmydata/storage/mutable.py                       289      8     90      6    96%   12, 162, 252, 289, 362-367, 11->12, 160->162, 247->252, 307->311, 354->362, 448->exit
 src/allmydata/storage/server.py                        371      9    120      9    96%   13, 92, 222, 243, 329, 349, 375, 422-423, 10->13, 91->92, 221->222, 241->243, 289->300, 317->329, 325->305, 346->349, 374->375
@@ -8899,7 +8893,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                                                27477  11798   8244    605    54%
+TOTAL                                                27477  11768   8244    601    54%

 18 files skipped due to complete coverage.
 + '[' '!' -z 1 ']'
```
2020-10-04 20:56:14 -07:00
Ross Patterson
baa36157b6 feat(py3): Update Python internal data model refs
As of Python 2.7, some of [the `func_*` and `im_*` attributes also can be accessed
through their corresponding `__*__` attributes for Python 3
compatibility](https://docs.python.org/2/reference/datamodel.html?highlight=__self__#the-standard-type-hierarchy).
I searched for all such occurrences and this is all that needed changing AFAICT.

Converts 9 test errors to errors with new exceptions and improves Python 3 test coverage
a smidge:

```diff
--- ../../.tox/make-test-py3-all-old.log	2020-10-04 15:16:34.054975263 -0700
+++ ../../.tox/make-test-py3-all-new.log	2020-10-04 15:59:59.355692613 -0700
@@ -2273,9 +2273,9 @@
     node.Node.__init__(self, config, main_tub, control_tub, i2p_provider, tor_provider)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 734, in __init__
     self.setup_logging()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 824, in setup_logging
-    ob = o.im_self
-builtins.AttributeError: 'function' object has no attribute 'im_self'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 826, in setup_logging
+    newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__)
+builtins.AttributeError: module 'types' has no attribute 'UnboundMethodType'

 allmydata.test.test_node.IntroducerNotListening.test_port_none_introducer
@@ -5935,9 +5935,9 @@
     node.Node.__init__(self, config, main_tub, control_tub, i2p_provider, tor_provider)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 734, in __init__
     self.setup_logging()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 824, in setup_logging
-    ob = o.im_self
-builtins.AttributeError: 'function' object has no attribute 'im_self'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 826, in setup_logging
+    newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__)
+builtins.AttributeError: module 'types' has no attribute 'UnboundMethodType'

 allmydata.test.test_client.Basic.test_web_apiauthtoken
 ===============================================================================
@@ -7146,9 +7146,9 @@
     node.Node.__init__(self, config, main_tub, control_tub, i2p_provider, tor_provider)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 734, in __init__
     self.setup_logging()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 824, in setup_logging
-    ob = o.im_self
-AttributeError: 'function' object has no attribute 'im_self'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 826, in setup_logging
+    newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__)
+AttributeError: module 'types' has no attribute 'UnboundMethodType'

 allmydata.test.test_introducer.Node.test_create
@@ -7171,9 +7171,9 @@
     node.Node.__init__(self, config, main_tub, control_tub, i2p_provider, tor_provider)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 734, in __init__
     self.setup_logging()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 824, in setup_logging
-    ob = o.im_self
-AttributeError: 'function' object has no attribute 'im_self'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 826, in setup_logging
+    newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__)
+AttributeError: module 'types' has no attribute 'UnboundMethodType'

 allmydata.test.test_introducer.Node.test_furl
@@ -7550,9 +7550,9 @@
     node.Node.__init__(self, config, main_tub, control_tub, i2p_provider, tor_provider)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 734, in __init__
     self.setup_logging()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 824, in setup_logging
-    ob = o.im_self
-builtins.AttributeError: 'function' object has no attribute 'im_self'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 826, in setup_logging
+    newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__)
+builtins.AttributeError: module 'types' has no attribute 'UnboundMethodType'

 allmydata.test.test_node.TestCase.test_logdir_is_str
 ===============================================================================
@@ -8448,9 +8448,9 @@
     node.Node.__init__(self, config, main_tub, control_tub, i2p_provider, tor_provider)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 734, in __init__
     self.setup_logging()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 824, in setup_logging
-    ob = o.im_self
-builtins.AttributeError: 'function' object has no attribute 'im_self'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 826, in setup_logging
+    newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__)
+builtins.AttributeError: module 'types' has no attribute 'UnboundMethodType'

 allmydata.test.test_system.Connections.test_rref
 allmydata.test.test_system.SystemTest.test_filesystem
@@ -8567,9 +8567,9 @@
     node.Node.__init__(self, config, main_tub, control_tub, i2p_provider, tor_provider)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 734, in __init__
     self.setup_logging()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 824, in setup_logging
-    ob = o.im_self
-builtins.AttributeError: 'function' object has no attribute 'im_self'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 826, in setup_logging
+    newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__)
+builtins.AttributeError: module 'types' has no attribute 'UnboundMethodType'

 allmydata.test.web.test_introducer.IntroducerWeb.test_basic_information
 ===============================================================================
@@ -8589,9 +8589,9 @@
     node.Node.__init__(self, config, main_tub, control_tub, i2p_provider, tor_provider)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 734, in __init__
     self.setup_logging()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 824, in setup_logging
-    ob = o.im_self
-builtins.AttributeError: 'function' object has no attribute 'im_self'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 826, in setup_logging
+    newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__)
+builtins.AttributeError: module 'types' has no attribute 'UnboundMethodType'

 allmydata.test.web.test_introducer.IntroducerWeb.test_json_front_page
 ===============================================================================
@@ -8611,9 +8611,9 @@
     node.Node.__init__(self, config, main_tub, control_tub, i2p_provider, tor_provider)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 734, in __init__
     self.setup_logging()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 824, in setup_logging
-    ob = o.im_self
-builtins.AttributeError: 'function' object has no attribute 'im_self'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 826, in setup_logging
+    newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__)
+builtins.AttributeError: module 'types' has no attribute 'UnboundMethodType'

 allmydata.test.web.test_introducer.IntroducerWeb.test_tahoe_css
 ===============================================================================
@@ -8633,9 +8633,9 @@
     node.Node.__init__(self, config, main_tub, control_tub, i2p_provider, tor_provider)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 734, in __init__
     self.setup_logging()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 824, in setup_logging
-    ob = o.im_self
-builtins.AttributeError: 'function' object has no attribute 'im_self'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 826, in setup_logging
+    newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__)
+builtins.AttributeError: module 'types' has no attribute 'UnboundMethodType'

 allmydata.test.web.test_introducer.IntroducerWeb.test_welcome
 ===============================================================================
@@ -8742,9 +8742,9 @@
     node.Node.__init__(self, config, main_tub, control_tub, i2p_provider, tor_provider)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 734, in __init__
     self.setup_logging()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 824, in setup_logging
-    ob = o.im_self
-builtins.AttributeError: 'function' object has no attribute 'im_self'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 826, in setup_logging
+    newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__)
+builtins.AttributeError: module 'types' has no attribute 'UnboundMethodType'
 + test_exit=1
 + ./.tox/py36-coverage/bin/coverage combine
 + ./.tox/py36-coverage/bin/coverage html
@@ -8802,7 +8802,7 @@
 src/allmydata/mutable/repairer.py                       57     37     18      0    29%   13, 15, 17, 19, 29-34, 65-71, 74-126, 129-131
 src/allmydata/mutable/retrieve.py                      489    123    120     33    71%   46, 48, 50, 52, 56, 58, 60, 62, 64, 89-90, 133, 186-193, 204-208, 211-212, 224-226, 231, 240, 251, 312, 318, 344-354, 377, 385-386, 399-400, 425-434, 490, 501, 515-516, 529-540, 564-578, 591-592, 629-630, 653-654, 674-675, 681-682, 698, 712-729, 758-760, 765, 772-774, 790-792, 871, 883, 909-910, 919-941, 965-966, 981-994, 999-1005, 129->133, 167->169, 169->171, 201->204, 223->224, 230->231, 237->239, 239->240, 243->247, 249->251, 309->312, 317->318, 376->377, 381->385, 391->394, 396->399, 424->425, 489->490, 499->501, 514->515, 590->591, 628->629, 652->653, 673->674, 677->687, 680->681, 687->694, 694->698, 755->764, 764->765, 868->871, 880->883, 964->965
 src/allmydata/mutable/servermap.py                     612    240    186     26    56%   45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 74, 130-139, 142, 148, 159-161, 175, 177, 183, 186-199, 206, 213, 217-220, 231, 234-238, 243-252, 255-259, 315, 328-350, 358-363, 370-372, 379, 429, 433, 443-447, 495, 498, 506-508, 514-516, 569-570, 603-611, 623-638, 718-721, 732-741, 792, 796, 803-804, 850-851, 872-874, 911-915, 929-945, 961-975, 982-999, 1003-1013, 1043-1045, 1050-1052, 1060-1064, 1069-1070, 1093-1100, 1106-1186, 1214-1215, 1232-1233, 313->315, 427->429, 432->433, 439->443, 459->461, 493->495, 497->498, 504->506, 509->514, 566->569, 597->603, 687->exit, 702->exit, 710->exit, 717->718, 727->732, 759->exit, 791->792, 795->796, 869->872, 1039->1043, 1047->1050, 1059->1060, 1066->1069, 1092->1093, 1213->1214
-src/allmydata/node.py                                  388     84    146     33    75%   120, 132, 190, 241, 243-245, 278, 284, 294-295, 303-306, 315, 320, 339, 341, 361, 393-396, 422, 449, 453, 490, 493, 500, 511-512, 548, 566, 574, 581, 583, 590-591, 601, 612, 629-633, 679, 681, 738-741, 747, 756, 764, 792-805, 808-809, 814-815, 825-846, 189->190, 240->241, 242->243, 277->278, 314->315, 319->320, 338->339, 340->341, 360->361, 391->393, 421->422, 448->449, 451->453, 489->490, 492->493, 499->500, 510->511, 547->548, 565->566, 573->574, 580->581, 582->583, 589->590, 600->601, 611->612, 622->629, 673->679, 680->681, 737->738, 746->747, 763->764, 821->830, 823->821
+src/allmydata/node.py                                  388     82    146     33    76%   120, 132, 190, 241, 243-245, 278, 284, 294-295, 303-306, 315, 320, 339, 341, 361, 393-396, 422, 449, 453, 490, 493, 500, 511-512, 548, 566, 574, 581, 583, 590-591, 601, 612, 629-633, 679, 681, 738-741, 747, 756, 764, 792-805, 808-809, 814-815, 827-846, 189->190, 240->241, 242->243, 277->278, 314->315, 319->320, 338->339, 340->341, 360->361, 391->393, 421->422, 448->449, 451->453, 489->490, 492->493, 499->500, 510->511, 547->548, 565->566, 573->574, 580->581, 582->583, 589->590, 600->601, 611->612, 622->629, 673->679, 680->681, 737->738, 746->747, 763->764, 821->830, 823->821
 src/allmydata/nodemaker.py                              97     23     38     10    70%   49, 61, 66, 70, 81, 94, 107-115, 130-138, 141-150, 57->61, 65->66, 69->70, 79->81, 86->95, 90->94, 104->107, 124->exit, 129->130, 129->133
 src/allmydata/scripts/admin.py                          51     20      2      1    60%   9-14, 25, 28, 31-37, 40-46, 57, 59, 61-66, 56->57
 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
@@ -8899,7 +8899,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                                                27477  11800   8244    605    54%
+TOTAL                                                27477  11798   8244    605    54%

 18 files skipped due to complete coverage.
 + '[' '!' -z 1 ']'
```
2020-10-04 16:01:32 -07:00
Ross Patterson
b2332b5bf1 fix(py3): Duplicate section name that py3 catches
Python 3 raises an exception that Python 2 doesn't and as such exposes malformed cfg/ini
contents used in the tests.

The test output diff shows that this mostly converts test `DuplicateSectionError` errors
to test errors with different exceptions which is reasonable for the type of fix this
is.  It does seem to reduce coverage which I'm guessing is because the malformed
contents were triggering error handling code paths that aren't triggered now, but I
haven't confirmed that.  I would think that to cover those cases we should write tests
that do that explicitly rather than accidentally.

```diff
--- ../../.tox/make-test-py3-all-old.log	2020-10-04 15:13:09.670578482 -0700
+++ ../../.tox/make-test-py3-all-new.log	2020-10-04 15:16:34.054975263 -0700
@@ -1835,7 +1835,7 @@
     raise self.failureException(msg)
 twisted.trial.unittest.FailTest: ['allmydata', 'allmydata.__main__', 'allm[5873 chars]try'] != set() : Some unported modules remain:
 Ported files: 96 / 292
-Ported lines: 27978 / 93480
+Ported lines: 27978 / 93482

 allmydata.test.test_python3.Python3PortingEffortTests.test_finished_porting
@@ -2166,11 +2166,11 @@
     result = result.throwExceptionIntoGenerator(g)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/python/failure.py", line 512, in throwExceptionIntoGenerator
     return g.throw(self.type, self.value, self.tb)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 685, in test_disabled_but_helper
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 687, in test_disabled_but_helper
     yield client.create_client(basedir)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/trial/_synctest.py", line 355, in __exit__
     self._expectedName, reason.getTraceback()),
-twisted.trial.unittest.FailTest: configparser.DuplicateSectionError raised instead of ValueError:
+twisted.trial.unittest.FailTest: builtins.NameError raised instead of ValueError:
  Traceback (most recent call last):
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/internet/defer.py", line 1529, in _cancellableInlineCallbacks
     _inlineCallbacks(None, g, status)
@@ -2178,12 +2178,12 @@
     result = result.throwExceptionIntoGenerator(g)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/python/failure.py", line 512, in throwExceptionIntoGenerator
     return g.throw(self.type, self.value, self.tb)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 685, in test_disabled_but_helper
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 687, in test_disabled_but_helper
     yield client.create_client(basedir)
 --- <exception caught here> ---
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 685, in test_disabled_but_helper
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 687, in test_disabled_but_helper
     yield client.create_client(basedir)
-configparser.DuplicateSectionError: While reading from '/home/rpatterson/src/work/sfu/tahoe-lafs/_trial_temp/test_node/test_disabled_but_helper/tahoe.cfg' [line 10]: section 'node' already exists
+builtins.NameError: name 'unicode' is not defined

 allmydata.test.test_node.ClientNotListening.test_disabled_but_helper
@@ -2194,11 +2194,11 @@
     result = result.throwExceptionIntoGenerator(g)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/python/failure.py", line 512, in throwExceptionIntoGenerator
     return g.throw(self.type, self.value, self.tb)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 668, in test_disabled_but_storage
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 670, in test_disabled_but_storage
     yield client.create_client(basedir)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/trial/_synctest.py", line 355, in __exit__
     self._expectedName, reason.getTraceback()),
-twisted.trial.unittest.FailTest: configparser.DuplicateSectionError raised instead of ValueError:
+twisted.trial.unittest.FailTest: builtins.NameError raised instead of ValueError:
  Traceback (most recent call last):
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/internet/defer.py", line 1529, in _cancellableInlineCallbacks
     _inlineCallbacks(None, g, status)
@@ -2206,12 +2206,12 @@
     result = result.throwExceptionIntoGenerator(g)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/python/failure.py", line 512, in throwExceptionIntoGenerator
     return g.throw(self.type, self.value, self.tb)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 668, in test_disabled_but_storage
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 670, in test_disabled_but_storage
     yield client.create_client(basedir)
 --- <exception caught here> ---
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 668, in test_disabled_but_storage
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 670, in test_disabled_but_storage
     yield client.create_client(basedir)
-configparser.DuplicateSectionError: While reading from '/home/rpatterson/src/work/sfu/tahoe-lafs/_trial_temp/test_node/test_disabled_but_storage/tahoe.cfg' [line 10]: section 'node' already exists
+builtins.NameError: name 'unicode' is not defined

 allmydata.test.test_node.ClientNotListening.test_disabled_but_storage
@@ -2222,7 +2222,7 @@
     result = result.throwExceptionIntoGenerator(g)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/python/failure.py", line 512, in throwExceptionIntoGenerator
     return g.throw(self.type, self.value, self.tb)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 739, in test_create_client_invalid_config
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 741, in test_create_client_invalid_config
     yield client.create_client(self.basedir)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/trial/_synctest.py", line 355, in __exit__
     self._expectedName, reason.getTraceback()),
@@ -2234,10 +2234,10 @@
     result = result.throwExceptionIntoGenerator(g)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/python/failure.py", line 512, in throwExceptionIntoGenerator
     return g.throw(self.type, self.value, self.tb)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 739, in test_create_client_invalid_config
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 741, in test_create_client_invalid_config
     yield client.create_client(self.basedir)
 --- <exception caught here> ---
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 739, in test_create_client_invalid_config
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 741, in test_create_client_invalid_config
     yield client.create_client(self.basedir)
 builtins.TypeError: startswith first arg must be str or a tuple of str, not bytes

@@ -2250,7 +2250,7 @@
     result = result.throwExceptionIntoGenerator(g)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/python/failure.py", line 512, in throwExceptionIntoGenerator
     return g.throw(self.type, self.value, self.tb)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 702, in test_port_none_introducer
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 704, in test_port_none_introducer
     yield create_introducer(basedir)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/trial/_synctest.py", line 355, in __exit__
     self._expectedName, reason.getTraceback()),
@@ -2262,10 +2262,10 @@
     result = result.throwExceptionIntoGenerator(g)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/python/failure.py", line 512, in throwExceptionIntoGenerator
     return g.throw(self.type, self.value, self.tb)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 702, in test_port_none_introducer
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 704, in test_port_none_introducer
     yield create_introducer(basedir)
 --- <exception caught here> ---
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 702, in test_port_none_introducer
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 704, in test_port_none_introducer
     yield create_introducer(basedir)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/introducer/server.py", line 76, in create_introducer
     tor_provider,
@@ -7432,23 +7432,17 @@
 ===============================================================================
 [ERROR]
 Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 655, in test_disabled
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 657, in test_disabled
     n = yield client.create_client(basedir)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/client.py", line 243, in create_client
-    config = read_config(basedir, u"client.port")
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/client.py", line 219, in read_config
-    _valid_config=_valid_config(),
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 187, in read_config
-    parser = configutil.get_config(config_fname)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/util/configutil.py", line 50, in get_config
-    config.readfp(f)
-  File "/usr/lib/python3.6/configparser.py", line 764, in readfp
-    self.read_file(fp, source=filename)
-  File "/usr/lib/python3.6/configparser.py", line 718, in read_file
-    self._read(f, source)
-  File "/usr/lib/python3.6/configparser.py", line 1067, in _read
-    lineno)
-configparser.DuplicateSectionError: While reading from '/home/rpatterson/src/work/sfu/tahoe-lafs/_trial_temp/test_node/test_disabled/tahoe.cfg' [line 10]: section 'node' already exists
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/internet/defer.py", line 1418, in _inlineCallbacks
+    result = g.send(result)
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/client.py", line 285, in create_client_from_config
+    introducer_clients = create_introducer_clients(config, main_tub, _introducer_factory)
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/client.py", line 519, in create_introducer_clients
+    introducer_cache_filepath,
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/introducer/client.py", line 29, in __init__
+    assert type(nickname) is unicode
+builtins.NameError: name 'unicode' is not defined

 allmydata.test.test_node.ClientNotListening.test_disabled
 ===============================================================================
@@ -7456,7 +7450,7 @@
 Traceback (most recent call last):
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 577, in test_listen_on_zero
     t = FakeTub()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 549, in __init__
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 548, in __init__
     self.tubID = base64.b32encode("foo")
   File "/usr/lib/python3.6/base64.py", line 154, in b32encode
     s = memoryview(s).tobytes()
@@ -7466,9 +7460,9 @@
 ===============================================================================
 [ERROR]
 Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 605, in test_multiple_ports
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 606, in test_multiple_ports
     t = FakeTub()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 549, in __init__
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 548, in __init__
     self.tubID = base64.b32encode("foo")
   File "/usr/lib/python3.6/base64.py", line 154, in b32encode
     s = memoryview(s).tobytes()
@@ -7478,9 +7472,9 @@
 ===============================================================================
 [ERROR]
 Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 624, in test_tor_i2p_listeners
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 626, in test_tor_i2p_listeners
     t = FakeTub()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 549, in __init__
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 548, in __init__
     self.tubID = base64.b32encode("foo")
   File "/usr/lib/python3.6/base64.py", line 154, in b32encode
     s = memoryview(s).tobytes()
@@ -8781,11 +8775,11 @@
 src/allmydata/immutable/downloader/__init__.py           7      1      2      1    78%   12, 11->12
 src/allmydata/immutable/downloader/common.py            14      1      2      1    88%   12, 11->12
 src/allmydata/immutable/downloader/fetcher.py          147      1     56      1    99%   12, 11->12
-src/allmydata/immutable/downloader/finder.py           143      9     40      5    92%   11, 88-89, 108, 115, 170-173, 10->11, 87->88, 107->108, 113->115, 165->exit
+src/allmydata/immutable/downloader/finder.py           143     11     40      5    91%   11, 88-89, 108, 115, 170-173, 231-232, 10->11, 87->88, 107->108, 113->115, 165->exit
 src/allmydata/immutable/downloader/node.py             282      9     66      9    94%   11, 170-172, 224-235, 271, 10->11, 43->exit, 60->68, 165->169, 169->170, 256->exit, 270->271, 517->exit, 537->exit
 src/allmydata/immutable/downloader/segmentation.py     118      1     22      1    99%   11, 10->11
-src/allmydata/immutable/downloader/share.py            453     15    154      8    96%   11, 210, 248-250, 354, 430-437, 518, 722-725, 862, 10->11, 209->210, 239->248, 352->354, 515->518, 660->663, 710->722, 762->exit
-src/allmydata/immutable/downloader/status.py           154      9     36      1    95%   11, 223, 226, 230, 232, 234, 274, 285, 287, 10->11
+src/allmydata/immutable/downloader/share.py            453     23    154     11    94%   11, 210, 239-250, 289-290, 354, 399-400, 430-437, 518, 722-725, 775, 862, 10->11, 209->210, 222->239, 288->289, 352->354, 397->399, 515->518, 660->663, 710->722, 762->exit, 774->775
+src/allmydata/immutable/downloader/status.py           154     12     36      1    93%   11, 65-67, 223, 226, 230, 232, 234, 274, 285, 287, 10->11
 src/allmydata/immutable/encode.py                      421     13    124     10    95%   114, 197-200, 278-280, 405, 412, 462, 509, 562, 687, 102->104, 113->114, 195->197, 404->405, 411->412, 461->462, 499->509, 505->511, 561->562, 685->687
 src/allmydata/immutable/filenode.py                    196     48     30      5    72%   77-78, 83, 85, 88, 94-101, 104-124, 127-172, 254, 258, 315, 40->42, 224->227, 227->229, 251->254, 257->258
 src/allmydata/immutable/happiness_upload.py            214      1    132      3    99%   15, 13->15, 213->211, 280->279
@@ -8808,7 +8802,7 @@
 src/allmydata/mutable/repairer.py                       57     37     18      0    29%   13, 15, 17, 19, 29-34, 65-71, 74-126, 129-131
 src/allmydata/mutable/retrieve.py                      489    123    120     33    71%   46, 48, 50, 52, 56, 58, 60, 62, 64, 89-90, 133, 186-193, 204-208, 211-212, 224-226, 231, 240, 251, 312, 318, 344-354, 377, 385-386, 399-400, 425-434, 490, 501, 515-516, 529-540, 564-578, 591-592, 629-630, 653-654, 674-675, 681-682, 698, 712-729, 758-760, 765, 772-774, 790-792, 871, 883, 909-910, 919-941, 965-966, 981-994, 999-1005, 129->133, 167->169, 169->171, 201->204, 223->224, 230->231, 237->239, 239->240, 243->247, 249->251, 309->312, 317->318, 376->377, 381->385, 391->394, 396->399, 424->425, 489->490, 499->501, 514->515, 590->591, 628->629, 652->653, 673->674, 677->687, 680->681, 687->694, 694->698, 755->764, 764->765, 868->871, 880->883, 964->965
 src/allmydata/mutable/servermap.py                     612    240    186     26    56%   45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 74, 130-139, 142, 148, 159-161, 175, 177, 183, 186-199, 206, 213, 217-220, 231, 234-238, 243-252, 255-259, 315, 328-350, 358-363, 370-372, 379, 429, 433, 443-447, 495, 498, 506-508, 514-516, 569-570, 603-611, 623-638, 718-721, 732-741, 792, 796, 803-804, 850-851, 872-874, 911-915, 929-945, 961-975, 982-999, 1003-1013, 1043-1045, 1050-1052, 1060-1064, 1069-1070, 1093-1100, 1106-1186, 1214-1215, 1232-1233, 313->315, 427->429, 432->433, 439->443, 459->461, 493->495, 497->498, 504->506, 509->514, 566->569, 597->603, 687->exit, 702->exit, 710->exit, 717->718, 727->732, 759->exit, 791->792, 795->796, 869->872, 1039->1043, 1047->1050, 1059->1060, 1066->1069, 1092->1093, 1213->1214
-src/allmydata/node.py                                  388     84    146     34    75%   120, 132, 190, 241, 243-245, 278, 284, 294-295, 303-306, 315, 320, 339, 341, 361, 393-396, 422, 449, 453, 490, 493, 500, 511-512, 548, 566, 574, 581, 583, 590-591, 601, 612, 629-633, 679, 681, 738-741, 747, 756, 764, 792-805, 808-809, 814-815, 825-846, 189->190, 240->241, 242->243, 277->278, 314->315, 319->320, 338->339, 340->341, 360->361, 391->393, 421->422, 448->449, 451->453, 489->490, 492->493, 499->500, 510->511, 537->535, 547->548, 565->566, 573->574, 580->581, 582->583, 589->590, 600->601, 611->612, 622->629, 673->679, 680->681, 737->738, 746->747, 763->764, 821->830, 823->821
+src/allmydata/node.py                                  388     84    146     33    75%   120, 132, 190, 241, 243-245, 278, 284, 294-295, 303-306, 315, 320, 339, 341, 361, 393-396, 422, 449, 453, 490, 493, 500, 511-512, 548, 566, 574, 581, 583, 590-591, 601, 612, 629-633, 679, 681, 738-741, 747, 756, 764, 792-805, 808-809, 814-815, 825-846, 189->190, 240->241, 242->243, 277->278, 314->315, 319->320, 338->339, 340->341, 360->361, 391->393, 421->422, 448->449, 451->453, 489->490, 492->493, 499->500, 510->511, 547->548, 565->566, 573->574, 580->581, 582->583, 589->590, 600->601, 611->612, 622->629, 673->679, 680->681, 737->738, 746->747, 763->764, 821->830, 823->821
 src/allmydata/nodemaker.py                              97     23     38     10    70%   49, 61, 66, 70, 81, 94, 107-115, 130-138, 141-150, 57->61, 65->66, 69->70, 79->81, 86->95, 90->94, 104->107, 124->exit, 129->130, 129->133
 src/allmydata/scripts/admin.py                          51     20      2      1    60%   9-14, 25, 28, 31-37, 40-46, 57, 59, 61-66, 56->57
 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
@@ -8843,7 +8837,7 @@
 src/allmydata/storage/common.py                         24      1      4      2    89%   11, 10->11, 36->39
 src/allmydata/storage/crawler.py                       222      1     64      3    99%   16, 13->16, 96->99, 496->505
 src/allmydata/storage/expirer.py                       240      1     81      2    99%   9, 7->9, 250->exit
-src/allmydata/storage/immutable.py                     198      1     48      5    98%   12, 11->12, 142->140, 155->160, 187->197, 273->exit
+src/allmydata/storage/immutable.py                     198      2     48      6    97%   12, 101, 11->12, 100->101, 142->140, 155->160, 187->197, 273->exit
 src/allmydata/storage/lease.py                          35      1      4      1    95%   12, 11->12
 src/allmydata/storage/mutable.py                       289      8     90      6    96%   12, 162, 252, 289, 362-367, 11->12, 160->162, 247->252, 307->311, 354->362, 448->exit
 src/allmydata/storage/server.py                        371      9    120      9    96%   13, 92, 222, 243, 329, 349, 375, 422-423, 10->13, 91->92, 221->222, 241->243, 289->300, 317->329, 325->305, 346->349, 374->375
@@ -8905,7 +8899,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                                                27477  11786   8244    602    54%
+TOTAL                                                27477  11800   8244    605    54%

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

Trac: refs #3455
2020-10-04 15:57:01 -07:00
Ross Patterson
447881a0e0 feat(py3): Cleanup redundant string cast
I confirmed that `add_version(...)` itself calls `str(...)` on the argument that
`things_version` is passed in to under both the Python 2.7 and Python 3.6 version of the
library so this is unnecessary here.

This results in an empty diff in py3 tests output.
2020-10-04 15:57:01 -07:00
Ross Patterson
3f297bf0e3 feat(py3): Fix test runner exception
The exception this addresses was preventing the test runner from running to completion
under Python 3, thus preventing using the full test suite to evaluate the impact of
porting efforts.

This change causes no regressions in the test suite under python 2.7 and only affects
tests AFAICT.  I added debug logging to check all the strings that seem to make it to
that point and I didn't see anything that looked like it needed to be decoded in
particular, so I think this change is relatively safe.

The traceback for reference

```
Traceback (most recent call last):
  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36/bin/trial", line 8, in <module>
    sys.exit(run())
  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36/lib/python3.6/site-packages/twisted/scripts/trial.py", line 621, in run
    test_result = trialRunner.run(suite)
  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36/lib/python3.6/site-packages/twisted/trial/runner.py", line 998, in run
    return self._runWithoutDecoration(test, self._forceGarbageCollection)
  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36/lib/python3.6/site-packages/twisted/trial/runner.py", line 1025, in _runWithoutDecoration
    run()
  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36/lib/python3.6/site-packages/twisted/trial/runner.py", line 1020, in <lambda>
    run = lambda: suite.run(result)
  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36/lib/python3.6/site-packages/twisted/trial/runner.py", line 253, in run
    TestSuite.run(self, result)
  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36/lib/python3.6/site-packages/twisted/trial/_asyncrunner.py", line 38, in run
    test(result)
  File "/usr/lib/python3.6/unittest/suite.py", line 84, in __call__
    return self.run(*args, **kwds)
  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36/lib/python3.6/site-packages/twisted/trial/runner.py", line 212, in run
    super(LoggedSuite, self).run(result)
  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36/lib/python3.6/site-packages/twisted/trial/_asyncrunner.py", line 38, in run
    test(result)
  File "/usr/lib/python3.6/unittest/suite.py", line 84, in __call__
    return self.run(*args, **kwds)
  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36/lib/python3.6/site-packages/twisted/trial/runner.py", line 185, in run
    test(result)
  File "/usr/lib/python3.6/unittest/suite.py", line 84, in __call__
    return self.run(*args, **kwds)
  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36/lib/python3.6/site-packages/twisted/trial/runner.py", line 185, in run
    test(result)
  File "/usr/lib/python3.6/unittest/suite.py", line 84, in __call__
    return self.run(*args, **kwds)
  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36/lib/python3.6/site-packages/twisted/trial/runner.py", line 185, in run
    test(result)
  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36/lib/python3.6/site-packages/twisted/trial/_asyncrunner.py", line 59, in __call__
    return self.run(result)
  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36/lib/python3.6/site-packages/twisted/trial/_asyncrunner.py", line 69, in run
    reporter._AdaptedReporter(result, self.__class__))
  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36/lib/python3.6/site-packages/testtools/testcase.py", line 675, in run
    return run_test.run(result)
  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/eliotutil.py", line 110, in run_and_republish
    with RUN_TEST(name=self.id().decode("utf-8")).context() as action:
AttributeError: 'str' object has no attribute 'decode'
```
2020-10-04 15:57:01 -07:00
Jean-Paul Calderone
36c9bebf3d Construct the new NativeStorageServer after deciding we need it
... not before.
2020-10-02 13:49:36 -04:00
Jean-Paul Calderone
5cd7703c83 reduce the amount of unnecessary UTF-8 encoding and decoding 2020-10-02 11:57:27 -04:00
Itamar Turner-Trauring
963f9ba94b Closer to passing tests. 2020-10-02 11:01:24 -04:00
Itamar Turner-Trauring
f8f8329d70 More passing tests on Python 3. 2020-10-02 10:48:54 -04:00
Itamar Turner-Trauring
1088e5368d A little progress on passing tests. 2020-10-02 10:42:44 -04:00
Itamar Turner-Trauring
ade4a5a543 As far as I can tell, none of the IServer implementations actually implement comparison methods. 2020-10-02 10:42:32 -04:00
Itamar Turner-Trauring
18e1c290a7 Reorganize code so allmydata.web.check_results can import without Nevow being installed. 2020-10-02 10:28:55 -04:00
Ross Patterson
8355e0b712 Merge branch '3448.convert-only-unicode-to-str'
Trac: fixes #3448
2020-10-01 12:23:04 -07:00
Ross Patterson
ae1aab611d fix(py3): Match wiki porting conventions
Address feedback from PR pointing out that my python-future imports aren't matching the
conventions from the wiki.

Trac: refs #3448
2020-10-01 08:57:54 -07:00
Itamar Turner-Trauring
5899cfdabd Fix callRemote unicode issues on Python 2 universally, using monkeypatching. 2020-10-01 10:48:09 -04:00
Chad Whitacre
41fcd9673e Move SignalMixin and TimeMixin back to common_util
This concludes our service.
2020-09-30 23:31:33 -04:00
Chad Whitacre
93d4a8373f Move ReallyEqualMixin and s31e back to common_util
s31e = skip_if_cannot_represent_filename
2020-09-30 23:31:13 -04:00
Chad Whitacre
b75b48e68c Move FakeCanary to common_util
Couldn't bring myself to move it back to test_storage.
2020-09-30 23:29:08 -04:00
Chad Whitacre
23140b8b1c Move ShouldFailMixin back to common_util
There were originally two versions of this, one in common and another in
common_util. We moved both into common_py3 but then removed the one from
common, so here we move back to common_util, while allowing imports from
common to avoid a noisy changeset.
2020-09-30 23:01:46 -04:00
Chad Whitacre
2c2b61676c Move LoggingServiceParent back to common 2020-09-30 22:32:13 -04:00
Ross Patterson
fb87daad0b Merge branch 'master' into 3448.convert-only-unicode-to-str 2020-09-30 11:50:42 -07:00
Itamar Turner-Trauring
2fae4b06bf Fix Python 2 tests. 2020-09-30 14:12:48 -04:00
Itamar Turner-Trauring
4051a17313 Merge remote-tracking branch 'origin/master' into 3453.downloader-share-python-3 2020-09-30 13:28:18 -04:00
Itamar Turner-Trauring
6c72c8b77f Merge branch '3451.immutable-downloader-start-python-3' into 3452.immutable-downloader-more-python-3 2020-09-30 11:52:37 -04:00
Ross Patterson
362c121426 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
2020-09-30 08:47:02 -07:00
Itamar Turner-Trauring
d797ca1162 Merge remote-tracking branch 'origin/master' into 3451.immutable-downloader-start-python-3 2020-09-30 11:42:58 -04:00
Itamar Turner-Trauring
df69ca8b5b
Merge pull request #836 from tahoe-lafs/3450.immutable-literal-python-3
Port allmydata.immutable.literal to Python 3 (and fix a bug)

Fixes ticket:3450
2020-09-30 11:39:07 -04:00
Jean-Paul Calderone
751bc14521 Always make the todo message a native string.
If the todo message isn't a native string, trial ignores it completely.  Awesome.
2020-09-30 11:11:44 -04:00
Itamar Turner-Trauring
206f25d87e Port to Python 3. 2020-09-29 13:50:59 -04:00
Itamar Turner-Trauring
9eb6241c0a Fix lint. 2020-09-29 13:46:36 -04:00
Itamar Turner-Trauring
2a1e108722 Port to Python 3. 2020-09-29 11:29:49 -04:00
Itamar Turner-Trauring
867a1b71a1 Ported to Python 3. 2020-09-29 11:22:52 -04:00
Itamar Turner-Trauring
87838dd2bb
Merge pull request #834 from tahoe-lafs/3449.interfaces-to-python-3
Port allmydata.introducer.interfaces to Python 3

Fixes ticket:3449
2020-09-29 11:05:18 -04:00
Itamar Turner-Trauring
1fa724899b Port to Python 3. 2020-09-29 11:04:14 -04:00
Itamar Turner-Trauring
b721e3c5f2 Fix missing test coverage in fetcher.py. 2020-09-29 10:51:21 -04:00
Itamar Turner-Trauring
369cd98d5a Clarify what "JSON-serializable bytes" means. 2020-09-29 10:17:26 -04:00
Sajith Sasidharan
9c8fb6f901
Merge pull request #781 from sajith/3382.remove-multi-format-page
Remove web.common.MultiFormatPage

Fixes ticket:3382
2020-09-28 21:28:23 -04:00
Sajith Sasidharan
769f87c24d Remove unused import 2020-09-28 20:39:13 -04:00
Itamar Turner-Trauring
c84a2ef869
Merge pull request #835 from tahoe-lafs/3417.audit-for-loops-mutable-dict-views-python-3
Audit for loops for mutable dict views bugs on Python 3

Fixes ticket:3417
2020-09-28 16:53:12 -04:00
Itamar Turner-Trauring
f42634cfe7 Port to Python 3. 2020-09-28 16:51:29 -04:00
Itamar Turner-Trauring
e3a9f5fa75 Test and bugfix for LiteralFileNode equality. 2020-09-28 16:49:30 -04:00
Itamar Turner-Trauring
66c6522325 Unused code. 2020-09-28 16:44:50 -04:00
Itamar Turner-Trauring
7aa7716f3a Wrap with list(), just in case. 2020-09-28 15:44:29 -04:00
Itamar Turner-Trauring
66b4330ca2 Remove unused API. 2020-09-28 15:43:42 -04:00
Jean-Paul Calderone
76ecae2e44 Merge remote-tracking branch 'origin/master' into 3382.remove-multi-format-page 2020-09-28 15:09:29 -04:00
Jean-Paul Calderone
6d14eb55b5
Merge pull request #832 from tahoe-lafs/3443.referrer-policy-tests
Add a test for referrer-policy

Fixes: ticket:3443
2020-09-28 15:04:55 -04:00
Itamar Turner-Trauring
eb787ae540 Make items into list, just in case someone tries to merge object into itself. 2020-09-28 11:55:35 -04:00
Itamar Turner-Trauring
5e6201aede
Merge pull request #833 from tahoe-lafs/3446.test-helper-python-3
Port test_helper.py to Python 3

Fixes ticket:3446
2020-09-28 11:35:15 -04:00
Jean-Paul Calderone
a5686de460 Don't claim behavior about *all* pages 2020-09-28 10:26:00 -04:00
Itamar Turner-Trauring
64516aac41 Port to Python 3. 2020-09-28 10:20:00 -04:00
Itamar Turner-Trauring
d7b5230f0e Explain why __remote_name__ is a native string. 2020-09-28 10:06:06 -04:00
Itamar Turner-Trauring
f796b8a7da Fix typo. 2020-09-28 10:02:43 -04:00
Itamar Turner-Trauring
4e7e84796a
Merge pull request #829 from tahoe-lafs/3439.test-download-python-3
Port test_download.py to Python 3

Fixes ticket:3439
2020-09-28 09:59:53 -04:00
Chad Whitacre
afd28f3402
Merge pull request #823 from tahoe-lafs/3431.port-test_immutable
Port test_immutable to Python 3
2020-09-28 08:34:03 -04:00
Jean-Paul Calderone
60f531e970
Merge pull request #831 from tahoe-lafs/3438.test_introweb
Split `_test_introweb` into a separate suite

Fixes: ticket:3438
2020-09-27 19:14:24 -04:00
Itamar Turner-Trauring
21e3b355ec Finish porting to Python 3. 2020-09-25 14:03:25 -04:00
Itamar Turner-Trauring
d19ae1e511 Apparently __remote_name__ needs to be a native string. 2020-09-25 14:00:18 -04:00
Sajith Sasidharan
65f206e39b
Merge pull request #816 from sajith/3427.return-error-page-from-unlinked
Return ErrorPage from unlinked

Fixes ticket:3427
2020-09-25 13:30:02 -04:00
Itamar Turner-Trauring
565c48045e Closer to passing tests. 2020-09-25 13:28:59 -04:00
Itamar Turner-Trauring
d8c9affccb Bunch more places that need to be bytes for protocol backwards compatibility. 2020-09-25 13:28:49 -04:00
Itamar Turner-Trauring
9e5d5b5f8b Remove typo. 2020-09-25 13:16:47 -04:00
Itamar Turner-Trauring
47aa724c42 Merge remote-tracking branch 'origin/master' into 3439.test-download-python-3 2020-09-25 13:16:12 -04:00
Itamar Turner-Trauring
5e52691433
Merge pull request #827 from tahoe-lafs/3437.test-filenode-python-3
Port test_filenode.py to Python 3

Fixes ticket:3437
2020-09-25 13:15:30 -04:00
Sajith Sasidharan
569ac924ec
Merge pull request #825 from sajith/3436.remove-web-common-getxmlfile
Remove unused web.common.getxmlfile()

Fixes ticket:3436
2020-09-25 12:54:51 -04:00
Itamar Turner-Trauring
5d9a1a5ab5 Some progress towards passing tests. 2020-09-25 11:46:31 -04:00
Jean-Paul Calderone
8cdf5cbf26 unused import 2020-09-25 11:09:55 -04:00
Jean-Paul Calderone
2314a9f2f6 add a test for referrer-policy 2020-09-25 11:06:54 -04:00
Jean-Paul Calderone
3dddcd6f62 Remove assertions about Twisted Web's quoting behavior
It quotes stuff.  It's cool.  BeautifulSoup even looks at it for us and will
tell us if something is amiss.
2020-09-25 09:44:04 -04:00
Jean-Paul Calderone
dc15f19ee0 Merge remote-tracking branch 'origin/master' into 3382.remove-multi-format-page 2020-09-25 09:37:02 -04:00
Jean-Paul Calderone
44cc42351f remove duplicate request 2020-09-25 09:32:06 -04:00
Jean-Paul Calderone
05def35c26 nicer cleanup plus a comment 2020-09-25 09:31:57 -04:00
Jean-Paul Calderone
b218b5426b docstrings 2020-09-25 09:31:53 -04:00
Jean-Paul Calderone
dcb834c7a6 Merge remote-tracking branch 'origin/master' into 3438.test_introweb 2020-09-25 09:26:34 -04:00
Itamar Turner-Trauring
51709d5562
Merge pull request #817 from tahoe-lafs/3430-test-upload-python-3
Port test_upload.py to Python 3

Fixes ticket:3430
2020-09-24 16:57:38 -04:00
Jean-Paul Calderone
1c5f4e2bf0 Compatible with the interface I used in test_web.py 2020-09-24 11:08:18 -04:00
Jean-Paul Calderone
16ab1690de rewrite _test_introweb part of SystemTest as its own test suite 2020-09-24 11:08:18 -04:00
Jean-Paul Calderone
e981fea007 make FakeCanary more realistic 2020-09-24 11:08:18 -04:00
Itamar Turner-Trauring
26f28f341f Finish port to Python 3. 2020-09-24 11:03:42 -04:00
Itamar Turner-Trauring
8167a9fda6 All tests pass on Python 3. 2020-09-24 11:01:35 -04:00
Itamar Turner-Trauring
5cd00d6f2e And even more tests passing in Python 3. 2020-09-24 10:55:47 -04:00
Itamar Turner-Trauring
37bc022edc Even more tests passing on Python 3. 2020-09-24 10:46:10 -04:00
Jean-Paul Calderone
f1bcf4eb07 remove unused imports 2020-09-24 10:42:57 -04:00
Itamar Turner-Trauring
d9036e83b2 More tests passing on Python 3. 2020-09-24 10:39:06 -04:00
Itamar Turner-Trauring
e7fe2f0a3f It imports on Python 3. 2020-09-24 10:32:41 -04:00
Jean-Paul Calderone
e7101b1711 Turn exceptions into error pages like Nevow does 2020-09-24 10:23:05 -04:00
Jean-Paul Calderone
34bade4091 Use the newly introduced helper instead of our own internal thing 2020-09-24 10:22:07 -04:00
Jean-Paul Calderone
ed049da34f Add a helper that can render a Page or a Resource 2020-09-24 10:21:18 -04:00
Chad Whitacre
06cd64c891 De-lint 2020-09-23 21:41:23 -04:00
Chad Whitacre
3ae927eab9 Respond to review
- Preserve int division
- Dial back the __future__ imports
2020-09-23 21:18:24 -04:00
Itamar Turner-Trauring
5a2728fa05 Finish port to Python 3. 2020-09-23 15:56:09 -04:00
Itamar Turner-Trauring
5790ae8ece Tests pass on Python 3. 2020-09-23 15:53:13 -04:00
Sajith Sasidharan
c2e9d6057f
Merge pull request #819 from sajith/3425.return-errorpage-from-root
Return ErrorPage from web.root

Fixes ticket:3425
2020-09-23 10:18:44 -04:00
Chad Whitacre
42eaf08a52 Remove duplicate import 2020-09-23 08:32:34 -04:00
Sajith Sasidharan
a413eb8626 Use BeautifulSoup in RenderSlashUri tests 2020-09-23 08:32:19 -04:00
Chad Whitacre
d21046fe9f A couple more cleanups
- attempt the same future imports in both common and common_util
- put an import in a better place
2020-09-23 08:31:08 -04:00
Chad Whitacre
9fccf37053 Make new code more idiomatic 2020-09-23 08:24:39 -04:00
Chad Whitacre
de48dff981 Dial back future imports in common_util.py
Don't set the plow too deep.
2020-09-23 08:19:07 -04:00
Sajith Sasidharan
704b36d7e1 Remove test for web.common.getxmlfile() 2020-09-22 21:15:58 -04:00
Sajith Sasidharan
e6a5dda7e1 Rearrange imports 2020-09-22 21:14:00 -04:00
Sajith Sasidharan
22a1721b62 Remove unused web.common.getxmlfile() 2020-09-22 21:05:17 -04:00
Sajith Sasidharan
9aee312d8c
Merge pull request #822 from sajith/3429.return-errorpage-from-check-results
Return ErrorPage from web.check_results

Fixes ticket:3429
2020-09-22 20:40:00 -04:00
Sajith Sasidharan
4e4c5f9b7f
Merge pull request #820 from sajith/3424.return-errorpage-from-operations
Return ErrorPage from web.operations

Fixes ticket:3424
2020-09-22 20:38:34 -04:00
Sajith Sasidharan
da78bc05d0
Merge pull request #818 from sajith/3423.return-errorpage-from-filenode
Return ErrorPage from filenode

Fixes ticket:3423
2020-09-22 20:37:55 -04:00
Sajith Sasidharan
0f118bdd67 Return error page from unlinked 2020-09-22 12:23:40 -04:00
Chad Whitacre
0b6b4b69e9 Port test_immutable to Python 3 2020-09-22 08:36:39 -04:00
Sajith Sasidharan
136a70217c Remove unused import 2020-09-21 20:44:49 -04:00
Sajith Sasidharan
fd5436b867 Expect ErrorPage in RenderSlashUri tests 2020-09-21 18:34:53 -04:00
Sajith Sasidharan
18e56e41fc Return error page when an exception is raised from web.check_results 2020-09-21 18:18:29 -04:00
Sajith Sasidharan
20101f8146 Return ErrorPage when an exception is raised in web.status 2020-09-21 16:51:27 -04:00
Sajith Sasidharan
c16cf00c6b Return an error page when an exception is raised from web.root 2020-09-21 16:37:36 -04:00
Sajith Sasidharan
e8f7643a8f Return ErrorPage when web.operations raises an exception 2020-09-21 16:26:51 -04:00
Sajith Sasidharan
c34dc78875 Merge 'origin/master' into 3423.return-errorpage-from-filenode 2020-09-21 16:22:57 -04:00
Jean-Paul Calderone
58c99d0c0c
Merge pull request #815 from tahoe-lafs/3422.directory-weberror
Handle exceptions raised by getChild and render_* in directory.py

Fixes: ticket:3422
2020-09-21 16:04:39 -04:00
Jean-Paul Calderone
0e139114f7 add a limited amount of missing test coverage for humanize_exception 2020-09-21 14:07:11 -04:00
Sajith Sasidharan
199fbfcc1c Return error pages when an exception is raised in filenode 2020-09-21 13:24:01 -04:00
Itamar Turner-Trauring
40b4244146 Port to Python 3. 2020-09-21 13:21:19 -04:00
Itamar Turner-Trauring
6fe68c792c Tests pass on Python 2 and 3. 2020-09-21 13:21:19 -04:00
Itamar Turner-Trauring
0cee40c009 Even more progress towards test_upload on Python 3. 2020-09-21 13:21:19 -04:00
Itamar Turner-Trauring
125a6855d6 More progress towards test_upload on Python 3. 2020-09-21 13:21:19 -04:00
Itamar Turner-Trauring
9f00343478 Some progress towards test_upload running on Python 3. 2020-09-21 13:21:19 -04:00
Sajith Sasidharan
c674198074 Rearrage imports 2020-09-21 13:03:51 -04:00
Itamar Turner-Trauring
139bcb1500
Merge pull request #814 from tahoe-lafs/3419.test-encode-python-3-trying-again
Port test_encode to Python 3

Fixes ticket:3419
2020-09-21 11:52:34 -04:00
Itamar Turner-Trauring
7c6e3104ac
Merge pull request #812 from tahoe-lafs/3416.test-encode-python-3
Port allmydata.test.no_network to Python 3

Fixes ticket:3416
2020-09-21 11:51:34 -04:00
Itamar Turner-Trauring
a4da6c3dbe Clarify comment. 2020-09-21 10:35:56 -04:00
Itamar Turner-Trauring
02b4ec8101 Get rid of stray print(). 2020-09-21 10:33:16 -04:00
Jean-Paul Calderone
b200d20430 minor cleanups/rearranging 2020-09-18 15:01:53 -04:00
Jean-Paul Calderone
97872118a5 derived function below 2020-09-18 14:50:45 -04:00
Jean-Paul Calderone
e648965fb6 Add helpers to implement the desired exception behavior and use them 2020-09-18 14:49:19 -04:00
Itamar Turner-Trauring
8ef2252bd4 Finish porting to Python 3. 2020-09-18 14:32:19 -04:00
Itamar Turner-Trauring
c3bb367a93 Tests pass on Python 3. 2020-09-18 14:31:23 -04:00
Itamar Turner-Trauring
050388ee12 Work better on Python 3, until Nevow is gone. 2020-09-18 14:31:21 -04:00
Jean-Paul Calderone
059bb2250b Add a BadRequest resource to help with BAD REQUEST 2020-09-18 14:10:09 -04:00
Itamar Turner-Trauring
cb24c3eccf Merge branch '3416.test-encode-python-3' into 3419.test-encode-python-3-trying-again 2020-09-18 13:38:44 -04:00
Itamar Turner-Trauring
a0ff941fff Try to fix Python 3 again. 2020-09-18 13:36:54 -04:00
Itamar Turner-Trauring
e75beb6eae
Merge pull request #811 from tahoe-lafs/3415.storage-server-python-3
Port allmydata.storage.server to Python 3

Fixes ticket:3415
2020-09-18 13:32:36 -04:00
Jean-Paul Calderone
9682e68528
Merge pull request #805 from jaraco/3408.print-functions
Convert print statements to print functions, even when commented

Fixes: ticket:3408
2020-09-18 12:59:44 -04:00
Itamar Turner-Trauring
7b302871e4 Python 2 tests pass again. 2020-09-18 11:41:28 -04:00
Itamar Turner-Trauring
c5ce988c7e Merge branch '3416.test-encode-python-3' into 3419.test-encode-python-3-trying-again 2020-09-18 11:33:15 -04:00
Itamar Turner-Trauring
1a4744d1f7 Merge branch '3415.storage-server-python-3' into 3416.test-encode-python-3 2020-09-18 11:32:45 -04:00
Itamar Turner-Trauring
02cb451a6b Fix failing tests. 2020-09-17 16:06:26 -04:00
Itamar Turner-Trauring
3d79793ee8 Try to fix hashutil. 2020-09-17 15:38:08 -04:00
Itamar Turner-Trauring
6c85f392dd Fix another future newbytes leak that was breaking Foolscap. 2020-09-17 13:39:47 -04:00
Itamar Turner-Trauring
b784f9654c Merge branch '3415.storage-server-python-3' into 3416.test-encode-python-3 2020-09-17 13:12:46 -04:00
Itamar Turner-Trauring
9818512802 Fix newbytes leak. 2020-09-17 13:10:52 -04:00
Itamar Turner-Trauring
03fd566e2c Fix flake error. 2020-09-17 12:37:10 -04:00
Itamar Turner-Trauring
cecbc260fa Fix order. 2020-09-17 11:43:35 -04:00
Itamar Turner-Trauring
498e69c72e Some progress. 2020-09-16 14:57:55 -04:00
Itamar Turner-Trauring
2588e757e5 Only semi-break the web service. 2020-09-16 14:42:39 -04:00
Itamar Turner-Trauring
833bc72ac3 Merge remote-tracking branch 'origin/master' into 3416.test-encode-python-3 2020-09-16 14:40:40 -04:00