[Checkins] SVN: zope.index/branches/nadako-sorting/ Make the same changes as for KeywordIndex to TopicIndex. Mention that in CHANGES.txt.

Dan Korostelev nadako at gmail.com
Sun Dec 28 02:23:19 EST 2008


Log message for revision 94405:
  Make the same changes as for KeywordIndex to TopicIndex. Mention that in CHANGES.txt.

Changed:
  U   zope.index/branches/nadako-sorting/CHANGES.txt
  U   zope.index/branches/nadako-sorting/buildout.cfg
  U   zope.index/branches/nadako-sorting/src/zope/index/topic/__init__.py
  U   zope.index/branches/nadako-sorting/src/zope/index/topic/filter.py
  U   zope.index/branches/nadako-sorting/src/zope/index/topic/index.py
  U   zope.index/branches/nadako-sorting/src/zope/index/topic/interfaces.py
  U   zope.index/branches/nadako-sorting/src/zope/index/topic/tests/test_topicindex.py

-=-
Modified: zope.index/branches/nadako-sorting/CHANGES.txt
===================================================================
--- zope.index/branches/nadako-sorting/CHANGES.txt	2008-12-28 06:43:06 UTC (rev 94404)
+++ zope.index/branches/nadako-sorting/CHANGES.txt	2008-12-28 07:23:19 UTC (rev 94405)
@@ -9,14 +9,19 @@
 - Define IIndexSort interface for indexes that support sorting and
   implement it in the FieldIndex.
 
-- Add an ``apply`` method for KeywordIndex, making it implementing
-  IIndexSearch that can be useful in catalog.
+- Add an ``apply`` method for KeywordIndex/TopicIndex, making them
+  implement IIndexSearch that can be useful in catalog.
 
-- Make KeywordIndex use IFSets instead of IISets. This makes it more
-  compatible with other indexes. 
+- Make KeywordIndex/TopicIndex use IFSets instead of IISets. This makes
+  it more compatible with other indexes.
+  
+  IMPORTANT: This change can lead to problems, if your code somehow
+  depends on the II nature of sets, as it was before. Also, TopicIndexes
+  have IISets pickled, their ``getIds`` method now checks if it's still
+  IISet and repickles it as IFSet.
 
-- Optimize the ``search`` method of KeywordIndex by using multiunion
-  for the ``or`` operator and sorting before intersection for ``and``.
+- Optimize the ``search`` method of KeywordIndex/TopicIndex by using
+  multiunion for the ``or`` operator and sorting before intersection for ``and``.
 
 Thanks Chris McDonough of repoze for supporting and useful code.
 

Modified: zope.index/branches/nadako-sorting/buildout.cfg
===================================================================
--- zope.index/branches/nadako-sorting/buildout.cfg	2008-12-28 06:43:06 UTC (rev 94404)
+++ zope.index/branches/nadako-sorting/buildout.cfg	2008-12-28 07:23:19 UTC (rev 94405)
@@ -1,6 +1,6 @@
 [buildout]
 develop = .
-parts = test coverage-test coverage-report
+parts = test coverage-test coverage-report python
 find-links = http://download.zope.org/distribution/
 
 [test]
@@ -17,3 +17,8 @@
 eggs = z3c.coverage
 scripts = coverage=coverage-report
 arguments = ('coverage', 'coverage/report')
+
+[python]
+recipe = zc.recipe.egg
+eggs = zope.index
+interpreter = python

Modified: zope.index/branches/nadako-sorting/src/zope/index/topic/__init__.py
===================================================================
--- zope.index/branches/nadako-sorting/src/zope/index/topic/__init__.py	2008-12-28 06:43:06 UTC (rev 94404)
+++ zope.index/branches/nadako-sorting/src/zope/index/topic/__init__.py	2008-12-28 07:23:19 UTC (rev 94405)
@@ -1,2 +1 @@
-#
-# This file is necessary to make this directory a package.
+from zope.index.topic.index import TopicIndex

