def _hashValues(self): item = self._item kind = item._kind view = item.itsView hash = 0 names = self.keys() names.sort() for name in names: if kind is not None: attribute = kind.getAttribute(name, False, item) else: attribute = None if not self._isTransient(name): hash = _combine(hash, _hash(name)) value = self[name] if attribute is not None: attrType = attribute.type else: attrType = None if attrType is not None: hash = _combine(hash, attrType.hashValue(value)) else: hash = _combine(hash, TypeHandler.hashValue(view, value)) return hash
def _unchangedValue(self, item, name): try: self.values.append((name, self.oldValues[_hash(name)])) except KeyError: raise AssertionError, "unchanged value for '%s' not found" % (name) return 0
def _hashValues(self): hash = 0 for key in self.iterkeys(): link = self._get(key) hash = _combine(hash, key._hash) if link.alias is not None: hash = _combine(hash, _hash(link.alias)) return hash
def _hashItem(self): hash = 0 isMixin = self.isMixin() if not isMixin: hash = _combine(hash, _hash(str(self.itsPath))) for superKind in self.getAttributeValue('superKinds', self._references): hash = _combine(hash, superKind.hashItem()) if not isMixin: attributes = list(self.iterAttributes(False)) attributes.sort() for name, attribute, kind in attributes: hash = _combine(hash, _hash(name)) hash = _combine(hash, attribute.hashItem()) return hash
def _hashItem(self): hash = 0 view = self.itsView item = self.getAttributeValue('superAttribute', self._references, None, None) if item is not None: hash = _combine(hash, item.hashItem()) def hashValue(hash, type, value): if type is not None: return _combine(hash, type.hashValue(value)) else: return _combine(hash, TypeHandler.hashValue(view, value)) for aspect in Attribute.valueAspects: value = self.getAttributeValue(aspect, self._values, None, Nil) if value is not Nil: hash = _combine(hash, _hash(aspect)) type = self.getAttributeAspect(aspect, 'type', False, None, None) card = self.getAttributeAspect(aspect, 'cardinality', False, None, 'single') if card == 'single': hash = hashValue(hash, type, value) elif card == 'list': for v in value: hash = hashValue(hash, type, v) else: raise NotImplementedError, card item = self.getAttributeValue('type', self._references, None, None) if item is not None: if isinstance(item, Kind): hash = _combine(hash, _hash(str(item.itsPath))) else: hash = _combine(hash, item.hashItem()) return hash
def hashItem(self): """ Compute a hash value from this aliase's schema. The hash value is computed from the aliase's path and types. @return: an integer """ hash = _hash(str(self.itsPath)) if 'types' in self._references: for t in self.types: hash = _combine(hash, t.hashItem()) return hash
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 getItemClass(self): """ Return the class used to create items of this Kind. If this Kind has superKinds and C{self.classes['python']} is not set a composite class is generated and cached from the superKinds. The L{Item<chandlerdb.item.Item.Item>} class is returned by default. """ missing = False try: cls = self._values['classes']['python'] if cls is not MissingClass: return cls missing = True except KeyError: pass except TypeError: pass superClasses = [] for superKind in self._references.get('superKinds', Nil): c = superKind.getItemClass() if c is not Item and c not in superClasses: superClasses.append(c) count = len(superClasses) if count == 0: c = self.itsView.classLoader.getItemClass() elif count == 1: c = superClasses[0] else: # Filter out redundant superclasses that may cause MRO wonkiness. # A redundant superclass is one with a subclass occurring later # in the superclass list. classes = superClasses superClasses = [] while classes: cls = classes.pop(0) for c in classes: if issubclass(c, cls): break else: superClasses.append(cls) hash = 0 for c in superClasses: hash = _combine(hash, _hash('.'.join((c.__module__, c.__name__)))) if hash < 0: hash = ~hash name = "class_%08x" % (hash) c = classobj(name, tuple(superClasses), {}) self._values['classes'] = {'python': c} self._values._setTransient('classes') self._setupClass(c) if missing: self.itsView.logger.warn( 'Missing class for Kind %s replaced by %s.%s', self.itsPath, c.__module__, c.__name__) return c
def getItemClass(self): """ Return the class used to create items of this Kind. If this Kind has superKinds and C{self.classes['python']} is not set a composite class is generated and cached from the superKinds. The L{Item<chandlerdb.item.Item.Item>} class is returned by default. """ missing = False try: cls = self._values['classes']['python'] if cls is not MissingClass: return cls missing = True except KeyError: pass except TypeError: pass superClasses = [] for superKind in self._references.get('superKinds', Nil): c = superKind.getItemClass() if c is not Item and c not in superClasses: superClasses.append(c) count = len(superClasses) if count == 0: c = self.itsView.classLoader.getItemClass() elif count == 1: c = superClasses[0] else: # Filter out redundant superclasses that may cause MRO wonkiness. # A redundant superclass is one with a subclass occurring later # in the superclass list. classes = superClasses superClasses = [] while classes: cls = classes.pop(0) for c in classes: if issubclass(c, cls): break else: superClasses.append(cls) hash = 0 for c in superClasses: hash = _combine(hash, _hash('.'.join((c.__module__, c.__name__)))) if hash < 0: hash = ~hash name = "class_%08x" %(hash) c = classobj(name, tuple(superClasses), {}) self._values['classes'] = { 'python': c } self._values._setTransient('classes') self._setupClass(c) if missing: self.itsView.logger.warn('Missing class for Kind %s replaced by %s.%s', self.itsPath, c.__module__, c.__name__) return c
def iterAttributes(self, inherited=True, localOnly=False, globalOnly=False): """ Return a generator of C{(name, attribute, kind)} tuples for iterating over the Chandler attributes defined for and inherited by this kind. The C{kind} element is the kind the attribute was inherited from or this kind. The name of an attribute is defined to be the alias with which it was added into the kind's C{attributes} attribute. This alias name may of course be the same as the corresponding attribute's item name. @param inherited: if C{True}, iterate also over attributes that are inherited by this kind via its superKinds. @type inherited: boolean @param localOnly: if C{True}, only pairs for local attributes are returned. Local attributes are defined as direct children items of the kinds they're defined on and are not meant to be shared except through inheritance. @type localOnly: boolean @param globalOnly: if C{True}, only pairs for the global attributes are returned. Global attributes are not defined as direct children items and are intended to be shareable by multiple kinds. @type globalOnly: boolean """ c = self.c allAttributes = c.allAttributes if not c.attributesCached: allNames = c.allNames notifyAttributes = c.notifyAttributes allCorrelations = c.allCorrelations allAttributes.clear() allCorrelations.clear() allNames.clear() notifyAttributes.clear() notify = False references = self.itsRefs for superKind in references['superKinds']: notify = notify or superKind.c.notify for name, attribute, kind in superKind.iterAttributes(): if name not in allAttributes: allAttributes[name] = (attribute.itsUUID, kind.itsUUID, False, False) h = _hash(name) if h in allNames: if allNames[h] != name: raise AssertionError, ('clash', allNames[h], name) allNames[h] = name if attribute.getAspect('notify', False): notifyAttributes.add(name) allCorrelations.update(superKind.c.allCorrelations) else: notify = True attributes = references.get('attributes', None) if attributes is not None: correlations = references.get('correlations', None) uuid = self.itsUUID for attribute in attributes: name = attributes.getAlias(attribute) allAttributes[name] = (attribute.itsUUID, uuid, attribute.itsParent is self, True) allNames[_hash(name)] = name if attribute.getAspect('notify', False): notifyAttributes.add(name) elif name in notifyAttributes: notifyAttributes.remove(name) if correlations: uuids = [ corr.itsUUID for corr in correlations if name in corr.itsValues['names'] ] if uuids: if name in allCorrelations: allCorrelations[name].extend(uuids) else: allCorrelations[name] = uuids c.attributesCached = True c.notify = self.itsValues.get('notify', notify) view = self.itsView for name, (aUUID, kUUID, local, defined) in allAttributes.iteritems(): if not ((globalOnly and local) or (localOnly and not local) or (not inherited and not defined)): yield (name, view[aUUID], view[kUUID])
def iterAttributes(self, inherited=True, localOnly=False, globalOnly=False): """ Return a generator of C{(name, attribute, kind)} tuples for iterating over the Chandler attributes defined for and inherited by this kind. The C{kind} element is the kind the attribute was inherited from or this kind. The name of an attribute is defined to be the alias with which it was added into the kind's C{attributes} attribute. This alias name may of course be the same as the corresponding attribute's item name. @param inherited: if C{True}, iterate also over attributes that are inherited by this kind via its superKinds. @type inherited: boolean @param localOnly: if C{True}, only pairs for local attributes are returned. Local attributes are defined as direct children items of the kinds they're defined on and are not meant to be shared except through inheritance. @type localOnly: boolean @param globalOnly: if C{True}, only pairs for the global attributes are returned. Global attributes are not defined as direct children items and are intended to be shareable by multiple kinds. @type globalOnly: boolean """ c = self.c allAttributes = c.allAttributes if not c.attributesCached: allNames = c.allNames notifyAttributes = c.notifyAttributes allCorrelations = c.allCorrelations allAttributes.clear() allCorrelations.clear() allNames.clear() notifyAttributes.clear() notify = False references = self.itsRefs for superKind in references['superKinds']: notify = notify or superKind.c.notify for name, attribute, kind in superKind.iterAttributes(): if name not in allAttributes: allAttributes[name] = (attribute.itsUUID, kind.itsUUID, False, False) h = _hash(name) if h in allNames: if allNames[h] != name: raise AssertionError, ('clash', allNames[h], name) allNames[h] = name if attribute.getAspect('notify', False): notifyAttributes.add(name) allCorrelations.update(superKind.c.allCorrelations) else: notify = True attributes = references.get('attributes', None) if attributes is not None: correlations = references.get('correlations', None) uuid = self.itsUUID for attribute in attributes: name = attributes.getAlias(attribute) allAttributes[name] = (attribute.itsUUID, uuid, attribute.itsParent is self, True) allNames[_hash(name)] = name if attribute.getAspect('notify', False): notifyAttributes.add(name) elif name in notifyAttributes: notifyAttributes.remove(name) if correlations: uuids = [corr.itsUUID for corr in correlations if name in corr.itsValues['names']] if uuids: if name in allCorrelations: allCorrelations[name].extend(uuids) else: allCorrelations[name] = uuids c.attributesCached = True c.notify = self.itsValues.get('notify', notify) view = self.itsView for name, (aUUID, kUUID, local, defined) in allAttributes.iteritems(): if not ((globalOnly and local) or (localOnly and not local) or (not inherited and not defined)): yield (name, view[aUUID], view[kUUID])