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
2020-09-14 07:38:54 -04:00
2020-07-28 13:00:44 -04:00
2018-05-29 13:17:32 -06:00
2015-07-17 22:12:25 +01:00
2018-04-26 15:41:38 -04:00
2018-05-18 14:41:48 -06:00
2020-03-11 18:41:32 -06:00
2020-07-07 09:19:30 -04:00
2020-02-07 09:27:02 -05:00
2019-03-21 15:00:02 -04:00

Tahoe-LAFS

Tahoe-LAFS is a Free and Open decentralized cloud storage system. It distributes your data across multiple servers. Even if some of the servers fail or are taken over by an attacker, the entire file store continues to function correctly, preserving your privacy and security.

For full documentation, please see http://tahoe-lafs.readthedocs.io/en/latest/ .

code of conduct documentation status build status circleci test coverage percentage

INSTALLING

There are three ways to install Tahoe-LAFS.

using OS packages

Pre-packaged versions are available for several operating systems:

  • Debian and Ubuntu users can apt-get install tahoe-lafs
  • NixOS, NetBSD (pkgsrc), ArchLinux, Slackware, and Gentoo have packages available, see OSPackages for details
  • Mac and Windows installers are in development.

via pip

If you don't use an OS package, you'll need Python 2.7 and pip. You may also need a C compiler, and the development headers for python, libffi, and OpenSSL. On a Debian-like system, use apt-get install build-essential python-dev libffi-dev libssl-dev python-virtualenv. On Windows, see docs/windows.rst.

Then, to install the most recent release, just run:

  • pip install tahoe-lafs

from source

To install from source (either so you can hack on it, or just to run pre-release code), you should create a virtualenv and install into that:

  • git clone https://github.com/tahoe-lafs/tahoe-lafs.git
  • cd tahoe-lafs
  • virtualenv --python=python2.7 venv
  • venv/bin/pip install --upgrade setuptools
  • venv/bin/pip install --editable .
  • venv/bin/tahoe --version

To run the unit test suite:

  • tox

You can pass arguments to trial with an environment variable. For example, you can run the test suite on multiple cores to speed it up:

  • TAHOE_LAFS_TRIAL_ARGS="-j4" tox

For more detailed instructions, read docs/INSTALL.rst .

Once tahoe --version works, see docs/running.rst to learn how to set up your first Tahoe-LAFS node.

LICENCE

Copyright 2006-2018 The Tahoe-LAFS Software Foundation

You may use this package under the GNU General Public License, version 2 or, at your option, any later version. You may use this package under the Transitive Grace Period Public Licence, version 1.0, or at your option, any later version. (You may choose to use this package under the terms of either licence, at your option.) See the file COPYING.GPL for the terms of the GNU General Public License, version 2. See the file COPYING.TGPPL for the terms of the Transitive Grace Period Public Licence, version 1.0.

See TGPPL.PDF for why the TGPPL exists, graphically illustrated on three slides.


Description
The Tahoe-LAFS decentralized secure filesystem.
Readme 91 MiB
Languages
Python 98.1%
HTML 0.9%
Nix 0.3%
Shell 0.3%
Makefile 0.2%
Other 0.1%