[pypy-svn] r45780 - in pypy/branch/pypy-more-rtti-inprogress/rlib: . test
arigo at codespeak.net
arigo at codespeak.net
Fri Aug 17 09:17:28 CEST 2007
Author: arigo
Date: Fri Aug 17 09:17:27 2007
New Revision: 45780
Added:
pypy/branch/pypy-more-rtti-inprogress/rlib/rmarshal.py (contents, props changed)
pypy/branch/pypy-more-rtti-inprogress/rlib/test/test_rmarshal.py (contents, props changed)
Log:
Playing with a limited version of marshall/unmarshall for RPython programs.
Added: pypy/branch/pypy-more-rtti-inprogress/rlib/rmarshal.py
==============================================================================
--- (empty file)
+++ pypy/branch/pypy-more-rtti-inprogress/rlib/rmarshal.py Fri Aug 17 09:17:27 2007
@@ -0,0 +1,157 @@
+"""A way to serialize data in the same format as the 'marshal' module
+but accessible to RPython programs.
+"""
+
+from pypy.annotation import model as annmodel
+from pypy.annotation.signature import annotation
+from pypy.annotation.listdef import ListDef, TooLateForChange
+from pypy.annotation.pairtype import pair, pairtype
+from pypy.rlib.rarithmetic import formatd
+from pypy.rlib.unroll import unrolling_iterable
+
+class CannotMarshal(Exception):
+ pass
+
+def get_marshaller(type):
+ s_obj = annotation(type, None)
+ try:
+ # look for a marshaller in the 'dumpers' dictionary
+ return find_dumper(s_obj)
+ except CannotMarshal:
+ # ask the annotation to produce an appropriate dumper
+ pair(_tag, s_obj).install_marshaller()
+ return find_dumper(s_obj)
+get_marshaller._annspecialcase_ = 'specialize:memo'
+
+def get_unmarshaller(type):
+ xxx
+get_unmarshaller._annspecialcase_ = 'specialize:memo'
+
+# ____________________________________________________________
+#
+# Dumpers and loaders
+
+TYPE_NONE = 'N'
+TYPE_INT = 'i'
+TYPE_FLOAT = 'f'
+#TYPE_LONG = 'l'
+TYPE_STRING = 's'
+TYPE_TUPLE = '('
+TYPE_LIST = '['
+
+dumpers = []
+s_list_of_chars = ListDef(None, annmodel.SomeChar(),
+ mutated=True, resized=True)
+
+def add_dumper(s_obj, dumper):
+ dumpers.append((s_obj, dumper))
+ dumper._annenforceargs_ = [s_list_of_chars, s_obj]
+
+def get_dumper_annotation(dumper):
+ return dumper._annenforceargs_[1]
+
+def find_dumper(s_obj):
+ for s_cond, dumper in dumpers:
+ if weakly_contains(s_cond, s_obj):
+ return dumper
+ raise CannotMarshal(s_obj)
+
+def w_long(buf, x):
+ buf.append(chr(x & 0xff))
+ x >>= 8
+ buf.append(chr(x & 0xff))
+ x >>= 8
+ buf.append(chr(x & 0xff))
+ x >>= 8
+ buf.append(chr(x & 0xff))
+w_long._annenforceargs_ = [None, int]
+
+def dump_none(buf, x):
+ buf.append(TYPE_NONE)
+add_dumper(annmodel.s_None, dump_none)
+
+def dump_int(buf, x):
+ buf.append(TYPE_INT)
+ w_long(buf, x)
+add_dumper(annmodel.SomeInteger(), dump_int)
+
+def dump_float(buf, x):
+ buf.append(TYPE_FLOAT)
+ s = formatd("%.17g", x)
+ buf.append(chr(len(s)))
+ buf += s
+add_dumper(annmodel.SomeFloat(), dump_float)
+
+def dump_string_or_none(buf, x):
+ if x is None:
+ dump_none(buf, x)
+ else:
+ buf.append(TYPE_STRING)
+ w_long(buf, len(x))
+ buf += x
+add_dumper(annmodel.SomeString(can_be_None=True), dump_string_or_none)
+
+# ____________________________________________________________
+#
+# Annotations => dumpers and loaders
+
+class MTag(object):
+ """Tag for pairtype(), for the purpose of making the get_marshaller()
+ and get_unmarshaller() methods of SomeObject only locally visible."""
+_tag = MTag()
+
+def weakly_contains(s_bigger, s_smaller):
+ # a special version of s_bigger.contains(s_smaller). Warning, to
+ # support ListDefs properly, this works by trying to produce a side-effect
+ # on s_bigger. It relies on the fact that s_bigger was created with
+ # an expression like 'annotation([s_item])' which returns a ListDef with
+ # no bookkeeper, on which side-effects are not allowed.
+ try:
+ s_union = annmodel.unionof(s_bigger, s_smaller)
+ return s_bigger.contains(s_union)
+ except (annmodel.UnionError, TooLateForChange):
+ return False
+
+
+class __extend__(pairtype(MTag, annmodel.SomeObject)):
+
+ def install_marshaller((tag, s_obj)):
+ raise CannotMarshal(s_obj)
+
+
+class __extend__(pairtype(MTag, annmodel.SomeList)):
+
+ def install_marshaller((tag, s_list)):
+ def dump_list_or_none(buf, x):
+ if x is None:
+ dump_none(buf, x)
+ else:
+ buf.append(TYPE_LIST)
+ w_long(buf, len(x))
+ for item in x:
+ itemdumper(buf, item)
+
+ itemdumper = get_marshaller(s_list.listdef.listitem.s_value)
+ if s_list.listdef.listitem.dont_change_any_more:
+ s_general_list = s_list
+ else:
+ s_item = get_dumper_annotation(itemdumper)
+ s_general_list = annotation([s_item])
+ add_dumper(s_general_list, dump_list_or_none)
+
+
+class __extend__(pairtype(MTag, annmodel.SomeTuple)):
+
+ def install_marshaller((tag, s_tuple)):
+ def dump_tuple(buf, x):
+ buf.append(TYPE_TUPLE)
+ w_long(buf, len(x))
+ for i, itemdumper in unroll_item_dumpers:
+ itemdumper(buf, x[i])
+
+ itemdumpers = [get_marshaller(s_item) for s_item in s_tuple.items]
+ unroll_item_dumpers = unrolling_iterable(enumerate(itemdumpers))
+ dumper_annotations = [get_dumper_annotation(itemdumper)
+ for itemdumper in itemdumpers]
+ s_general_tuple = annmodel.SomeTuple(dumper_annotations)
+ add_dumper(s_general_tuple, dump_tuple)
Added: pypy/branch/pypy-more-rtti-inprogress/rlib/test/test_rmarshal.py
==============================================================================
--- (empty file)
+++ pypy/branch/pypy-more-rtti-inprogress/rlib/test/test_rmarshal.py Fri Aug 17 09:17:27 2007
@@ -0,0 +1,25 @@
+import marshal
+from pypy.rlib.rmarshal import *
+
+
+def test_marshaller():
+ buf = []
+ get_marshaller(int)(buf, 5)
+ assert marshal.loads(''.join(buf)) == 5
+
+ buf = []
+ get_marshaller(float)(buf, 3.25)
+ assert marshal.loads(''.join(buf)) == 3.25
+
+ buf = []
+ get_marshaller(str)(buf, "hello, world")
+ assert marshal.loads(''.join(buf)) == "hello, world"
+
+ buf = []
+ get_marshaller([int])(buf, [2, 5, -7])
+ assert marshal.loads(''.join(buf)) == [2, 5, -7]
+
+ buf = []
+ get_marshaller((int, float, (str, ())))(buf, (7, -1.5, ("foo", ())))
+ assert marshal.loads(''.join(buf)) == (7, -1.5, ("foo", ()))
+
More information about the Pypy-commit
mailing list