[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