comparison gamelib/serializer.py @ 415:8f012ef1f64f

Start of ability to serialize game state.
author Simon Cross <hodgestar@gmail.com>
date Sat, 21 Nov 2009 12:55:08 +0000
parents
children cf4b020e6385
comparison
equal deleted inserted replaced
414:9096c237928c 415:8f012ef1f64f
1 """
2 Interface for converting objects to and from simple structures: lists, dicts,
3 strings, integers and combinations there of. Used for sending objects over
4 the communications API.
5 """
6
7 REGISTERED_CLASSES = {}
8
9 def simplify(item):
10 """Convert an item to a simple data structure."""
11 if issubclass(type(item), Simplifiable):
12 return item.simplify()
13 elif type(item) is list:
14 return { 'list': [simplify(x) for x in item] }
15 elif type(item) is tuple:
16 return { 'tuple': tuple([simplify(x) for x in item]) }
17 elif item is None:
18 return { 'none': '' }
19 else:
20 return { 'raw': item }
21
22 def unsimplify(value):
23 """Reverse the simplify process."""
24 if value.has_key('class'):
25 cls = REGISTERED_CLASSES[value['class']]
26 return cls.unsimplify(value)
27 elif value.has_key('list'):
28 return [unsimplify(x) for x in value['list']]
29 elif value.has_key('tuple'):
30 return tuple([unsimplify(x) for x in value['tuple']])
31 elif value.has_key('none'):
32 return None
33 elif value.has_key('raw'):
34 return value['raw']
35 else:
36 raise SimplifyError("Unknown tar type key.")
37
38 class SimplifyError(Exception):
39 pass
40
41 class SimplifiableMetaclass(type):
42 def __init__(cls, name, bases, dct):
43 super(SimplifiableMetaclass, cls).__init__(name, bases, dct)
44 REGISTERED_CLASSES[cls.__name__] = cls
45
46 class Simplifiable(object):
47 """
48 Object which can be simplified() and unsimplified() (i.e.
49 converted to a data type which, for example, Python's XMLRPC
50 or json module is capable of handling). Each subclass
51 must provide SIMPLIFY (a list of strings giving the names
52 of attributes which should be stored) unless a parent class
53 provides the right thing.
54 """
55 __metaclass__ = SimplifiableMetaclass
56
57 # List of attributes which need to be stored and restored
58 SIMPLIFY = []
59
60 def make(cls):
61 """
62 Create an object of this class without any attributes set.
63 """
64 return cls.__new__(cls)
65 make = classmethod(make)
66
67 def unsimplify(cls, value):
68 """
69 Create an object of this class (or a sub-class) from its
70 simplification.
71 """
72 actual_cls = REGISTERED_CLASSES[value['class']]
73 attrs = value['attributes']
74
75 if not issubclass(actual_cls, cls):
76 raise SimplifyError("Real class not a subclass of this class")
77
78 if not len(attrs) == len(actual_cls.SIMPLIFY):
79 raise SimplifyError("Wrong number of attributes for this class")
80
81 obj = actual_cls.make()
82 for attr, value in zip(actual_cls.SIMPLIFY, attrs):
83 setattr(obj, attr, unsimplify(value))
84
85 return obj
86 unsimplify = classmethod(unsimplify)
87
88 def simplify(self):
89 """
90 Create a simplified version (tar) of the object.
91 """
92 value = {}
93 value['class'] = self.__class__.__name__
94
95 attrs = []
96 for attr in self.SIMPLIFY:
97 o = getattr(self, attr)
98 attrs.append(simplify(o))
99
100 value['attributes'] = attrs
101 return value
102
103 def copy(self):
104 """
105 Return a copy of the object.
106 """
107 return self.__class__.unsimplify(self.simplify())