[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