Commit Graph

6591 Commits

Author SHA1 Message Date
Itamar Turner-Trauring
dfdaac7474 Ported to Python 3. 2020-11-06 11:25:48 -05:00
Itamar Turner-Trauring
bcc6d91444 Tests pass on Python 3. 2020-11-06 11:24:07 -05:00
Itamar Turner-Trauring
6017b11910 Merge branch '3475.mutable-tests-part-2-python-3' into 3496.mutable-tests-python-3-part-3 2020-11-06 11:20:54 -05:00
Itamar Turner-Trauring
eab228f22a
Merge pull request #887 from tahoe-lafs/3465.storage_client-python-3-take-2
Port storage_client to Python 3

Fixes ticket:3465
2020-11-06 11:18:31 -05:00
Itamar Turner-Trauring
84a33625bd Port to Python 3. 2020-11-06 10:21:33 -05:00
Itamar Turner-Trauring
31ee2e18f3 Tests pass on Python 3. 2020-11-06 10:20:18 -05:00
Itamar Turner-Trauring
836d41a92d Ported to Python 3. 2020-11-06 10:12:56 -05:00
Itamar Turner-Trauring
e4734468e5 Ported to Python 3. 2020-11-06 10:11:09 -05:00
Itamar Turner-Trauring
95df57382f Tests pass on Python 3. 2020-11-06 10:09:11 -05:00
Itamar Turner-Trauring
e17be38d69 Start porting test infrastructure to Python 3 compatibility. 2020-11-06 10:04:46 -05:00
Itamar Turner-Trauring
cd01d4dafa Test for Python 2 BytesKeyDict and UnicodeKeyDict behavior. 2020-11-05 10:15:38 -05:00
Itamar Turner-Trauring
a49ef086b6 No need for explicit unicode. 2020-11-05 10:09:52 -05:00
Itamar Turner-Trauring
f57ba3c927 Can't send unicode over foolscap. 2020-11-04 14:13:08 -05:00
Itamar Turner-Trauring
813594bbac Go back to the way it was. 2020-11-04 13:45:41 -05:00
Itamar Turner-Trauring
2c8a91fb6e
Merge pull request #883 from tahoe-lafs/3493.node-to-python-3
Port allmydata.node to python 3

Fixes ticket:3493
2020-11-04 13:44:21 -05:00
Itamar Turner-Trauring
0a6321cc9a Tests and additional check for typed key dicts. 2020-11-04 13:36:08 -05:00
Itamar Turner-Trauring
dc818757b6 Port to Python 3. 2020-11-04 13:22:34 -05:00
Itamar Turner-Trauring
2b557287c8 Lint fix. 2020-11-04 13:21:13 -05:00
Itamar Turner-Trauring
d407cb5005 Port to Python 3. 2020-11-04 13:19:16 -05:00
Itamar Turner-Trauring
f34597ac61 All tests pass on Python 3. 2020-11-04 13:09:55 -05:00
Itamar Turner-Trauring
d30014f8f5 The Resource dictionary is keyed by bytes, so storing unicode means you don't
get the cached resource!
2020-11-03 11:14:25 -05:00
Itamar Turner-Trauring
f6eb4aef57 Work consistently across Python 2 and 3. 2020-11-03 10:41:13 -05:00
Itamar Turner-Trauring
3edc1cb29e The dictionary is unicode, not bytes. 2020-11-03 10:41:02 -05:00
Itamar Turner-Trauring
60992174ff twisted.web expects bytes. 2020-11-03 10:40:53 -05:00
Itamar Turner-Trauring
672c440091 Better error reporting. 2020-11-03 10:40:41 -05:00
Itamar Turner-Trauring
e3a0f61dca More passing tests. 2020-11-03 10:04:24 -05:00
Itamar Turner-Trauring
35c304cd82 Workaround for Eliot flaw. 2020-11-03 10:04:16 -05:00
Jean-Paul Calderone
540c70f835
Merge pull request #871 from exarkun/2928.remote-allocate_tcp_port-test_node.py
Remove `allocate_tcp_port` from test_node.py

