diff options
author | Tim Burke <tim.burke@gmail.com> | 2018-11-02 21:38:49 +0000 |
---|---|---|
committer | Tim Burke <tim.burke@gmail.com> | 2018-11-02 21:38:53 +0000 |
commit | c112203e0ef8f69cdd5a78c260029839a8763d26 (patch) | |
tree | 7c0573d15254b9903b4a2f828fe6bc643f76ffdf /swift/__init__.py | |
parent | 887ba87c5a1114eb43de78f42f0a62cd6fd9706f (diff) | |
download | swift-c112203e0ef8f69cdd5a78c260029839a8763d26.tar.gz |
py3: Monkey-patch json.loads to accept bytes on py35
I'm tired of creating code churn where I just slap
.decode("nearly arbitrary choice of encoding")
in a bunch of places.
Change-Id: I79b2bc59fed130ca537e96c1074212861d7db6b8
Diffstat (limited to 'swift/__init__.py')
-rw-r--r-- | swift/__init__.py | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/swift/__init__.py b/swift/__init__.py index 9d0e8896f..f9f093132 100644 --- a/swift/__init__.py +++ b/swift/__init__.py @@ -14,6 +14,7 @@ # limitations under the License. import os +import sys import gettext import pkg_resources @@ -39,3 +40,37 @@ _t = gettext.translation('swift', localedir=_localedir, fallback=True) def gettext_(msg): return _t.gettext(msg) + + +if (3, 0) <= sys.version_info[:2] <= (3, 5): + # In the development of py3, json.loads() stopped accepting byte strings + # for a while. https://bugs.python.org/issue17909 got fixed for py36, but + # since it was termed an enhancement and not a regression, we don't expect + # any backports. At the same time, it'd be better if we could avoid + # leaving a whole bunch of json.loads(resp.body.decode(...)) scars in the + # code that'd probably persist even *after* we drop support for 3.5 and + # earlier. So, monkey patch stdlib. + import json + if not getattr(json.loads, 'patched_to_decode', False): + class JsonLoadsPatcher(object): + def __init__(self, orig): + self._orig = orig + + def __call__(self, s, **kw): + if isinstance(s, bytes): + # No fancy byte-order mark detection for us; just assume + # UTF-8 and raise a UnicodeDecodeError if appropriate. + s = s.decode('utf8') + return self._orig(s, **kw) + + def __getattribute__(self, attr): + if attr == 'patched_to_decode': + return True + if attr == '_orig': + return super().__getattribute__(attr) + # Pass through all other attrs to the original; among other + # things, this preserves doc strings, etc. + return getattr(self._orig, attr) + + json.loads = JsonLoadsPatcher(json.loads) + del JsonLoadsPatcher |