[Checkins] SVN: z3c.contents/branches/darrylcousins/src/z3c/contents/ * Changed the default attribute search filter into a filter that uses

Darryl Cousins darryl at darrylcousins.net.nz
Sun Mar 23 19:19:54 EDT 2008


Log message for revision 84896:
  * Changed the default attribute search filter into a filter that uses
    ISearchableText adapter on the contained objects. This and the `id` search
    filter are the default search filters.
  * Moved the actual deletion of objects to its own method `executeDelete`. This
    makes it easier to subclass (my use case is for content objects that are
    stored on postgres).
  

Changed:
  U   z3c.contents/branches/darrylcousins/src/z3c/contents/README.txt
  U   z3c.contents/branches/darrylcousins/src/z3c/contents/browser.py
  U   z3c.contents/branches/darrylcousins/src/z3c/contents/search.py
  U   z3c.contents/branches/darrylcousins/src/z3c/contents/testing.py

-=-
Modified: z3c.contents/branches/darrylcousins/src/z3c/contents/README.txt
===================================================================
--- z3c.contents/branches/darrylcousins/src/z3c/contents/README.txt	2008-03-23 21:09:31 UTC (rev 84895)
+++ z3c.contents/branches/darrylcousins/src/z3c/contents/README.txt	2008-03-23 23:19:54 UTC (rev 84896)
@@ -843,9 +843,15 @@
 
   >>> from z3c.contents.interfaces import ISearch
   >>> from z3c.contents.search import SearchForContainer
-  >>> zope.component.provideAdapter(SearchForContainer,
-  ...     (IContainer, ), provides=ISearch)
+  >>> zope.component.provideAdapter(SearchForContainer)
 
+And also register ISearchableText adapter for the contained objects, the default
+filters for searching include searching the keys (content __name__) and using
+an ISearchableText adapter for the contained objects.
+
+  >>> from z3c.contents.testing import SearchableTextForContent
+  >>> zope.component.provideAdapter(SearchableTextForContent)
+
 The default search adapter matches search terms to the objects id in the
 container or to any possible string attribute.
 
@@ -880,11 +886,6 @@
 
 We have adapters to the columns that support inclusion of links in the headers
 to sort the columns.
-      for="zope.app.container.interfaces.IContainer
-           zope.interface.Interface
-           z3c.contents.interfaces.IContentsPage
-           z3c.contents.column.RenameColumn"
-      provides="z3c.table.interfaces.IColumnHeader"
 
   >>> from z3c.contents.header import ContentsColumnHeader
   >>> from z3c.table.interfaces import IColumnHeader

Modified: z3c.contents/branches/darrylcousins/src/z3c/contents/browser.py
===================================================================
--- z3c.contents/branches/darrylcousins/src/z3c/contents/browser.py	2008-03-23 21:09:31 UTC (rev 84895)
+++ z3c.contents/branches/darrylcousins/src/z3c/contents/browser.py	2008-03-23 23:19:54 UTC (rev 84896)
@@ -40,7 +40,7 @@
 from z3c.template.template import getPageTemplate
 
 from z3c.contents import interfaces
-from z3c.contents.search import SimpleAttributeFindFilter
+from z3c.contents.search import SearchableTextFindFilter
 
 _ = zope.i18nmessageid.MessageFactory('z3c')
 
@@ -211,6 +211,7 @@
 
     @property
     def values(self):
+
         # not searching
         if not self.searchterm:
             return self.context.values()
@@ -225,10 +226,9 @@
         searchterms = self.searchterm.split(' ')
 
         # possible enhancement would be to look up these filters as adapters to
-        # the container!
-        result = search.search(id_filters=[SimpleIdFindFilter(searchterms)],
-                            object_filters=[SimpleAttributeFindFilter(searchterms)])
-        return result
+        # the container! Maybe we can use catalogs here?
+        return search.search(id_filters=[SimpleIdFindFilter(searchterms)],
+                            object_filters=[SearchableTextFindFilter(searchterms)])
 
 
     @property
@@ -396,7 +396,7 @@
             return
         try:
             for item in self.selectedItems:
-                del self.context[api.getName(item)]
+                self.executeDelete(item)
         except KeyError:
             self.status = self.deleteErrorMessage
             transaction.doom()
