Module Object
[hide private]
[frames] | no frames]

Source Code for Module Object

  1  ##################################################################### 
  2  # -*- coding: iso-8859-1 -*-                                        # 
  3  #                                                                   # 
  4  # Frets on Fire                                                     # 
  5  # Copyright (C) 2006 Sami Kyöstilä                                  # 
  6  #                                                                   # 
  7  # This program is free software; you can redistribute it and/or     # 
  8  # modify it under the terms of the GNU General Public License       # 
  9  # as published by the Free Software Foundation; either version 2    # 
 10  # of the License, or (at your option) any later version.            # 
 11  #                                                                   # 
 12  # This program is distributed in the hope that it will be useful,   # 
 13  # but WITHOUT ANY WARRANTY; without even the implied warranty of    # 
 14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     # 
 15  # GNU General Public License for more details.                      # 
 16  #                                                                   # 
 17  # You should have received a copy of the GNU General Public License # 
 18  # along with this program; if not, write to the Free Software       # 
 19  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,        # 
 20  # MA  02110-1301, USA.                                              # 
 21  ##################################################################### 
 22   
 23  import pickle 
 24  from StringIO import StringIO 
 25   
26 -class Serializer(pickle.Pickler):
27 - def persistent_id(self, obj):
28 return getattr(obj, "id", None)
29
30 -class Unserializer(pickle.Unpickler):
31 - def __init__(self, manager, data):
32 pickle.Unpickler.__init__(self, data) 33 self.manager = manager
34
35 - def persistent_load(self, id):
36 return self.manager.getObject(id)
37
38 -def serialize(data):
39 file = StringIO() 40 Serializer(file, protocol = 2).dump(data) 41 return file.getvalue()
42
43 -def unserialize(manager, data):
44 return Unserializer(manager, StringIO(data)).load()
45
46 -class Manager:
47 MSG_CREATE = 0 48 MSG_CHANGE = 1 49 MSG_DELETE = 2 50
51 - def __init__(self, id = 0):
52 self.id = id 53 self.reset()
54
55 - def setId(self, id):
56 self.id = id
57
58 - def reset(self):
59 self.objects = {} 60 self.__creationData = {} 61 self.__created = [] 62 self.__changed = [] 63 self.__deleted = [] 64 self.__idCounter = 0
65
66 - def createObject(self, instance, *args, **kwargs):
67 self.__idCounter += 1 68 id = self.globalObjectId(self.__idCounter) 69 self.objects[id] = instance 70 self.__creationData[id] = (instance.__class__, args, kwargs) 71 self.__created.append(instance) 72 return id
73
74 - def setChanged(self, obj):
75 if not obj in self.__changed: 76 self.__changed.append(obj)
77
78 - def deleteObject(self, obj):
79 del self.objects[obj.id] 80 del self.__creationData[obj.id] 81 if obj in self.__created: self.__created.remove(obj) 82 self.__deleted.append(obj.id)
83
84 - def getObject(self, id):
85 return self.objects.get(id, None)
86
87 - def getChanges(self, everything = False):
88 data = [] 89 if everything: 90 data += [(self.MSG_CREATE, [(id, data) for id, data in self.__creationData.items()])] 91 data += [(self.MSG_CHANGE, [(o.id, o.getChanges(everything = True)) for o in self.objects.values()])] 92 else: 93 if self.__created: data += [(self.MSG_CREATE, [(o.id, self.__creationData[o.id]) for o in self.__created])] 94 if self.__changed: data += [(self.MSG_CHANGE, [(o.id, o.getChanges()) for o in self.__changed])] 95 if self.__deleted: data += [(self.MSG_DELETE, self.__deleted)] 96 self.__created = [] 97 self.__changed = [] 98 self.__deleted = [] 99 return [serialize(d) for d in data]
100
101 - def globalObjectId(self, objId):
102 return (self.id << 20) + objId
103
104 - def applyChanges(self, managerId, data):
105 for d in data: 106 try: 107 msg, data = unserialize(self, d) 108 if msg == self.MSG_CREATE: 109 for id, data in data: 110 objectClass, args, kwargs = data 111 self.__creationData[id] = data 112 self.objects[id] = objectClass(id = id, manager = self, *args, **kwargs) 113 elif msg == self.MSG_CHANGE: 114 for id, data in data: 115 if data: self.objects[id].applyChanges(data) 116 elif msg == self.MSG_DELETE: 117 id = data 118 del self.__creationData[id] 119 del self.objects[id] 120 except Exception, e: 121 print "Exception %s while processing incoming changes from manager %s." % (str(e), managerId) 122 raise
123
124 -def enableGlobalManager():
125 global manager 126 manager = Manager()
127
128 -class Message:
129 classes = {} 130
131 - def __init__(self):
132 if not self.__class__ in self.classes: 133 self.classes[self.__class__] = len(self.classes) 134 self.id = self.classes[self.__class__]
135
136 -class ObjectCreated(Message):
137 pass
138
139 -class ObjectDeleted(Message):
140 - def __init__(self, obj):
141 self.object = obj
142
143 -class Object(object):
144 - def __init__(self, id = None, manager = None, *args, **kwargs):
145 self.__modified = {} 146 self.__messages = [] 147 self.__messageMap = {} 148 self.__shared = [] 149 #if not manager: manager = globals()["manager"] 150 self.manager = manager 151 self.id = id or manager.createObject(self, *args, **kwargs)
152
153 - def share(self, *attr):
154 [(self.__shared.append(str(a)), self.__modified.__setitem__(a, self.__dict__[a])) for a in attr]
155
156 - def __setattr__(self, attr, value):
157 if attr in getattr(self, "_Object__shared", {}): 158 self.__modified[attr] = value 159 self.manager.setChanged(self) 160 object.__setattr__(self, attr, value)
161
162 - def delete(self):
163 self.emit(ObjectDeleted(self)) 164 self.manager.deleteObject(self)
165
166 - def getChanges(self, everything = False):
167 if self.__messages: 168 self.__modified["_Object__messages"] = self.__messages 169 170 self.__processMessages() 171 172 if everything: 173 return dict([(k, getattr(self, k)) for k in self.__shared]) 174 175 if self.__modified: 176 (data, self.__modified) = (self.__modified, {}) 177 return data
178
179 - def applyChanges(self, data):
180 self.__dict__.update(data) 181 self.__processMessages()
182
183 - def emit(self, message):
184 self.__messages.append(message)
185
186 - def connect(self, messageClass, callback):
187 if not messageClass in self.__messageMap: 188 self.__messageMap[messageClass] = [] 189 self.__messageMap[messageClass].append(callback)
190
191 - def disconnect(self, messageClass, callback):
192 if messageClass in self.__messageMap: 193 self.__messageMap[messageClass].remove(callback)
194
195 - def __processMessages(self):
196 for m in self.__messages: 197 if m.__class__ in self.__messageMap: 198 for c in self.__messageMap[m.__class__]: 199 c(m) 200 self.__messages = []
201