Fixes: ticket:2928
2020-10-31 19:24:09 -04:00
Jean-Paul Calderone
7ad55e0fba Merge remote-tracking branch 'origin/master' into 2928.remote-allocate_tcp_port-test_node.py 2020-10-31 11:42:01 -04:00
Jean-Paul Calderone
651c42ac0f remove unused import 2020-10-31 11:41:20 -04:00
Jean-Paul Calderone
4d469d7b64 The test is faster now, leave the max_examples setting alone 2020-10-30 21:05:46 -04:00
Itamar Turner-Trauring
92a4a5afcc Closer to more passing tests, maybe. 2020-10-30 15:04:00 -04:00
Itamar Turner-Trauring
45a2fcc3f2 Fix for Python 2. 2020-10-30 14:49:25 -04:00
Itamar Turner-Trauring
e79d1adeea Fix lint. 2020-10-30 14:35:09 -04:00
Itamar Turner-Trauring
d52f6747f6 Some progress towards passing tests. 2020-10-30 14:21:16 -04:00
Itamar Turner-Trauring
6264cf15b1 Fix some failing tests. 2020-10-30 14:08:09 -04:00
Chad Whitacre
266b707d25
Merge pull request #861 from tahoe-lafs/3474.easy-ports
Port some easy files to Python 3
2020-10-30 13:33:34 -04:00
Itamar Turner-Trauring
6b4be7aee3 Should be unicode. 2020-10-30 11:23:30 -04:00
Itamar Turner-Trauring
36d1056ad0 Delete dead code, note porting. 2020-10-30 11:21:14 -04:00
Itamar Turner-Trauring
468beb05f6 Port to Python 3. 2020-10-29 14:09:18 -04:00
Itamar Turner-Trauring
dce368016b Duplicates test coverage in test_connections. 2020-10-29 14:01:05 -04:00
Itamar Turner-Trauring
c3248524f0 Drop support for '\#', never was used by anything as far as we know. 2020-10-29 13:51:29 -04:00
Itamar Turner-Trauring
0cf6ca86fb Improve test coverage. 2020-10-29 13:36:31 -04:00
Itamar Turner-Trauring
fa0dbcfd0e Configs are always unicode now. 2020-10-29 10:26:07 -04:00
Chad Whitacre
a10c2606f4
Merge pull request #868 from tahoe-lafs/3468.offloaded-test-coverage
More test coverage for the upload helper
2020-10-28 15:20:34 -04:00
Chad Whitacre
d04b6c103a Pick off a couple of easy ports 2020-10-28 14:57:10 -04:00
Itamar Turner-Trauring
6f2027e824 Fix lint. 2020-10-27 16:59:43 -04:00
Itamar Turner-Trauring
20a64d5767 Test new fileutil behavior. 2020-10-27 14:24:23 -04:00
Itamar Turner-Trauring
f1b281123d Fix tests. 2020-10-27 14:24:20 -04:00
Itamar Turner-Trauring
bcb6822171 Merge branch '3485.backported-configparser-for-py-2' into 3479.test-node-python-3 2020-10-27 14:06:35 -04:00
Itamar Turner-Trauring
b62bd13bee Merge remote-tracking branch 'origin/master' into 3479.test-node-python-3 2020-10-27 14:02:27 -04:00
Itamar Turner-Trauring
b79504a43b Refactor to unify different code paths. 2020-10-27 13:59:45 -04:00
Itamar Turner-Trauring
0d270e1290 Create ConfigParsers in a consistent manner. 2020-10-27 11:48:25 -04:00
Itamar Turner-Trauring
207111fb9c Documentation fixes. 2020-10-27 11:43:27 -04:00
Itamar Turner-Trauring
1a7bb06587 SafeConfigParser has been replaced by ConfigParser. 2020-10-27 09:35:09 -04:00
Itamar Turner-Trauring
c76afc9ece Try to fix some failing unit tests in ASCII locale. 2020-10-27 08:54:28 -04:00
Itamar Turner-Trauring
d5333ae9f9 Merge remote-tracking branch 'origin/master' into 3485.backported-configparser-for-py-2 2020-10-26 16:53:19 -04:00
Itamar Turner-Trauring
4a54377208 Some more fixes. 2020-10-26 16:48:18 -04:00
Itamar Turner-Trauring
4dc1adc817 Some progress towards passing Python 2 tests. 2020-10-26 16:37:00 -04:00
Itamar Turner-Trauring
76697c8c1b It's already unicode. 2020-10-26 14:33:59 -04:00
Itamar Turner-Trauring
375ed5096c Config parsing now always returns Unicode. 2020-10-26 12:12:49 -04:00
Itamar Turner-Trauring
f50fd8e474 Switch to new configparser backport. 2020-10-26 12:12:46 -04:00
Jean-Paul Calderone
25ee76104a
Merge pull request #872 from tahoe-lafs/3486.netifaces
Switch to netifaces

