Mercurial > parpg-source
diff bGrease/component/field.py @ 65:e856b604b650
Changed "import bGrease" to "import parpg.bGrease".
author | KarstenBock@gmx.net |
---|---|
date | Wed, 21 Sep 2011 16:10:14 +0200 |
parents | ff3e395abf91 |
children |
line wrap: on
line diff
--- a/bGrease/component/field.py Wed Sep 21 15:43:12 2011 +0200 +++ b/bGrease/component/field.py Wed Sep 21 16:10:14 2011 +0200 @@ -1,303 +1,303 @@ -############################################################################# -# -# Copyright (c) 2010 by Casey Duncan and contributors -# All Rights Reserved. -# -# This software is subject to the provisions of the MIT License -# A copy of the license should accompany this distribution. -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -# -############################################################################# - -__version__ = '$Id$' - -import operator -from bGrease.geometry import Vec2d, Vec2dArray, Rect -from bGrease import color - -# Allowed field types -> default values -types = {int:lambda: 0, - float:lambda: 0.0, - bool:lambda: False, - str:lambda:"", - object:lambda:None, - Vec2d:lambda: Vec2d(0,0), - Vec2dArray:lambda: Vec2dArray(), - color.RGBA: lambda: color.RGBA(0.0, 0.0, 0.0, 0.0), - Rect: lambda: Rect(0.0, 0.0, 0.0, 0.0), - list: lambda: list(), - dict: lambda: dict(), - } - -class Schema(dict): - """Field schema definition for custom components""" - - def __init__(self, **fields): - for ftype in fields.values(): - assert ftype in types, fname + " has an illegal field type" - self.update(fields) - - -class FieldAccessor(object): - """Facade for manipulating a field for a set of entities""" - - __field = None - __entities = None - __attrs = None - __getter = None - __parent_getters = () - - def __init__(self, field, entities, attrs=()): - self.__field = field - self.__entities = entities - field_getter = operator.attrgetter(field.name) - self.__attrs = attrs - if attrs: - getters = [field_getter] + [operator.attrgetter(attr) for attr in attrs] - def get(entity): - value = entity - for getter in getters: - value = getter(value) - return value - self.__getter = get - self.__parent_getters = getters[:-1] - else: - self.__getter = field_getter - - def __getattr__(self, name): - """Return a FieldAccessor for the child attribute""" - return self.__class__(self.__field, self.__entities, self.__attrs + (name,)) - - def __setattr__(self, name, value): - if value is self: - return # returned by mutators - if hasattr(self.__class__, name): - # Set local attr - self.__dict__[name] = value - elif not name.startswith('_'): - getattr(self, name).__set__(value) - else: - raise AttributeError("Cannot set field attribute: %s" % name) - - @property - def __setter(self): - """Return the proper setter function for setting the field value""" - if not self.__attrs: - return setattr - else: - parent_getters = self.__parent_getters - def setter(data, name, value): - for getter in parent_getters: - data = getter(data) - setattr(data, name, value) - self.__setter = setter - return setter - - def __set__(self, value): - """Set field values en masse""" - # Mass set field attr - setter = self.__setter - component = self.__field.component - if self.__attrs: - name = self.__attrs[-1] - else: - name = self.__field.name - if isinstance(value, FieldAccessor): - # Join set between two entity sets - if not self.__attrs: - cast = self.__field.cast - else: - cast = lambda x: x - for entity in self.__entities: - try: - setter(component[entity], name, cast(value[entity])) - except KeyError: - pass - else: - if not self.__attrs: - value = self.__field.cast(value) - for entity in self.__entities: - try: - setter(component[entity], name, value) - except KeyError: - pass - - def __getitem__(self, entity): - """Return the field value for a single entity (used for joins)""" - if entity in self.__entities: - return self.__getter(self.__field.component[entity]) - raise KeyError(entity) - - def __contains__(self, entity): - return entity in self.__entities - - def __repr__(self): - return '<%s %s @ %x>' % ( - self.__class__.__name__, - '.'.join((self.__field.name,) + self.__attrs), id(self)) - - def __nonzero__(self): - return bool(self.__entities) - - def __iter__(self): - """Return an iterator of all field values in the set""" - component = self.__field.component - getter = self.__getter - for entity in self.__entities: - try: - data = component[entity] - except KeyError: - continue - yield getter(data) - - ## batch comparison operators ## - - def __match(self, value, op): - component = self.__field.component - getter = self.__getter - matches = set() - add = matches.add - if isinstance(value, FieldAccessor): - # Join match between entity sets - for entity in self.__entities: - try: - data = component[entity] - other = value[entity] - except KeyError: - continue - if op(getter(data), other): - add(entity) - else: - for entity in self.__entities: - try: - data = component[entity] - except KeyError: - continue - if op(getter(data), value): - add(entity) - return matches - - def __eq__(self, value): - """Return an entity set of all entities with a matching field value""" - return self.__match(value, operator.eq) - - def __ne__(self, value): - """Return an entity set of all entities not matching field value""" - return self.__match(value, operator.ne) - - def __gt__(self, value): - """Return an entity set of all entities with a greater field value""" - return self.__match(value, operator.gt) - - def __ge__(self, value): - """Return an entity set of all entities with a greater or equal field value""" - return self.__match(value, operator.ge) - - def __lt__(self, value): - """Return an entity set of all entities with a lesser field value""" - return self.__match(value, operator.lt) - - def __le__(self, value): - """Return an entity set of all entities with a lesser or equal field value""" - return self.__match(value, operator.le) - - def _contains(self, values): - """Return an entity set of all entities with a field value contained in values""" - return self.__match(values, operator.contains) - - ## Batch in-place mutator methods - - def __mutate(self, value, op): - component = self.__field.component - if self.__attrs: - name = self.__attrs[-1] - else: - name = self.__field.name - getter = self.__getter - setter = self.__setter - if isinstance(value, FieldAccessor): - # Join between entity sets - for entity in self.__entities: - try: - data = component[entity] - other = value[entity] - except KeyError: - continue - setter(data, name, op(getter(data), other)) - else: - for entity in self.__entities: - try: - data = component[entity] - except KeyError: - continue - setter(data, name, op(getter(data), value)) - return self - - def __iadd__(self, value): - return self.__mutate(value, operator.iadd) - - def __isub__(self, value): - return self.__mutate(value, operator.isub) - - def __imul__(self, value): - return self.__mutate(value, operator.imul) - - def __idiv__(self, value): - return self.__mutate(value, operator.idiv) - - def __itruediv__(self, value): - return self.__mutate(value, operator.itruediv) - - def __ifloordiv__(self, value): - return self.__mutate(value, operator.ifloordiv) - - def __imod__(self, value): - return self.__mutate(value, operator.imod) - - def __ipow__(self, value): - return self.__mutate(value, operator.ipow) - - def __ilshift__(self, value): - return self.__mutate(value, operator.ilshift) - - def __irshift__(self, value): - return self.__mutate(value, operator.irshift) - - def __iand__(self, value): - return self.__mutate(value, operator.iand) - - def __ior__(self, value): - return self.__mutate(value, operator.ior) - - def __ixor__(self, value): - return self.__mutate(value, operator.ixor) - - -class Field(object): - """Component field metadata and accessor interface""" - - def __init__(self, component, name, type, accessor_factory=FieldAccessor): - self.component = component - self.name = name - self.type = type - self.default = types.get(type) - self.accessor_factory = accessor_factory - - def cast(self, value): - """Cast value to the appropriate type for thi field""" - if self.type is not object: - return self.type(value) - else: - return value - - def accessor(self, entities=None): - """Return the field accessor for the entities in the component, - or all entities in the set specified that are also in the component - """ - if entities is None or entities is self.component.entities: - entities = self.component.entities - else: - entities = entities & self.component.entities - return self.accessor_factory(self, entities) +############################################################################# +# +# Copyright (c) 2010 by Casey Duncan and contributors +# All Rights Reserved. +# +# This software is subject to the provisions of the MIT License +# A copy of the license should accompany this distribution. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# +############################################################################# + +__version__ = '$Id$' + +import operator +from parpg.bGrease.geometry import Vec2d, Vec2dArray, Rect +from parpg.bGrease import color + +# Allowed field types -> default values +types = {int:lambda: 0, + float:lambda: 0.0, + bool:lambda: False, + str:lambda:"", + object:lambda:None, + Vec2d:lambda: Vec2d(0,0), + Vec2dArray:lambda: Vec2dArray(), + color.RGBA: lambda: color.RGBA(0.0, 0.0, 0.0, 0.0), + Rect: lambda: Rect(0.0, 0.0, 0.0, 0.0), + list: lambda: list(), + dict: lambda: dict(), + } + +class Schema(dict): + """Field schema definition for custom components""" + + def __init__(self, **fields): + for ftype in fields.values(): + assert ftype in types, fname + " has an illegal field type" + self.update(fields) + + +class FieldAccessor(object): + """Facade for manipulating a field for a set of entities""" + + __field = None + __entities = None + __attrs = None + __getter = None + __parent_getters = () + + def __init__(self, field, entities, attrs=()): + self.__field = field + self.__entities = entities + field_getter = operator.attrgetter(field.name) + self.__attrs = attrs + if attrs: + getters = [field_getter] + [operator.attrgetter(attr) for attr in attrs] + def get(entity): + value = entity + for getter in getters: + value = getter(value) + return value + self.__getter = get + self.__parent_getters = getters[:-1] + else: + self.__getter = field_getter + + def __getattr__(self, name): + """Return a FieldAccessor for the child attribute""" + return self.__class__(self.__field, self.__entities, self.__attrs + (name,)) + + def __setattr__(self, name, value): + if value is self: + return # returned by mutators + if hasattr(self.__class__, name): + # Set local attr + self.__dict__[name] = value + elif not name.startswith('_'): + getattr(self, name).__set__(value) + else: + raise AttributeError("Cannot set field attribute: %s" % name) + + @property + def __setter(self): + """Return the proper setter function for setting the field value""" + if not self.__attrs: + return setattr + else: + parent_getters = self.__parent_getters + def setter(data, name, value): + for getter in parent_getters: + data = getter(data) + setattr(data, name, value) + self.__setter = setter + return setter + + def __set__(self, value): + """Set field values en masse""" + # Mass set field attr + setter = self.__setter + component = self.__field.component + if self.__attrs: + name = self.__attrs[-1] + else: + name = self.__field.name + if isinstance(value, FieldAccessor): + # Join set between two entity sets + if not self.__attrs: + cast = self.__field.cast + else: + cast = lambda x: x + for entity in self.__entities: + try: + setter(component[entity], name, cast(value[entity])) + except KeyError: + pass + else: + if not self.__attrs: + value = self.__field.cast(value) + for entity in self.__entities: + try: + setter(component[entity], name, value) + except KeyError: + pass + + def __getitem__(self, entity): + """Return the field value for a single entity (used for joins)""" + if entity in self.__entities: + return self.__getter(self.__field.component[entity]) + raise KeyError(entity) + + def __contains__(self, entity): + return entity in self.__entities + + def __repr__(self): + return '<%s %s @ %x>' % ( + self.__class__.__name__, + '.'.join((self.__field.name,) + self.__attrs), id(self)) + + def __nonzero__(self): + return bool(self.__entities) + + def __iter__(self): + """Return an iterator of all field values in the set""" + component = self.__field.component + getter = self.__getter + for entity in self.__entities: + try: + data = component[entity] + except KeyError: + continue + yield getter(data) + + ## batch comparison operators ## + + def __match(self, value, op): + component = self.__field.component + getter = self.__getter + matches = set() + add = matches.add + if isinstance(value, FieldAccessor): + # Join match between entity sets + for entity in self.__entities: + try: + data = component[entity] + other = value[entity] + except KeyError: + continue + if op(getter(data), other): + add(entity) + else: + for entity in self.__entities: + try: + data = component[entity] + except KeyError: + continue + if op(getter(data), value): + add(entity) + return matches + + def __eq__(self, value): + """Return an entity set of all entities with a matching field value""" + return self.__match(value, operator.eq) + + def __ne__(self, value): + """Return an entity set of all entities not matching field value""" + return self.__match(value, operator.ne) + + def __gt__(self, value): + """Return an entity set of all entities with a greater field value""" + return self.__match(value, operator.gt) + + def __ge__(self, value): + """Return an entity set of all entities with a greater or equal field value""" + return self.__match(value, operator.ge) + + def __lt__(self, value): + """Return an entity set of all entities with a lesser field value""" + return self.__match(value, operator.lt) + + def __le__(self, value): + """Return an entity set of all entities with a lesser or equal field value""" + return self.__match(value, operator.le) + + def _contains(self, values): + """Return an entity set of all entities with a field value contained in values""" + return self.__match(values, operator.contains) + + ## Batch in-place mutator methods + + def __mutate(self, value, op): + component = self.__field.component + if self.__attrs: + name = self.__attrs[-1] + else: + name = self.__field.name + getter = self.__getter + setter = self.__setter + if isinstance(value, FieldAccessor): + # Join between entity sets + for entity in self.__entities: + try: + data = component[entity] + other = value[entity] + except KeyError: + continue + setter(data, name, op(getter(data), other)) + else: + for entity in self.__entities: + try: + data = component[entity] + except KeyError: + continue + setter(data, name, op(getter(data), value)) + return self + + def __iadd__(self, value): + return self.__mutate(value, operator.iadd) + + def __isub__(self, value): + return self.__mutate(value, operator.isub) + + def __imul__(self, value): + return self.__mutate(value, operator.imul) + + def __idiv__(self, value): + return self.__mutate(value, operator.idiv) + + def __itruediv__(self, value): + return self.__mutate(value, operator.itruediv) + + def __ifloordiv__(self, value): + return self.__mutate(value, operator.ifloordiv) + + def __imod__(self, value): + return self.__mutate(value, operator.imod) + + def __ipow__(self, value): + return self.__mutate(value, operator.ipow) + + def __ilshift__(self, value): + return self.__mutate(value, operator.ilshift) + + def __irshift__(self, value): + return self.__mutate(value, operator.irshift) + + def __iand__(self, value): + return self.__mutate(value, operator.iand) + + def __ior__(self, value): + return self.__mutate(value, operator.ior) + + def __ixor__(self, value): + return self.__mutate(value, operator.ixor) + + +class Field(object): + """Component field metadata and accessor interface""" + + def __init__(self, component, name, type, accessor_factory=FieldAccessor): + self.component = component + self.name = name + self.type = type + self.default = types.get(type) + self.accessor_factory = accessor_factory + + def cast(self, value): + """Cast value to the appropriate type for thi field""" + if self.type is not object: + return self.type(value) + else: + return value + + def accessor(self, entities=None): + """Return the field accessor for the entities in the component, + or all entities in the set specified that are also in the component + """ + if entities is None or entities is self.component.entities: + entities = self.component.entities + else: + entities = entities & self.component.entities + return self.accessor_factory(self, entities)