tahoe-lafs/newsfragments/3455.minor
Ross Patterson f1da68f340 feat(py3): Fix config from string compatibility
I did an audit of the code base and AFAICT the `node.config_from_string(...)` is only
used internally.  Much of that usage is in tests where most of the usages feed in
non-specific, simple `"..."` string literals (IOW, bytes under py2, unicode under py3) while one
test module used `b"..."` byte string literals.  Given all that it seems to me that the
best goal would be to use simple string literals throughout the usage of
`node.config_from_string(...)` and have only one special case in that function to handle
the difference between versions.

I just discovered that running the test with `TEST_SUITE=allmydata` doesn't run the
tests in `allmydata.test.test_node` but running them with
`TEST_SUITE=allmydata.test.test_node` does run them.  I'm trying to figure out why that
is, but in the meantime here are the differences in the Python 3 test output when
running just the `allmydata.test.test_node` tests.  This changes converts 11 tests from
errros to success, changes the specific errors for others and improves coverage a bit:

```diff
--- ../../.tox/make-test-py3-all-old.log	2020-10-01 11:56:15.428609940 -0700
+++ ../../.tox/make-test-py3-all-new.log	2020-10-01 11:56:55.052792565 -0700
@@ -95,9 +95,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__
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 739, in __init__
     self.setup_logging()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 826, in setup_logging
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 831, in setup_logging
     newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__)
 builtins.AttributeError: module 'types' has no attribute 'UnboundMethodType'

@@ -158,53 +158,29 @@
 (#.### secs)
 allmydata.test.test_node.TestCase.test_config_required ... [OK]
 (#.### secs)
-allmydata.test.test_node.TestCase.test_location1 ... Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 112, in test_location1
-    tub_location="192.0.2.0:1234")
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 99, in _test_location
-    tub = testing_tub(config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 53, in testing_tub
-    config = config_from_string(basedir, 'DEFAULT_PORTNUMFILE_BLANK', config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
-[ERROR]
+allmydata.test.test_node.TestCase.test_location1 ... [OK]
 (#.### secs)
 allmydata.test.test_node.TestCase.test_location2 ... Traceback (most recent call last):
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 117, in test_location2
     tub_location="192.0.2.0:1234,example.org:8091")
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 99, in _test_location
     tub = testing_tub(config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 53, in testing_tub
-    config = config_from_string(basedir, 'DEFAULT_PORTNUMFILE_BLANK', config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 65, in testing_tub
+    cert_filename='DEFAULT_CERTFILE_BLANK'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 669, in create_main_tub
+    portlocation = _tub_portlocation(config)
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 596, in _tub_portlocation
+    tubport = _convert_tub_port(file_tubport)
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 552, in _convert_tub_port
+    if re.search(r'^\d+$', s):
+  File "/usr/lib/python3.6/re.py", line 182, in search
+    return _compile(pattern, flags).search(string)
+builtins.TypeError: cannot use a string pattern on a bytes-like object
 [ERROR]
 (#.### secs)
-allmydata.test.test_node.TestCase.test_location_auto_and_explicit ... Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 142, in test_location_auto_and_explicit
-    local_addresses=["127.0.0.1", "192.0.2.0", "example.com:4321"],
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 99, in _test_location
-    tub = testing_tub(config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 53, in testing_tub
-    config = config_from_string(basedir, 'DEFAULT_PORTNUMFILE_BLANK', config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
-[ERROR]
+allmydata.test.test_node.TestCase.test_location_auto_and_explicit ... [OK]
 (#.### secs)
-allmydata.test.test_node.TestCase.test_location_not_set ... Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 128, in test_location_not_set
-    local_addresses=["127.0.0.1", "192.0.2.0"],
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 99, in _test_location
-    tub = testing_tub(config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 53, in testing_tub
-    config = config_from_string(basedir, 'DEFAULT_PORTNUMFILE_BLANK', config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
-[ERROR]
+allmydata.test.test_node.TestCase.test_location_not_set ... [OK]
 (#.### secs)
 allmydata.test.test_node.TestCase.test_logdir_is_str ... 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
@@ -215,27 +191,31 @@
     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__
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 739, in __init__
     self.setup_logging()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 826, in setup_logging
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 831, in setup_logging
     newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__)
 builtins.AttributeError: module 'types' has no attribute 'UnboundMethodType'
 [ERROR]
 (#.### secs)
 allmydata.test.test_node.TestCase.test_private_config ... 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
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
-[ERROR]
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 261, in test_private_config
+    self.assertEqual(config.get_private_config("already"), "secret")
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/trial/_synctest.py", line 434, in assertEqual
+    super(_Assertions, self).assertEqual(first, second, msg)
+  File "/usr/lib/python3.6/unittest/case.py", line 829, in assertEqual
+    assertion_func(first, second, msg=msg)
+  File "/usr/lib/python3.6/unittest/case.py", line 822, in _baseAssertEqual
+    raise self.failureException(msg)
+twisted.trial.unittest.FailTest: b'secret' != 'secret'
+[FAILURE]
 (#.### secs)
 allmydata.test.test_node.TestCase.test_private_config_missing ... [OK]
 (#.### secs)
 allmydata.test.test_node.TestCase.test_private_config_unreadable ... Traceback (most recent call last):
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 213, in test_private_config_unreadable
     config.get_or_create_private_config("foo", "contents")
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 369, in get_or_create_private_config
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 374, in get_or_create_private_config
     fileutil.write(privname, value)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/util/fileutil.py", line 275, in write
     f.write(data)
@@ -258,77 +238,33 @@
 (#.### secs)
 allmydata.test.test_node.TestCase.test_timestamp ... [OK]
 (#.### secs)
-allmydata.test.test_node.TestCase.test_write_config_unwritable_file ... Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 288, in test_write_config_unwritable_file
-    config = config_from_string(basedir, "", "")
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
-[ERROR]
+allmydata.test.test_node.TestCase.test_write_config_unwritable_file ... [OK]
 (#.### secs)
-allmydata.test.test_node.TestMissingPorts.test_disabled_port_not_tub ... Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 488, in test_disabled_port_not_tub
-    config = config_from_string(self.basedir, "portnum", config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
-[ERROR]
+allmydata.test.test_node.TestMissingPorts.test_disabled_port_not_tub ... [OK]
 (#.### secs)
-allmydata.test.test_node.TestMissingPorts.test_disabled_tub_not_port ... Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 506, in test_disabled_tub_not_port
-    config = config_from_string(self.basedir, "portnum", config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
-[ERROR]
+allmydata.test.test_node.TestMissingPorts.test_disabled_tub_not_port ... [OK]
 (#.### secs)
-allmydata.test.test_node.TestMissingPorts.test_empty_tub_location ... Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 470, in test_empty_tub_location
-    config = config_from_string(self.basedir, "portnum", config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
-[ERROR]
+allmydata.test.test_node.TestMissingPorts.test_empty_tub_location ... [OK]
 (#.### secs)
-allmydata.test.test_node.TestMissingPorts.test_empty_tub_port ... Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 453, in test_empty_tub_port
-    config = config_from_string(self.basedir, "portnum", config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
-[ERROR]
+allmydata.test.test_node.TestMissingPorts.test_empty_tub_port ... [OK]
 (#.### secs)
-allmydata.test.test_node.TestMissingPorts.test_parsing_all_disabled ... Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 439, in test_parsing_all_disabled
-    config = config_from_string(self.basedir, "portnum", config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
-[ERROR]
+allmydata.test.test_node.TestMissingPorts.test_parsing_all_disabled ... [OK]
 (#.### secs)
-allmydata.test.test_node.TestMissingPorts.test_parsing_defaults ... Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 392, in test_parsing_defaults
-    config = config_from_string(self.basedir, "portnum", config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
-[ERROR]
+allmydata.test.test_node.TestMissingPorts.test_parsing_defaults ... [OK]
 (#.### secs)
 allmydata.test.test_node.TestMissingPorts.test_parsing_location_complex ... Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 415, in test_parsing_location_complex
-    config = config_from_string(self.basedir, "portnum", config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 418, in test_parsing_location_complex
+    tubport, tublocation = _tub_portlocation(config)
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 596, in _tub_portlocation
+    tubport = _convert_tub_port(file_tubport)
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 552, in _convert_tub_port
+    if re.search(r'^\d+$', s):
+  File "/usr/lib/python3.6/re.py", line 182, in search
+    return _compile(pattern, flags).search(string)
+builtins.TypeError: cannot use a string pattern on a bytes-like object
 [ERROR]
 (#.### secs)
-allmydata.test.test_node.TestMissingPorts.test_parsing_tcp ... Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 370, in test_parsing_tcp
-    config = config_from_string(self.basedir, "portnum", config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
-[ERROR]
+allmydata.test.test_node.TestMissingPorts.test_parsing_tcp ... [OK]
 (#.### secs)

 ===============================================================================
@@ -415,9 +351,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__
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 739, in __init__
     self.setup_logging()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 826, in setup_logging
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 831, in setup_logging
     newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__)
 builtins.AttributeError: module 'types' has no attribute 'UnboundMethodType'

@@ -449,6 +385,20 @@

 allmydata.test.test_node.TestCase.test_config_items
 ===============================================================================
+[FAIL]
+Traceback (most recent call last):
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 261, in test_private_config
+    self.assertEqual(config.get_private_config("already"), "secret")
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/.tox/py36-coverage/lib/python3.6/site-packages/twisted/trial/_synctest.py", line 434, in assertEqual
+    super(_Assertions, self).assertEqual(first, second, msg)
+  File "/usr/lib/python3.6/unittest/case.py", line 829, in assertEqual
+    assertion_func(first, second, msg=msg)
+  File "/usr/lib/python3.6/unittest/case.py", line 822, in _baseAssertEqual
+    raise self.failureException(msg)
+twisted.trial.unittest.FailTest: b'secret' != 'secret'
+
+allmydata.test.test_node.TestCase.test_private_config
+===============================================================================
 [ERROR]
 Traceback (most recent call last):
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 657, in test_disabled
@@ -503,62 +453,26 @@
 ===============================================================================
 [ERROR]
 Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 112, in test_location1
-    tub_location="192.0.2.0:1234")
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 99, in _test_location
-    tub = testing_tub(config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 53, in testing_tub
-    config = config_from_string(basedir, 'DEFAULT_PORTNUMFILE_BLANK', config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
-
-allmydata.test.test_node.TestCase.test_location1
-===============================================================================
-[ERROR]
-Traceback (most recent call last):
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 117, in test_location2
     tub_location="192.0.2.0:1234,example.org:8091")
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 99, in _test_location
     tub = testing_tub(config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 53, in testing_tub
-    config = config_from_string(basedir, 'DEFAULT_PORTNUMFILE_BLANK', config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 65, in testing_tub
+    cert_filename='DEFAULT_CERTFILE_BLANK'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 669, in create_main_tub
+    portlocation = _tub_portlocation(config)
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 596, in _tub_portlocation
+    tubport = _convert_tub_port(file_tubport)
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 552, in _convert_tub_port
+    if re.search(r'^\d+$', s):
+  File "/usr/lib/python3.6/re.py", line 182, in search
+    return _compile(pattern, flags).search(string)
+builtins.TypeError: cannot use a string pattern on a bytes-like object

 allmydata.test.test_node.TestCase.test_location2
 ===============================================================================
 [ERROR]
 Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 142, in test_location_auto_and_explicit
-    local_addresses=["127.0.0.1", "192.0.2.0", "example.com:4321"],
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 99, in _test_location
-    tub = testing_tub(config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 53, in testing_tub
-    config = config_from_string(basedir, 'DEFAULT_PORTNUMFILE_BLANK', config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
-
-allmydata.test.test_node.TestCase.test_location_auto_and_explicit
-===============================================================================
-[ERROR]
-Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 128, in test_location_not_set
-    local_addresses=["127.0.0.1", "192.0.2.0"],
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 99, in _test_location
-    tub = testing_tub(config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 53, in testing_tub
-    config = config_from_string(basedir, 'DEFAULT_PORTNUMFILE_BLANK', config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
-
-allmydata.test.test_node.TestCase.test_location_not_set
-===============================================================================
-[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
@@ -567,9 +481,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__
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 739, in __init__
     self.setup_logging()
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 826, in setup_logging
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 831, in setup_logging
     newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__)
 builtins.AttributeError: module 'types' has no attribute 'UnboundMethodType'

@@ -577,19 +491,9 @@
 ===============================================================================
 [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
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
-
-allmydata.test.test_node.TestCase.test_private_config
-===============================================================================
-[ERROR]
-Traceback (most recent call last):
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 213, in test_private_config_unreadable
     config.get_or_create_private_config("foo", "contents")
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 369, in get_or_create_private_config
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 374, in get_or_create_private_config
     fileutil.write(privname, value)
   File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/util/fileutil.py", line 275, in write
     f.write(data)
@@ -607,97 +511,21 @@
 ===============================================================================
 [ERROR]
 Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 288, in test_write_config_unwritable_file
-    config = config_from_string(basedir, "", "")
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
-
-allmydata.test.test_node.TestCase.test_write_config_unwritable_file
-===============================================================================
-[ERROR]
-Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 488, in test_disabled_port_not_tub
-    config = config_from_string(self.basedir, "portnum", config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
-
-allmydata.test.test_node.TestMissingPorts.test_disabled_port_not_tub
-===============================================================================
-[ERROR]
-Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 506, in test_disabled_tub_not_port
-    config = config_from_string(self.basedir, "portnum", config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
-
-allmydata.test.test_node.TestMissingPorts.test_disabled_tub_not_port
-===============================================================================
-[ERROR]
-Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 470, in test_empty_tub_location
-    config = config_from_string(self.basedir, "portnum", config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
-
-allmydata.test.test_node.TestMissingPorts.test_empty_tub_location
-===============================================================================
-[ERROR]
-Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 453, in test_empty_tub_port
-    config = config_from_string(self.basedir, "portnum", config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
-
-allmydata.test.test_node.TestMissingPorts.test_empty_tub_port
-===============================================================================
-[ERROR]
-Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 439, in test_parsing_all_disabled
-    config = config_from_string(self.basedir, "portnum", config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
-
-allmydata.test.test_node.TestMissingPorts.test_parsing_all_disabled
-===============================================================================
-[ERROR]
-Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 392, in test_parsing_defaults
-    config = config_from_string(self.basedir, "portnum", config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
-
-allmydata.test.test_node.TestMissingPorts.test_parsing_defaults
-===============================================================================
-[ERROR]
-Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 415, in test_parsing_location_complex
-    config = config_from_string(self.basedir, "portnum", config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 418, in test_parsing_location_complex
+    tubport, tublocation = _tub_portlocation(config)
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 596, in _tub_portlocation
+    tubport = _convert_tub_port(file_tubport)
+  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 552, in _convert_tub_port
+    if re.search(r'^\d+$', s):
+  File "/usr/lib/python3.6/re.py", line 182, in search
+    return _compile(pattern, flags).search(string)
+builtins.TypeError: cannot use a string pattern on a bytes-like object

 allmydata.test.test_node.TestMissingPorts.test_parsing_location_complex
-===============================================================================
-[ERROR]
-Traceback (most recent call last):
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/test/test_node.py", line 370, in test_parsing_tcp
-    config = config_from_string(self.basedir, "portnum", config_data)
-  File "/home/rpatterson/src/work/sfu/tahoe-lafs/src/allmydata/node.py", line 209, in config_from_string
-    parser.readfp(BytesIO(config_str))
-builtins.TypeError: a bytes-like object is required, not 'str'
-
-allmydata.test.test_node.TestMissingPorts.test_parsing_tcp
 -------------------------------------------------------------------------------
-Ran 34 tests in 2.788s
+Ran 34 tests in 2.516s

-FAILED (failures=4, errors=21, successes=9)
+FAILED (failures=5, errors=9, successes=20)
 Name                                                 Stmts   Miss Branch BrPart  Cover   Missing
 ------------------------------------------------------------------------------------------------
 src/allmydata/__init__.py                               16      4      0      0    75%   18-22, 28-32
@@ -751,7 +579,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    411    120      0    13%   29-43, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 67-69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89-90, 105-160, 164, 167-171, 174-175, 186-193, 201-208, 211-212, 223-227, 230-232, 236-254, 257-275, 278-283, 286-332, 344-354, 362-454, 485-516, 529-540, 564-578, 586-597, 607-633, 643-663, 671-699, 712-729, 738-798, 806-829, 839-889, 897-905, 909-910, 919-941, 950-971, 981-994, 999-1005
 src/allmydata/mutable/servermap.py                     623    524    198      0    12%   26-38, 41-42, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 70, 72, 74, 76, 78, 80, 82, 116-124, 130-139, 142, 145, 148, 159-161, 165, 170-172, 175, 177, 180-181, 183, 186-199, 202, 206, 213, 217-220, 225-228, 231, 234-238, 243-252, 255-259, 263-265, 269-275, 280-290, 295-305, 311-315, 320-322, 328-350, 358-363, 370-372, 379, 390-450, 454, 457-461, 466-545, 549-557, 560-575, 578-593, 596-613, 623-638, 642-779, 787, 791-799, 803-804, 816-880, 883-904, 910-914, 919-920, 928-944, 960-974, 981-998, 1002-1012, 1020-1183, 1186-1205, 1209-1225, 1228-1229
-src/allmydata/node.py                                  388    106    146     39    69%   120, 132, 190, 211-213, 241, 243-245, 278, 284, 291-295, 303-306, 315, 320, 339, 341, 361, 368, 370, 377-379, 393-396, 422, 424, 449, 453, 490, 493, 500, 511-512, 547-549, 566, 574, 581, 583, 590-591, 597, 601, 612, 622-634, 679, 681, 736-750, 756, 764, 792-805, 808-809, 814-815, 827-846, 189->190, 204->208, 240->241, 242->243, 277->278, 314->315, 319->320, 338->339, 340->341, 360->361, 365->368, 391->393, 421->422, 423->424, 448->449, 451->453, 489->490, 492->493, 499->500, 510->511, 565->566, 567->570, 573->574, 575->578, 580->581, 582->583, 585->597, 589->590, 600->601, 603->606, 610->616, 611->612, 618->622, 673->679, 680->681, 763->764, 766->768, 821->830, 823->821
+src/allmydata/node.py                                  391     87    148     30    75%   20, 125, 137, 195, 246, 248-250, 283, 289, 308-311, 320, 325, 344, 346, 366, 373, 375, 382-384, 398-401, 427, 429, 454, 458, 495, 498, 505, 516-517, 606, 617, 634-638, 684, 686, 741-755, 761, 769, 797-810, 813-814, 819-820, 832-851, 19->20, 194->195, 209->213, 245->246, 247->248, 282->283, 319->320, 324->325, 343->344, 345->346, 365->366, 370->373, 396->398, 426->427, 428->429, 453->454, 456->458, 494->495, 497->498, 504->505, 515->516, 605->606, 616->617, 627->634, 678->684, 685->686, 768->769, 771->773, 826->835, 828->826
 src/allmydata/nodemaker.py                              97     71     38      0    21%   23-33, 36, 38, 41, 44-47, 49, 53-95, 98-115, 118-125, 129-138, 141-150
 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    146     14      0     0%   1-341
@@ -810,7 +638,7 @@
 src/allmydata/util/dictutil.py                          38     22     12      1    34%   16, 21-24, 27-31, 34-38, 55-56, 59-60, 63-64, 71, 77-78, 12->16
 src/allmydata/util/eliotutil.py                        115     68     24      0    35%   82-85, 91-94, 104, 117-122, 129-139, 151, 155-159, 163-167, 179-186, 198-199, 202-210, 222-226, 231-247, 250, 266-294, 308-312
 src/allmydata/util/encodingutil.py                     217    123     80     12    36%   18, 37-38, 41, 43, 52-53, 69, 75-78, 102, 108, 114-122, 130-134, 145-155, 164, 173-175, 178-181, 187, 196-213, 217-231, 237-243, 279-282, 291-296, 314, 320-322, 327, 334-340, 343-355, 358-363, 366-367, 370-373, 379, 395-405, 412-420, 423, 429, 16->18, 36->37, 40->41, 42->43, 66->69, 72->74, 74->75, 278->279, 285->295, 288->291, 299->310, 319->320
-src/allmydata/util/fileutil.py                         343    244    120     13    25%   15, 23-25, 47-55, 71-85, 96-97, 100, 103, 106, 109, 115-116, 119-125, 128, 131, 134, 137-138, 142-145, 151-153, 158, 166-176, 179-184, 201-203, 214-237, 241-244, 247-254, 262, 279, 282-290, 293-304, 326, 328, 336-342, 348, 351, 358, 366-376, 382-400, 405, 410-426, 434-462, 486-529, 548-554, 566-568, 573-604, 608-612, 615-627, 633, 636-659, 13->15, 22->23, 200->201, 259->262, 325->326, 327->328, 332->336, 345->351, 347->348, 357->358, 380->382, 404->405, 571->573
+src/allmydata/util/fileutil.py                         343    243    120     13    25%   15, 23-25, 47-55, 71-85, 96-97, 100, 103, 106, 109, 115-116, 119-125, 128, 131, 134, 137-138, 142-145, 151-153, 158, 166-176, 179-184, 201-203, 214-237, 241-244, 247-254, 262, 282-290, 293-304, 326, 328, 336-342, 348, 351, 358, 366-376, 382-400, 405, 410-426, 434-462, 486-529, 548-554, 566-568, 573-604, 608-612, 615-627, 633, 636-659, 13->15, 22->23, 200->201, 259->262, 325->326, 327->328, 332->336, 345->351, 347->348, 357->358, 380->382, 404->405, 571->573
 src/allmydata/util/gcutil.py                            23      3      8      3    81%   20, 51-57, 19->20, 50->51, 64->exit
 src/allmydata/util/happinessutil.py                     77     62     42      1    13%   15, 25-54, 64-69, 82-92, 142-183, 207-223, 235-249, 13->15
 src/allmydata/util/hashutil.py                         157     76      8      1    50%   14, 40-42, 45-46, 49-56, 60-62, 66-68, 72-76, 118, 122, 126, 130, 134, 138, 142, 146, 150, 154, 158, 162, 166, 174-176, 180-183, 187, 191, 195, 199, 204, 209-210, 214-215, 219, 223-228, 232, 236, 240, 244, 248-250, 254, 258, 262, 266, 270-271, 278, 282, 12->14
@@ -818,7 +646,7 @@
 src/allmydata/util/i2p_provider.py                     121     73     36      5    35%   44-67, 72-81, 85-135, 151-161, 168, 176-180, 183-184, 187, 193-216, 219, 226, 167->168, 175->176, 182->183, 186->187, 192->193
 src/allmydata/util/idlib.py                              5      2      0      0    60%   6, 9
 src/allmydata/util/iputil.py                           172     74     56     12    52%   14, 63-102, 123-140, 151-184, 209, 216, 229, 237-238, 242, 246, 254-257, 271-277, 328-329, 353-354, 13->14, 215->216, 220->242, 226->229, 234->220, 239->234, 245->246, 249->259, 265->261, 291->329, 295->328, 360->exit
-src/allmydata/util/log.py                               52     27     16      1    38%   13, 38-41, 46-48, 51-61, 67-75, 78, 12->13
+src/allmydata/util/log.py                               52     23     16      2    46%   13, 46-48, 51-61, 67-75, 78, 12->13, 39->41
 src/allmydata/util/mathutil.py                          12      3      2      1    71%   16, 25-26, 15->16
 src/allmydata/util/netstring.py                         35     24     12      1    26%   13, 31-54, 12->13
 src/allmydata/util/observer.py                          91     56     20      1    32%   14, 29-32, 36-38, 41, 44, 47, 50-54, 57-60, 63-66, 69-70, 79, 82, 93-97, 103, 106, 109, 112-113, 119-121, 134, 137-139, 142-145, 148-151, 154-157, 13->14
@@ -854,7 +682,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                                                27467  22018   8248    184    17%
+TOTAL                                                27470  21994   8250    176    17%

 12 files skipped due to complete coverage.
 make[#]: Leaving directory '/home/rpatterson/src/work/sfu/tahoe-lafs'
```
2020-10-04 21:52:27 -07:00

2 lines
45 B
Plaintext

Begin porting the `node` module to Python 3.