diff --git a/newsfragments/3708.minor b/newsfragments/3708.minor new file mode 100644 index 000000000..e69de29bb diff --git a/src/allmydata/util/jsonbytes.py b/src/allmydata/util/jsonbytes.py index f6143f4d1..08e0cb68e 100644 --- a/src/allmydata/util/jsonbytes.py +++ b/src/allmydata/util/jsonbytes.py @@ -28,8 +28,8 @@ if PY2: codecs.register_error("backslashreplace_tahoe_py2", backslashreplace_py2) -def _bytes_to_unicode(any_bytes, obj): - """Create a function that recursively converts bytes to unicode. +def bytes_to_unicode(any_bytes, obj): + """Convert bytes to unicode. :param any_bytes: If True, also support non-UTF-8-encoded bytes. :param obj: Object to de-byte-ify. @@ -63,11 +63,11 @@ class UTF8BytesJSONEncoder(json.JSONEncoder): """ def encode(self, o, **kwargs): return json.JSONEncoder.encode( - self, _bytes_to_unicode(False, o), **kwargs) + self, bytes_to_unicode(False, o), **kwargs) def iterencode(self, o, **kwargs): return json.JSONEncoder.iterencode( - self, _bytes_to_unicode(False, o), **kwargs) + self, bytes_to_unicode(False, o), **kwargs) class AnyBytesJSONEncoder(json.JSONEncoder): @@ -79,11 +79,11 @@ class AnyBytesJSONEncoder(json.JSONEncoder): """ def encode(self, o, **kwargs): return json.JSONEncoder.encode( - self, _bytes_to_unicode(True, o), **kwargs) + self, bytes_to_unicode(True, o), **kwargs) def iterencode(self, o, **kwargs): return json.JSONEncoder.iterencode( - self, _bytes_to_unicode(True, o), **kwargs) + self, bytes_to_unicode(True, o), **kwargs) def dumps(obj, *args, **kwargs): diff --git a/src/allmydata/util/log.py b/src/allmydata/util/log.py index 509deb6a4..b442d30bb 100644 --- a/src/allmydata/util/log.py +++ b/src/allmydata/util/log.py @@ -18,6 +18,16 @@ from pyutil import nummedobj from foolscap.logging import log from twisted.python import log as tw_log +if PY2: + def bytes_to_unicode(ign, obj): + return obj +else: + # We want to convert bytes keys to Unicode, otherwise JSON serialization + # inside foolscap will fail (for details see + # https://github.com/warner/foolscap/issues/88) + from .jsonbytes import bytes_to_unicode + + NOISY = log.NOISY # 10 OPERATIONAL = log.OPERATIONAL # 20 UNUSUAL = log.UNUSUAL # 23 @@ -28,7 +38,8 @@ SCARY = log.SCARY # 35 BAD = log.BAD # 40 -msg = log.msg +def msg(*args, **kwargs): + return log.msg(*args, **bytes_to_unicode(True, kwargs)) # If log.err() happens during a unit test, the unit test should fail. We # accomplish this by sending it to twisted.log too. When a WEIRD/SCARY/BAD @@ -39,7 +50,7 @@ def err(failure=None, _why=None, **kwargs): tw_log.err(failure, _why, **kwargs) if 'level' not in kwargs: kwargs['level'] = log.UNUSUAL - return log.err(failure, _why, **kwargs) + return log.err(failure, _why, **bytes_to_unicode(True, kwargs)) class LogMixin(object): """ I remember a msg id and a facility and pass them to log.msg() """ @@ -57,7 +68,8 @@ class LogMixin(object): if pmsgid is None: pmsgid = self._grandparentmsgid kwargs = {ensure_str(k): v for (k, v) in kwargs.items()} - msgid = log.msg(msg, facility=facility, parent=pmsgid, *args, **kwargs) + msgid = log.msg(msg, facility=facility, parent=pmsgid, *args, + **bytes_to_unicode(True, kwargs)) if self._parentmsgid is None: self._parentmsgid = msgid return msgid