[or-cvs] r17090: {updater} Support older versions of simplejson. (updater/trunk/lib/thandy)

nickm at seul.org nickm at seul.org
Tue Oct 14 16:20:19 UTC 2008


Author: nickm
Date: 2008-10-14 12:20:19 -0400 (Tue, 14 Oct 2008)
New Revision: 17090

Modified:
   updater/trunk/lib/thandy/formats.py
Log:
Support older versions of simplejson.

Modified: updater/trunk/lib/thandy/formats.py
===================================================================
--- updater/trunk/lib/thandy/formats.py	2008-10-14 15:56:10 UTC (rev 17089)
+++ updater/trunk/lib/thandy/formats.py	2008-10-14 16:20:19 UTC (rev 17090)
@@ -152,6 +152,60 @@
 
     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 @@
        >>> 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)
 



More information about the tor-commits mailing list