[Checkins] SVN: zope.app.catalog/trunk/ Merge nadako-sorting branch.

Dan Korostelev nadako at gmail.com
Sat Jan 3 10:36:27 EST 2009


Log message for revision 94477:
  Merge nadako-sorting branch.

Changed:
  U   zope.app.catalog/trunk/CHANGES.txt
  U   zope.app.catalog/trunk/setup.py
  U   zope.app.catalog/trunk/src/zope/app/catalog/README.txt
  U   zope.app.catalog/trunk/src/zope/app/catalog/browser/configure.zcml
  U   zope.app.catalog/trunk/src/zope/app/catalog/catalog.py
  U   zope.app.catalog/trunk/src/zope/app/catalog/classes.zcml
  U   zope.app.catalog/trunk/src/zope/app/catalog/interfaces.py
  A   zope.app.catalog/trunk/src/zope/app/catalog/keyword.py
  U   zope.app.catalog/trunk/src/zope/app/catalog/text.py

-=-
Modified: zope.app.catalog/trunk/CHANGES.txt
===================================================================
--- zope.app.catalog/trunk/CHANGES.txt	2009-01-03 15:21:36 UTC (rev 94476)
+++ zope.app.catalog/trunk/CHANGES.txt	2009-01-03 15:36:27 UTC (rev 94477)
@@ -5,8 +5,19 @@
 3.6.0 (unreleased)
 ------------------
 
-- ...
+- Make TextIndex addform use default values as specified in
+  zope.app.catalog.text.ITextIndex interface. Also, change
+  "searchableText" to "getSearchableText" there, as it's the
+  right value.
 
+- Add Keyword (case-insensitive and case-sensitive) catalog
+  indices. It's now possible to use them, because ones in
+  zope.index now implement IIndexSearch interface.
+
+- Add support for sorting, reversing and limiting result set
+  in the ``searchResults`` method, using new IIndexSort interface
+  features of zope.index.
+
 3.5.2 (2008-12-28)
 ------------------
 

Modified: zope.app.catalog/trunk/setup.py
===================================================================
--- zope.app.catalog/trunk/setup.py	2009-01-03 15:21:36 UTC (rev 94476)
+++ zope.app.catalog/trunk/setup.py	2009-01-03 15:36:27 UTC (rev 94477)
@@ -69,7 +69,7 @@
           'zope.app.container',
           'zope.app.intid',
           'zope.component',
-          'zope.index',
+          'zope.index>=3.5.0',
           'zope.interface',
           'zope.lifecycleevent',
           'zope.location',

Modified: zope.app.catalog/trunk/src/zope/app/catalog/README.txt
===================================================================
--- zope.app.catalog/trunk/src/zope/app/catalog/README.txt	2009-01-03 15:21:36 UTC (rev 94476)
+++ zope.app.catalog/trunk/src/zope/app/catalog/README.txt	2009-01-03 15:36:27 UTC (rev 94477)
@@ -22,6 +22,7 @@
     ...     zope.interface.implements(
     ...         zope.index.interfaces.IInjection,
     ...         zope.index.interfaces.IIndexSearch,
+    ...         zope.index.interfaces.IIndexSort,
     ...         )
     ...
     ...     def clear(self):
@@ -53,6 +54,12 @@
     ...         if set is None:
     ...             set = BTrees.IFBTree.IFTreeSet()
     ...         return set
+    ...
+    ...     def sort(self, docids, limit=None, reverse=False):
+    ...         for i, docid in enumerate(sorted(docids, key=self.backward.get, reverse=reverse)):
+    ...             yield docid
+    ...             if limit and i >= (limit - 1):
+    ...                 break
 
 The class implements `IInjection` to allow values to be indexed and
 unindexed and `IIndexSearch` to support searching via the `apply`
@@ -227,6 +234,54 @@
     >>> list(result) == [o4, o5]
     True
 
