summaryrefslogtreecommitdiff
path: root/swift/__init__.py
diff options
context:
space:
mode:
authorTim Burke <tim.burke@gmail.com>2018-11-02 21:38:49 +0000
committerTim Burke <tim.burke@gmail.com>2018-11-02 21:38:53 +0000
commitc112203e0ef8f69cdd5a78c260029839a8763d26 (patch)
tree7c0573d15254b9903b4a2f828fe6bc643f76ffdf /swift/__init__.py
parent887ba87c5a1114eb43de78f42f0a62cd6fd9706f (diff)
downloadswift-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__.py35
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