Author: Carl Friedrich Bolz-Tereick <[email protected]>
Branch: expose-jsonmap
Changeset: r97840:8504b741f563
Date: 2019-10-24 07:49 +0200
http://bitbucket.org/pypy/pypy/changeset/8504b741f563/

Log:    expose a way to create a dict structure from applevel, and
        instantiate it. can be used in csv module and other places.

diff --git a/pypy/module/__pypy__/interp_dictstructure.py 
b/pypy/module/__pypy__/interp_dictstructure.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/__pypy__/interp_dictstructure.py
@@ -0,0 +1,26 @@
+from pypy.interpreter.baseobjspace import W_Root
+from pypy.interpreter.error import oefmt
+from pypy.interpreter.gateway import interp2app, unwrap_spec
+from pypy.interpreter.typedef import TypeDef
+
+def make_terminator(space):
+    from pypy.module._pypyjson.interp_decoder import Terminator
+    return Terminator(space)
+
+def newdictstructure(space, w_list=None):
+    from pypy.objspace.std.unicodeobject import W_UnicodeObject
+    m = terminator = space.fromcache(make_terminator) # a different one than 
the one _pypyjson uses
+    if w_list is None:
+        return m
+    for w_x in space.listview(w_list):
+        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)
+        if not m.is_state_useful():
+            m.mark_useful(terminator)  # XXX too aggressive?
+    return m
+
+
+
+
diff --git a/pypy/module/__pypy__/moduledef.py 
b/pypy/module/__pypy__/moduledef.py
--- a/pypy/module/__pypy__/moduledef.py
+++ b/pypy/module/__pypy__/moduledef.py
@@ -118,6 +118,8 @@
         'stack_almost_full'         : 'interp_magic.stack_almost_full',
         'pyos_inputhook'            : 'interp_magic.pyos_inputhook',
         'newmemoryview'             : 'interp_buffer.newmemoryview',
+
+        'newdictstructure'          : 'interp_dictstructure.newdictstructure',
     }
     if sys.platform == 'win32':
         interpleveldefs['get_console_cp'] = 'interp_magic.get_console_cp'
diff --git a/pypy/module/__pypy__/test/test_dictstructure.py 
b/pypy/module/__pypy__/test/test_dictstructure.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/__pypy__/test/test_dictstructure.py
@@ -0,0 +1,26 @@
+
+class AppTestDictStructure(object):
+    spaceconfig = dict(usemodules=['__pypy__', '_pypyjson'])
+
+    def test_simple(self):
+        from __pypy__ import newdictstructure, strategy
+        m = newdictstructure([u"a", u"b", u"c"])
+        assert m.last_key == u"c"
+        assert m.previous.last_key == u"b"
+        m2 = newdictstructure([u"a", u"b", u"c"])
+        assert m2 is m
+        d = m.instantiate_dict([1, 2, 3])
+        assert d == {u"a": 1, u"b": 2, u"c": 3}
+        assert strategy(d) == "JsonDictStrategy"
+
+        with raises(ValueError):
+            m.instantiate_dict([5])
+
+        with raises(TypeError):
+            newdictstructure([b"a"])
+
+
+    def test_repr(self):
+        from __pypy__ import newdictstructure, strategy
+        m = newdictstructure([u"a"])
+        assert repr(m) == "<DictStructure [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
@@ -9,6 +9,9 @@
 from pypy.interpreter.baseobjspace import W_Root
 from pypy.module._pypyjson import simd
 
+from pypy.interpreter.gateway import interp2app, unwrap_spec
+from pypy.interpreter.typedef import TypeDef, GetSetProperty
+
 OVF_DIGITS = len(str(sys.maxint))
 
 def is_whitespace(ch):
@@ -692,7 +695,7 @@
         return True
 
 
-class MapBase(object):
+class MapBase(W_Root):
     """ A map implementation to speed up parsing of json dicts, and to
     represent the resulting dicts more compactly and make access faster. """
 
@@ -866,6 +869,30 @@
         reading from values_w."""
         raise NotImplementedError("abstract base")
 
+    # ____________________________________________________________
+    # exposed methods
+
+    def descr_instantiate_dict(self, space, w_l):
+        from pypy.objspace.std.jsondict import from_values_and_jsonmap
+        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)
+        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()]))
+
+
+    # ____________________________________________________________
+    # graphviz
+
     def _all_dot(self, output):
         identity = objectmodel.compute_unique_id(self)
         output.append('%s [shape=box%s];' % (identity, self._get_dot_text()))
@@ -1166,3 +1193,18 @@
     finally:
         decoder.close()
 
+
+
+def get_last_key(w_obj, space):
+    return w_obj.w_key if isinstance(w_obj, JSONMap) else space.w_None
+
+def get_previous(w_obj, space):
+    return w_obj.prev if isinstance(w_obj, JSONMap) else space.w_None
+
+MapBase.typedef = TypeDef("DictStructure",
+    instantiate_dict = interp2app(MapBase.descr_instantiate_dict),
+    __repr__ = interp2app(MapBase.descr_repr),
+    last_key = GetSetProperty(get_last_key, name="last_key"),
+    previous = GetSetProperty(get_previous, name="previous"),
+)
+MapBase.typedef.acceptable_as_base_class = False
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to