Mercurial > rinkhals
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()) |