def _setValue(self, name, other, otherName, noFireChanges=False, cardinality=None, alias=None, dictKey=None, otherKey=None, otherCard=None, otherAlias=None): item = self._item view = item.itsView if name in self: value = self._getRef(name, None, otherName) if value is not None and isitem(value): value.itsRefs._removeRef(otherName, item) if isitem(other): if other.isDeleting(): raise ValueError, ('setting bi-ref with an item being deleted', item, name, other) otherView = other.itsView if otherView is not view: raise ViewMismatchError, (item, other) if otherName in other.itsRefs: value = other.itsRefs._getRef(otherName, None, name) if value is not None and isitem(value): value.itsRefs._removeRef(name, other) value = self._setRef(name, other, otherName, cardinality, alias, dictKey, otherKey) try: otherValue = other.itsRefs._setRef(otherName, item, name, otherCard, otherAlias, otherKey, dictKey) except: self._removeRef(name, other) # remove dangling ref raise if not noFireChanges: if not item._isNoDirty(): item._fireChanges('set', name) if not (other is None or other._isNoDirty()): other._fireChanges('set', otherName) if value._isRefs(): view._notifyChange(item._collectionChanged, 'add', 'collection', name, other.itsUUID, ()) if otherValue._isRefs(): view._notifyChange(other._collectionChanged, 'add', 'collection', otherName, item.itsUUID, ()) elif other in (None, Empty): self._setRef(name, other, otherName, cardinality, alias, dictKey, otherKey) if not (noFireChanges or item._isNoDirty()): item._fireChanges('set', name) else: raise TypeError, other
def iterValues(self, item): def append(values, value): if not (value is None or isitemref(value)): if isitem(value) or isinstance(value, RefList): values.append(value) elif isinstance(value, PersistentCollection): values.append(value._iterItems()) elif isinstance(value, AbstractSet): values.append(value) else: raise TypeError, type(value) value = item for name in self.attribute: if isinstance(value, PersistentCollection): values = [] for v in value._iterItems(): append(values, v.getAttributeValue(name, None, None, None)) value = values elif isinstance(value, RefList): values = [] for v in value: append(values, v.getAttributeValue(name, None, None, None)) value = values elif isinstance(value, AbstractSet): values = [] for v in value: append(values, v.getAttributeValue(name, None, None, None)) value = values elif isinstance(value, list): values = [] for v in value: if isitem(v): append(values, v.getAttributeValue(name, None, None, None)) else: for i in v: append(values, i.getAttributeValue(name, None, None, None)) value = values else: value = value.getAttributeValue(name, None, None, None) if value is None or isitemref(value): break if not (isitem(value) or isinstance(value, (PersistentCollection, RefList, AbstractSet))): value = None break if value is None: return [] if isitem(value): return [value] if isinstance(value, PersistentCollection): return value._iterItems() return value
def iterValues(self, item): def append(values, value): if not (value is None or isitemref(value)): if isitem(value) or isinstance(value, RefList): values.append(value) elif isinstance(value, PersistentCollection): values.append(value._iterItems()) elif isinstance(value, AbstractSet): values.append(value) else: raise TypeError, type(value) value = item for name in self.attribute: if isinstance(value, PersistentCollection): values = [] for v in value._iterItems(): append(values, v.getAttributeValue(name, None, None, None)) value = values elif isinstance(value, RefList): values = [] for v in value: append(values, v.getAttributeValue(name, None, None, None)) value = values elif isinstance(value, AbstractSet): values = [] for v in value: append(values, v.getAttributeValue(name, None, None, None)) value = values elif isinstance(value, list): values = [] for v in value: if isitem(v): append(values, v.getAttributeValue(name, None, None, None)) else: for i in v: append(values, i.getAttributeValue(name, None, None, None)) value = values else: value = value.getAttributeValue(name, None, None, None) if value is None or isitemref(value): break if not (isitem(value) or isinstance( value, (PersistentCollection, RefList, AbstractSet))): value = None break if value is None: return [] if isitem(value): return [value] if isinstance(value, PersistentCollection): return value._iterItems() return value
def recognizes(self, value): if value is None: return True if isitemref(value): item = value(True) if isitem(item): return item.isItemOf(self) return True if isitem(value): return value.isItemOf(self) return False
def _getRef(self, name, other=None, otherName=None, default=Default): value = self.get(name, self) item = self._item if other is None: if value is self: if default is not Default: return default raise KeyError, name if value in (None, Empty) or isitem(value) or value._isRefs(): return value raise TypeError, '%s, type: %s' % (value, type(value)) if value is other: return other if value is self or value is None: raise BadRefError, (item, name, value, other) if value is Empty: raise DanglingRefError(item, name, other) if value._isRefs(): if other in value: return other else: raise DanglingRefError(item, name, other) raise BadRefError, (item, name, value, other)
def _getRef(self, name, other=None, otherName=None, default=Default): value = self.get(name, self) item = self._item if other is None: if value is self: if default is not Default: return default raise KeyError, name if value in (None, Empty) or isitem(value) or value._isRefs(): return value raise TypeError, '%s, type: %s' %(value, type(value)) if value is other: return other if value is self or value is None: raise BadRefError, (item, name, value, other) if value is Empty: raise DanglingRefError(item, name, other) if value._isRefs(): if other in value: return other else: raise DanglingRefError(item, name, other) raise BadRefError, (item, name, value, other)
def __repr__(self): owner = self._owner(True) if isitem(owner): owner = owner._repr_() return '<%s: %s.%s<->%s>' % (type(self).__name__, owner, self._name, self._otherName)
def __repr__(self): owner = self._owner(True) if isitem(owner): owner = owner._repr_() return '<%s: %s.%s<->%s>' %(type(self).__name__, owner, self._name, self._otherName)
def _checkCardinality(self, logger, name, value, cardType, attrCard, repair): if not (value in (None, Empty) or (cardType is None and isitem(value)) or (cardType is not None and isinstance(value, cardType))): logger.error("Value %s of type %s in attribute '%s' on %s is not an instance of type %s which is required for cardinality '%s'", repr(value), type(value), name, self._item._repr_(), cardType, attrCard) return False return True
def append(values, value): if not (value is None or isitemref(value)): if isitem(value) or isinstance(value, RefList): values.append(value) elif isinstance(value, PersistentCollection): values.append(value._iterItems()) elif isinstance(value, AbstractSet): values.append(value) else: raise TypeError, type(value)
def append(values, value): if value is not None: if isuuid(value) or isinstance(value, RefList): values.append(value) elif isitem(value) or isitemref(value): values.append(value.itsUUID) elif isinstance(value, PersistentCollection): values.extend(value._iterKeys()) elif isinstance(value, AbstractSet): values.append(value) else: raise TypeError, type(value)
def _checkCardinality(self, logger, name, value, cardType, attrCard, repair): if not (value in (None, Empty) or (cardType is None and isitem(value)) or (cardType is not None and isinstance(value, cardType))): logger.error( "Value %s of type %s in attribute '%s' on %s is not an instance of type %s which is required for cardinality '%s'", repr(value), type(value), name, self._item._repr_(), cardType, attrCard) return False return True
def _iterItems(self, items=None): if items is None: items = {} for value in self._itervalues(): if isitemref(value): item = value(True) if isitem(item): uuid = item.itsUUID if uuid not in items: items[uuid] = item yield item elif isinstance(value, PersistentCollection): for v in value._iterItems(items): yield v
def refCount(self, name, loaded): count = 0 value = self._dict.get(name) if value not in (None, Empty): if isitemref(value): if not loaded: count += 1 elif isitem(value.itsItem): count += 1 elif value._isRefs(): count += value.refCount(loaded) return count
def _setItem(self, item): if self._owner is not Nil: assert item.itsUUID == self._owner.itsUUID for link in self._itervalues(): link.value._parent = item if isitem(item): item._status |= CItem.CONTAINER self._owner = item.itsRef self._view = item.itsView elif item is None: self._owner = Nil self._owner = ref(item)
def _copy(self, item, attribute, copyPolicy, copyFn=None): copy = type(self)(item, attribute) policy = copyPolicy or item.getAttributeAspect(attribute, 'copyPolicy', False, None, 'copy') for value in self: if isitem(value): if copyFn is not None: value = copyFn(item, value, policy) if value is not Nil: copy.add(value, False) elif isinstance(value, ItemValue): copy.add(value._copy(item, attribute, policy, copyFn), False) else: copy.add(value, False) return copy
def prepareValue(self, item, attribute, value, setDirty=True): if isinstance(value, ItemValue): if value._owner is not Nil: value = value._copy(item, attribute, 'copy') else: value._setOwner(item, attribute) elif isinstance(value, list): value = PersistentList(item, attribute, value, setDirty) elif isinstance(value, dict): value = PersistentDict(item, attribute, value, setDirty) elif isinstance(value, tuple): value = PersistentTuple(item, attribute, value, setDirty) elif isinstance(value, set): value = PersistentSet(item, attribute, value, setDirty) elif isitem(value): value = value.itsRef return value
def _hashValues(self): hash = 0 names = self.keys() names.sort() for name in names: hash = _combine(hash, _hash(name)) value = self[name] if value in (None, Empty): hash = _combine(hash, 0) elif isitem(value): hash = _combine(hash, value._uuid._hash) elif value._isRefs(): hash = _combine(hash, value._hashValues()) else: raise TypeError, value return hash
def useValue(self, value): if isitem(value): return value.itsRef if isinstance(value, PersistentCollection): return value if isitemref(value): return value if isinstance(value, list): return [self.useValue(v) for v in value] elif isinstance(value, set): return set([self.useValue(v) for v in value]) elif isinstance(value, tuple): return tuple([self.useValue(v) for v in value]) elif isinstance(value, dict): d = {} for k, v in value.itervalues(): d[k] = self.useValue(v) return d else: return value
def typeHandler(cls, view, value): try: method = getattr(type(value), "getTypeItem", None) if method is not None: return method(value, view) else: for t in cls.typeHandlers[view][type(value)]: if t.recognizes(value): return t except KeyError: pass if isitem(value): return cls.typeHandlers[view][ItemRef][0] typeKind = cls.typeHandlers[view][None] types = typeKind.findTypes(value) if types: return types[0] raise TypeError, "No handler for values of type %s" % (type(value))
def _checkRef(self, logger, name, other, repair): if other is not None: if not isitem(other): other = self._item.find(other) if other is None: logger.error('DanglingRefError: %s.%s', self._item.itsPath, name) return False if other.isStale(): logger.error('Found stale item %s at %s.%s', other, self._item.itsPath, name) return False if other.itsView is not self._item.itsView: logger.error("views don't match: %s at %s.%s", other, self._item.itsPath, name) return False item = self._item otherName = item.itsKind.getOtherName(name, item, None) if otherName is None: logger.error('otherName is None for attribute %s.%s', self._item._kind.itsPath, name) return False if other not in (None, Empty): if other.itsKind is None: raise AssertionError, 'no kind for %s' % (other.itsPath) otherOtherName = other.itsKind.getOtherName(otherName, other, None) if otherOtherName != name: logger.error( "otherName for attribute %s.%s, %s, does not match otherName for attribute %s.%s, %s", self._item.itsKind.itsPath, name, otherName, other.itsKind.itsPath, otherName, otherOtherName) return False otherOther = other.itsRefs._getRef(otherName) if otherOther is self._item: return True elif otherOther._isRefs(): if (otherOther._isDict() or # check not yet implemented self._item in otherOther): return True logger.error( "%s doesn't contain a reference to %s, yet %s.%s references %s", otherOther, self._item._repr_(), self._item._repr_(), name, other._repr_()) if repair: logger.warning("Removing dangling ref to %s from %s.%s", other._repr_(), self._item._repr_(), name) self._removeRef(name, other) return None elif isitem(otherOther): logger.error("%s.%s doesn't reference %s.%s but %s", other._repr_(), otherName, self._item._repr_(), name, otherOther._repr_()) else: logger.error("%s.%s doesn't reference %s.%s but %s", other._repr_(), otherName, self._item._repr_(), name, otherOther) return False return True
def iterKeys(self, key, firstValue=Default): view = self.itsView def append(values, value): if value is not None: if isuuid(value) or isinstance(value, RefList): values.append(value) elif isitem(value) or isitemref(value): values.append(value.itsUUID) elif isinstance(value, PersistentCollection): values.extend(value._iterKeys()) elif isinstance(value, AbstractSet): values.append(value) else: raise TypeError, type(value) if firstValue is not Default: names = self.attribute[1:] value = firstValue else: names = self.attribute value = key for name in names: if isinstance(value, PersistentCollection): values = [] for v in value._iterKeys(): append(values, view.findValue(v, name, None)) value = values elif isinstance(value, RefList): values = [] for v in value.iterkeys(): append(values, view.findValue(v, name, None)) value = values elif isinstance(value, AbstractSet): values = [] for v in value.iterkeys(): append(values, view.findValue(v, name, None)) value = values elif isinstance(value, list): values = [] for v in value: if isuuid(v): append(values, view.findValue(v, name, None)) else: for k in v.iterkeys(): append(values, view.findValue(k, name, None)) value = values else: value = view.findValue(value, name, None) if value is None: break if isitemref(value) or isitem(value): value = value.itsUUID elif not (isuuid(value) or isinstance(value, (PersistentCollection, RefList, AbstractSet))): value = None break if value is None: return [] if isuuid(value): return [value] if isitemref(value) or isitem(value): return [value.itsUUID] if isinstance(value, PersistentCollection): return value._iterKeys() if isinstance(value, RefList): return value.iterkeys() return value
def __setitem__(self, dictKey, value): if isitem(value): self._refList(dictKey).append(value) else: self._refList(dictKey).extend(value)
def str(self, arg): if isitem(arg): return arg._repr_() else: return str(arg)
def iterKeys(self, key, firstValue=Default): view = self.itsView def append(values, value): if value is not None: if isuuid(value) or isinstance(value, RefList): values.append(value) elif isitem(value) or isitemref(value): values.append(value.itsUUID) elif isinstance(value, PersistentCollection): values.extend(value._iterKeys()) elif isinstance(value, AbstractSet): values.append(value) else: raise TypeError, type(value) if firstValue is not Default: names = self.attribute[1:] value = firstValue else: names = self.attribute value = key for name in names: if isinstance(value, PersistentCollection): values = [] for v in value._iterKeys(): append(values, view.findValue(v, name, None)) value = values elif isinstance(value, RefList): values = [] for v in value.iterkeys(): append(values, view.findValue(v, name, None)) value = values elif isinstance(value, AbstractSet): values = [] for v in value.iterkeys(): append(values, view.findValue(v, name, None)) value = values elif isinstance(value, list): values = [] for v in value: if isuuid(v): append(values, view.findValue(v, name, None)) else: for k in v.iterkeys(): append(values, view.findValue(k, name, None)) value = values else: value = view.findValue(value, name, None) if value is None: break if isitemref(value) or isitem(value): value = value.itsUUID elif not (isuuid(value) or isinstance( value, (PersistentCollection, RefList, AbstractSet))): value = None break if value is None: return [] if isuuid(value): return [value] if isitemref(value) or isitem(value): return [value.itsUUID] if isinstance(value, PersistentCollection): return value._iterKeys() if isinstance(value, RefList): return value.iterkeys() return value
def _checkRef(self, logger, name, other, repair): if other is not None: if not isitem(other): other = self._item.find(other) if other is None: logger.error('DanglingRefError: %s.%s', self._item.itsPath, name) return False if other.isStale(): logger.error('Found stale item %s at %s.%s', other, self._item.itsPath, name) return False if other.itsView is not self._item.itsView: logger.error("views don't match: %s at %s.%s", other, self._item.itsPath, name) return False item = self._item otherName = item.itsKind.getOtherName(name, item, None) if otherName is None: logger.error('otherName is None for attribute %s.%s', self._item._kind.itsPath, name) return False if other not in (None, Empty): if other.itsKind is None: raise AssertionError, 'no kind for %s' %(other.itsPath) otherOtherName = other.itsKind.getOtherName(otherName, other, None) if otherOtherName != name: logger.error("otherName for attribute %s.%s, %s, does not match otherName for attribute %s.%s, %s", self._item.itsKind.itsPath, name, otherName, other.itsKind.itsPath, otherName, otherOtherName) return False otherOther = other.itsRefs._getRef(otherName) if otherOther is self._item: return True elif otherOther._isRefs(): if (otherOther._isDict() or # check not yet implemented self._item in otherOther): return True logger.error("%s doesn't contain a reference to %s, yet %s.%s references %s", otherOther, self._item._repr_(), self._item._repr_(), name, other._repr_()) if repair: logger.warning("Removing dangling ref to %s from %s.%s", other._repr_(), self._item._repr_(), name) self._removeRef(name, other) return None elif isitem(otherOther): logger.error("%s.%s doesn't reference %s.%s but %s", other._repr_(), otherName, self._item._repr_(), name, otherOther._repr_()) else: logger.error("%s.%s doesn't reference %s.%s but %s", other._repr_(), otherName, self._item._repr_(), name, otherOther) return False return True
def xmlValue(cls, view, name, value, tag, attrType, attrCard, attrId, attrs, generator, withSchema): if name is not None: if not isinstance(name, (str, unicode)): attrs['nameType'] = cls.typeHandler(view, value).handlerName() attrs['name'] = cls.makeString(view, name) else: attrs['name'] = name if attrId is not None: attrs['id'] = attrId.str64() if attrCard == 'single': if attrType is not None and attrType.isAlias(): aliasType = attrType.type(value) if aliasType is None: raise TypeError, "%s does not alias type of value '%s' of type %s" % ( attrType.itsPath, value, type(value)) attrType = aliasType attrs['typeid'] = attrType._uuid.str64() elif withSchema or attrType is None: attrType = cls.typeHandler(view, value) attrs['typeid'] = attrType._uuid.str64() else: attrs['cardinality'] = attrCard generator.startElement(tag, attrs) if attrCard == 'single': if isitem(value): raise TypeError, "item %s cannot be stored as a literal value" % ( value.itsPath) if value is Nil: raise ValueError, 'Cannot persist Nil' if attrType is not None: if not attrType.recognizes(value): raise TypeError, "value '%s' of type %s is not recognized by type %s" % ( value, type(value), attrType.itsPath) else: attrType.typeXML(value, generator, withSchema) else: generator.characters(cls.makeString(view, value)) elif attrCard in ('list', 'set'): for val in value._itervalues(): cls.xmlValue(view, None, val, 'value', attrType, 'single', None, {}, generator, withSchema) elif attrCard == 'dict': for key, val in value._iteritems(): cls.xmlValue(view, key, val, 'value', attrType, 'single', None, {}, generator, withSchema) else: raise ValueError, attrCard generator.endElement(tag)
def xmlValue(cls, view, name, value, tag, attrType, attrCard, attrId, attrs, generator, withSchema): if name is not None: if not isinstance(name, (str, unicode)): attrs['nameType'] = cls.typeHandler(view, value).handlerName() attrs['name'] = cls.makeString(view, name) else: attrs['name'] = name if attrId is not None: attrs['id'] = attrId.str64() if attrCard == 'single': if attrType is not None and attrType.isAlias(): aliasType = attrType.type(value) if aliasType is None: raise TypeError, "%s does not alias type of value '%s' of type %s" %(attrType.itsPath, value, type(value)) attrType = aliasType attrs['typeid'] = attrType._uuid.str64() elif withSchema or attrType is None: attrType = cls.typeHandler(view, value) attrs['typeid'] = attrType._uuid.str64() else: attrs['cardinality'] = attrCard generator.startElement(tag, attrs) if attrCard == 'single': if isitem(value): raise TypeError, "item %s cannot be stored as a literal value" %(value.itsPath) if value is Nil: raise ValueError, 'Cannot persist Nil' if attrType is not None: if not attrType.recognizes(value): raise TypeError, "value '%s' of type %s is not recognized by type %s" %(value, type(value), attrType.itsPath) else: attrType.typeXML(value, generator, withSchema) else: generator.characters(cls.makeString(view, value)) elif attrCard in ('list', 'set'): for val in value._itervalues(): cls.xmlValue(view, None, val, 'value', attrType, 'single', None, {}, generator, withSchema) elif attrCard == 'dict': for key, val in value._iteritems(): cls.xmlValue(view, key, val, 'value', attrType, 'single', None, {}, generator, withSchema) else: raise ValueError, attrCard generator.endElement(tag)