Fixes: ticket:3486
2020-10-26 11:55:31 -04:00
Chad Whitacre
338ee89e63 Stick with unicode (new str) for file path parts
This seems to be the pattern, e.g.:

https://github.com/tahoe-lafs/tahoe-lafs/blob/master/src/allmydata/client.py#L229
2020-10-23 12:52:32 -04:00
Chad Whitacre
725291c2aa Merge branch 'master' into 3468.offloaded-test-coverage 2020-10-23 12:08:48 -04:00
Chad Whitacre
f0657aec69
Merge pull request #853 from tahoe-lafs/3346.port-immutable-offloaded
Port immutable.offloaded to Python 3
2020-10-23 12:05:20 -04:00
Jean-Paul Calderone
96c848b2ad flakes 2020-10-23 09:50:31 -04:00
Jean-Paul Calderone
c60d62d858 Direct test for the new implementation 2020-10-23 09:32:13 -04:00
Jean-Paul Calderone
931bdef2a2 Get rid of the old implementation and related unused code
Also put in the new implementation, though now it needs tests because *there
were no direct tests for the old one*.
2020-10-23 09:23:16 -04:00
Jean-Paul Calderone
a5e889f707 flakes 2020-10-22 15:31:39 -04:00
Jean-Paul Calderone
606617cbfd clean up the tub location tests a bit 2020-10-22 14:41:28 -04:00
Jean-Paul Calderone
ea257681bb Stop starting the services so that we stop binding the ports 2020-10-22 14:36:49 -04:00
Jean-Paul Calderone
8e41c2d3e1 whitespace 2020-10-22 14:36:45 -04:00
Jean-Paul Calderone
83dbcdb3bf Switch away from EmptyNode since it's gone from master 2020-10-22 14:31:33 -04:00
Jean-Paul Calderone
af5531d81b Merge remote-tracking branch 'origin/master' into 2928.remote-allocate_tcp_port-test_node.py 2020-10-22 14:31:21 -04:00
Jean-Paul Calderone
a58fd5c88e remove unused attribute 2020-10-22 07:23:02 -04:00
Jean-Paul Calderone
e97b5f6bb4 document get_arg req parameter 2020-10-22 07:22:51 -04:00
Jean-Paul Calderone
8401547b35 docstring for TahoeLAFSRequest 2020-10-22 07:22:41 -04:00
Jean-Paul Calderone
e3b1d4f536 enforce the type requirement 2020-10-22 07:17:52 -04:00
Jean-Paul Calderone
c8b9a0265a get_root docs 2020-10-22 07:16:57 -04:00
Jean-Paul Calderone
612cbb583a combine common_web and common_tweb now that there is no nevow renderer 2020-10-22 07:13:13 -04:00
Jean-Paul Calderone
0f574dc019 docstring for the helper 2020-10-21 14:47:56 -04:00
Jean-Paul Calderone
d1599a924e Test and fix cap censoring in HTTP access logs 2020-10-21 14:42:30 -04:00
Jean-Paul Calderone
b2999d283f Somewhat clarify this test 2020-10-21 12:37:34 -04:00
Jean-Paul Calderone
62f5fb9d28 Make sure the JSON is given back as bytes 2020-10-21 12:27:08 -04:00
Jean-Paul Calderone
444c3e6ce4 typo fix 2020-10-21 12:23:43 -04:00
Jean-Paul Calderone
37016f4ab5 pyflakes 2020-10-21 12:21:44 -04:00
Jean-Paul Calderone
c31300fd0d Handle interrupted connections 2020-10-21 12:21:01 -04:00
Jean-Paul Calderone
14b9dc090d Replace some ctx names with req 2020-10-21 10:12:48 -04:00
Jean-Paul Calderone
03a144755d Nevow is no longer a dependency 2020-10-21 10:02:32 -04:00
Jean-Paul Calderone
7eecf51dc5 Just talk about rendering, not Nevow 2020-10-21 10:02:22 -04:00
Jean-Paul Calderone
6500f742dc Twisted Web handles UnsupportedMethod for us 2020-10-21 10:02:10 -04:00
Jean-Paul Calderone
816ca79d8a Talk about os.stat and tracebacks instead of Nevow 2020-10-21 10:01:57 -04:00
Jean-Paul Calderone
2ba34a4759 Talk about Nevow as a proper noun where necessary 2020-10-21 10:01:46 -04:00
Jean-Paul Calderone
a577f1e48d pyflakes 2020-10-21 09:49:03 -04:00
Jean-Paul Calderone
80549f5f02 Make this request a little more realistic 2020-10-21 09:46:21 -04:00
Jean-Paul Calderone
7d54af7928 re-use our other renderer 2020-10-21 09:46:14 -04:00
Jean-Paul Calderone
27c2fd80c8 re-use our other renderer 2020-10-21 09:46:00 -04:00
Jean-Paul Calderone
c8db069960 Get rid of no-longer used Nevow exception handler 2020-10-21 09:45:41 -04:00
Jean-Paul Calderone
c64a71a642 Re-arrange some of the requestReceived logic and switch to t.web Site 2020-10-21 09:45:11 -04:00
Jean-Paul Calderone
538cefed3d Update Twisted Web-based render to use our request
Also to do one other thing Twisted Web does for resources automatically -
handle UnsupportedMethod
2020-10-21 08:51:45 -04:00
Jean-Paul Calderone
637bb2e576 De-Nevow `render` 2020-10-21 08:51:25 -04:00
Jean-Paul Calderone
304a9880e6 De-Nevow `get_root` 2020-10-21 08:50:53 -04:00
Jean-Paul Calderone
743ead71a4 De-Nevow `get_arg` 2020-10-21 08:50:37 -04:00
Jean-Paul Calderone
7f02128973 [wip] test form posts 2020-10-21 08:29:41 -04:00
Jean-Paul Calderone
0dcc3e13c0 Remove unused imports 2020-10-21 08:21:29 -04:00
Jean-Paul Calderone
7ca8ede88c Merge remote-tracking branch 'origin/master' into 3428.dont-return-deferred-to-twistedweb.2 2020-10-21 07:35:10 -04:00
Jean-Paul Calderone
f602382244 Comments about __get__ calls 2020-10-21 07:34:27 -04:00
Jean-Paul Calderone
7ce2122e71 one more reference 2020-10-21 07:26:12 -04:00
Jean-Paul Calderone
e8761c98ad A comment about what _finish is here for 2020-10-21 07:25:48 -04:00
Jean-Paul Calderone
d8b6e36c6f docstring for StaticResource 2020-10-21 07:23:16 -04:00
Jean-Paul Calderone
dbe2d4efd7 It isn't the root, it's wherever we actually are 2020-10-21 07:22:00 -04:00
Jean-Paul Calderone
a91dba5f5b _finish docstring 2020-10-21 07:18:41 -04:00
Jean-Paul Calderone
1ed74604c7 Use twisted.web.server.Request instead of DummyRequest in the tests
Always prefer the real thing if possible
2020-10-21 07:15:36 -04:00
Jean-Paul Calderone
3192715e37 everything newstyle 2020-10-19 14:37:03 -04:00
Jean-Paul Calderone
a9e9efb336 direct tests for @render_exception 2020-10-19 14:26:12 -04:00
Jean-Paul Calderone
b68c08cff9 Yank direct support for URLPath from common.py 2020-10-19 12:33:15 -04:00
Jean-Paul Calderone
72e60f8301 Fix imports 2020-10-18 11:12:44 -04:00
Jean-Paul Calderone
e710fd883a Add a Twisted Web-based renderer and start using it on Python 3
This could be the thing that eventually replaces the Nevow-based testing
renderer on Python 2 as well.
2020-10-18 11:00:57 -04:00
Jean-Paul Calderone
84acf4e50f Accept unicode return values and encode them to UTF-8
Nevow accepts unicode in most places it accepts bytes and does the usual
sloppy Python 2 thing, lets one or the other get implicitly re-coded,
typically using the ascii codec.

