Mercurial > parpg-core
comparison src/parpg/grease/component/field.py @ 35:d07c8f891089
Added dict and list as possible component field types
author | KarstenBock@gmx.net |
---|---|
date | Sun, 31 Jul 2011 21:53:38 +0200 |
parents | 09b581087d68 |
children |
comparison
equal
deleted
inserted
replaced
34:5ac50245e42c | 35:d07c8f891089 |
---|---|
18 from grease import color | 18 from grease import color |
19 | 19 |
20 # Allowed field types -> default values | 20 # Allowed field types -> default values |
21 types = {int:lambda: 0, | 21 types = {int:lambda: 0, |
22 float:lambda: 0.0, | 22 float:lambda: 0.0, |
23 bool:lambda: False, | 23 bool:lambda: False, |
24 str:lambda:"", | 24 str:lambda:"", |
25 object:lambda:None, | 25 object:lambda:None, |
26 Vec2d:lambda: Vec2d(0,0), | 26 Vec2d:lambda: Vec2d(0,0), |
27 Vec2dArray:lambda: Vec2dArray(), | 27 Vec2dArray:lambda: Vec2dArray(), |
28 color.RGBA: lambda: color.RGBA(0.0, 0.0, 0.0, 0.0), | 28 color.RGBA: lambda: color.RGBA(0.0, 0.0, 0.0, 0.0), |
29 Rect: lambda: Rect(0.0, 0.0, 0.0, 0.0)} | 29 Rect: lambda: Rect(0.0, 0.0, 0.0, 0.0), |
30 list: lambda: list(), | |
31 dict: lambda: dict(), | |
32 } | |
30 | 33 |
31 class Schema(dict): | 34 class Schema(dict): |
32 """Field schema definition for custom components""" | 35 """Field schema definition for custom components""" |
33 | 36 |
34 def __init__(self, **fields): | 37 def __init__(self, **fields): |
35 for ftype in fields.values(): | 38 for ftype in fields.values(): |
36 assert ftype in types, fname + " has an illegal field type" | 39 assert ftype in types, fname + " has an illegal field type" |
37 self.update(fields) | 40 self.update(fields) |
38 | 41 |
39 | 42 |
40 class FieldAccessor(object): | 43 class FieldAccessor(object): |
41 """Facade for manipulating a field for a set of entities""" | 44 """Facade for manipulating a field for a set of entities""" |
42 | 45 |
43 __field = None | 46 __field = None |
44 __entities = None | 47 __entities = None |
45 __attrs = None | 48 __attrs = None |
46 __getter = None | 49 __getter = None |
47 __parent_getters = () | 50 __parent_getters = () |
48 | 51 |
49 def __init__(self, field, entities, attrs=()): | 52 def __init__(self, field, entities, attrs=()): |
50 self.__field = field | 53 self.__field = field |
51 self.__entities = entities | 54 self.__entities = entities |
52 field_getter = operator.attrgetter(field.name) | 55 field_getter = operator.attrgetter(field.name) |
53 self.__attrs = attrs | 56 self.__attrs = attrs |
54 if attrs: | 57 if attrs: |
55 getters = [field_getter] + [operator.attrgetter(attr) for attr in attrs] | 58 getters = [field_getter] + [operator.attrgetter(attr) for attr in attrs] |
56 def get(entity): | 59 def get(entity): |
57 value = entity | 60 value = entity |
58 for getter in getters: | 61 for getter in getters: |
59 value = getter(value) | 62 value = getter(value) |
60 return value | 63 return value |
61 self.__getter = get | 64 self.__getter = get |
62 self.__parent_getters = getters[:-1] | 65 self.__parent_getters = getters[:-1] |
63 else: | 66 else: |
64 self.__getter = field_getter | 67 self.__getter = field_getter |
65 | 68 |
66 def __getattr__(self, name): | 69 def __getattr__(self, name): |
67 """Return a FieldAccessor for the child attribute""" | 70 """Return a FieldAccessor for the child attribute""" |
68 return self.__class__(self.__field, self.__entities, self.__attrs + (name,)) | 71 return self.__class__(self.__field, self.__entities, self.__attrs + (name,)) |
69 | 72 |
70 def __setattr__(self, name, value): | 73 def __setattr__(self, name, value): |
71 if value is self: | 74 if value is self: |
72 return # returned by mutators | 75 return # returned by mutators |
73 if hasattr(self.__class__, name): | 76 if hasattr(self.__class__, name): |
74 # Set local attr | 77 # Set local attr |
75 self.__dict__[name] = value | 78 self.__dict__[name] = value |
76 elif not name.startswith('_'): | 79 elif not name.startswith('_'): |
77 getattr(self, name).__set__(value) | 80 getattr(self, name).__set__(value) |
78 else: | 81 else: |
79 raise AttributeError("Cannot set field attribute: %s" % name) | 82 raise AttributeError("Cannot set field attribute: %s" % name) |
80 | 83 |
81 @property | 84 @property |
82 def __setter(self): | 85 def __setter(self): |
83 """Return the proper setter function for setting the field value""" | 86 """Return the proper setter function for setting the field value""" |
84 if not self.__attrs: | 87 if not self.__attrs: |
85 return setattr | 88 return setattr |
86 else: | 89 else: |
87 parent_getters = self.__parent_getters | 90 parent_getters = self.__parent_getters |
88 def setter(data, name, value): | 91 def setter(data, name, value): |
89 for getter in parent_getters: | 92 for getter in parent_getters: |
90 data = getter(data) | 93 data = getter(data) |
91 setattr(data, name, value) | 94 setattr(data, name, value) |
92 self.__setter = setter | 95 self.__setter = setter |
93 return setter | 96 return setter |
94 | 97 |
95 def __set__(self, value): | 98 def __set__(self, value): |
96 """Set field values en masse""" | 99 """Set field values en masse""" |
97 # Mass set field attr | 100 # Mass set field attr |
98 setter = self.__setter | 101 setter = self.__setter |
99 component = self.__field.component | 102 component = self.__field.component |
100 if self.__attrs: | 103 if self.__attrs: |
101 name = self.__attrs[-1] | 104 name = self.__attrs[-1] |
102 else: | 105 else: |
103 name = self.__field.name | 106 name = self.__field.name |
104 if isinstance(value, FieldAccessor): | 107 if isinstance(value, FieldAccessor): |
105 # Join set between two entity sets | 108 # Join set between two entity sets |
106 if not self.__attrs: | 109 if not self.__attrs: |
107 cast = self.__field.cast | 110 cast = self.__field.cast |
108 else: | 111 else: |
109 cast = lambda x: x | 112 cast = lambda x: x |
110 for entity in self.__entities: | 113 for entity in self.__entities: |
111 try: | 114 try: |
112 setter(component[entity], name, cast(value[entity])) | 115 setter(component[entity], name, cast(value[entity])) |
113 except KeyError: | 116 except KeyError: |
114 pass | 117 pass |
115 else: | 118 else: |
116 if not self.__attrs: | 119 if not self.__attrs: |
117 value = self.__field.cast(value) | 120 value = self.__field.cast(value) |
118 for entity in self.__entities: | 121 for entity in self.__entities: |
119 try: | 122 try: |
120 setter(component[entity], name, value) | 123 setter(component[entity], name, value) |
121 except KeyError: | 124 except KeyError: |
122 pass | 125 pass |
123 | 126 |
124 def __getitem__(self, entity): | 127 def __getitem__(self, entity): |
125 """Return the field value for a single entity (used for joins)""" | 128 """Return the field value for a single entity (used for joins)""" |
126 if entity in self.__entities: | 129 if entity in self.__entities: |
127 return self.__getter(self.__field.component[entity]) | 130 return self.__getter(self.__field.component[entity]) |
128 raise KeyError(entity) | 131 raise KeyError(entity) |
129 | 132 |
130 def __contains__(self, entity): | 133 def __contains__(self, entity): |
131 return entity in self.__entities | 134 return entity in self.__entities |
132 | 135 |
133 def __repr__(self): | 136 def __repr__(self): |
134 return '<%s %s @ %x>' % ( | 137 return '<%s %s @ %x>' % ( |
135 self.__class__.__name__, | 138 self.__class__.__name__, |
136 '.'.join((self.__field.name,) + self.__attrs), id(self)) | 139 '.'.join((self.__field.name,) + self.__attrs), id(self)) |
137 | 140 |
138 def __nonzero__(self): | 141 def __nonzero__(self): |
139 return bool(self.__entities) | 142 return bool(self.__entities) |
140 | 143 |
141 def __iter__(self): | 144 def __iter__(self): |
142 """Return an iterator of all field values in the set""" | 145 """Return an iterator of all field values in the set""" |
143 component = self.__field.component | 146 component = self.__field.component |
144 getter = self.__getter | 147 getter = self.__getter |
145 for entity in self.__entities: | 148 for entity in self.__entities: |
146 try: | 149 try: |
147 data = component[entity] | 150 data = component[entity] |
148 except KeyError: | 151 except KeyError: |
149 continue | 152 continue |
150 yield getter(data) | 153 yield getter(data) |
151 | 154 |
152 ## batch comparison operators ## | 155 ## batch comparison operators ## |
153 | 156 |
154 def __match(self, value, op): | 157 def __match(self, value, op): |
155 component = self.__field.component | 158 component = self.__field.component |
156 getter = self.__getter | 159 getter = self.__getter |
157 matches = set() | 160 matches = set() |
158 add = matches.add | 161 add = matches.add |
159 if isinstance(value, FieldAccessor): | 162 if isinstance(value, FieldAccessor): |
160 # Join match between entity sets | 163 # Join match between entity sets |
161 for entity in self.__entities: | 164 for entity in self.__entities: |
162 try: | 165 try: |
163 data = component[entity] | 166 data = component[entity] |
164 other = value[entity] | 167 other = value[entity] |
165 except KeyError: | 168 except KeyError: |
166 continue | 169 continue |
167 if op(getter(data), other): | 170 if op(getter(data), other): |
168 add(entity) | 171 add(entity) |
169 else: | 172 else: |
170 for entity in self.__entities: | 173 for entity in self.__entities: |
171 try: | 174 try: |
172 data = component[entity] | 175 data = component[entity] |
173 except KeyError: | 176 except KeyError: |
174 continue | 177 continue |
175 if op(getter(data), value): | 178 if op(getter(data), value): |
176 add(entity) | 179 add(entity) |
177 return matches | 180 return matches |
178 | 181 |
179 def __eq__(self, value): | 182 def __eq__(self, value): |
180 """Return an entity set of all entities with a matching field value""" | 183 """Return an entity set of all entities with a matching field value""" |
181 return self.__match(value, operator.eq) | 184 return self.__match(value, operator.eq) |
182 | 185 |
183 def __ne__(self, value): | 186 def __ne__(self, value): |
184 """Return an entity set of all entities not matching field value""" | 187 """Return an entity set of all entities not matching field value""" |
185 return self.__match(value, operator.ne) | 188 return self.__match(value, operator.ne) |
186 | 189 |
187 def __gt__(self, value): | 190 def __gt__(self, value): |
188 """Return an entity set of all entities with a greater field value""" | 191 """Return an entity set of all entities with a greater field value""" |
189 return self.__match(value, operator.gt) | 192 return self.__match(value, operator.gt) |
190 | 193 |
191 def __ge__(self, value): | 194 def __ge__(self, value): |
192 """Return an entity set of all entities with a greater or equal field value""" | 195 """Return an entity set of all entities with a greater or equal field value""" |
193 return self.__match(value, operator.ge) | 196 return self.__match(value, operator.ge) |
194 | 197 |
195 def __lt__(self, value): | 198 def __lt__(self, value): |
196 """Return an entity set of all entities with a lesser field value""" | 199 """Return an entity set of all entities with a lesser field value""" |
197 return self.__match(value, operator.lt) | 200 return self.__match(value, operator.lt) |
198 | 201 |
199 def __le__(self, value): | 202 def __le__(self, value): |
200 """Return an entity set of all entities with a lesser or equal field value""" | 203 """Return an entity set of all entities with a lesser or equal field value""" |
201 return self.__match(value, operator.le) | 204 return self.__match(value, operator.le) |
202 | 205 |
203 def _contains(self, values): | 206 def _contains(self, values): |
204 """Return an entity set of all entities with a field value contained in values""" | 207 """Return an entity set of all entities with a field value contained in values""" |
205 return self.__match(values, operator.contains) | 208 return self.__match(values, operator.contains) |
206 | 209 |
207 ## Batch in-place mutator methods | 210 ## Batch in-place mutator methods |
208 | 211 |
209 def __mutate(self, value, op): | 212 def __mutate(self, value, op): |
210 component = self.__field.component | 213 component = self.__field.component |
211 if self.__attrs: | 214 if self.__attrs: |
212 name = self.__attrs[-1] | 215 name = self.__attrs[-1] |
213 else: | 216 else: |
214 name = self.__field.name | 217 name = self.__field.name |
215 getter = self.__getter | 218 getter = self.__getter |
216 setter = self.__setter | 219 setter = self.__setter |
217 if isinstance(value, FieldAccessor): | 220 if isinstance(value, FieldAccessor): |
218 # Join between entity sets | 221 # Join between entity sets |
219 for entity in self.__entities: | 222 for entity in self.__entities: |
220 try: | 223 try: |
221 data = component[entity] | 224 data = component[entity] |
222 other = value[entity] | 225 other = value[entity] |
223 except KeyError: | 226 except KeyError: |
224 continue | 227 continue |
225 setter(data, name, op(getter(data), other)) | 228 setter(data, name, op(getter(data), other)) |
226 else: | 229 else: |
227 for entity in self.__entities: | 230 for entity in self.__entities: |
228 try: | 231 try: |
229 data = component[entity] | 232 data = component[entity] |
230 except KeyError: | 233 except KeyError: |
231 continue | 234 continue |
232 setter(data, name, op(getter(data), value)) | 235 setter(data, name, op(getter(data), value)) |
233 return self | 236 return self |
234 | 237 |
235 def __iadd__(self, value): | 238 def __iadd__(self, value): |
236 return self.__mutate(value, operator.iadd) | 239 return self.__mutate(value, operator.iadd) |
237 | 240 |
238 def __isub__(self, value): | 241 def __isub__(self, value): |
239 return self.__mutate(value, operator.isub) | 242 return self.__mutate(value, operator.isub) |
240 | 243 |
241 def __imul__(self, value): | 244 def __imul__(self, value): |
242 return self.__mutate(value, operator.imul) | 245 return self.__mutate(value, operator.imul) |
243 | 246 |
244 def __idiv__(self, value): | 247 def __idiv__(self, value): |
245 return self.__mutate(value, operator.idiv) | 248 return self.__mutate(value, operator.idiv) |
246 | 249 |
247 def __itruediv__(self, value): | 250 def __itruediv__(self, value): |
248 return self.__mutate(value, operator.itruediv) | 251 return self.__mutate(value, operator.itruediv) |
249 | 252 |
250 def __ifloordiv__(self, value): | 253 def __ifloordiv__(self, value): |
251 return self.__mutate(value, operator.ifloordiv) | 254 return self.__mutate(value, operator.ifloordiv) |
252 | 255 |
253 def __imod__(self, value): | 256 def __imod__(self, value): |
254 return self.__mutate(value, operator.imod) | 257 return self.__mutate(value, operator.imod) |
255 | 258 |
256 def __ipow__(self, value): | 259 def __ipow__(self, value): |
257 return self.__mutate(value, operator.ipow) | 260 return self.__mutate(value, operator.ipow) |
258 | 261 |
259 def __ilshift__(self, value): | 262 def __ilshift__(self, value): |
260 return self.__mutate(value, operator.ilshift) | 263 return self.__mutate(value, operator.ilshift) |
261 | 264 |
262 def __irshift__(self, value): | 265 def __irshift__(self, value): |
263 return self.__mutate(value, operator.irshift) | 266 return self.__mutate(value, operator.irshift) |
264 | 267 |
265 def __iand__(self, value): | 268 def __iand__(self, value): |
266 return self.__mutate(value, operator.iand) | 269 return self.__mutate(value, operator.iand) |
267 | 270 |
268 def __ior__(self, value): | 271 def __ior__(self, value): |
269 return self.__mutate(value, operator.ior) | 272 return self.__mutate(value, operator.ior) |
270 | 273 |
271 def __ixor__(self, value): | 274 def __ixor__(self, value): |
272 return self.__mutate(value, operator.ixor) | 275 return self.__mutate(value, operator.ixor) |
273 | 276 |
274 | 277 |
275 class Field(object): | 278 class Field(object): |
276 """Component field metadata and accessor interface""" | 279 """Component field metadata and accessor interface""" |
277 | 280 |
278 def __init__(self, component, name, type, accessor_factory=FieldAccessor): | 281 def __init__(self, component, name, type, accessor_factory=FieldAccessor): |
279 self.component = component | 282 self.component = component |
280 self.name = name | 283 self.name = name |
281 self.type = type | 284 self.type = type |
282 self.default = types.get(type) | 285 self.default = types.get(type) |
283 self.accessor_factory = accessor_factory | 286 self.accessor_factory = accessor_factory |
284 | 287 |
285 def cast(self, value): | 288 def cast(self, value): |
286 """Cast value to the appropriate type for thi field""" | 289 """Cast value to the appropriate type for thi field""" |
287 if self.type is not object: | 290 if self.type is not object: |
288 return self.type(value) | 291 return self.type(value) |
289 else: | 292 else: |
290 return value | 293 return value |
291 | 294 |
292 def accessor(self, entities=None): | 295 def accessor(self, entities=None): |
293 """Return the field accessor for the entities in the component, | 296 """Return the field accessor for the entities in the component, |
294 or all entities in the set specified that are also in the component | 297 or all entities in the set specified that are also in the component |
295 """ | 298 """ |
296 if entities is None or entities is self.component.entities: | 299 if entities is None or entities is self.component.entities: |
297 entities = self.component.entities | 300 entities = self.component.entities |
298 else: | 301 else: |
299 entities = entities & self.component.entities | 302 entities = entities & self.component.entities |
300 return self.accessor_factory(self, entities) | 303 return self.accessor_factory(self, entities) |
301 |