changeset 439:cf4b020e6385

Start of serializer for buildings and support for reference cycles.
author Simon Cross <hodgestar@gmail.com>
date Sat, 21 Nov 2009 18:34:36 +0000
parents 16437cf4a2b8
children e945c4186ee5
files gamelib/animal.py gamelib/buildings.py gamelib/serializer.py
diffstat 3 files changed, 78 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/gamelib/animal.py	Sat Nov 21 18:15:01 2009 +0000
+++ b/gamelib/animal.py	Sat Nov 21 18:34:36 2009 +0000
@@ -54,9 +54,9 @@
         return cls((0, 0))
     make = classmethod(make)
 
-    def unsimplify(cls, value):
+    def unsimplify(cls, *args, **kwargs):
         """Override default Simplifiable unsimplification."""
-        obj = super(Animal, cls).unsimplify(value)
+        obj = super(Animal, cls).unsimplify(*args, **kwargs)
         obj.redraw()
         return obj
     unsimplify = classmethod(unsimplify)
--- a/gamelib/buildings.py	Sat Nov 21 18:15:01 2009 +0000
+++ b/gamelib/buildings.py	Sat Nov 21 18:34:36 2009 +0000
@@ -13,9 +13,15 @@
 import warnings
 warnings.filterwarnings("ignore", "os.popen3 is deprecated.")
 
-class Place(object):
+class Place(serializer.Simplifiable):
     """Space within a building that can be occupied."""
 
+    SIMPLIFY = [
+        'occupant',
+        'building',
+        'offset',
+    ]
+
     def __init__(self, building, offset):
         self.occupant = None
         self.building = building
@@ -40,11 +46,16 @@
         return (bpos[0] + self.offset[0], bpos[1] + self.offset[1],
                 self.offset[2])
 
-class Floor(object):
+class Floor(serializer.Simplifiable):
     """A set of places within a building. Places on a
        floor are organised into rows and columns.
        """
 
+    SIMPLIFY = [
+        'title',
+        'places',
+    ]
+
     def __init__(self, title, places):
         self.title = title # str
         self.places = places # list of lists of places
@@ -81,7 +92,7 @@
         '_repair_price',
         '_sun_on',
         '_broken',
-        '_predators',
+        '_floors',
     ]
 
     def __init__(self, pos):
--- a/gamelib/serializer.py	Sat Nov 21 18:15:01 2009 +0000
+++ b/gamelib/serializer.py	Sat Nov 21 18:34:36 2009 +0000
@@ -6,34 +6,77 @@
 
 REGISTERED_CLASSES = {}
 
-def simplify(item):
+def simplify(item, refs=None):
     """Convert an item to a simple data structure."""
+    if refs is None:
+        refs = set()
+
+    refid = id(item)
+
+    if refid in refs:
+        return { 'byref': refid }
+
     if issubclass(type(item), Simplifiable):
-        return item.simplify()
+        refs.add(refid)
+        value = item.simplify(refs)
+        value['refid'] = refid
     elif type(item) is list:
-        return { 'list': [simplify(x) for x in item] }
+        refs.add(refid)
+        value = { 'list': [simplify(x, refs) for x in item] }
+        value['refid'] = refid
+    elif type(item) is set:
+        refs.add(refid)
+        value = { 'set': [simplify(x, refs) for x in item] }
+        value['refid'] = refid
     elif type(item) is tuple:
-        return { 'tuple': tuple([simplify(x) for x in item]) }
+        refs.add(refid)
+        value = { 'tuple': tuple([simplify(x, refs) for x in item]) }
+        value['refid'] = refid
     elif item is None:
-        return { 'none': '' }
+        value = { 'none': '' }
     else:
-        return { 'raw': item }
+        value = { 'raw': item }
+
+    return value
 
-def unsimplify(value):
+def unsimplify(value, refs=None):
     """Reverse the simplify process."""
+    if refs is None:
+        refs = {}
+
+    if 'refid' in value:
+        refid = value['refid']
+
     if value.has_key('class'):
         cls = REGISTERED_CLASSES[value['class']]
-        return cls.unsimplify(value)
+        item = cls.unsimplify(value, refs)
     elif value.has_key('list'):
-        return [unsimplify(x) for x in value['list']]
+        item = []
+        refs[refid] = item
+        item.extend(unsimplify(x, refs) for x in value['list'])
+    elif value.has_key('set'):
+        item = set()
+        refs[refid] = item
+        item.update(unsimplify(x, refs) for x in value['set'])
     elif value.has_key('tuple'):
-        return tuple([unsimplify(x) for x in value['tuple']])
+        item = tuple([unsimplify(x, refs) for x in value['tuple']])
     elif value.has_key('none'):
-        return None
+        item = None
     elif value.has_key('raw'):
-        return value['raw']
+        item = value['raw']
+    elif value.has_key('byref'):
+        refid = value['byref']
+        if refid in refs:
+            item = refs[refid]
+        else:
+            raise SimplifyError("Unknown refid %r in byref." % (refid,))
     else:
-        raise SimplifyError("Unknown tar type key.")
+        raise SimplifyError("Unknown unsimplify type key.")
+
+    if 'refid' in value:
+        refs[value['refid']] = item
+
+    return item
 
 class SimplifyError(Exception):
     pass
@@ -64,7 +107,7 @@
         return cls.__new__(cls)
     make = classmethod(make)
 
-    def unsimplify(cls, value):
+    def unsimplify(cls, value, refs=None):
         """
         Create an object of this class (or a sub-class) from its
         simplification.
@@ -79,13 +122,15 @@
             raise SimplifyError("Wrong number of attributes for this class")
 
         obj = actual_cls.make()
+        refs[value['refid']] = obj
+
         for attr, value in zip(actual_cls.SIMPLIFY, attrs):
-            setattr(obj, attr, unsimplify(value))
+            setattr(obj, attr, unsimplify(value, refs))
 
         return obj
     unsimplify = classmethod(unsimplify)
 
-    def simplify(self):
+    def simplify(self, refs=None):
         """
         Create a simplified version (tar) of the object.
         """
@@ -95,7 +140,7 @@
         attrs = []
         for attr in self.SIMPLIFY:
             o = getattr(self, attr)
-            attrs.append(simplify(o))
+            attrs.append(simplify(o, refs))
 
         value['attributes'] = attrs
         return value