Title: [commits] (vajda) [11099] - moved DelegatingIndex to C
Revision
11099
Author
vajda
Date
2006-07-08 09:26:57 -0700 (Sat, 08 Jul 2006)

Log Message

- moved DelegatingIndex to C
- upgraded build to chandlerdb 0.6-29
- fixed bug in MultiIntersection of 1, made it behave as an empty set
- refactored collections code to support dynamic source changes and deletion
- fixed bug 6210 (http://bugzilla.osafoundation.org/show_bug.cgi?id=6210)

Modified Paths

Diff

Modified: trunk/chandler/Makefile (11098 => 11099)

--- trunk/chandler/Makefile	2006-07-08 16:09:33 UTC (rev 11098)
+++ trunk/chandler/Makefile	2006-07-08 16:26:57 UTC (rev 11099)
@@ -66,7 +66,7 @@
 
 # these get installed into release or debug
 ARCHIVES=$(CHANDLERARCHIVES)/Launchers-$(SNAP)-0.8-$(BP)8.tar.gz \
-         $(CHANDLERARCHIVES)/chandlerdb-$(SNAP)-0.6-$(BP)28.tar.gz \
+         $(CHANDLERARCHIVES)/chandlerdb-$(SNAP)-0.6-$(BP)29.tar.gz \
          $(CHANDLERARCHIVES)/db-$(SNAP)-4.4.20-$(BP)5.tar.gz \
          $(CHANDLERARCHIVES)/python-$(SNAP)-2.4.3-$(BP)3.tar.gz \
          $(CHANDLERARCHIVES)/epydoc-$(SNAP)-2.1-$(BP)9.tar.gz \

Modified: trunk/chandler/application/Utility.py (11098 => 11099)

--- trunk/chandler/application/Utility.py	2006-07-08 16:09:33 UTC (rev 11098)
+++ trunk/chandler/application/Utility.py	2006-07-08 16:26:57 UTC (rev 11099)
@@ -33,7 +33,7 @@
 # with your name (and some helpful text). The comment's really there just to
 # cause Subversion to warn you of a conflict when you update, in case someone 
 # else changes it at the same time you do (that's why it's on the same line).
-SCHEMA_VERSION = "215" # John: added bufferedDraw to BoxContainer
+SCHEMA_VERSION = "216" #vajda: refactored collections for dynamic source changes
 
 logger = None # initialized in initLogging()
 

Modified: trunk/chandler/parcels/osaf/pim/collections.py (11098 => 11099)

--- trunk/chandler/parcels/osaf/pim/collections.py	2006-07-08 16:09:33 UTC (rev 11098)
+++ trunk/chandler/parcels/osaf/pim/collections.py	2006-07-08 16:26:57 UTC (rev 11099)
@@ -22,7 +22,7 @@
 from chandlerdb.item.c import Default
 from repository.item.Sets import \
     Set, MultiUnion, Union, MultiIntersection, Intersection, Difference, \
-    KindSet, ExpressionFilteredSet, MethodFilteredSet
+    KindSet, ExpressionFilteredSet, MethodFilteredSet, EmptySet
 from repository.item.Collection import Collection
 
 from osaf.pim.items import ContentItem
@@ -31,7 +31,6 @@
 DEBUG = logger.getEffectiveLevel() <= logging.DEBUG
 
 
-
 class ContentCollection(ContentItem, Collection):
     """
     The base class for Chandler Collection types.
@@ -107,7 +106,7 @@
             invitees,
             byRef=['contentsOwner', 'subscribers']
         ),
-        sharing = schema.Cloud( none = ["displayName"] ),
+        sharing = schema.Cloud(none=["displayName"]),
     )
 
     def __str__(self):
@@ -163,9 +162,7 @@
 
     set = schema.One(schema.TypeReference('//Schema/Core/AbstractSet'))
 
-    schema.kindInfo(
-        displayName=u"KindCollection"
-    )
+    schema.kindInfo(displayName=u"KindCollection")
 
     kind = schema.One(schema.TypeReference('//Schema/Core/Kind'))
     recursive = schema.One(schema.Boolean, defaultValue=False)
@@ -199,13 +196,9 @@
             item.delete(True)
 
 
-class DifferenceCollection(ContentCollection):
+class WrapperCollection(ContentCollection):
     """
-    A ContentCollection containing the set theoretic difference of two
-    ContentCollections.
-
-    The C{sources} attribute (a list) contains the ContentCollection
-    instances to be differenced.
+    A class for collections wrapping other collections
     """
 
     __metaclass__ = schema.CollectionClass
@@ -213,48 +206,15 @@
 
     set = schema.One(schema.TypeReference('//Schema/Core/AbstractSet'))
 
-    schema.kindInfo(
-        displayName=u"DifferenceCollection"
-    )
+    sources = schema.Sequence(ContentCollection, otherName='sourceFor',
+                              doc="the collections being wrapped",
+                              initialValue=[])
+    schema.addClouds(copying=schema.Cloud(byCloud=[sources]))
 
-    sources = schema.Sequence(ContentCollection, otherName='sourceFor')
-
-    schema.addClouds(
-        copying = schema.Cloud(byCloud=[sources]),
-    )
-
     def __init__(self, *args, **kwds):
 
-        super(DifferenceCollection, self).__init__(*args, **kwds)
+        super(WrapperCollection, self).__init__(*args, **kwds)
 
-        a, b = self.sources
-        setattr(self, self.__collection__, Difference(a, b))
-
-
-class MultiCollection(ContentCollection):
-    """
-    A ContentCollection containing the set theoretic union or intersection
-    of at least two ContentCollections.
-
-    The C{sources} attribute (a ref collection) contains the ContentCollection
-    instances to be combined and can be changed.
-    """
-
-    __metaclass__ = schema.CollectionClass
-    __collection__ = 'set'
-
-    set = schema.One(schema.TypeReference('//Schema/Core/AbstractSet'))
-
-    sources = schema.Sequence(ContentCollection,
-                              otherName='sourceFor', initialValue=[])
-
-    schema.kindInfo(displayName=u"UnionCollection")
-    schema.addClouds(copying = schema.Cloud(byCloud=[sources]))
-
-    def __init__(self, *args, **kwds):
-
-        super(MultiCollection, self).__init__(*args, **kwds)
-
         self._sourcesChanged_()
         self.watchCollection(self, 'sources', '_sourcesChanged')
 
@@ -267,7 +227,7 @@
             if op == 'add':
                 set = self._sourcesChanged_()
                 sourceChanged = set.sourceChanged
-                actualSource = set.findSource(source.itsUUID)
+                actualSource = set.findSource(sourceId)
                 assert actualSource is not None
                 for uuid in source.iterkeys():
                     view._notifyChange(sourceChanged, 'add', 'collection',
@@ -276,7 +236,7 @@
             elif op == 'remove':
                 set = getattr(self, self.__collection__)
                 sourceChanged = set.sourceChanged
-                actualSource = set.findSource(source.itsUUID)
+                actualSource = set.findSource(sourceId)
                 assert actualSource is not None
                 for uuid in source.iterkeys():
                     view._notifyChange(sourceChanged, 'remove', 'collection',
@@ -295,12 +255,81 @@
             self.sources.remove(source)
 
 
-class UnionCollection(MultiCollection):
+class SingleSourceWrapperCollection(WrapperCollection):
     """
+    A class for collections wrapping another collection
+    """
+
+    def _getSource(self):
+        sources = self.sources
+        if sources:
+            return sources.first()
+        return None
+    def _setSource(self, source):
+        sources = self.sources
+        if sources and sources.first() is not source:
+            sources.clear()
+            if source is not None:
+                sources.append(source)
+    def _delSource(self):
+        self.sources.clear()
+    source = property(_getSource, _setSource, _delSource)
+
+    def __init__(self, *args, **kwds):
+
+        source = kwds.pop('source', None)
+        if source is not None:
+            kwds['sources'] = [source]
+
+        super(SingleSourceWrapperCollection, self).__init__(*args, **kwds)
+
+
+class DifferenceCollection(WrapperCollection):
+    """
+    A ContentCollection containing the set theoretic difference of two
+    ContentCollections.
+
+    The C{sources} attribute (a list) contains the ContentCollection
+    instances to be differenced.
+    """
+
+    schema.kindInfo(displayName=u"DifferenceCollection")
+
+    def _sourcesChanged_(self):
+
+        sources = self.sources
+        sourceCount = len(sources)
+
+        if sourceCount == 0:
+            set = EmptySet()
+        elif sourceCount == 1:
+            set = getattr(self, self.__collection__)
+            source = sources.first()
+            if instance(set, Difference):
+                if set._left[0] == source.itsUUID:
+                    set = Set(source)
+                else:
+                    set = EmptySet()
+            else:
+                set = Set(source)
+        elif sourceCount == 2:
+            a, b = self.sources
+            set = Difference(a, b)
+        else:
+            raise ValueError, 'too many sources'
+
+        setattr(self, self.__collection__, set)
+        return set
+
+
+class UnionCollection(WrapperCollection):
+    """
     A ContentCollection containing the set theoretic union of at least two
     ContentCollections.
     """
 
+    schema.kindInfo(displayName=u"UnionCollection")
+
     def _sourcesChanged_(self):
 
         sources = self.sources
@@ -308,11 +337,12 @@
 
         # For now, when we join collections with Union, we pull trash
         # out of the equation with withoutTrash()
-        if sourceCount == 1:
+        if sourceCount == 0:
+            set = EmptySet()
+        elif sourceCount == 1:
             set = Set(sources.first().withoutTrash())
         elif sourceCount == 2:
-            left = sources.first()
-            right = sources.next(left)
+            left, right = sources
             set = Union(left.withoutTrash(), right.withoutTrash())
         else:
             set = MultiUnion(*(source.withoutTrash()
@@ -322,12 +352,14 @@
         return set
 
 
-class IntersectionCollection(MultiCollection):
+class IntersectionCollection(WrapperCollection):
     """
     A ContentCollection containing the set theoretic intersection of at
     least two ContentCollections.
     """
 
+    schema.kindInfo(displayName=u"IntersectionCollection")
+
     def _sourcesChanged_(self):
 
         sources = self.sources
@@ -335,11 +367,10 @@
 
         # For now, when we join collections with Intersection, we pull trash
         # out of the equation with withoutTrash()
-        if sourceCount == 1:
-            set = Set(sources.first().withoutTrash())
+        if sourceCount < 2:
+            set = EmptySet()
         elif sourceCount == 2:
-            left = sources.first()
-            right = sources.next(left)
+            left, right = sources
             set = Intersection(left.withoutTrash(), right.withoutTrash())
         else:
             set = MultiIntersection(*(source.withoutTrash()
@@ -349,7 +380,7 @@
         return set
 
 
-class FilteredCollection(ContentCollection):
+class FilteredCollection(SingleSourceWrapperCollection):
     """
     A ContentCollection which is the result of applying a boolean predicate
     to every item of another ContentCollection.
@@ -366,49 +397,33 @@
     Failure to provide this list will result in missing notifications.
     """
 
-    __metaclass__ = schema.CollectionClass
-    __collection__ = 'set'
+    schema.kindInfo(displayName=u"FilteredCollection")
 
-    set = schema.One(schema.TypeReference('//Schema/Core/AbstractSet'))
-
-    schema.kindInfo(
-        displayName=u"FilteredCollection"
-    )
-
-    sources = schema.Sequence(ContentCollection, otherName='sourceFor')
-
     filterExpression = schema.One(schema.Text)
     filterMethod = schema.One(schema.Tuple)
     filterAttributes = schema.Sequence(schema.Symbol, initialValue=[])
 
-    schema.addClouds(
-        copying = schema.Cloud(byCloud=[sources]),
-    )
+    def _sourcesChanged_(self):
 
-    def __init__(self, *args, **kwds):
+        source = self.source
+        if source is None:
+            s = EmptySet()
+        else:
+            attrTuples = set()
+            for name in self.filterAttributes:
+                attrTuples.add((name, "set"))
+                attrTuples.add((name, "remove"))
+            attrs = tuple(attrTuples)
 
-        source = kwds.pop('source', None)
-        if source is not None:
-            kwds['sources'] = [source]
+            if hasattr(self, 'filterExpression'):
+                s = ExpressionFilteredSet(source, self.filterExpression, attrs)
+            else:
+                s = MethodFilteredSet(source, self.filterMethod, attrs)
 
-        super(FilteredCollection, self).__init__(*args, **kwds)
+        setattr(self, self.__collection__, s)
+        return s
 
-        attrTuples = set()
-        for i in self.filterAttributes:
-            attrTuples.add((i, "set"))
-            attrTuples.add((i, "remove"))
 
-        source = self.sources.first()
-        attrs = tuple(attrTuples)
-
-        if 'filterExpression' in kwds:
-            setattr(self, self.__collection__,
-                    ExpressionFilteredSet(source, self.filterExpression, attrs))
-        else:
-            setattr(self, self.__collection__,
-                    MethodFilteredSet(source, self.filterMethod, attrs))
-
-
 class AppCollection(ContentCollection):
     """
     AppCollections implement inclusions, exclusions, source,
@@ -626,35 +641,33 @@
     pass
 
 
-class IndexedSelectionCollection(ContentCollection):
+class IndexedSelectionCollection(SingleSourceWrapperCollection):
     """
     A collection that adds an index, e.g. for sorting items, a
     selection and visibility attribute to another source collection.
     """
 
-    __metaclass__ = schema.CollectionClass
-    __collection__ = 'set'
+    indexName = schema.One(schema.Symbol, initialValue="__adhoc__")
 
-    set = schema.One(schema.TypeReference('//Schema/Core/AbstractSet'))
+    def _sourcesChanged_(self):
+        
+        source = self.source
+        trash = schema.ns('osaf.pim', self.itsView).trashCollection
 
-    indexName   = schema.One(schema.Text, initialValue="__adhoc__")
-    source      = schema.One(ContentCollection, defaultValue=None)
-
-    def __init__(self, *args, **kwds):
-
-        super(IndexedSelectionCollection, self).__init__(*args, **kwds)
-
-        trash = schema.ns('osaf.pim', self.itsView).trashCollection
-        if (isinstance(self.source, MultiCollection) and
-            trash not in self.source.sources):
+        if source is None:
+            set = EmptySet()
+        elif (isinstance(source, WrapperCollection) and
+              trash not in source.sources):
             # bug 5899 - alpha2 workaround: When SmartCollections are
             # wrapped with IntersectionCollection/UnionCollection,
             # they drop the trash. So we artificially insert it back
-            sourceMinusTrash = Difference(self.source, trash)
-            setattr(self, self.__collection__, sourceMinusTrash)
+            set = Difference(source, trash)
         else:
-            setattr(self, self.__collection__, Set(self.source))
+            set = Set(self.source)
 
+        setattr(self, self.__collection__, set)
+        return set
+
     def getCollectionIndex(self, indexName=None):
         """
         Get the index. If it doesn't exist, create. Also create a RangeSet
@@ -716,7 +729,6 @@
             self.setDescending (currentIndexName, not self.isDescending(currentIndexName))
             self.setSelectionRanges(newRanges)
 
-
     def __len__(self):
 
         return len(self.getCollectionIndex())
@@ -748,7 +760,7 @@
     # Range-based selection methods
     # 
 
-    def getSelectionRanges (self):
+    def getSelectionRanges(self):
         """
         Return the ranges associated with the current index as an
         array of tuples, where each tuple represents a start and
@@ -756,7 +768,7 @@
         """
         return self.getCollectionIndex().getRanges()
         
-    def setSelectionRanges (self, ranges):
+    def setSelectionRanges(self, ranges):
         """
         Sets the ranges associated with the current index with
         C{ranges} which should be an array of tuples, where each
@@ -765,7 +777,7 @@
         """
         self.setRanges(self.indexName, ranges)
 
-    def isSelected (self, range):
+    def isSelected(self, range):
         """
         Returns C{True} if the C{range} is completely inside the selected
         ranges of the index.  C{range} may be a tuple: (start, end) or
@@ -774,7 +786,7 @@
         """
         return self.getCollectionIndex().isInRanges(range)
 
-    def addSelectionRange (self, range):
+    def addSelectionRange(self, range):
         """
         Selects a C{range} of indexes. C{range} may be a tuple:
         (start, end) or an integer index, where negative indexing
@@ -782,7 +794,7 @@
         """
         self.addRange(self.indexName, range)
 
-    def removeSelectionRange (self, range):
+    def removeSelectionRange(self, range):
         """
         Unselects a C{range} of indexes. C{range} may be a tuple:
         (start, end) or an integer index, where negative indexing
@@ -793,14 +805,14 @@
     # Item-based selection methods
     #
     
-    def setSelectionToItem (self, item):
+    def setSelectionToItem(self, item):
         """
         Sets the entire selection to include only the C{item}.
         """
         index = self.index (item)
         self.setRanges(self.indexName, [(index, index)])
 
-    def getFirstSelectedItem (self):
+    def getFirstSelectedItem(self):
         """
         Returns the first selected item in the index or C{None} if
         there is no selection.
@@ -827,13 +839,13 @@
                 for idx in range(start,end+1):
                     yield self[idx]
 
-    def selectItem (self, item):
+    def selectItem(self, item):
         """
         Selects an C{item} in the index.
         """
         self.addSelectionRange (self.index (item))
 
-    def unselectItem (self, item):
+    def unselectItem(self, item):
         """
         Unselects an C{item} in the index.
         """
@@ -843,7 +855,7 @@
     # index-based methods
     #
 
-    def __getitem__ (self, index):
+    def __getitem__(self, index):
         """
         Support indexing using [].
         """
@@ -852,7 +864,7 @@
         self.getCollectionIndex()
         return self.getByIndex(self.indexName, index)
 
-    def index (self, item):
+    def index(self, item):
         """
         Return the position of item in the index.
         """
@@ -863,7 +875,6 @@
         self.getCollectionIndex()
         return self.positionInIndex(self.indexName, item)
 
-
     def add(self, item):
         self.source.add(item)
 

Modified: trunk/chandler/repository/item/Indexed.py (11098 => 11099)

--- trunk/chandler/repository/item/Indexed.py	2006-07-08 16:09:33 UTC (rev 11098)
+++ trunk/chandler/repository/item/Indexed.py	2006-07-08 16:26:57 UTC (rev 11099)
@@ -451,7 +451,7 @@
 
     def iterindexkeys(self, indexName, first=None, last=None):
 
-        for key in self.getIndex(indexName).__iter__(first, last):
+        for key in self.getIndex(indexName).iterkeys(first, last):
             yield key
 
     def iterindexvalues(self, indexName, first=None, last=None):
@@ -614,7 +614,7 @@
     def _checkIndexes(self, logger, item, attribute):
 
         result = True
-        
+
         if self._indexes:
             try:
                 indexes = self._indexes

Modified: trunk/chandler/repository/item/Indexes.py (11098 => 11099)

--- trunk/chandler/repository/item/Indexes.py	2006-07-08 16:09:33 UTC (rev 11098)
+++ trunk/chandler/repository/item/Indexes.py	2006-07-08 16:26:57 UTC (rev 11099)
@@ -16,7 +16,7 @@
 from struct import pack, unpack
 from itertools import izip
 
-from chandlerdb.item.c import Nil
+from chandlerdb.item.c import Nil, DelegatingIndex
 from chandlerdb.util.c import SkipList, CLinkedMap
 from PyICU import Collator, Locale
   
@@ -30,7 +30,7 @@
         super(Index, self).__init__()
         self._count = 0
 
-    def __iter__(self, firstKey=None, lastKey=None, backwards=False):
+    def iterkeys(self, firstKey=None, lastKey=None, backwards=False):
 
         if backwards:
             getFirstKey = self.getLastKey
@@ -49,6 +49,9 @@
         if lastKey is not None:
             yield lastKey
 
+    def __iter__(self):
+        return self.iterkeys()
+
     def clear(self):
 
         self._count = 0
@@ -311,36 +314,6 @@
         return offset
 
 
-class DelegatingIndex(object):
-
-    def __init__(self, index, **kwds):
-        self._index = index
-
-    def __repr__(self):
-        return '<%s: %d>' %(type(self).__name__, self._count)
-
-    def __len__(self):
-        return len(self._index)
-
-    def __iter__(self, firstKey=None, lastKey=None, backwards=False):
-        return self._index.__iter__(firstKey, lastKey, backwards)
-
-    def __getattr__(self, name):
-        return getattr(self._index, name)
-
-    def __contains__(self, key):
-        return key in self._index
-
-    def has_key(self, key):
-        return key in self._index
-
-    def _writeValue(self, itemWriter, buffer, version):
-        self._index._writeValue(itemWriter, buffer, version)
-
-    def _readValue(self, itemReader, offset, data):
-        return self._index._readValue(itemReader, offset, data)
-
-
 class SortedIndex(DelegatingIndex):
 
     def __init__(self, valueMap, index, **kwds):
@@ -353,12 +326,12 @@
         if not kwds.get('loading', False):
             self._descending = str(kwds.pop('descending', 'False')) == 'True'
 
-    def __iter__(self, firstKey=None, lastKey=None, backwards=False):
+    def iterkeys(self, firstKey=None, lastKey=None, backwards=False):
 
         if self._descending:
             backwards = not backwards
 
-        return self._index.__iter__(firstKey, lastKey, backwards)
+        return self._index.iterkeys(firstKey, lastKey, backwards)
 
     def getInitKeywords(self):
 
@@ -476,7 +449,7 @@
 
     def _writeValue(self, itemWriter, buffer, version):
 
-        super(SortedIndex, self)._writeValue(itemWriter, buffer, version)
+        self._index._writeValue(itemWriter, buffer, version)
         itemWriter.writeBoolean(buffer, self._descending)
         if self._subIndexes:
             itemWriter.writeShort(buffer, len(self._subIndexes))
@@ -489,7 +462,7 @@
 
     def _readValue(self, itemReader, offset, data):
 
-        offset = super(SortedIndex, self)._readValue(itemReader, offset, data)
+        offset = self._index._readValue(itemReader, offset, data)
         offset, self._descending = itemReader.readBoolean(offset, data)
         offset, count = itemReader.readShort(offset, data)
 

Modified: trunk/chandler/repository/item/Sets.py (11098 => 11099)

--- trunk/chandler/repository/item/Sets.py	2006-07-08 16:09:33 UTC (rev 11098)
+++ trunk/chandler/repository/item/Sets.py	2006-07-08 16:26:57 UTC (rev 11099)
@@ -100,7 +100,7 @@
 
         index = self._anIndex()
         if index is not None:
-            return index.__iter__()
+            return index.iterkeys()
 
         return self._iterkeys()
 
@@ -1092,7 +1092,7 @@
     def _iterkeys(self):
 
         sources = self._sources
-        if sources:
+        if len(sources) > 1:
             source = sources[0]
             for key in self._iterSourceKeys(source):
                 everywhere = True
@@ -1108,7 +1108,7 @@
     def _itervalues(self):
 
         sources = self._sources
-        if sources:
+        if len(sources) > 1:
             source = sources[0]
             for item in self._iterSource(source):
                 everywhere = True
@@ -1124,17 +1124,18 @@
     def _op(self, ops, other):
 
         sources = self._sources
-        for op, source in izip(ops, sources):
-            if op is not None:
-                everywhere = True
-                for src in sources:
-                    if src is source:
-                        continue
-                    if not self._sourceContains(other, src):
-                        everywhere = False
-                        break
-                if everywhere:
-                    return op
+        if len(sources) > 1:
+            for op, source in izip(ops, sources):
+                if op is not None:
+                    everywhere = True
+                    for src in sources:
+                        if src is source:
+                            continue
+                        if not self._sourceContains(other, src):
+                            everywhere = False
+                            break
+                    if everywhere:
+                        return op
 
         return None
 




_______________________________________________
Commits mailing list
[email protected]
http://lists.osafoundation.org/mailman/listinfo/commits

Reply via email to