+The searchResults method also provides a way to sort, limit and reverse
+results.
+
+When not using sorting, limiting and reversing are done by simple slicing
+and list reversing.
+
+    >>> list(cat.searchResults(size=5, _reverse=True)) == [o5, o4]
+    True
+
+    >>> list(cat.searchResults(size=5, _limit=1)) == [o4]
+    True
+
+    >>> list(cat.searchResults(size=5, _limit=1, _reverse=True)) == [o5]
+    True
+
+However, when using sorting by index, the limit and reverse parameters
+are passed to the index ``sort`` method so it can do it efficiently.
+
+Let's index more objects to work with:
+
+    >>> o7 = DiscriminatingPerson(7, 'blue')
+    >>> o8 = DiscriminatingPerson(3, 'blue')
+    >>> o9 = DiscriminatingPerson(14, 'blue')
+    >>> o10 = DiscriminatingPerson(1, 'blue')
+    >>> ids.data.update({7: o7, 8: o8, 9: o9, 10: o10})
+    >>> cat.index_doc(7, o7)
+    >>> cat.index_doc(8, o8)
+    >>> cat.index_doc(9, o9)
+    >>> cat.index_doc(10, o10)
+
+Now we can search all people who like blue, ordered by age:
+
+    >>> results = list(cat.searchResults(color='blue', _sort_index='age'))
+    >>> results == [o3, o10, o8, o7, o6, o9]
+    True
+
+    >>> results = list(cat.searchResults(color='blue', _sort_index='age', _limit=3))
+    >>> results == [o3, o10, o8]
+    True
+
+    >>> results = list(cat.searchResults(color='blue', _sort_index='age', _reverse=True))
+    >>> results == [o9, o6, o7, o8, o10, o3]
+    True
+
+    >>> results = list(cat.searchResults(color='blue', _sort_index='age', _reverse=True, _limit=4))
+    >>> results == [o9, o6, o7, o8]
+    True
+
 The index example we looked at didn't provide document scores.  Simple
 indexes normally don't, but more complex indexes might give results
 scores, according to how closely a document matches a query.  Let's

Modified: zope.app.catalog/trunk/src/zope/app/catalog/browser/configure.zcml
===================================================================
--- zope.app.catalog/trunk/src/zope/app/catalog/browser/configure.zcml	2009-01-03 15:21:36 UTC (rev 94476)
+++ zope.app.catalog/trunk/src/zope/app/catalog/browser/configure.zcml	2009-01-03 15:36:27 UTC (rev 94477)
@@ -65,9 +65,55 @@
     />
 
 <addform
+    name="AddKeywordIndex"
+    label="Add a keyword index"
+    schema="..interfaces.IAttributeIndex"
+    permission="zope.ManageServices"
+    content_factory="..keyword.KeywordIndex"
+    arguments="field_name"
+    keyword_arguments="interface field_callable"
+    />
+
+<addMenuItem
+    title="Keyword Index"
+    description="Index items based on sequence of keywords"
+    class="..keyword.KeywordIndex"
+    permission="zope.ManageServices"
+    view="AddKeywordIndex"
+   />
+
+<addform
+    name="AddCaseInsensitiveKeywordIndex"
+    label="Add a keyword index (case-omsensitive)"
+    schema="..interfaces.IAttributeIndex"
+    permission="zope.ManageServices"
+    content_factory="..keyword.CaseInsensitiveKeywordIndex"
+    arguments="field_name"
+    keyword_arguments="interface field_callable"
+    />
+
+<addMenuItem
+    title="Keyword Index (case-insensitive)"
+    description="Index items based on sequence of keywords"
+    class="..keyword.CaseInsensitiveKeywordIndex"
+    permission="zope.ManageServices"
+    view="AddCaseInsensitiveKeywordIndex"
+   />
+
+<schemadisplay
+    name="index.html"
+    schema="..keyword.IKeywordIndex"
+    label="Keyword Index"
+    fields="interface field_name field_callable"
+    permission="zope.ManageServices"
+    menu="zmi_views" title="Configuration"
+    />
+
+<addform
     name="AddTextIndex"
     label="Add a text index"
-    schema="..interfaces.IAttributeIndex"
+    schema="..text.ITextIndex"
+    fields="interface field_name field_callable"
     permission="zope.ManageServices"
     content_factory="..text.TextIndex"
     arguments="field_name"

Modified: zope.app.catalog/trunk/src/zope/app/catalog/catalog.py
===================================================================
--- zope.app.catalog/trunk/src/zope/app/catalog/catalog.py	2009-01-03 15:21:36 UTC (rev 94476)
+++ zope.app.catalog/trunk/src/zope/app/catalog/catalog.py	2009-01-03 15:36:27 UTC (rev 94477)
@@ -134,8 +134,23 @@
         return result
 
     def searchResults(self, **searchterms):
+        sort_index = searchterms.pop('_sort_index', None)
+        limit = searchterms.pop('_limit', None)
+        reverse = searchterms.pop('_reverse', False)
         results = self.apply(searchterms)
         if results is not None:
+            if sort_index is not None:
+                index = self[sort_index]
+                if not zope.index.interfaces.IIndexSort.providedBy(index):
+                    raise ValueError('Index %s does not support sorting.' % sort_index)
+                results = list(index.sort(results, limit=limit, reverse=reverse))
+            else:
+                if reverse or limit:
+                    results = list(results)
+                if reverse:
+                    results.reverse()
+                if limit:
+                    del results[limit:]
             uidutil = component.getUtility(IIntIds)
             results = ResultSet(results, uidutil)
         return results

