From 935d1856967cb18e5403658f5d6d3cb5c24085c4 Mon Sep 17 00:00:00 2001
From: Brian Warner <warner@allmydata.com>
Date: Tue, 30 Sep 2008 15:21:06 -0700
Subject: [PATCH] tolerate simplejson-2.0.0 and newer, which frequently return
 bytestrings instead of unicode objects. Closes #523

---
 src/allmydata/scripts/tahoe_cp.py | 16 ++++++++++++----
 src/allmydata/scripts/tahoe_ls.py |  1 +
 src/allmydata/scripts/tahoe_mv.py |  4 ++--
 src/allmydata/test/check_load.py  |  5 ++++-
 src/allmydata/test/test_web.py    | 12 ++++++++----
 src/allmydata/web/directory.py    |  1 +
 6 files changed, 28 insertions(+), 11 deletions(-)

diff --git a/src/allmydata/scripts/tahoe_cp.py b/src/allmydata/scripts/tahoe_cp.py
index 32e0ca9e..91cc1ea2 100644
--- a/src/allmydata/scripts/tahoe_cp.py
+++ b/src/allmydata/scripts/tahoe_cp.py
@@ -222,7 +222,9 @@ class TahoeDirectorySource:
         nodetype, d = parsed
         assert nodetype == "dirnode"
         self.mutable = d.get("mutable", False) # older nodes don't provide it
-        self.children_d = d["children"]
+        self.children_d = dict( [(unicode(name),value)
+                                 for (name,value)
+                                 in d["children"].iteritems()] )
         self.children = None
 
     def init_from_parsed(self, parsed):
@@ -230,7 +232,9 @@ class TahoeDirectorySource:
         self.writecap = ascii_or_none(d.get("rw_uri"))
         self.readcap = ascii_or_none(d.get("ro_uri"))
         self.mutable = d.get("mutable", False) # older nodes don't provide it
-        self.children_d = d["children"]
+        self.children_d = dict( [(unicode(name),value)
+                                 for (name,value)
+                                 in d["children"].iteritems()] )
         self.children = None
 
     def populate(self, recurse):
@@ -294,7 +298,9 @@ class TahoeDirectoryTarget:
         self.writecap = ascii_or_none(d.get("rw_uri"))
         self.readcap = ascii_or_none(d.get("ro_uri"))
         self.mutable = d.get("mutable", False) # older nodes don't provide it
-        self.children_d = d["children"]
+        self.children_d = dict( [(unicode(name),value)
+                                 for (name,value)
+                                 in d["children"].iteritems()] )
         self.children = None
 
     def init_from_grid(self, writecap, readcap):
@@ -308,7 +314,9 @@ class TahoeDirectoryTarget:
         nodetype, d = parsed
         assert nodetype == "dirnode"
         self.mutable = d.get("mutable", False) # older nodes don't provide it
-        self.children_d = d["children"]
+        self.children_d = dict( [(unicode(name),value)
+                                 for (name,value)
+                                 in d["children"].iteritems()] )
         self.children = None
 
     def just_created(self, writecap):
diff --git a/src/allmydata/scripts/tahoe_ls.py b/src/allmydata/scripts/tahoe_ls.py
index 39d6d49b..d0d63799 100644
--- a/src/allmydata/scripts/tahoe_ls.py
+++ b/src/allmydata/scripts/tahoe_ls.py
@@ -53,6 +53,7 @@ def list(options):
     rows = []
 
     for name in childnames:
+        name = unicode(name)
         child = children[name]
         childtype = child[0]
         ctime = child[1]["metadata"].get("ctime")
diff --git a/src/allmydata/scripts/tahoe_mv.py b/src/allmydata/scripts/tahoe_mv.py
index c06631f9..6889032e 100644
--- a/src/allmydata/scripts/tahoe_mv.py
+++ b/src/allmydata/scripts/tahoe_mv.py
@@ -25,8 +25,8 @@ def mv(options, mode="move"):
     data = urllib.urlopen(from_url + "?t=json").read()
     nodetype, attrs = simplejson.loads(data)
     cap = attrs.get("rw_uri") or attrs["ro_uri"]
