[pypy-commit] pypy expose-jsonmap: expose dictstructure.append, which needs a bit of refactoring

cfbolz pypy.commits at gmail.com
Mon Nov 4 05:33:41 EST 2019


Author: Carl Friedrich Bolz-Tereick <cfbolz at gmx.de>
Branch: expose-jsonmap
Changeset: r97947:68a281f37aaa
Date: 2019-11-04 11:22 +0100
http://bitbucket.org/pypy/pypy/changeset/68a281f37aaa/

Log:	expose dictstructure.append, which needs a bit of refactoring

diff --git a/pypy/module/__pypy__/interp_dictstructure.py b/pypy/module/__pypy__/interp_dictstructure.py
--- a/pypy/module/__pypy__/interp_dictstructure.py
+++ b/pypy/module/__pypy__/interp_dictstructure.py
@@ -16,7 +16,7 @@
         if type(w_x) is not W_UnicodeObject:
             raise oefmt(space.w_TypeError, "expected unicode, got %T", w_x)
         u = space.utf8_w(w_x)
-        m = m.get_next(w_x, u, 0, len(u), terminator)
+        m = m.get_next(w_x, u, 0, len(u))
         if m is None:
             raise oefmt(space.w_ValueError, "repeated key %R", w_x)
         if not m.is_state_useful():
diff --git a/pypy/module/__pypy__/test/test_dictstructure.py b/pypy/module/__pypy__/test/test_dictstructure.py
--- a/pypy/module/__pypy__/test/test_dictstructure.py
+++ b/pypy/module/__pypy__/test/test_dictstructure.py
@@ -29,3 +29,13 @@
         from __pypy__ import newdictstructure
         with raises(ValueError):
             newdictstructure([u"a", u"a"])
+
+    def test_getnext(self):
+        from __pypy__ import newdictstructure
+        s = newdictstructure([u"a"])
+        s1 = s.append(u"b")
+        assert s.append(u"b") is s1
+        assert s1.instantiate_dict([1, 2]) == {u"a": 1, u"b": 2}
+        with raises(ValueError):
+            s.append(u"a")
+
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
@@ -638,7 +638,7 @@
             self._raise("Key name must be string at char %d", i)
         i += 1
         w_key = self._decode_key_string(i)
-        return currmap.get_next(w_key, self.s, start, self.pos, self.startmap)
+        return currmap.get_next(w_key, self.s, start, self.pos)
 
     def _decode_key_string(self, i):
         """ decode key at position i as a string. Key strings are always
@@ -800,7 +800,7 @@
         elif self.nextmap_first:
             self.nextmap_first._check_invariants()
 
-    def get_next(self, w_key, string, start, stop, terminator):
+    def get_next(self, w_key, string, start, stop):
         """ Returns the next map, given a wrapped key w_key, the json input
         string with positions start and stop, as well as a terminator.
 
@@ -819,7 +819,7 @@
 
         if nextmap_first is None:
             # first transition ever seen, don't initialize nextmap_all
-            next = self._make_next_map(w_key, string[start:stop])
+            next, terminator = self._make_next_map(w_key, string[start:stop])
             if next is None:
                 return None
             self.nextmap_first = next
@@ -835,7 +835,7 @@
                     return next
             # if we are at this point we didn't find the transition yet, so
             # create a new one
-            next = self._make_next_map(w_key, string[start:stop])
+            next, terminator = self._make_next_map(w_key, string[start:stop])
             if next is None:
                 return None
             self.nextmap_all[w_key] = next
@@ -886,9 +886,10 @@
         check = self
         while isinstance(check, JSONMap):
             if check.w_key._utf8 == w_key._utf8:
-                return None
+                return None, None
             check = check.prev