Modified: zope.app.catalog/trunk/src/zope/app/catalog/classes.zcml
===================================================================
--- zope.app.catalog/trunk/src/zope/app/catalog/classes.zcml	2009-01-03 15:21:36 UTC (rev 94476)
+++ zope.app.catalog/trunk/src/zope/app/catalog/classes.zcml	2009-01-03 15:36:27 UTC (rev 94477)
@@ -42,6 +42,19 @@
         />
   </class>
 
+  <class class=".keyword.KeywordIndex">
+    <require
+        permission="zope.ManageServices"
+        interface=".interfaces.IAttributeIndex
+                   zope.index.interfaces.IStatistics"
+        set_schema=".interfaces.IAttributeIndex"
+        />
+  </class>
+
+  <class class=".keyword.CaseInsensitiveKeywordIndex">
+    <require like_class=".keyword.KeywordIndex" /> 
+  </class>
+
   <class class=".text.TextIndex">
     <require
         permission="zope.ManageServices"

Modified: zope.app.catalog/trunk/src/zope/app/catalog/interfaces.py
===================================================================
--- zope.app.catalog/trunk/src/zope/app/catalog/interfaces.py	2009-01-03 15:21:36 UTC (rev 94476)
+++ zope.app.catalog/trunk/src/zope/app/catalog/interfaces.py	2009-01-03 15:36:27 UTC (rev 94477)
@@ -28,9 +28,26 @@
     """Provides Catalog Queries."""
 
     def searchResults(**kw):
-        """Search on the given indexes."""
+        """Search on the given indexes.
+        
+        Keyword arguments dictionary keys
+        are index names and values are queries
+        for these indexes.
+        
+        Keyword arguments has some special names,
+        used by the catalog itself:
+        
+         * _sort_index - The name of index to sort
+           results with. This index must implement
+           zope.index.interfaces.IIndexSort.
+         * _limit - Limit result set by this number,
+           useful when used with sorting.
+         * _reverse - Reverse result set, also
+           useful with sorting.
 
+        """
 
+
 class ICatalogEdit(zope.index.interfaces.IInjection):
     """Allows one to manipulate the Catalog information."""
 

Copied: zope.app.catalog/trunk/src/zope/app/catalog/keyword.py (from rev 94476, zope.app.catalog/branches/nadako-sorting/src/zope/app/catalog/keyword.py)
===================================================================
--- zope.app.catalog/trunk/src/zope/app/catalog/keyword.py	                        (rev 0)
+++ zope.app.catalog/trunk/src/zope/app/catalog/keyword.py	2009-01-03 15:36:27 UTC (rev 94477)
@@ -0,0 +1,39 @@
+##############################################################################
+#
+# Copyright (c) 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Keyword catalog index
+
+$Id:$
+"""
+import zope.index.keyword
+import zope.interface
+
+import zope.app.container.contained
+import zope.app.catalog.attribute
+import zope.app.catalog.interfaces
+
+class IKeywordIndex(zope.app.catalog.interfaces.IAttributeIndex,
+                     zope.app.catalog.interfaces.ICatalogIndex):
+    """Interface-based catalog keyword index"""
+
+class KeywordIndex(zope.app.catalog.attribute.AttributeIndex,
+                    zope.index.keyword.KeywordIndex,
+                    zope.app.container.contained.Contained):
+
+    zope.interface.implements(IKeywordIndex)
+
+class CaseInsensitiveKeywordIndex(zope.app.catalog.attribute.AttributeIndex,
+                                      zope.index.keyword.CaseInsensitiveKeywordIndex,
+                                      zope.app.container.contained.Contained):
+
+    zope.interface.implements(IKeywordIndex)

Modified: zope.app.catalog/trunk/src/zope/app/catalog/text.py
===================================================================
--- zope.app.catalog/trunk/src/zope/app/catalog/text.py	2009-01-03 15:21:36 UTC (rev 94476)
+++ zope.app.catalog/trunk/src/zope/app/catalog/text.py	2009-01-03 15:36:27 UTC (rev 94477)
@@ -40,7 +40,7 @@
     field_name = zope.schema.BytesLine(
         title=_(u"Field Name"),
         description=_(u"Name of the field to index"),
-        default="searchableText"
+        default="getSearchableText"
         )
 
     field_callable = zope.schema.Bool(



More information about the Checkins mailing list