Modified: zope.index/branches/nadako-sorting/src/zope/index/topic/filter.py
===================================================================
--- zope.index/branches/nadako-sorting/src/zope/index/topic/filter.py	2008-12-28 06:43:06 UTC (rev 94404)
+++ zope.index/branches/nadako-sorting/src/zope/index/topic/filter.py	2008-12-28 07:23:19 UTC (rev 94405)
@@ -36,19 +36,21 @@
     def __init__(self, id, expr, family=None):
         if family is not None:
             self.family = family
-        self.id   = id
+        self.id = id
         self.expr = expr
         self.clear()
 
     def clear(self):
-        self._ids = self.family.II.Set()
+        self._ids = self.family.IF.Set()
 
     def index_doc(self, docid, context):
         raise NotImplementedError
 
     def unindex_doc(self, docid):
-        try: self._ids.remove(docid)
-        except KeyError: pass
+        try:
+            self._ids.remove(docid)
+        except KeyError:
+            pass
 
     def getId(self):            
         return self.id
@@ -59,11 +61,16 @@
     def setExpression(self, expr): 
         self.expr = expr
 
-    def getIds(self): 
+    def getIds(self):
+        if isinstance(self._ids, self.family.II.Set):
+            # Backward-compatibility. If there was an
+            # IISet ids, repickle it as IFSet.
+            # XXX Is that okay?
+            self._ids = self.family.IF.Set(self._ids)
         return self._ids
 
     def __repr__(self):
-        return '%s: (%s) %s' % (self.id, self.expr, map(None, self._ids))
+        return '%s: (%s) %s' % (self.id, self.expr, list(self._ids))
 
     __str__ = __repr__
 
@@ -73,6 +80,7 @@
 
     def index_doc(self, docid, context):
         try:
-            if eval(self.expr): self._ids.insert(docid)
+            if eval(self.expr):
+                self._ids.insert(docid)
         except:
             pass  # ignore errors 

Modified: zope.index/branches/nadako-sorting/src/zope/index/topic/index.py
===================================================================
--- zope.index/branches/nadako-sorting/src/zope/index/topic/index.py	2008-12-28 06:43:06 UTC (rev 94404)
+++ zope.index/branches/nadako-sorting/src/zope/index/topic/index.py	2008-12-28 07:23:19 UTC (rev 94405)
@@ -21,13 +21,13 @@
 
 from zope.interface import implements
 
-from zope.index.interfaces import IInjection
+from zope.index.interfaces import IInjection, IIndexSearch
 from zope.index.topic.interfaces import ITopicQuerying
 
 
 class TopicIndex(Persistent):
 
-    implements(IInjection, ITopicQuerying)
+    implements(IInjection, ITopicQuerying, IIndexSearch)
 
     family = BTrees.family32
 
@@ -61,20 +61,42 @@
             f.unindex_doc(docid)
 
     def search(self, query, operator='and'):
-        if isinstance(query, basestring): query = [query]
+        if isinstance(query, basestring):
+            query = [query]
+
         if not isinstance(query, (tuple, list)):
             raise TypeError(
                 'query argument must be a list/tuple of filter ids')
 
-        f = {'and': self.family.II.intersection,
-             'or': self.family.II.union,
-             }[operator]
-    
-        rs = None
+        sets = []
         for id in self._filters.keys():
             if id in query:
                 docids = self._filters[id].getIds()
-                rs = f(rs, docids)
+                sets.append(docids)
+
+        if operator == 'or':
+            rs = self.family.IF.multiunion(sets)
+        elif operator == 'and':
+            # sort smallest to largest set so we intersect the smallest
+            # number of document identifiers possible
+            sets.sort(key=len)
+            rs = None
+            for set in sets:
+                rs = self.family.IF.intersection(rs, set)
+                if not rs:
+                    break
+        else:
+            raise TypeError('Topic index only supports `and` and `or` operators, not `%s`.' % operator)
             
-        if rs: return rs
-        else: return self.family.II.Set()
+        if rs:
+            return rs
+        else:
+            return self.family.IF.Set()
+
+    def apply(self, query):
+        operator = 'and'
+        if isinstance(query, dict):
+            if 'operator' in query:
+                operator = query.pop('operator')
+            query = query['query']
+        return self.search(query, operator=operator)