We'll go with UTF-8 because that fails less often than ASCII.  We may want to
clean up the code at some point so we're not accidentally slinging both bytes
and text around as if they were the same thing.
2020-10-18 10:58:09 -04:00
Jean-Paul Calderone
fc1f43c7a3 How does it go without the type check
This is for py36:

> TypeError: helper_furl must be bytes, got 'pb://kl5iekm6itcyjejirxva2upthepsasnn@bogus:1234/frekgeq7gsongibyeuvzmvqoyf4h5pcx' instead
2020-10-16 19:07:28 -04:00
Jean-Paul Calderone
a403d25146 Merge remote-tracking branch 'origin/master' into 3468.offloaded-test-coverage 2020-10-16 14:34:35 -04:00
Jean-Paul Calderone
85bb0a7834 Get rid of the original token-based authorization helper
It was only used by magic-folder and that's gone now.  We have a different
authorization helper for other things now, allmydata.web.private.
2020-10-16 14:14:15 -04:00
Jean-Paul Calderone
292f136547 pyflakes 2020-10-16 13:21:07 -04:00
Jean-Paul Calderone
a22426011b import and naming cleanups post-merge 2020-10-16 12:49:36 -04:00
Itamar Turner-Trauring
8e618b9383 Fix Python 2 issue. 2020-10-16 11:25:29 -04:00
Itamar Turner-Trauring
6aa96bbb8d Port test_node.py to Python 3. 2020-10-16 11:23:38 -04:00
Itamar Turner-Trauring
f7a89f76e7 All tests pass on Python 3. 2020-10-16 11:20:10 -04:00
Itamar Turner-Trauring
51d472e221 More progress towards passing tests on Python 3. 2020-10-16 11:13:11 -04:00
Itamar Turner-Trauring
f689d59a40 More passing tests on Python 3. 2020-10-16 10:55:33 -04:00
Itamar Turner-Trauring
bcd7cdf86f Some passing tests on Python 3. 2020-10-16 10:47:49 -04:00
Jean-Paul Calderone
32051f93b9 Merge remote-tracking branch 'origin/master' into 3428.dont-return-deferred-to-twistedweb.2 2020-10-16 10:37:54 -04:00
Itamar Turner-Trauring
c2fe5a65a6
Merge pull request #847 from tahoe-lafs/3459.test-checker-python-3
Port test_checker.py to Python 3