-        return JSONMap(self.space, self, w_key, key_repr)
+        assert isinstance(check, Terminator)
+        return JSONMap(self.space, self, w_key, key_repr), check
 
     def fill_dict(self, dict_w, values_w):
         """ recursively fill the dictionary dict_w in the correct order,
@@ -899,21 +900,36 @@
     # exposed methods
 
     def descr_instantiate_dict(self, space, w_l):
-        from pypy.objspace.std.jsondict import from_values_and_jsonmap
+        """ Create a dict instance given from the structure, using the list l
+        as values. It must have the same length as the structure has keys. """
+        from pypy.objspace.std.jsondict import from_values_and_jsonmap_checked
         from pypy.objspace.std.jsondict import devolve_jsonmap_dict
         l_w = space.listview(w_l)
         if not isinstance(self, JSONMap):
             return space.newdict()
-        keys_w = self.get_keys_in_order()
-        if len(l_w) != len(keys_w):
-            raise oefmt(space.w_ValueError, "expected %s values, got %s", str(len(keys_w)), str(len(l_w)))
-        w_dict = from_values_and_jsonmap(self.space, l_w[:], self)
+        w_dict = from_values_and_jsonmap_checked(self.space, l_w[:], self)
         if self.is_state_blocked():
             devolve_jsonmap_dict(w_dict)
         return w_dict
 
     def descr_repr(self, space):
-        return space.newtext("<DictStructure [%s]>" % ", ".join([space.text_w(space.repr(w_key)) for w_key in self.get_keys_in_order()]))
+        res = []
+        curr = self
+        while type(curr) is JSONMap:
+            res.append(space.text_w(space.repr(self.w_key)))
+            curr = curr.prev
+        res.reverse()
+        return space.newtext("<DictStructure [%s]>" % ", ".join(res))
+
+    def descr_append(self, space, w_u):
+        from pypy.objspace.std.unicodeobject import W_UnicodeObject
+        if type(w_u) is not W_UnicodeObject:
+            raise oefmt(space.w_TypeError, "expected unicode, got %T", w_u)
+        u = space.utf8_w(w_u)
+        res = self.get_next(w_u, u, 0, len(u))
+        if res is None:
+            raise oefmt(space.w_ValueError, "repeated key %R", w_u)
+        return res
 
 
     # ____________________________________________________________
@@ -1190,5 +1206,6 @@
     __repr__ = interp2app(MapBase.descr_repr),
     last_key = GetSetProperty(get_last_key, name="last_key"),
     previous = GetSetProperty(get_previous, name="previous"),
+    append = interp2app(MapBase.descr_append),
 )
 MapBase.typedef.acceptable_as_base_class = False
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
@@ -19,7 +19,7 @@
         w_a = self.space.newutf8("a", 1)
         w_b = self.space.newutf8("b", 1)
         w_c = self.space.newutf8("c", 1)
-        m1 = m.get_next(w_a, '"a"', 0, 3, m)
+        m1 = m.get_next(w_a, '"a"', 0, 3)
         assert m1.w_key == w_a
         assert m1.nextmap_first is None
         assert m1.key_repr == '"a"'
@@ -27,16 +27,16 @@
         assert not m1.key_repr_cmp('b": 123', 0)
         assert m.nextmap_first.w_key == w_a
 
-        m2 = m.get_next(w_a, '"a"', 0, 3, m)
+        m2 = m.get_next(w_a, '"a"', 0, 3)
         assert m2 is m1
 
-        m3 = m.get_next(w_b, '"b"', 0, 3, m)
+        m3 = m.get_next(w_b, '"b"', 0, 3)
         assert m3.w_key == w_b
         assert m3.nextmap_first is None
         assert m3.key_repr == '"b"'
         assert m.nextmap_first is m1
 
-        m4 = m3.get_next(w_c, '"c"', 0, 3, m)
+        m4 = m3.get_next(w_c, '"c"', 0, 3)
         assert m4.w_key == w_c
         assert m4.nextmap_first is None
         assert m4.key_repr == '"c"'
@@ -49,9 +49,9 @@
         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)
+        m1 = m.get_next(w_a, 'a"', 0, 2)
+        m2 = m1.get_next(w_b, 'b"', 0, 2)
+        m3 = m2.get_next(w_c, 'c"', 0, 2)
         d = OrderedDict()
         m3.fill_dict(d, [space.w_None, space.w_None, space.w_None])
         assert list(d) == [w_a, w_b, w_c]
@@ -61,10 +61,10 @@
         w_a = self.space.newutf8("a", 1)
         w_b = self.space.newutf8("b", 1)
         w_c = self.space.newutf8("c", 1)
-        m1 = m.get_next(w_a, '"a"', 0, 3, m)
-        m1 = m1.get_next(w_b, '"b"', 0, 3, m)
-        m1 = m1.get_next(w_c, '"c"', 0, 3, m)
-        m2 = m1.get_next(w_a, '"a"', 0, 3, m)
+        m1 = m.get_next(w_a, '"a"', 0, 3)
+        m1 = m1.get_next(w_b, '"b"', 0, 3)
+        m1 = m1.get_next(w_c, '"c"', 0, 3)
+        m2 = m1.get_next(w_a, '"a"', 0, 3)
         assert m2 is None
 
 
@@ -111,10 +111,10 @@
         w_d = self.space.newutf8("d", 1)
         base = Terminator(self.space)
         base.instantiation_count = 6
-        m1 = base.get_next(w_a, 'a"', 0, 2, base)
-        m2 = m1.get_next(w_b, 'b"', 0, 2, base)
-        m3 = m2.get_next(w_c, 'c"', 0, 2, base)
-        m4 = m2.get_next(w_d, 'd"', 0, 2, base)
+        m1 = base.get_next(w_a, 'a"', 0, 2)
+        m2 = m1.get_next(w_b, 'b"', 0, 2)
+        m3 = m2.get_next(w_c, 'c"', 0, 2)
+        m4 = m2.get_next(w_d, 'd"', 0, 2)
         return base, m1, m2, m3, m4
 
     # unit tests for map state transistions
@@ -152,7 +152,7 @@
         assert m2.number_of_leaves == 2
         assert m3.number_of_leaves == 1
         assert m4.number_of_leaves == 1
-        m5 = m2.get_next(w_x, 'x"', 0, 2, base)
+        m5 = m2.get_next(w_x, 'x"', 0, 2)
         assert base.number_of_leaves == 3
         assert m1.number_of_leaves == 3
         assert m2.number_of_leaves == 3
@@ -161,7 +161,7 @@
     def test_number_of_leaves_after_mark_blocked(self):
         w_x = self.space.newutf8("x", 1)
         base, m1, m2, m3, m4 = self._make_some_maps()
-        m5 = m2.get_next(w_x, 'x"', 0, 2, base)
+        m5 = m2.get_next(w_x, 'x"', 0, 2)
         assert base.number_of_leaves == 3
         m2.mark_blocked(base)
         assert base.number_of_leaves == 1
@@ -186,11 +186,11 @@
         w_d = self.space.newutf8("d", 1)
         base = Terminator(self.space)
         base.instantiation_count = 6
-        m1 = base.get_next(w_a, 'a"', 0, 2, base)
-        m2 = base.get_next(w_b, 'b"', 0, 2, base)
-        m3 = base.get_next(w_c, 'c"', 0, 2, base)
-        m4 = base.get_next(w_d, 'd"', 0, 2, base)
-        m5 = m4.get_next(w_a, 'a"', 0, 2, base)
+        m1 = base.get_next(w_a, 'a"', 0, 2)
+        m2 = base.get_next(w_b, 'b"', 0, 2)
+        m3 = base.get_next(w_c, 'c"', 0, 2)
+        m4 = base.get_next(w_d, 'd"', 0, 2)
+        m5 = m4.get_next(w_a, 'a"', 0, 2)
         base.instantiation_count = 7
         m1.instantiation_count = 2
         m2.instantiation_count = 2
@@ -216,8 +216,8 @@
         s = '{"a": 1, "b": 2, "c": 3}'
         dec = JSONDecoder(space, s)
         dec.startmap = base = Terminator(space)
-        m1 = base.get_next(w_a, 'a"', 0, 2, base)
-        m2 = m1.get_next(w_b, 'b"', 0, 2, base)
+        m1 = base.get_next(w_a, 'a"', 0, 2)
+        m2 = m1.get_next(w_b, 'b"', 0, 2)
         m2.mark_blocked(base)
         w_res = dec.decode_object(1)
         assert space.int_w(space.len(w_res)) == 3
@@ -233,10 +233,10 @@
         w_u = self.space.newutf8("u", 1)
         space = self.space
         base = Terminator(space)
-        m1 = base.get_next(w_a, 'a"', 0, 2, base)
-        m2 = m1.get_next(w_b, 'b"', 0, 2, base)
-        m2.get_next(w_x, 'x"', 0, 2, base)
-        m2.get_next(w_u, 'u"', 0, 2, base)
+        m1 = base.get_next(w_a, 'a"', 0, 2)
+        m2 = m1.get_next(w_b, 'b"', 0, 2)
+        m2.get_next(w_x, 'x"', 0, 2)
+        m2.get_next(w_u, 'u"', 0, 2)
         assert base.number_of_leaves == 2
         m2.mark_blocked(base)
         assert base.number_of_leaves == 1
diff --git a/pypy/objspace/std/jsondict.py b/pypy/objspace/std/jsondict.py
--- a/pypy/objspace/std/jsondict.py
+++ b/pypy/objspace/std/jsondict.py
@@ -8,7 +8,7 @@
 from pypy.objspace.std.dictmultiobject import (
     UnicodeDictStrategy, DictStrategy,
     create_iterator_classes, W_DictObject)
-
+from pypy.interpreter.error import oefmt
 
 def from_values_and_jsonmap(space, values_w, jsonmap):
     debug.make_sure_not_resized(values_w)
@@ -21,6 +21,18 @@
     storage = strategy.erase(values_w)
     return W_DictObject(space, strategy, storage)
 
+def from_values_and_jsonmap_checked(space, values_w, jsonmap):
+    debug.make_sure_not_resized(values_w)
+    strategy = jsonmap.strategy_instance
+    if strategy is None:
+        jsonmap.strategy_instance = strategy = JsonDictStrategy(space, jsonmap)
+    keys_w = strategy.get_keys_in_order()
+    if len(values_w) != len(keys_w):
+        raise oefmt(space.w_ValueError, "expected %s values, got %s", str(len(keys_w)), str(len(values_w)))
+    storage = strategy.erase(values_w)
+    return W_DictObject(space, strategy, storage)
+
+
 def devolve_jsonmap_dict(w_dict):
     assert isinstance(w_dict, W_DictObject)
     strategy = w_dict.get_strategy()
diff --git a/pypy/objspace/std/test/test_jsondict.py b/pypy/objspace/std/test/test_jsondict.py
--- a/pypy/objspace/std/test/test_jsondict.py
+++ b/pypy/objspace/std/test/test_jsondict.py
@@ -10,25 +10,23 @@
         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)
+        m1 = m.get_next(w_a, 'a"', 0, 2)
         dm1 = JsonDictStrategy(space, m1)
         assert dm1.get_index(w_a) == 0
         assert dm1.get_index(w_b) == -1
 
-        m2 = m.get_next(w_b, 'b"', 0, 2, m)
+        m2 = m.get_next(w_b, 'b"', 0, 2)
         dm2 = JsonDictStrategy(space, m2)
         assert dm2.get_index(w_b) == 0
         assert dm2.get_index(w_a) == -1
 
-        m3 = m2.get_next(w_c, 'c"', 0, 2, m)
+        m3 = m2.get_next(w_c, 'c"', 0, 2)
         dm3 = JsonDictStrategy(space, m3)
         assert dm3.get_index(w_b) == 0
         assert dm3.get_index(w_c) == 1
         assert dm3.get_index(w_a) == -1
 
 
-
-
 class AppTest(object):
     spaceconfig = {"objspace.usemodules._pypyjson": True}
 
@@ -150,8 +148,8 @@
         w_a = self.space.newutf8("a", 1)
         w_b = self.space.newutf8("b", 1)
         base = interp_decoder.Terminator(space)
-        m1 = base.get_next(w_a, 'a"', 0, 2, base)
-        m2 = m1.get_next(w_b, 'b"', 0, 2, base)
+        m1 = base.get_next(w_a, 'a"', 0, 2)
+        m2 = m1.get_next(w_b, 'b"', 0, 2)
 
         w_d = from_values_and_jsonmap(space, [w_a, w_b], m2)
         return base, m2, w_d, w_a, w_b


More information about the pypy-commit mailing list