Modified: zope.index/branches/nadako-sorting/src/zope/index/topic/interfaces.py
===================================================================
--- zope.index/branches/nadako-sorting/src/zope/index/topic/interfaces.py	2008-12-28 06:43:06 UTC (rev 94404)
+++ zope.index/branches/nadako-sorting/src/zope/index/topic/interfaces.py	2008-12-28 07:23:19 UTC (rev 94405)
@@ -25,7 +25,7 @@
           'operator' can be 'and' or 'or' to search for matches in all
            or any filter.
 
-           Return an IISet of docids
+           Return an IFSet of docids
         """
 
 class ITopicFilteredSet(Interface):
@@ -50,4 +50,4 @@
         """Return the filter expression."""
 
     def getIds():
-        """Return an IISet of docids."""
+        """Return an IFSet of docids."""

Modified: zope.index/branches/nadako-sorting/src/zope/index/topic/tests/test_topicindex.py
===================================================================
--- zope.index/branches/nadako-sorting/src/zope/index/topic/tests/test_topicindex.py	2008-12-28 06:43:06 UTC (rev 94404)
+++ zope.index/branches/nadako-sorting/src/zope/index/topic/tests/test_topicindex.py	2008-12-28 07:23:19 UTC (rev 94405)
@@ -46,6 +46,11 @@
             PythonFilteredSet('doc3', "context.meta_type == 'doc3'",
                               self.family))
 
+        self.index.addFilter(
+            PythonFilteredSet('compat', "context.meta_type == 'doc3'",
+                              self.family))
+        self.index._filters['compat']._ids = self.family.II.Set()
+
         self.index.index_doc(0 , O('doc0'))
         self.index.index_doc(1 , O('doc1'))
         self.index.index_doc(2 , O('doc1'))
@@ -65,6 +70,18 @@
     def _search_and(self, query, expected):
         return self._search(query, expected, 'and')
 
+    def _apply(self, query, expected, operator='and'):
+        result = self.index.apply(query)
+        self.assertEqual(result.keys(), expected)
+
+    def _apply_or(self, query, expected):
+        result = self.index.apply({'query': query, 'operator': 'or'})
+        self.assertEqual(result.keys(), expected)
+         
+    def _apply_and(self, query, expected):
+        result = self.index.apply({'query': query, 'operator': 'and'})
+        self.assertEqual(result.keys(), expected)
+
     def testInterfaces(self):
         for iface in implementedBy(PythonFilteredSet):
             verifyClass(iface, PythonFilteredSet)
@@ -96,7 +113,32 @@
         self._search_and(['doc2'], [3,4])
         self._search_and(['doc1','doc2'], [])
 
+    def test_apply_or(self):
+        self._apply_or('doc1',  [1,2])
+        self._apply_or(['doc1'],[1,2])
+        self._apply_or('doc2',  [3,4]),
+        self._apply_or(['doc2'],[3,4])
+        self._apply_or(['doc1','doc2'], [1,2,3,4])
 
+    def test_apply_and(self):
+        self._apply_and('doc1',   [1,2])
+        self._apply_and(['doc1'], [1,2])
+        self._apply_and('doc2',   [3,4])
+        self._apply_and(['doc2'], [3,4])
+        self._apply_and(['doc1','doc2'], [])
+
+    def test_apply(self):
+        self._apply('doc1',   [1,2])
+        self._apply(['doc1'], [1,2])
+        self._apply('doc2',   [3,4])
+        self._apply(['doc2'], [3,4])
+        self._apply(['doc1','doc2'], [])
+
+    def test_compat(self):
+        result = self.index.search('compat')
+        self.assert_(isinstance(result, self.family.IF.Set))
+        self.assertEqual(result.keys(), [5, 6])
+
 class TopicIndexTest64(TopicIndexTest):
 
     family = BTrees.family64



More information about the Checkins mailing list