Fixes ticket:3459
2020-10-16 10:31:25 -04:00
Jean-Paul Calderone
a73a919a20 flakes 2020-10-16 10:22:42 -04:00
Jean-Paul Calderone
a1f1f00be7 Use the more feaetureful rendering helper 2020-10-16 09:53:30 -04:00
Jean-Paul Calderone
31207e4b6b don't double-apply the renderer logic
since that leads to double-finishing requests too
2020-10-16 09:53:24 -04:00
Jean-Paul Calderone
0faa24d344 Add a mess of eliot logging to request handling 2020-10-16 09:53:19 -04:00
Jean-Paul Calderone
0339ba97b9 Turn getChild None and Deferred results into something Twisted Web can manage 2020-10-16 09:52:41 -04:00
Jean-Paul Calderone
fa02e46033 maybeDeferred always returns a Deferred 2020-10-16 09:52:33 -04:00
Jean-Paul Calderone
f733a244aa Just gonna produce text instead 2020-10-16 09:52:26 -04:00
Jean-Paul Calderone
d38ae4d6dd Stop reading server module attributes all the time
It jumps through a ton of deprecation machinery that is at least tedious in
the debugger, if not wasteful at runtime.
2020-10-16 09:52:18 -04:00
Jean-Paul Calderone
07246b3509 Render requests more thoroughly 2020-10-16 09:52:10 -04:00
Jean-Paul Calderone
df949868b6 Stop explicitly finishing and then returning a string 2020-10-16 09:51:50 -04:00
Jean-Paul Calderone
69c7c40510 handle Deferred from render 2020-10-16 09:51:42 -04:00
Jean-Paul Calderone
f15086d995
Merge pull request #844 from tahoe-lafs/3460.improved-got_announcement
Improved `_got_announcement`