@@ -404,6 +404,11 @@
         self.updateAfterActionExecution()
         self.status = self.deleteSucsessMessage
 
+    def executeDelete(self, item):
+        """Do the actual item deletion
+        """
+        del self.context[api.getName(item)]
+
     @button.buttonAndHandler(_('Rename'), name='rename', condition=canRename)
     def handlerRename(self, action):
         changed = False

Modified: z3c.contents/branches/darrylcousins/src/z3c/contents/search.py
===================================================================
--- z3c.contents/branches/darrylcousins/src/z3c/contents/search.py	2008-03-23 21:09:31 UTC (rev 84895)
+++ z3c.contents/branches/darrylcousins/src/z3c/contents/search.py	2008-03-23 23:19:54 UTC (rev 84896)
@@ -12,7 +12,7 @@
 #
 ##############################################################################
 """
-$Id:$
+$Id$
 """
 __docformat__ = "reStructuredText"
 
@@ -20,15 +20,15 @@
 from zope.app.container.interfaces import (IObjectFindFilter,
                                            IReadContainer)
 from zope.security.proxy import removeSecurityProxy
+from zope.index.text.interfaces import ISearchableText
 
 from z3c.contents.interfaces import ISearch
 
 class SearchForContainer(object):
 
     zope.interface.implements(ISearch)
+    zope.component.adapts(IReadContainer)
 
-    __used_for__ = IReadContainer
-
     def __init__(self, context):
         self._context = context
 
@@ -67,26 +67,27 @@
         _search_helper(id, object, container, id_filters, object_filters, result)
 
 
-class SimpleAttributeFindFilter(object):
-    """Filter objects on text or integer attributes"""
+class SearchableTextFindFilter(object):
+    """Filter objects on the ISearchableText adapters to the object
+    
+    """
+
     zope.interface.implements(IObjectFindFilter)
     
     def __init__(self, terms):
         self.terms = terms
     
     def matches(self, object):
-        """Check if one of the search terms is in any text or integer field of
-        this object
-
+        """Check if one of the search terms is found in the searchable text
+        interface
         """
-        # surely a better way to get to the attributes than is done here?
-        object = removeSecurityProxy(object)
 
-        for key in [k for k in dir(object) if not k.startswith('_')]:
-            value = str(getattr(object, key)).lower()
-            for term in self.terms:
-                term = term.lower()
-                if term in value:
-                    return True
+        adapter = zope.component.queryAdapter(object, ISearchableText)
+        if not adapter:
+            return False
+        searchable = adapter.getSearchableText().lower()
+        for term in [t.lower() for t in self.terms]:
+            if term in searchable:
+                return True
         return False
 

Modified: z3c.contents/branches/darrylcousins/src/z3c/contents/testing.py
===================================================================
--- z3c.contents/branches/darrylcousins/src/z3c/contents/testing.py	2008-03-23 21:09:31 UTC (rev 84895)
+++ z3c.contents/branches/darrylcousins/src/z3c/contents/testing.py	2008-03-23 23:19:54 UTC (rev 84896)
@@ -18,23 +18,29 @@
 
 import zope.interface
 from zope.publisher.interfaces.browser import IBrowserRequest
+from zope.index.text.interfaces import ISearchableText
 
 import z3c.layer.ready2go
 
 class IContentsTestBrowserLayer(z3c.layer.ready2go.IReady2GoBrowserLayer):
         """test layer."""
 
+
 class IContentsTestBrowserSkin(IContentsTestBrowserLayer):
     """The browser skin."""
 
+
 class IContent(zope.interface.Interface):
 
     title = zope.schema.TextLine(title=u'Title')
     number = zope.schema.Int(title=u'Number')
 
+
 class Content(object):
     """Sample content which is pickable for copy test."""
+
     zope.interface.implements(IContent)
+
     def __init__(self, title, number):
         self.title = title
         self.number = number
@@ -42,3 +48,15 @@
     def __repr__(self):
         return u'<%s %s %s>' % (self.__class__.__name__, self.title,
             self.number)
+
+
+class SearchableTextForContent:
+
+    zope.interface.implements(ISearchableText)
+    zope.component.adapts(IContent)
+
+    def __init__(self, content):
+        self.content = content
+
+    def getSearchableText(self):
+        return '%s %d' % (self.content.title, self.content.number)



More information about the Checkins mailing list