Author: Carl Friedrich Bolz-Tereick <[email protected]>
Branch: json-decoder-maps
Changeset: r97572:06effcd1097c
Date: 2019-09-20 17:07 +0200
http://bitbucket.org/pypy/pypy/changeset/06effcd1097c/

Log:    fix remaining anto comment: when hitting a blocked map, insert keys
        in the correct order into the real dict, to preserve dict order

diff --git a/pypy/module/_pypyjson/interp_decoder.py 
b/pypy/module/_pypyjson/interp_decoder.py
--- a/pypy/module/_pypyjson/interp_decoder.py
+++ b/pypy/module/_pypyjson/interp_decoder.py
@@ -388,28 +388,8 @@
         return get_jsonmap_from_dict(w_dict)
 
     def _switch_to_dict(self, currmap, values_w, nextindex):
-        # <antocuni> not sure if this is a problem, but it's something which I
-        # noticed and I think it's worth thinking about it for 5 minutes.
-        # <cfbolz> are you also concerned about the fact that jsonmap dicts
-        # have their keys in the opposite order generally? or just the weird
-        # "c b a | d e f" effect?
-        #
-        # In Python3 dicts preserve the order of keys; this means that a
-        # "naive" json parser produces dicts whose keys are in the same order
-        # as in the source document (CPython 3.7 does this). I don't think it
-        # is guaranteed at all, but I'd not be surprised if real world
-        # programs will rely on this anyway.
-        #
-        # But with the logic here we get the weird effect that the resulting
-        # dicts contains the first keys in reversed order (up to when we reach
-        # the blocked state in the map), then the subsequent ones are in the
-        # "correct" order.
         dict_w = self._create_empty_dict()
-        index = nextindex - 1
-        while isinstance(currmap, JSONMap):
-            dict_w[currmap.w_key] = values_w[index]
-            index -= 1
-            currmap = currmap.prev
+        currmap.fill_dict(dict_w, values_w)
         assert len(dict_w) == nextindex
         return dict_w
 
@@ -878,6 +858,11 @@
     def _make_next_map(self, w_key, key_repr):
         return JSONMap(self.space, self, w_key, key_repr)
 
+    def fill_dict(self, dict_w, values_w):
+        """ recursively fill the dictionary dict_w in the correct order,
+        reading from values_w."""
+        raise NotImplementedError("abstract base")
+
     def _all_dot(self, output):
         identity = objectmodel.compute_unique_id(self)
         output.append('%s [shape=box%s];' % (identity, self._get_dot_text()))
@@ -950,6 +935,11 @@
         assert min_fringe
         min_fringe.mark_blocked(self)
 
+    def fill_dict(self, dict_w, values_w):
+        """ recursively fill the dictionary dict_w in the correct order,
+        reading from values_w."""
+        return 0
+
     def _check_invariants(self):
         for fringe in self.current_fringe:
             assert fringe.state == MapBase.FRINGE
@@ -1088,6 +1078,11 @@
             i += 1
         return True
 
+    def fill_dict(self, dict_w, values_w):
+        index = self.prev.fill_dict(dict_w, values_w)
+        dict_w[self.w_key] = values_w[index]
+        return index + 1
+
     # _____________________________________________________
     # methods for JsonDictStrategy
 
diff --git a/pypy/module/_pypyjson/test/test__pypyjson.py 
b/pypy/module/_pypyjson/test/test__pypyjson.py
--- a/pypy/module/_pypyjson/test/test__pypyjson.py
+++ b/pypy/module/_pypyjson/test/test__pypyjson.py
@@ -60,6 +60,21 @@
         assert m3.get_index(w_c) == 1
         assert m3.get_index(w_a) == -1
 
+    def test_jsonmap_fill_dict(self):
+        from collections import OrderedDict
+        m = Terminator(self.space)
+        space = self.space
+        w_a = space.newutf8("a", 1)
+        w_b = space.newutf8("b", 1)
+        w_c = space.newutf8("c", 1)
+        m1 = m.get_next(w_a, 'a"', 0, 2, m)
+        m2 = m1.get_next(w_b, 'b"', 0, 2, m)
+        m3 = m2.get_next(w_c, 'c"', 0, 2, m)
+        d = OrderedDict()
+        m3.fill_dict(d, [space.w_None, space.w_None, space.w_None])
+        assert list(d) == [w_a, w_b, w_c]
+
+
     def test_decode_key_map(self):
         m = Terminator(self.space)
         m_diff = Terminator(self.space)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to