Fixes: ticket:3460
2020-10-16 08:55:11 -04:00
Jean-Paul Calderone
99fe617069
Merge pull request #857 from tahoe-lafs/3470.oneshotobserverlist-immediately
Make OneShotObserverList immediate

Fixes: ticket:3470
2020-10-15 17:37:31 -04:00
Jean-Paul Calderone
733d393a07
Merge pull request #840 from tahoe-lafs/3454.unskip-test_python3
Unskip the Python 3 porting test on Python 2

Fixes: ticket:3454
2020-10-15 17:32:59 -04:00
Jean-Paul Calderone
4d56b5f4ed
Merge pull request #858 from tahoe-lafs/3471.immediate-localwrapper
Allow LocalWrapper to be immediate

Fixes: ticket:3471
2020-10-15 13:15:35 -04:00
Jean-Paul Calderone
2960a270ce Declare and document what LocalWrapper is/does 2020-10-15 12:00:03 -04:00
Itamar Turner-Trauring
707ab50606 Test BytesJSONEncoder with Unicode. 2020-10-15 08:37:09 -04:00
Itamar Turner-Trauring
1c976990a1 Make comment more meaningful. 2020-10-15 08:34:56 -04:00
Itamar Turner-Trauring
e6a196c144 Get rid of hopefully unnecessary sort. 2020-10-15 08:33:51 -04:00
Itamar Turner-Trauring
b658a66e7f Merge remote-tracking branch 'origin/master' into 3459.test-checker-python-3 2020-10-15 08:32:53 -04:00
Itamar Turner-Trauring
b094a00458
Merge pull request #860 from tahoe-lafs/3473-mutable-tests-part-1-python-3
Port allmydata.mutable.tests to Python 3: part 1 of N

