summaryrefslogtreecommitdiff
path: root/lib/thandy/formats.py
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2008-10-14 16:20:19 +0000
committerNick Mathewson <nickm@torproject.org>2008-10-14 16:20:19 +0000
commit6caa72442dc5767dea82d8e67089748c11a7fc46 (patch)
treed03b70a2cd994045492c0542bf14ced6a047c20c /lib/thandy/formats.py
parentd90990ee3ecd09a2725b8051759a900ebd488b8c (diff)
Support older versions of simplejson.
git-svn-id: file:///home/or/svnrepo/updater/trunk@17090 55e972cd-5a19-0410-ae62-a4d7a52db4cd
Diffstat (limited to 'lib/thandy/formats.py')
-rw-r--r--lib/thandy/formats.py76
1 files changed, 61 insertions, 15 deletions
diff --git a/lib/thandy/formats.py b/lib/thandy/formats.py
index 42d1086..7db1d8f 100644
--- a/lib/thandy/formats.py
+++ b/lib/thandy/formats.py
@@ -152,6 +152,60 @@ def checkSignatures(signed, keyDB, role=None, path=None):
return SignatureStatus(goodSigs, badSigs, unknownSigs, tangentialSigs)
+def _encodeCanonical_makeiter(obj):
+ """Return an iterator to encode 'obj' canonically, and a nil
+ cleanup function. Works with newer versions of simplejson that
+ have a _make_iterencode method.
+ """
+ def default(o):
+ raise TypeError("Can't encode %r", o)
+ def floatstr(o):
+ raise TypeError("Floats not allowed.")
+ def canonical_str_encoder(s):
+ return '"%s"' % re.sub(r'(["\\])', r'\\\1', s)
+
+ # XXX This is, alas, a hack. I'll submit a canonical JSon patch to
+ # the simplejson folks.
+ iterator = simplejson.encoder._make_iterencode(
+ None, default, canonical_str_encoder, None, floatstr,
+ ":", ",", True, False, True)(obj, 0)
+
+ return iterator, lambda:None
+
+def _encodeCanonical_monkeypatch(obj):
+ """Return an iterator to encode 'obj' canonically, and a cleanup
+ function to un-monkeypatch simplejson. Works with older
+ versions of simplejson. This is not threadsafe wrt other
+ invocations of simplejson, so until we're all upgraded, no
+ doing canonical encodings outside of the main thread.
+ """
+ def default(o):
+ raise TypeError("Can't encode %r", o)
+ save_floatstr = simplejson.encoder.floatstr
+ save_encode_basestring = simplejson.encoder.encode_basestring
+ def floatstr(o):
+ raise TypeError("Floats not allowed.")
+ def canonical_str_encoder(s):
+ return '"%s"' % re.sub(r'(["\\])', r'\\\1', s)
+ simplejson.encoder.floatstr = floatstr
+ simplejson.encoder.encode_basestring = canonical_str_encoder
+ def unpatch():
+ simplejson.encoder.floatstr = save_floatstr
+ simplejson.encoder.encode_basestring = save_encode_basestring
+
+ encoder = simplejson.encoder.JSONEncoder(ensure_ascii=False,
+ check_circular=False,
+ allow_nan=False,
+ sort_keys=True,
+ separators=(",",":"),
+ default=default)
+ return encoder.iterencode(obj), unpatch
+
+if hasattr(simplejson.encoder, "_make_iterencode"):
+ _encodeCanonical = _encodeCanonical_makeiter
+else:
+ _encodeCanonical = _encodeCanonical_monkeypatch
+
def encodeCanonical(obj, outf=None):
"""Encode the object obj in canoncial JSon form, as specified at
http://wiki.laptop.org/go/Canonical_JSON . It's a restricted
@@ -168,27 +222,19 @@ def encodeCanonical(obj, outf=None):
>>> encodeCanonical({"x" : 3, "y" : 2})
'{"x":3,"y":2}'
"""
- def default(o):
- raise TypeError("Can't encode %r", o)
- def floatstr(o):
- raise TypeError("Floats not allowed.")
- def canonical_str_encoder(s):
- return '"%s"' % re.sub(r'(["\\])', r'\\\1', s)
-
- # XXX This is, alas, a hack. I'll submit a canonical JSon patch to
- # the simplejson folks.
-
- iterator = simplejson.encoder._make_iterencode(
- None, default, canonical_str_encoder, None, floatstr,
- ":", ",", True, False, True)(obj, 0)
result = None
if outf == None:
result = [ ]
outf = result.append
- for u in iterator:
- outf(u.encode("utf-8"))
+ iterator, cleanup = _encodeCanonical(obj)
+
+ try:
+ for u in iterator:
+ outf(u.encode("utf-8"))
+ finally:
+ cleanup()
if result is not None:
return "".join(result)