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