Fixes ticket:3473
2020-10-15 08:27:45 -04:00
Itamar Turner-Trauring
fecbbb6733 Port to Python 3. 2020-10-14 16:05:02 -04:00
Itamar Turner-Trauring
7faea936df Tests pass on Python 3. 2020-10-14 16:03:53 -04:00
Itamar Turner-Trauring
b5e54f2ed2 Port to Python 3. 2020-10-14 15:50:02 -04:00
Itamar Turner-Trauring
fa92fde04a Port to Python 3. 2020-10-14 15:46:37 -04:00
Itamar Turner-Trauring
43f5a25ec2 Tests pass on Python 3. 2020-10-14 15:45:09 -04:00
Jean-Paul Calderone
40e0ef0fad Directly test CHKCheckerAndUEBFetcher cases 2020-10-14 12:02:56 -04:00
Jean-Paul Calderone
b0159a898e Parameterize the callRemote scheduling 2020-10-14 11:08:40 -04:00
Jean-Paul Calderone
5a51d98479 Add missing chk_upload, document two new attrs, and move them up 2020-10-14 10:58:50 -04:00
Jean-Paul Calderone
9a18843bb1 finish the comment 2020-10-14 10:58:50 -04:00
Jean-Paul Calderone
555b751af0 Further expand existing test coverage by reducing fake quantities
Helper_fake_upload is replaced by more narrowly focused CHKUploadHelper_fake
2020-10-14 10:58:50 -04:00
Jean-Paul Calderone
4e46f9ae12 expand the already-uploaded test for the helper to cover more
shrink the amount of fake code being used and increase the amount of real code
being used
2020-10-14 10:58:50 -04:00
Jean-Paul Calderone
ef11eeb4a2 exercise concurrent upload 2020-10-14 10:58:50 -04:00
Jean-Paul Calderone
8eb518a221 docstring for Helper._active_uploads 2020-10-14 10:58:50 -04:00
Jean-Paul Calderone
c88c2846e2 Point folks at docs for this 2020-10-14 10:58:50 -04:00
Jean-Paul Calderone
5974f5adf9 Stop using eventually in OneShotObserverList 2020-10-14 10:56:50 -04:00
Itamar Turner-Trauring
c0f486a9f6 Work on Python 3. 2020-10-13 09:51:25 -04:00
Itamar Turner-Trauring
50925fcec1 Get rid of more no-longer-needed moves. 2020-10-13 09:49:39 -04:00
Itamar Turner-Trauring
3ea18ca3fc As better alternative to common_py3, make common.py import on Python 3. 2020-10-13 09:45:03 -04:00
Chad Whitacre
a0963fc2da Keep future.builtins imports consistent
- remove int from a stock import
- comment a non-stock import
2020-10-13 08:39:25 -04:00
Chad Whitacre
574c63d350 Port immutable.offloaded to Python 3 2020-10-12 07:25:44 -04:00
Itamar Turner-Trauring
17f0676b3f
Merge branch 'master' into 3459.test-checker-python-3 2020-10-09 10:22:17 -04:00
Ross Patterson
cc8c9c0bdf
Merge pull request #851 from tahoe-lafs/3464.cleanup-bbb-comments
#3455: Address feedback, BBB comments
2020-10-08 13:49:34 -07:00
Ross Patterson
95f2d53f92 chore(refs #3455) Address feedback, BBB comments
https://github.com/tahoe-lafs/tahoe-lafs/pull/845#issuecomment-704469561
2020-10-07 12:28:41 -07:00
Itamar Turner-Trauring
d519d4b2fa
Merge branch 'master' into 3463.more-immutable-python-3 2020-10-07 13:22:04 -04:00
Itamar Turner-Trauring
72cc37bb95
Merge pull request #843 from tahoe-lafs/3458.callremote-unicode
Fix callRemote unicode issues on Python 2 universally, using monkeypatching

Fixes ticket:3458
2020-10-07 13:21:19 -04:00
Itamar Turner-Trauring
5b76bf7f44 Fix trailing whitespace. 2020-10-07 10:12:31 -04:00
Itamar Turner-Trauring
f2e5688723 Port to Python 3. 2020-10-07 10:06:02 -04:00
Itamar Turner-Trauring
af95769927 Merge branch '3458.callremote-unicode' into 3463.more-immutable-python-3 2020-10-07 09:53:30 -04:00
Itamar Turner-Trauring
9dc4f98987 Port to Python 3. 2020-10-07 09:29:41 -04:00
Itamar Turner-Trauring
3e87ba368e Port to Python 3. 2020-10-06 11:32:19 -04:00
Chad Whitacre
e78afd877c
Merge pull request #846 from tahoe-lafs/3456.tweak-docstring
Tweak docstring on FakeCanary
2020-10-06 06:19:54 -04:00
Itamar Turner-Trauring
c680b1d971 Lint fixes. 2020-10-05 11:38:53 -04:00
Ross Patterson
e89bbe1601
Merge pull request #845 from tahoe-lafs/3455.python-3-port-node-round1
3455: Round 1 of porting `allmydata.node`
2020-10-05 08:32:28 -07:00
Itamar Turner-Trauring
dd863a003f Port test_checker.py to Python 3. 2020-10-05 11:12:06 -04:00
Itamar Turner-Trauring
96231fab5f Support bytes in JSON output. 2020-10-05 11:01:11 -04:00
Itamar Turner-Trauring
b60cd13054 Fix the integration test failure. 2020-10-05 10:43:48 -04:00
Itamar Turner-Trauring
fe6917b48b Merge remote-tracking branch 'origin/master' into 3458.callremote-unicode 2020-10-05 10:24:36 -04:00
Chad Whitacre
ad4d7f7612 Tweak docstring
Since this class is used in multiple test modules now, it makes sense to
keep it in common_util instead of test_storage.
2020-10-05 08:34:41 -04:00
Chad Whitacre
2fe2acf4c7
Merge pull request #842 from tahoe-lafs/3456.bye-bye-common_py3
Fold common_py3 back into other files
2020-10-05 08:03:18 -04:00
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
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