From 5899cfdabdcc2e108d510588922586bf9f90c3d9 Mon Sep 17 00:00:00 2001 From: Itamar Turner-Trauring Date: Thu, 1 Oct 2020 10:48:09 -0400 Subject: [PATCH] Fix callRemote unicode issues on Python 2 universally, using monkeypatching. --- newsfragments/3458.minor | 0 src/allmydata/__init__.py | 6 +++ src/allmydata/_monkeypatch.py | 41 +++++++++++++++++++++ src/allmydata/immutable/downloader/share.py | 6 +-- src/allmydata/util/_python3.py | 1 + 5 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 newsfragments/3458.minor create mode 100644 src/allmydata/_monkeypatch.py diff --git a/newsfragments/3458.minor b/newsfragments/3458.minor new file mode 100644 index 000000000..e69de29bb diff --git a/src/allmydata/__init__.py b/src/allmydata/__init__.py index bbfcb89d4..15d5fb240 100644 --- a/src/allmydata/__init__.py +++ b/src/allmydata/__init__.py @@ -42,3 +42,9 @@ __full_version__ = __appname__ + '/' + str(__version__) # Install Python 3 module locations in Python 2: from future import standard_library standard_library.install_aliases() + + +# Monkey-patch 3rd party libraries: +from ._monkeypatch import patch +patch() +del patch diff --git a/src/allmydata/_monkeypatch.py b/src/allmydata/_monkeypatch.py new file mode 100644 index 000000000..87475f7de --- /dev/null +++ b/src/allmydata/_monkeypatch.py @@ -0,0 +1,41 @@ +""" +Monkey-patching of third party libraries. + +Ported to Python 3. +""" + + +from __future__ import unicode_literals +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from future.utils import PY2 +if PY2: + from future.builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, dict, list, object, range, str, max, min # noqa: F401 + + +def patch(): + """Path third-party libraries to make Tahoe-LAFS work.""" + # Make sure Foolscap always get native strings passed to method names in callRemote. + # This can be removed when any one of the following happens: + # + # 1. Tahoe-LAFS on Python 2 switches to version of Foolscap that fixes + # https://github.com/warner/foolscap/issues/72 + # 2. Foolscap is dropped as a dependency. + # 3. Tahoe-LAFS drops Python 2 support. + + if PY2: + # Only tested with this version; ensure correctness with new releases, + # and then either update the assert or hopefully drop the monkeypatch. + from foolscap import __version__ + assert __version__ == "0.13.1", "Wrong version %s of Foolscap" % (__version__,) + + from foolscap.referenceable import RemoteReference + original_getMethodInfo = RemoteReference._getMethodInfo + + def _getMethodInfo(self, name): + if isinstance(name, str): + name = name.encode("utf-8") + return original_getMethodInfo(self, name) + RemoteReference._getMethodInfo = _getMethodInfo diff --git a/src/allmydata/immutable/downloader/share.py b/src/allmydata/immutable/downloader/share.py index 261ed79e1..f279018ba 100644 --- a/src/allmydata/immutable/downloader/share.py +++ b/src/allmydata/immutable/downloader/share.py @@ -6,7 +6,7 @@ from __future__ import division from __future__ import print_function from __future__ import unicode_literals -from future.utils import PY2, native_str +from future.utils import PY2 if PY2: from future.builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, dict, list, object, range, str, max, min # noqa: F401 @@ -765,9 +765,7 @@ class Share(object): level=log.WEIRD, umid="qZu0wg")) def _send_request(self, start, length): - # For some reason tests fail on Python 2 if this is not a native - # string... - return self._rref.callRemote(native_str("read"), start, length) + return self._rref.callRemote("read", start, length) def _got_data(self, data, start, length, block_ev, lp): block_ev.finished(len(data), now()) diff --git a/src/allmydata/util/_python3.py b/src/allmydata/util/_python3.py index ccff0958a..8d00afc2c 100644 --- a/src/allmydata/util/_python3.py +++ b/src/allmydata/util/_python3.py @@ -24,6 +24,7 @@ if PY2: # Keep these sorted alphabetically, to reduce merge conflicts: PORTED_MODULES = [ + "allmydata._monkeypatch", "allmydata.codec", "allmydata.crypto", "allmydata.crypto.aes",