-    # simplejson always returns unicode, but we know that it's really just an
-    # ASCII file-cap.
+    # simplejson sometimes returns unicode, but we know that it's really just
+    # an ASCII file-cap.
     cap = str(cap)
 
     # now get the target
diff --git a/src/allmydata/test/check_load.py b/src/allmydata/test/check_load.py
index 5515dde8..6b4d2cd5 100644
--- a/src/allmydata/test/check_load.py
+++ b/src/allmydata/test/check_load.py
@@ -115,7 +115,10 @@ def listdir(nodeurl, root, vdrive_pathname):
     assert nodetype == "dirnode"
     global directories_read
     directories_read += 1
-    return d['children']
+    children = dict( [(unicode(name),value)
+                      for (name,value)
+                      in d["children"].iteritems()] )
+    return children
 
 
 def choose_random_descendant(server_url, root, pathname=""):
diff --git a/src/allmydata/test/test_web.py b/src/allmydata/test/test_web.py
index 365b5de9..93d7ce38 100644
--- a/src/allmydata/test/test_web.py
+++ b/src/allmydata/test/test_web.py
@@ -197,7 +197,7 @@ class WebMixin(object):
     def failUnlessIsBarJSON(self, res):
         data = simplejson.loads(res)
         self.failUnless(isinstance(data, list))
-        self.failUnlessEqual(data[0], "filenode")
+        self.failUnlessEqual(data[0], u"filenode")
         self.failUnless(isinstance(data[1], dict))
         self.failIf(data[1]["mutable"])
         self.failIf("rw_uri" in data[1]) # immutable
@@ -214,11 +214,13 @@ class WebMixin(object):
         self.failUnlessEqual(data[1]["rw_uri"], self._foo_uri)
         self.failUnlessEqual(data[1]["ro_uri"], self._foo_readonly_uri)
 
-        kidnames = sorted(data[1]["children"])
+        kidnames = sorted([unicode(n) for n in data[1]["children"]])
         self.failUnlessEqual(kidnames,
                              [u"bar.txt", u"blockingfile", u"empty",
                               u"n\u00fc.txt", u"sub"])
-        kids = data[1]["children"]
+        kids = dict( [(unicode(name),value)
+                      for (name,value)
+                      in data[1]["children"].iteritems()] )
         self.failUnlessEqual(kids[u"sub"][0], "dirnode")
         self.failUnless("metadata" in kids[u"sub"][1])
         self.failUnless("ctime" in kids[u"sub"][1]["metadata"])
@@ -1226,7 +1228,9 @@ class Web(WebMixin, unittest.TestCase):
         def _check_page_json(res):
             parsed = simplejson.loads(res)
             self.failUnlessEqual(parsed[0], "dirnode")
-            children = parsed[1]["children"]
+            children = dict( [(unicode(name),value)
+                              for (name,value)
+                              in parsed[1]["children"].iteritems()] )
             self.failUnless("new.txt" in children)
             new_json = children["new.txt"]
             self.failUnlessEqual(new_json[0], "filenode")
diff --git a/src/allmydata/web/directory.py b/src/allmydata/web/directory.py
index 5990570a..f6b8055e 100644
--- a/src/allmydata/web/directory.py
+++ b/src/allmydata/web/directory.py
@@ -372,6 +372,7 @@ class DirectoryNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin):
             raise
         cs = []
         for name, (file_or_dir, mddict) in children.iteritems():
+            name = unicode(name) # simplejson-2.0.1 returns str *or* unicode
             cap = str(mddict.get('rw_uri') or mddict.get('ro_uri'))
             cs.append((name, cap, mddict.get('metadata')))
         d = self.node.set_children(cs, replace)
-- 
2.45.2