[Checkins] SVN: z3c.searcher/ Added initial implementation

Roger Ineichen roger at projekt01.ch
Thu May 1 21:43:46 EDT 2008


Log message for revision 86042:
  Added initial implementation

Changed:
  A   z3c.searcher/branches/
  A   z3c.searcher/tags/
  A   z3c.searcher/trunk/
  A   z3c.searcher/trunk/CHANGES.txt
  A   z3c.searcher/trunk/LICENSE.txt
  A   z3c.searcher/trunk/README.txt
  A   z3c.searcher/trunk/bootstrap.py
  A   z3c.searcher/trunk/buildout.cfg
  A   z3c.searcher/trunk/setup.py
  A   z3c.searcher/trunk/src/
  A   z3c.searcher/trunk/src/z3c/
  A   z3c.searcher/trunk/src/z3c/__init__.py
  A   z3c.searcher/trunk/src/z3c/searcher/
  A   z3c.searcher/trunk/src/z3c/searcher/README.txt
  A   z3c.searcher/trunk/src/z3c/searcher/__init__.py
  A   z3c.searcher/trunk/src/z3c/searcher/browser.zcml
  A   z3c.searcher/trunk/src/z3c/searcher/configure.zcml
  A   z3c.searcher/trunk/src/z3c/searcher/criterium.pt
  A   z3c.searcher/trunk/src/z3c/searcher/criterium.py
  A   z3c.searcher/trunk/src/z3c/searcher/filter.pt
  A   z3c.searcher/trunk/src/z3c/searcher/filter.py
  A   z3c.searcher/trunk/src/z3c/searcher/form.py
  A   z3c.searcher/trunk/src/z3c/searcher/interfaces.py
  A   z3c.searcher/trunk/src/z3c/searcher/search.pt
  A   z3c.searcher/trunk/src/z3c/searcher/session.py
  A   z3c.searcher/trunk/src/z3c/searcher/table.pt
  A   z3c.searcher/trunk/src/z3c/searcher/table.py
  A   z3c.searcher/trunk/src/z3c/searcher/testing.py
  A   z3c.searcher/trunk/src/z3c/searcher/tests.py

-=-

Property changes on: z3c.searcher/trunk
___________________________________________________________________
Name: svn:ignore
   + bin
develop-eggs
parts
.installed.cfg


Added: z3c.searcher/trunk/CHANGES.txt
===================================================================
--- z3c.searcher/trunk/CHANGES.txt	                        (rev 0)
+++ z3c.searcher/trunk/CHANGES.txt	2008-05-02 01:43:46 UTC (rev 86042)
@@ -0,0 +1,8 @@
+=======
+CHANGES
+=======
+
+Version 0.5.0 (unreleased)
+-------------------------
+
+- Initial Release


Property changes on: z3c.searcher/trunk/CHANGES.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.searcher/trunk/LICENSE.txt
===================================================================
--- z3c.searcher/trunk/LICENSE.txt	                        (rev 0)
+++ z3c.searcher/trunk/LICENSE.txt	2008-05-02 01:43:46 UTC (rev 86042)
@@ -0,0 +1,54 @@
+Zope Public License (ZPL) Version 2.1
+-------------------------------------
+
+A copyright notice accompanies this license document that
+identifies the copyright holders.
+
+This license has been certified as open source. It has also
+been designated as GPL compatible by the Free Software
+Foundation (FSF).
+
+Redistribution and use in source and binary forms, with or
+without modification, are permitted provided that the
+following conditions are met:
+
+1. Redistributions in source code must retain the
+   accompanying copyright notice, this list of conditions,
+   and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the accompanying
+   copyright notice, this list of conditions, and the
+   following disclaimer in the documentation and/or other
+   materials provided with the distribution.
+
+3. Names of the copyright holders must not be used to
+   endorse or promote products derived from this software
+   without prior written permission from the copyright
+   holders.
+
+4. The right to distribute this software or to use it for
+   any purpose does not give you the right to use
+   Servicemarks (sm) or Trademarks (tm) of the copyright
+   holders. Use of them is covered by separate agreement
+   with the copyright holders.
+
+5. If any files are modified, you must cause the modified
+   files to carry prominent notices stating that you changed
+   the files and the date of any change.
+
+Disclaimer
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS''
+  AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
+  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+  NO EVENT SHALL THE COPYRIGHT HOLDERS BE
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+  DAMAGE.


Property changes on: z3c.searcher/trunk/LICENSE.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.searcher/trunk/README.txt
===================================================================
--- z3c.searcher/trunk/README.txt	                        (rev 0)
+++ z3c.searcher/trunk/README.txt	2008-05-02 01:43:46 UTC (rev 86042)
@@ -0,0 +1 @@
+This package provides an implementation for build search forms for Zope3.
\ No newline at end of file


Property changes on: z3c.searcher/trunk/README.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.searcher/trunk/bootstrap.py
===================================================================
--- z3c.searcher/trunk/bootstrap.py	                        (rev 0)
+++ z3c.searcher/trunk/bootstrap.py	2008-05-02 01:43:46 UTC (rev 86042)
@@ -0,0 +1,52 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+
+$Id: bootstrap.py 75940 2007-05-24 14:45:00Z srichter $
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+ez = {}
+exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+                     ).read() in ez
+ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+import pkg_resources
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+if sys.platform == 'win32':
+    cmd = '"%s"' % cmd # work around spawn lamosity on windows
+
+ws = pkg_resources.working_set
+assert os.spawnle(
+    os.P_WAIT, sys.executable, sys.executable,
+    '-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout',
+    dict(os.environ,
+         PYTHONPATH=
+         ws.find(pkg_resources.Requirement.parse('setuptools')).location
+         ),
+    ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout')
+import zc.buildout.buildout
+zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
+shutil.rmtree(tmpeggs)


Property changes on: z3c.searcher/trunk/bootstrap.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.searcher/trunk/buildout.cfg
===================================================================
--- z3c.searcher/trunk/buildout.cfg	                        (rev 0)
+++ z3c.searcher/trunk/buildout.cfg	2008-05-02 01:43:46 UTC (rev 86042)
@@ -0,0 +1,25 @@
+[buildout]
+develop = .
+parts = test checker coverage-test coverage-report
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = z3c.searcher [test]
+
+
+[checker]
+recipe = lovely.recipe:importchecker
+path = src/z3c/searcher
+
+
+[coverage-test]
+recipe = zc.recipe.testrunner
+eggs = z3c.searcher [test]
+defaults = ['--coverage', '../../coverage']
+
+
+[coverage-report]
+recipe = zc.recipe.egg
+eggs = z3c.coverage
+scripts = coverage=coverage-report
+arguments = ('coverage', 'coverage/report')

Added: z3c.searcher/trunk/setup.py
===================================================================
--- z3c.searcher/trunk/setup.py	                        (rev 0)
+++ z3c.searcher/trunk/setup.py	2008-05-02 01:43:46 UTC (rev 86042)
@@ -0,0 +1,86 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Setup
+
+$Id:$
+"""
+import os
+from setuptools import setup, find_packages
+
+def read(*rnames):
+    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
+
+setup (
+    name='z3c.searcher',
+    version='0.5.0dev',
+    author = "Roger Ineichen and the Zope Community",
+    author_email = "zope3-dev at zope.org",
+    description = "Persistent and session based search form for Zope3",
+    long_description=(
+        read('README.txt')
+        + '\n\n' +
+        read('CHANGES.txt')
+        ),
+    license = "ZPL 2.1",
+    keywords = "zope3 z3c catalog index indexer search searcher",
+    classifiers = [
+        'Development Status :: 4 - Beta',
+        'Environment :: Web Environment',
+        'Intended Audience :: Developers',
+        'License :: OSI Approved :: Zope Public License',
+        'Programming Language :: Python',
+        'Natural Language :: English',
+        'Operating System :: OS Independent',
+        'Topic :: Internet :: WWW/HTTP',
+        'Framework :: Zope3'],
+    url = 'http://cheeseshop.python.org/pypi/z3c.searcher',
+    packages = find_packages('src'),
+    include_package_data = True,
+    package_dir = {'':'src'},
+    namespace_packages = ['z3c',],
+    extras_require = dict(
+        test = [
+            'z3c.macro',
+            'z3c.testing',
+            'zope.app.authentication',
+            'zope.app.keyreference',
+            'zope.app.pagetemplate',
+            'zope.app.testing',
+            'zope.contentprovider',
+            'zope.publisher',
+            'zope.session',
+            'zope.testing',
+            ],
+        ),
+    install_requires = [
+        'setuptools',
+        'z3c.form',
+        'z3c.formui',
+        'z3c.i18n',
+        'z3c.indexer',
+        'z3c.template',
+        'z3c.table',
+        'zc.catalog',
+        'zope.app.intid',
+        'zope.app.container',
+        'zope.component',
+        'zope.event',
+        'zope.index',
+        'zope.interface',
+        'zope.location',
+        'zope.schema',
+        'zope.session',
+        ],
+    zip_safe = False,
+)


Property changes on: z3c.searcher/trunk/setup.py
___________________________________________________________________
Name: svn:eol-style
   + native


Property changes on: z3c.searcher/trunk/src
___________________________________________________________________
Name: svn:ignore
   + z3c.searcher.egg-info


Added: z3c.searcher/trunk/src/z3c/__init__.py
===================================================================
--- z3c.searcher/trunk/src/z3c/__init__.py	                        (rev 0)
+++ z3c.searcher/trunk/src/z3c/__init__.py	2008-05-02 01:43:46 UTC (rev 86042)
@@ -0,0 +1,7 @@
+# this is a namespace package
+try:
+    import pkg_resources
+    pkg_resources.declare_namespace(__name__)
+except ImportError:
+    import pkgutil
+    __path__ = pkgutil.extend_path(__path__, __name__)


Property changes on: z3c.searcher/trunk/src/z3c/__init__.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.searcher/trunk/src/z3c/searcher/README.txt
===================================================================
--- z3c.searcher/trunk/src/z3c/searcher/README.txt	                        (rev 0)
+++ z3c.searcher/trunk/src/z3c/searcher/README.txt	2008-05-02 01:43:46 UTC (rev 86042)
@@ -0,0 +1,666 @@
+======
+README
+======
+
+This package provides a persistent search query implementation. This search 
+query is implemented as a filter object which can use search criteria for build
+the search query. This package also offers some z3c.form based management views
+which allo us to manage the search filter and it's search criteria. Let's 
+define a site with indexes which allows us to build search filter for.
+
+Note, this package depends on the new z3c.indexer package which offers a  
+modular indexing concept. But you can use this package with the 
+zope.app.catalog package too. You only have to build our own search citerium. 
+
+
+Start a simple test setup
+-------------------------
+
+Setup some helpers:
+
+  >>> import zope.component
+  >>> from zope.app import folder
+  >>> from zope.app.component.site import LocalSiteManager
+  >>> from z3c.indexer.interfaces import IIndex
+
+Setup a site
+
+  >>> class SiteStub(folder.Folder):
+  ...     """Sample site."""
+  >>> site = SiteStub()
+
+  >>> root['site'] = site
+  >>> sm = LocalSiteManager(site)
+  >>> site.setSiteManager(sm)
+
+And set the site as the current site. This is normaly done by traversing to a 
+site:
+
+  >>> from zope.app.component import hooks
+  >>> hooks.setSite(site)
+
+Setup a IIntIds utility:
+
+  >>> from zope.app.intid import IntIds
+  >>> from zope.app.intid.interfaces import IIntIds
+  >>> intids = IntIds()
+  >>> sm['default']['intids'] = intids
+  >>> sm.registerUtility(intids, IIntIds)
+
+
+TextIndex
+---------
+
+Setup a text index:
+
+  >>> from z3c.indexer.index import TextIndex
+  >>> textIndex = TextIndex()
+  >>> sm['default']['textIndex'] = textIndex
+  >>> sm.registerUtility(textIndex, IIndex, name='textIndex')
+
+
+FieldIndex
+----------
+
+Setup a field index:
+
+  >>> from z3c.indexer.index import FieldIndex
+  >>> fieldIndex = FieldIndex()
+  >>> sm['default']['fieldIndex'] = fieldIndex
+  >>> sm.registerUtility(fieldIndex, IIndex, name='fieldIndex')
+
+
+ValueIndex
+----------
+
+Setup a value index:
+
+  >>> from z3c.indexer.index import ValueIndex
+  >>> valueIndex = ValueIndex()
+  >>> sm['default']['valueIndex'] = valueIndex
+  >>> sm.registerUtility(valueIndex, IIndex, name='valueIndex')
+
+
+SetIndex
+--------
+
+Setup a set index:
+
+  >>> from z3c.indexer.index import SetIndex
+  >>> setIndex = SetIndex()
+  >>> sm['default']['setIndex'] = setIndex
+  >>> sm.registerUtility(setIndex, IIndex, name='setIndex')
+
+
+DemoContent
+-----------
+
+Define a content object:
+
+  >>> import persistent
+  >>> import zope.interface
+  >>> from zope.app.container import contained
+  >>> from zope.schema.fieldproperty import FieldProperty
+
+  >>> class IDemoContent(zope.interface.Interface):
+  ...     """Demo content."""
+  ...     title = zope.schema.TextLine(
+  ...         title=u'Title',
+  ...         default=u'')
+  ... 
+  ...     body = zope.schema.TextLine(
+  ...         title=u'Body',
+  ...         default=u'')
+  ... 
+  ...     field = zope.schema.TextLine(
+  ...         title=u'a field',
+  ...         default=u'')
+  ... 
+  ...     value = zope.schema.TextLine(
+  ...         title=u'A value',
+  ...         default=u'')
+  ... 
+  ...     iterable = zope.schema.Tuple(
+  ...         title=u'A sequence of values',
+  ...         default=())
+
+  >>> class DemoContent(persistent.Persistent, contained.Contained):
+  ...     """Demo content."""
+  ...     zope.interface.implements(IDemoContent)
+  ... 
+  ...     title = FieldProperty(IDemoContent['title'])
+  ...     body = FieldProperty(IDemoContent['body'])
+  ...     field = FieldProperty(IDemoContent['field'])
+  ...     value = FieldProperty(IDemoContent['value'])
+  ...     iterable = FieldProperty(IDemoContent['iterable'])
+  ... 
+  ...     def __init__(self, title=u''):
+  ...         self.title = title
+  ... 
+  ...     def __repr__(self):
+  ...         return '<%s %r>' % (self.__class__.__name__, self.title)
+
+Create and add the content object to the site:
+
+  >>> demo = DemoContent(u'Title')
+  >>> demo.body = u'Body text'
+  >>> demo.field = u'Field'
+  >>> demo.value = u'Value'
+  >>> demo.iterable = (1, 2, 'Iterable')
+  >>> site['demo'] = demo
+
+The zope event subscriber for __setitem__ whould call the IIntIds register
+method for our content object. But we didn't setup the relevant subscribers, so
+we do this here:
+
+  >>> uid = intids.register(demo)
+
+
+Indexer
+-------
+
+Setup a indexer adapter for our content object.
+
+  >>> from z3c.indexer.indexer import MultiIndexer
+  >>> class DemoIndexer(MultiIndexer):
+  ...     zope.component.adapts(IDemoContent)
+  ... 
+  ...     def doIndex(self):
+  ... 
+  ...         # index context in valueIndex
+  ...         valueIndex = self.getIndex('textIndex')
+  ...         txt = '%s %s' % (self.context.title, self.context.body)
+  ...         valueIndex.doIndex(self.oid, txt)
+  ... 
+  ...         # index context in fieldIndex
+  ...         fieldIndex = self.getIndex('fieldIndex')
+  ...         fieldIndex.doIndex(self.oid, self.context.field)
+  ... 
+  ...         # index context in setIndex
+  ...         setIndex = self.getIndex('setIndex')
+  ...         setIndex.doIndex(self.oid, self.context.iterable)
+  ... 
+  ...         # index context in valueIndex
+  ...         valueIndex = self.getIndex('valueIndex')
+  ...         valueIndex.doIndex(self.oid, self.context.value)
+
+Register the indexer adapter as a named adapter:
+
+  >>> zope.component.provideAdapter(DemoIndexer, name='DemoIndexer')
+
+
+Indexing
+--------
+
+Before we start indexing, we check the index:
+
+  >>> textIndex.documentCount()
+  0
+
+  >>> fieldIndex.documentCount()
+  0
+
+  >>> setIndex.documentCount()
+  0
+
+  >>> valueIndex.documentCount()
+  0
+
+Now we can index our demo object:
+
+  >>> from z3c.indexer.indexer import index
+  >>> index(demo)
+
+And check our indexes:
+
+  >>> textIndex.documentCount()
+  1
+
+  >>> fieldIndex.documentCount()
+  1
+
+  >>> setIndex.documentCount()
+  1
+
+  >>> valueIndex.documentCount()
+  1
+
+
+Search Filter
+-------------
+
+Now we are ready and can start with our search filter implementation.
+The following search filter returns no results by default because it defines 
+NoTerm as getDefaultQuery. This is usefull if you have a larg set of data and 
+you like to start with a empty query if no cirterium is selected.
+
+  >>> from z3c.searcher import interfaces
+  >>> from z3c.searcher.filter import EmptyTerm
+  >>> from z3c.searcher.filter import SearchFilter
+
+  >>> class IContentSearchFilter(interfaces.ISearchFilter):
+  ...     """Search filter for content objects."""
+
+  >>> class ContentSearchFilter(SearchFilter):
+  ...     """Content search filter."""
+  ... 
+  ...     zope.interface.implements(IContentSearchFilter)
+  ... 
+  ...     def getDefaultQuery(self):
+  ...         return EmptyTerm()
+
+
+Search Criterium
+----------------
+
+And we define a criterium for our demo content. This text search criterium uses
+the text index registered as ``textIndex`` above:
+
+  >>> from z3c.searcher import criterium
+  >>> class TextCriterium(criterium.TextCriterium):
+  ...     """Full text search criterium for ``textIndex`` index."""
+  ... 
+  ...     indexOrName = 'textIndex'
+
+Such a criterium can search in our index. Let's start with a empty search query:
+
+  >>> from z3c.indexer.search import SearchQuery
+  >>> searchQuery = SearchQuery()
+
+You can see that the searchQuery returns a empty result.
+
+  >>> len(searchQuery.searchResults())
+  0
+
+showcase
+~~~~~~~~
+
+Now we can create a criterium instance and give them a value:
+
+  >>> sampleCriterium = TextCriterium()
+  >>> sampleCriterium.value = u'Bod*'
+
+Now the criterium is able to search in it's related index within the given 
+value within a given (emtpy) search query. This empty query is only used as
+a chainable query object. Each result get added or removed from this chain
+dependent on it's connector ``And``, ``OR`` or ``Not``:
+
+  >>> searchQuery = sampleCriterium.search(searchQuery)
+
+Now you can see that our criterium found a result from the text index:
+
+  >>> len(searchQuery.searchResults())
+  1
+
+  >>> content = list(searchQuery.searchResults())[0]
+  >>> content.body
+  u'Body text'
+
+
+Search Criterium Factory
+------------------------
+
+The test above shows you how criterium can search in indexes. But that's not 
+all. Our concept offers a search filter which can manage more then one search
+criterium in a filter. A criterium is an adapter for a filter. This means we
+need to create an adapter factory and register this factory as an adapter
+for our filter. Let's now create this criterium adapter factory:
+
+  >>> textCriteriumFactory = criterium.factory(TextCriterium, 'fullText')
+
+This search criterium factory class implements ISearchCriteriumFactory:
+
+  >>> interfaces.ISearchCriteriumFactory.implementedBy(textCriteriumFactory)
+  True
+
+and we register this adapter for our content search filter:
+
+  >>> zope.component.provideAdapter(textCriteriumFactory, 
+  ...     (IContentSearchFilter,), name='fullText')
+
+showcase
+~~~~~~~~
+
+Now you can see that our content search filter knows about the search criterium
+factories:
+
+  >>> contentSearchFilter = ContentSearchFilter()
+  >>> contentSearchFilter.criteriumFactories
+  [(u'fullText', <z3c.searcher.criterium.TextCriteriumFactory object at ...>)]
+
+Since the search criterium factory is an adapter for our search filter, the 
+factory can adapt our contentSearchFilter:
+
+  >>> textCriteriumFactory = textCriteriumFactory(contentSearchFilter)
+  >>> textCriteriumFactory
+  <z3c.searcher.criterium.TextCriteriumFactory object at ...>
+
+Now we can call the factory and we will get back our search criterium instance:
+
+  >>> textCriterium = textCriteriumFactory()
+  >>> textCriterium
+  <TextCriterium object at ...>
+
+Our search criterium provides ISearchCriterium:
+
+  >>> interfaces.ISearchCriterium.providedBy(textCriterium)
+  True
+
+
+Search Example
+--------------
+
+Now we are ready to search within our filter construct. First let's create a 
+plain content search filter:
+
+  >>> sampleFilter = ContentSearchFilter()
+
+Then let's add a criterium by it's factory name:
+
+  >>> sampleCriterium = sampleFilter.createCriterium('fullText')
+
+Now we can set a value for the criterium:
+
+  >>> sampleCriterium.value = u'Title'
+
+And add the criterium to our filter:
+
+  >>> sampleFilter.addCriterium(sampleCriterium)
+
+That's all, now our filter is a ble to genearet a query:
+
+  >>> sampleQuery = sampleFilter.generateQuery()
+
+And the sample search query can return the result:
+
+  >>> len(sampleQuery.searchResults())
+  1
+
+  >>> content = list(sampleQuery.searchResults())[0]
+  >>> content.title
+  u'Title'
+
+
+Search Session
+--------------
+
+Before we show how to use the criterium and filter within z3c.form components,
+we will show you how the search session is working. Let's register and create
+a search session:
+
+  >>> from z3c.searcher import session
+  >>> zope.component.provideAdapter(session.SearchSession)
+
+Now we can create a test request and get the session as adapter for a request:
+
+  >>> import z3c.form.testing
+  >>> request = z3c.form.testing.TestRequest()
+  >>> searchSession = interfaces.ISearchSession(request)
+  >>> searchSession
+  <z3c.searcher.session.SearchSession object at ...>
+
+The search session offers an API for store and manage filters: 
+
+  >>> searchSession.addFilter('foo', sampleFilter)
+
+And we can get such filters from the search session by name.
+
+  >>> searchSession.getFilter('foo')
+  <ContentSearchFilter object at ...>
+
+Or we can get all search filters sotred in this session:
+
+  >>> searchSession.getFilters()
+  [<ContentSearchFilter object at ...>]
+
+And we can remove a filter by it's name:
+
+  >>> searchSession.removeFilter('foo')
+  >>> searchSession.getFilters()
+  []
+
+There is also another argument called ``key`` in the search session methods. 
+This argument can be used as namespace. If you need to support a specific 
+filter only for one object instance, you can use a key which is unique to that 
+object as discriminator.
+
+  >>> myFilter = ContentSearchFilter()
+  >>> searchSession.addFilter('foo', myFilter, key='myKey')
+
+Such filters are only available if the right ``key`` is used:
+
+  >>> searchSession.getFilter('foo') is None
+  True
+
+  >>> searchSession.getFilter('foo', key='myKey')
+  <ContentSearchFilter object at ...>
+
+  >>> searchSession.getFilters()
+  []
+
+Now let's cleanup our search session and remove the filter stored by the key:
+
+  >>> searchSession.getFilters('myKey')
+  [<ContentSearchFilter object at ...>]
+
+  >>> searchSession.removeFilter('foo', 'myKey')
+  >>> searchSession.getFilters('myKey')
+  []
+
+
+Criterium Form
+--------------
+Now we will show you how the form part is working. Each criterium can render 
+itself within a form. We offer a CriteriumForm class for doing this. Let's
+create and render such a criterium form:
+
+  >>> import z3c.form.testing
+  >>> from z3c.searcher import form
+  >>> criteriumRow = form.CriteriumForm(textCriterium, request)
+  >>> criteriumRow
+  <z3c.searcher.form.CriteriumForm object at ...>
+
+Before we can render the form, we need to register the templates:
+
+  >>> from zope.configuration import xmlconfig
+  >>> import zope.component
+  >>> import zope.viewlet
+  >>> import zope.app.component
+  >>> import zope.app.security
+  >>> import zope.app.publisher.browser
+  >>> import z3c.template
+  >>> import z3c.macro
+  >>> import z3c.formui
+  >>> xmlconfig.XMLConfig('meta.zcml', zope.component)()
+  >>> xmlconfig.XMLConfig('meta.zcml', zope.viewlet)()
+  >>> xmlconfig.XMLConfig('meta.zcml', zope.app.component)()
+  >>> xmlconfig.XMLConfig('meta.zcml', zope.app.security)()
+  >>> xmlconfig.XMLConfig('meta.zcml', zope.app.publisher.browser)()
+  >>> xmlconfig.XMLConfig('meta.zcml', z3c.macro)()
+  >>> xmlconfig.XMLConfig('meta.zcml', z3c.template)()
+  >>> xmlconfig.XMLConfig('div-form.zcml', z3c.formui)()
+  >>> context = xmlconfig.file('meta.zcml', z3c.template)
+  >>> context = xmlconfig.string("""
+  ... <configure
+  ...     xmlns:z3c="http://namespaces.zope.org/z3c">
+  ...  <configure package="z3c.searcher">
+  ...  <z3c:template
+  ...      template="filter.pt"
+  ...      for=".form.FilterForm"
+  ...      />
+  ...  <z3c:template
+  ...      template="criterium.pt"
+  ...      for=".form.CriteriumForm"
+  ...      />
+  ...  <z3c:template
+  ...      template="search.pt"
+  ...      for=".form.SearchForm"
+  ...      />
+  ... </configure>
+  ... </configure>
+  ... """, context=context)
+
+And we also need some widgets from z3c.form:
+
+  >>> import z3c.form.testing
+  >>> z3c.form.testing.setupFormDefaults()
+
+Now we can render the criterium form:
+
+  >>> criteriumRow.update()
+  >>> print criteriumRow.render()
+  <tr>
+    <td style="padding-right:5px;">
+      <span>Text</span>
+    </td>
+    <td style="padding-right:5px;">
+      <b>matches</b>
+    </td>
+    <td style="padding-right:5px;">
+      <input type="text" id="form-widgets-value"
+         name="form.widgets.value"
+         class="text-widget required textline-field" value="" />
+      <span class="option">
+    <label for="form-widgets-connectorName-0">
+      <input type="radio" id="form-widgets-connectorName-0"
+             name="form.widgets.connectorName:list"
+             class="radio-widget required choice-field"
+             value="OR" checked="checked" />
+      <span class="label">or</span>
+    </label>
+  </span><span class="option">
+    <label for="form-widgets-connectorName-1">
+      <input type="radio" id="form-widgets-connectorName-1"
+             name="form.widgets.connectorName:list"
+             class="radio-widget required choice-field"
+             value="AND" />
+      <span class="label">and</span>
+    </label>
+  </span><span class="option">
+    <label for="form-widgets-connectorName-2">
+      <input type="radio" id="form-widgets-connectorName-2"
+             name="form.widgets.connectorName:list"
+             class="radio-widget required choice-field"
+             value="NOT" />
+      <span class="label">not</span>
+    </label>
+  </span>
+  <input name="form.widgets.connectorName-empty-marker"
+         type="hidden" value="1" />
+    </td>
+    <td style="padding-right:5px;">
+      <input type="submit" id="form-buttons-remove"
+         name="form.buttons.remove"
+         class="submit-widget button-field" value="Remove" />
+    </td>
+  </tr>
+
+
+Filter Form
+------------
+
+There is also a filter form which can represent the SearchFilter. This form
+includes the CriteriumForm part. Note we uses a dumy context becaue it's not
+relevant where you render this form because the form will get the filters
+from the session.
+
+  >>> filterForm = form.FilterForm(object(), request)
+  >>> filterForm
+  <z3c.searcher.form.FilterForm object at ...>
+
+But before we can use the form, we need to set our search filter class as 
+factory. Because only this search filter knows our criteria:
+
+  >>> filterForm.filterFactory = ContentSearchFilter
+
+Now we can render our filter form:
+
+  >>> filterForm.update()
+  >>> print filterForm.render()
+  <fieldset>
+  <legend>Filter</legend>
+  <div>
+    <label for="filterformnewCriterium">
+      New Criterium
+    </label>
+    <select name="filterformnewCriterium" size="1">
+      <option value="fullText">fullText</option>
+    </select>
+    <input type="submit" id="filterform-buttons-add"
+           name="filterform.buttons.add"
+           class="submit-widget button-field" value="Add" />
+  </div>
+  <div>
+    <input type="submit" id="filterform-buttons-search"
+           name="filterform.buttons.search"
+           class="submit-widget button-field" value="Search" />
+    <input type="submit" id="filterform-buttons-clear"
+           name="filterform.buttons.clear"
+           class="submit-widget button-field" value="Clear" />
+  </div>
+  </fieldset>
+
+
+Search Form
+-----------
+
+There is also a search form which allows you to simply define a search page.
+This search form uses the criterium and filter form and allows you to simply
+create a search page. Let's define a custom search page:
+
+  >>> class ContentSearchForm(form.SearchForm):
+  ... 
+  ...     filterFactory = ContentSearchFilter
+
+Before we can use the form, our request needs to provide the form UI layer:
+
+  >>> from zope.interface import alsoProvides
+  >>> from z3c.formui.interfaces import IDivFormLayer
+  >>> alsoProvides(request, IDivFormLayer)
+
+That's all you need for write a simple search form. This form uses it's own
+content search filter and of corse the criteria configured for this filter.
+
+  >>> searchForm = ContentSearchForm(object(), request)
+  >>> searchForm.update()
+  >>> print searchForm.render()
+  <form action="http://127.0.0.1" method="post"
+        enctype="multipart/form-data" class="edit-form"
+        name="form" id="form">
+    <div class="viewspace">
+        <div class="required-info">
+           <span class="required">*</span>
+           &ndash; required
+        </div>
+      <div>
+    <fieldset>
+  <legend>Filter</legend>
+  <div>
+    <label for="filterformnewCriterium">
+      New Criterium
+    </label>
+    <select name="filterformnewCriterium" size="1">
+      <option value="fullText">fullText</option>
+    </select>
+    <input type="submit" id="filterform-buttons-add"
+           name="filterform.buttons.add"
+           class="submit-widget button-field" value="Add" />
+  </div>
+  <div>
+    <input type="submit" id="filterform-buttons-search"
+           name="filterform.buttons.search"
+           class="submit-widget button-field" value="Search" />
+    <input type="submit" id="filterform-buttons-clear"
+           name="filterform.buttons.clear"
+           class="submit-widget button-field" value="Clear" />
+  </div>
+  </fieldset>
+    </div>
+      <div>
+      </div>
+    </div>
+    <div>
+      <div class="buttons">
+      </div>
+    </div>
+  </form>


Property changes on: z3c.searcher/trunk/src/z3c/searcher/README.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.searcher/trunk/src/z3c/searcher/__init__.py
===================================================================
--- z3c.searcher/trunk/src/z3c/searcher/__init__.py	                        (rev 0)
+++ z3c.searcher/trunk/src/z3c/searcher/__init__.py	2008-05-02 01:43:46 UTC (rev 86042)
@@ -0,0 +1 @@
+# make a package


Property changes on: z3c.searcher/trunk/src/z3c/searcher/__init__.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.searcher/trunk/src/z3c/searcher/browser.zcml
===================================================================
--- z3c.searcher/trunk/src/z3c/searcher/browser.zcml	                        (rev 0)
+++ z3c.searcher/trunk/src/z3c/searcher/browser.zcml	2008-05-02 01:43:46 UTC (rev 86042)
@@ -0,0 +1,34 @@
+<configure
+    xmlns:zope="http://namespaces.zope.org/zope"
+    xmlns="http://namespaces.zope.org/browser"
+    xmlns:z3c="http://namespaces.zope.org/z3c"
+    i18n_domain="z3c">
+
+  <!-- SearchCriterium row views -->
+  <page
+      name="row"
+      for=".interfaces.ISearchCriterium"
+      class=".form.CriteriumForm"
+      layer="zope.publisher.interfaces.browser.IBrowserRequest"
+      permission="zope.Public"
+      />
+
+  <z3c:template
+      template="criterium.pt"
+      for=".form.CriteriumForm"
+      layer="zope.publisher.interfaces.browser.IBrowserRequest"
+      />
+
+  <z3c:template
+      template="filter.pt"
+      for=".form.FilterForm"
+      layer="zope.publisher.interfaces.browser.IBrowserRequest"
+      />
+
+  <z3c:template
+      template="table.pt"
+      for=".interfaces.ISearchTable"
+      layer="zope.publisher.interfaces.browser.IBrowserRequest"
+      />
+
+</configure>


Property changes on: z3c.searcher/trunk/src/z3c/searcher/browser.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.searcher/trunk/src/z3c/searcher/configure.zcml
===================================================================
--- z3c.searcher/trunk/src/z3c/searcher/configure.zcml	                        (rev 0)
+++ z3c.searcher/trunk/src/z3c/searcher/configure.zcml	2008-05-02 01:43:46 UTC (rev 86042)
@@ -0,0 +1,11 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    i18n_domain="z3c">
+
+  <adapter
+      factory=".session.SearchSession"
+      />
+
+  <include file="browser.zcml" />
+
+</configure>


Property changes on: z3c.searcher/trunk/src/z3c/searcher/configure.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.searcher/trunk/src/z3c/searcher/criterium.pt
===================================================================
--- z3c.searcher/trunk/src/z3c/searcher/criterium.pt	                        (rev 0)
+++ z3c.searcher/trunk/src/z3c/searcher/criterium.pt	2008-05-02 01:43:46 UTC (rev 86042)
@@ -0,0 +1,16 @@
+<tr>
+  <td style="padding-right:5px;">
+    <span tal:content="context/label" i18n:translate="" />
+    <tal:block replace="structure view/widgets/object|nothing" />
+  </td>
+  <td style="padding-right:5px;">
+    <b tal:content="context/operatorLabel|nothing" i18n:translate="" />
+  </td>
+  <td style="padding-right:5px;">
+    <tal:block replace="structure view/widgets/value/render" />
+    <tal:block replace="structure view/widgets/connectorName/render" />
+  </td>
+  <td style="padding-right:5px;">
+	<input tal:replace="structure view/actions/remove/render" />
+  </td>
+</tr>


Property changes on: z3c.searcher/trunk/src/z3c/searcher/criterium.pt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.searcher/trunk/src/z3c/searcher/criterium.py
===================================================================
--- z3c.searcher/trunk/src/z3c/searcher/criterium.py	                        (rev 0)
+++ z3c.searcher/trunk/src/z3c/searcher/criterium.py	2008-05-02 01:43:46 UTC (rev 86042)
@@ -0,0 +1,110 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""
+$Id:$
+"""
+__docformat__ = "reStructuredText"
+
+import persistent
+import zope.interface
+from zope.schema.fieldproperty import FieldProperty
+from zope.app.container import contained
+
+from z3c.i18n import MessageFactory as _
+from z3c.indexer import query
+from z3c.searcher import interfaces
+
+
+class SearchCriterium(persistent.Persistent, contained.Contained):
+    """Search criterium for some data.
+
+    This search criterium is implemented as an adapter to the search
+    """
+    zope.interface.implements(interfaces.ISearchCriterium)
+
+    label = None
+    indexOrName = None
+
+    # See interfaces.ISearchCriterium
+    operator = query.Eq
+    operatorLabel = _('equals')
+
+    value = FieldProperty(interfaces.ISearchCriterium['value'])
+    connectorName = FieldProperty(interfaces.ISearchCriterium['connectorName'])
+
+    def search(self, searchQuery):
+        """See interfaces.ISearchCriterium.
+
+        Note, this can raise TypeError or zope.index.text.parsetree.ParseError 
+        for text index or any other error raised from other indexes. We only
+        catch te TypeError and ParseError in the offered FilterForm.
+        """
+        operatorQuery = self.operator(self.indexOrName, self.value)
+        if self.connectorName == interfaces.CONNECTOR_OR:
+            return searchQuery.Or(operatorQuery)
+        if self.connectorName == interfaces.CONNECTOR_AND:
+            return searchQuery.And(operatorQuery)
+        if self.connectorName == interfaces.CONNECTOR_NOT:
+            return searchQuery.Not(operatorQuery)
+
+
+class SetSearchCriterium(SearchCriterium):
+
+    operator = query.AnyOf
+    operatorLabel = _('is')
+
+    def search(self, searchQuery):
+        """See interfaces.ISearchCriterium.
+
+        Note, this can raise TypeError or zope.index.text.parsetree.ParseError 
+        for text index or any other error raised from other indexes. We only
+        catch te TypeError and ParseError in the offered FilterForm.
+        """
+        operatorQuery = self.operator(self.indexOrName, [self.value])
+        if self.connectorName == interfaces.CONNECTOR_OR:
+            return searchQuery.Or(operatorQuery)
+        if self.connectorName == interfaces.CONNECTOR_AND:
+            return searchQuery.And(operatorQuery)
+        if self.connectorName == interfaces.CONNECTOR_NOT:
+            return searchQuery.Not(operatorQuery)
+
+
+class TextCriterium(SearchCriterium):
+    """Search criterium for some data."""
+    zope.interface.implements(interfaces.ITextCriterium)
+
+    label = _('Text')
+    operator = query.TextQuery
+    operatorLabel = _('matches')
+    value = FieldProperty(interfaces.ITextCriterium['value'])
+
+
+class SearchCriteriumFactoryBase(object):
+    """Search Criterium Factory."""
+    zope.interface.implements(interfaces.ISearchCriteriumFactory)
+
+    klass = None
+    title = None
+    weight = 0
+
+    def __init__(self, context):
+        pass
+
+    def __call__(self):
+        return self.klass()
+
+
+def factory(klass, title):
+    return type('%sFactory' %klass.__name__, (SearchCriteriumFactoryBase,),
+                {'klass': klass, 'title': title})


Property changes on: z3c.searcher/trunk/src/z3c/searcher/criterium.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.searcher/trunk/src/z3c/searcher/filter.pt
===================================================================
--- z3c.searcher/trunk/src/z3c/searcher/filter.pt	                        (rev 0)
+++ z3c.searcher/trunk/src/z3c/searcher/filter.pt	2008-05-02 01:43:46 UTC (rev 86042)
@@ -0,0 +1,32 @@
+<fieldset tal:define="criteriumRows view/criteriumRows">
+<legend i18n:translate="">Filter</legend>
+<div tal:condition="view/status"
+       tal:content="view/status">
+  Status
+</div>
+<div>
+  <label for=""
+         tal:attributes="for string:${view/prefix}newCriterium"
+         i18n:translate="">
+    New Criterium
+  </label>
+  <select name="" size="1"
+          tal:attributes="name string:${view/prefix}newCriterium">
+    <option value=""
+            tal:repeat="criterium view/criteriumFactories"
+            tal:attributes="value criterium/name"
+            tal:content="criterium/title"> Criterium Factory Title </option>
+  </select>
+  <input tal:replace="structure view/actions/add/render" />
+</div>
+<div style="margin: 8px 0px" tal:condition="criteriumRows">
+  <table>
+    <tal:block repeat="row criteriumRows"
+               replace="structure row/render" />
+  </table>
+</div>
+<div>
+  <input tal:replace="structure view/actions/search/render" />
+  <input tal:replace="structure view/actions/clear/render" />
+</div>
+</fieldset>


Property changes on: z3c.searcher/trunk/src/z3c/searcher/filter.pt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.searcher/trunk/src/z3c/searcher/filter.py
===================================================================
--- z3c.searcher/trunk/src/z3c/searcher/filter.py	                        (rev 0)
+++ z3c.searcher/trunk/src/z3c/searcher/filter.py	2008-05-02 01:43:46 UTC (rev 86042)
@@ -0,0 +1,143 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""
+$Id:$
+"""
+__docformat__ = "reStructuredText"
+
+import persistent
+import persistent.list
+import zope.component
+import zope.interface
+import zope.event
+import zope.lifecycleevent
+from zope.location import location
+from zope.app.container import contained
+
+from z3c.indexer import query
+from z3c.indexer.search import SearchQuery
+from z3c.searcher import interfaces
+
+
+class EmptyTerm(object):
+    """Return a empty list as result."""
+
+    def apply(self):
+        return []
+
+
+class SearchFilter(persistent.Persistent, contained.Contained):
+    """Persistent search filter implementation.
+
+    This component uses the component architecture to determine its available
+    criterium components.
+    """
+    zope.interface.implements(interfaces.ISearchFilter)
+
+    def __init__(self):
+        super(SearchFilter, self).__init__()
+        self.criteria = persistent.list.PersistentList()
+
+    def clear(self):
+        """See interfaces.ISearchFilter"""
+        self.__init__()
+
+    @property
+    def criteriumFactories(self):
+        """See interfaces.ISearchFilter"""
+        adapters = zope.component.getAdapters(
+            (self,), interfaces.ISearchCriteriumFactory)
+        return sorted(adapters, key=lambda (n, a): a.weight)
+
+    def createCriterium(self, name, value=interfaces.NOVALUE):
+        """Create a criterium."""
+        criterium = zope.component.getAdapter(
+            self, interfaces.ISearchCriteriumFactory, name=name)()
+        if value is not interfaces.NOVALUE:
+            criterium.value = value
+        criterium.__name__ = name
+        criterium.__parent__ = self
+        return criterium
+
+    def addCriterium(self, criterium):
+        """See interfaces.ISearchFilter"""
+        location.locate(criterium, self)
+        self.criteria.append(criterium)
+
+    def createAndAddCriterium(self, name, value=interfaces.NOVALUE):
+        criterium = self.createCriterium(name)
+        if value is not interfaces.NOVALUE:
+            criterium.value = value
+        zope.event.notify(zope.lifecycleevent.ObjectCreatedEvent(criterium))
+        self.addCriterium(criterium)
+
+    def removeCriterium(self, criterium):
+        """See interfaces.ISearchFilter"""
+        self.criteria.remove(criterium)
+
+    def getDefaultQuery(self):
+        """See interfaces.ISearchFilter"""
+        return EmptyTerm()
+
+    def getAndQuery(self):
+        """See interfaces.ISearchFilter"""
+        return None
+
+    def getNotQuery(self):
+        """See interfaces.ISearchFilter"""
+        return None
+
+    def generateQuery(self):
+        """See interfaces.ISearchFilter"""
+        # If no criteria are selected, return all values
+        if not len(self.criteria):
+            return self.getDefaultQuery()
+
+        searchQuery = SearchQuery()
+
+        # order the criterium by the order or, and, not
+        orCriteria = []
+        andCriteria  = []
+        notCriteria  = []
+        for criterium in self.criteria:
+            if criterium.connectorName == interfaces.CONNECTOR_OR:
+                orCriteria.append(criterium)
+            if criterium.connectorName == interfaces.CONNECTOR_AND:
+                andCriteria.append(criterium)
+            if criterium.connectorName == interfaces.CONNECTOR_NOT:
+                notCriteria.append(criterium)
+
+        # apply given ``or`` criteria if any
+        for criterium in orCriteria:
+            searchQuery = criterium.search(searchQuery)
+
+        # apply given ``and`` criteria if any
+        for criterium in andCriteria:
+            searchQuery = criterium.search(searchQuery)
+
+        # apply default ``And`` query if available
+        andQuery = self.getAndQuery()
+        if andQuery is not None:
+            searchQuery = searchQuery.And(andQuery)
+
+        # apply (remove) default ``Not`` query if available
+        notQuery = self.getNotQuery()
+        if notQuery is not None:
+            return query.Not(self.getNotQuery)
+
+        # apply given ``not`` criteria if any
+        for criterium in notCriteria:
+            searchQuery = criterium.search(searchQuery)
+
+        return searchQuery


Property changes on: z3c.searcher/trunk/src/z3c/searcher/filter.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.searcher/trunk/src/z3c/searcher/form.py
===================================================================
--- z3c.searcher/trunk/src/z3c/searcher/form.py	                        (rev 0)
+++ z3c.searcher/trunk/src/z3c/searcher/form.py	2008-05-02 01:43:46 UTC (rev 86042)
@@ -0,0 +1,214 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""
+$Id:$
+"""
+__docformat__ = "reStructuredText"
+
+import zope.component
+import zope.event
+import zope.lifecycleevent
+
+from zope.index.text import parsetree
+from zope.location import location
+
+from z3c.indexer.search import SearchQuery
+from z3c.template.template import getPageTemplate
+from z3c.template.template import getLayoutTemplate
+
+from z3c.i18n import MessageFactory as _
+from z3c.form.interfaces import IWidgets
+from z3c.form import button
+from z3c.form import field
+from z3c.form import form
+from z3c.formui import form as formui
+from z3c.form.browser.radio import RadioFieldWidget
+from z3c.searcher import interfaces
+from z3c.searcher import criterium
+from z3c.searcher import filter
+
+
+class CriteriumForm(form.Form):
+
+    formErrorsMessage = _('There were some errors.')
+    successMessage = _('Data successfully updated.')
+    noChangesMessage = _('No changes were applied.')
+
+    fields = field.Fields(interfaces.ISearchCriterium).select('connectorName',
+        'value')
+    fields['connectorName'].widgetFactory = RadioFieldWidget
+
+    def updateWidgets(self):
+        self.widgets = zope.component.getMultiAdapter(
+            (self, self.request, self.getContent()), IWidgets)
+        self.widgets.update()
+
+    @property
+    def criteriumName(self):
+        return self.context.__name__
+
+    def save(self):
+        data, errors = self.widgets.extract()
+        if errors:
+            self.status = self.formErrorsMessage
+            return
+        content = self.getContent()
+        changed = form.applyChanges(self, content, data)
+        if changed:
+            zope.event.notify(
+                zope.lifecycleevent.ObjectModifiedEvent(content))
+            self.status = self.successMessage
+        else:
+            self.status = self.noChangesMessage
+
+    @button.buttonAndHandler(_('Remove'), name='remove')
+    def handleRemove(self, data):
+        searchFilter = self.context.__parent__
+        searchFilter.removeCriterium(self.context)
+        self.request.response.redirect(self.request.getURL())
+
+
+class TextCriteriumForm(CriteriumForm):
+
+    fields = field.Fields(interfaces.ITextCriterium).select('connectorName',
+        'value')
+    fields['connectorName'].widgetFactory = RadioFieldWidget
+
+
+class FilterForm(form.Form):
+    """Filter form."""
+
+    zope.interface.implements(interfaces.IFilterForm)
+
+    # default form vars
+    prefix = 'filterform'
+    ignoreContext = True
+    criteriumRows = []
+    searchFilter = None
+
+    # The filterName is used in the ISearchSession to identify filter
+    filterName = 'searchFilter'
+
+    # will probably get overriden by the parent form
+    filterFactory = filter.SearchFilter
+
+    # customization hooks
+    @property
+    def filterKey(self):
+        """Return the default filter key.
+        
+        You can override this method and use a KeyReference intid if you need
+        different filters for each context.
+        """
+        return interfaces.SEARCH_SESSION_FILTER_KEY
+
+    def criteriumFactories(self):
+        for name, factory in self.searchFilter.criteriumFactories:
+            yield {'name': name, 'title': factory.title}
+
+    @property
+    def searchFilter(self):
+        session = interfaces.ISearchSession(self.request)
+        searchFilter = session.getFilter(self.filterName, self.filterKey)
+        if searchFilter is None:
+            searchFilter = self.filterFactory()
+            session.addFilter(self.filterName, searchFilter, self.filterKey)
+            # Locate the search filter, so that security does not get lost
+            location.locate(searchFilter, self.context, self.filterName)
+        return searchFilter
+
+    def values(self):
+        # TODO: implement better error handling and allow to register error
+        # views for unknown index search error. Right now we only catch some
+        # known search index errors.
+        try:
+            # generate the search query
+            searchQuery = self.searchFilter.generateQuery()
+            # return result
+            return SearchQuery(searchQuery).searchResults()
+        except TypeError:
+            self.status = _('One of the search filter is setup improperly.')
+        except parsetree.ParseError, error:
+            self.status = _('Invalid search text.')
+        # Return an empty result, since an error must have occurred
+        return []
+
+    def setupCriteriumRows(self):
+        self.criteriumRows = []
+        append = self.criteriumRows.append
+        index = 0
+        for criterium in self.searchFilter.criteria:
+            row = zope.component.getMultiAdapter(
+                (criterium, self.request), name='row')
+            row.prefix = str(index)
+            row.update()
+            append(row)
+            index += 1
+
+    def update(self):
+        self.setupCriteriumRows()
+        super(FilterForm, self).update()
+
+    @button.buttonAndHandler(u'Add')
+    def handleAdd(self, action):
+        name = self.request.get(self.prefix + 'newCriterium', None)
+        if name is not None:
+            self.searchFilter.createAndAddCriterium(name)
+            self.setupCriteriumRows()
+            self.status = _('New criterium added.')
+
+    @button.buttonAndHandler(u'Clear', name='clear')
+    def handleClear(self, action):
+        self.searchFilter.clear()
+        self.setupCriteriumRows()
+        self.status = _('Criteria cleared.')
+
+    @button.buttonAndHandler(u'Search', name='search')
+    def handleSearch(self, action):
+        data, errors = self.widgets.extract()
+        for row in self.criteriumRows:
+            row.save()
+
+
+class SearchForm(formui.Form):
+    """Search form using a sub form for offering filters.
+    
+    Note this form uses the layout/content template pattern by default.
+    And the content template renders the search filter into the ``extra-info```
+    slot offered from z3c.formui ``form`` macro
+    """
+
+    zope.interface.implements(interfaces.ISearchForm)
+
+    template  = getPageTemplate()
+    values = []
+    filterFactory = filter.SearchFilter
+
+    def setupFilterForm(self):
+        """Setup filter form before super form get updated."""
+        self.filterForm = FilterForm(self.context, self.request)
+        self.filterForm.filterFactory = self.filterFactory
+
+    def updateFilterForm(self):
+        """Update filter form after super form get updated."""
+        self.filterForm.update()
+        self.values = self.filterForm.values()
+
+    def update(self):
+        # setup filter form
+        self.setupFilterForm()
+        # process super form
+        super(SearchForm, self).update()
+        # process filter form
+        self.updateFilterForm()


Property changes on: z3c.searcher/trunk/src/z3c/searcher/form.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.searcher/trunk/src/z3c/searcher/interfaces.py
===================================================================
--- z3c.searcher/trunk/src/z3c/searcher/interfaces.py	                        (rev 0)
+++ z3c.searcher/trunk/src/z3c/searcher/interfaces.py	2008-05-02 01:43:46 UTC (rev 86042)
@@ -0,0 +1,199 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""
+$Id:$
+"""
+__docformat__ = "reStructuredText"
+
+import zope.interface
+import zope.schema
+from zope.schema import vocabulary
+from zope.session.interfaces import ISession
+from zope.location.interfaces import ILocation
+
+from z3c.i18n import MessageFactory as _
+from z3c.indexer import interfaces
+from z3c.indexer import query
+from z3c.form.interfaces import IForm
+from z3c.table.interfaces import ITable
+
+
+SEARCH_SESSION = u'z3c.search.intefaces.ISearchSession'
+SEARCH_SESSION_FILTER_KEY = 'default'
+
+CONNECTOR_OR = 'OR'
+CONNECTOR_AND = 'AND'
+CONNECTOR_NOT = 'NOT'
+
+NOVALUE = object()
+
+
+class ISearchSession(ISession):
+    """Search session supporting API for filter management.
+
+    Filters contain the criterium rows and are stored persistent
+
+    The methods support a key argument. This could be a context reference key
+    give from the IntId utility or some other discriminator.  If we do not 
+    support a key, the string ``default`` is used.
+    """
+
+    def getFilter(name, key=SEARCH_SESSION_FILTER_KEY):
+        """Return search filter by name."""
+
+    def getFilters(name):
+        """Return a list of search filters."""
+
+    def addFilter(name, searchFilter, key=SEARCH_SESSION_FILTER_KEY):
+        """Add search filter."""
+
+    def removeFilter(name, key=SEARCH_SESSION_FILTER_KEY):
+        """Remove search filter."""
+
+
+connectorVocabulary = vocabulary.SimpleVocabulary([
+    vocabulary.SimpleTerm(CONNECTOR_OR, title=_('or')),
+    vocabulary.SimpleTerm(CONNECTOR_AND, title=_('and')),
+    vocabulary.SimpleTerm(CONNECTOR_NOT, title=_('not')),
+    ])
+
+class ISearchCriterium(ILocation):
+    """A search citerium of a piece of data."""
+
+    __name__ = zope.schema.TextLine(
+        title=_('Name'),
+        description=_('The locatable criterium name.'),
+        required=True)
+
+    label = zope.schema.TextLine(
+        title=_('Label'),
+        description=_('Label used to present the criterium.'),
+        required=True)
+
+    operatorLabel = zope.schema.TextLine(
+        title=_('Operator label'),
+        description=_('The operator label.'),
+        required=True)
+
+    indexOrName = zope.interface.Attribute("Index or index name.")
+
+    operator = zope.schema.Object(
+        title=_('Operator'),
+        description=_('The operator used for the chain the queries.'),
+        schema=interfaces.IQuery,
+        required=True)
+
+    connectorName = zope.schema.Choice(
+        title=_('Connector Name'),
+        description=_('The criterium connector name.'),
+        vocabulary=connectorVocabulary,
+        default=CONNECTOR_OR,
+        required=True)
+
+    value = zope.schema.TextLine(
+        title=_('Search Query'),
+        required=True)
+
+    def search(searchQuery):
+        """Generate chainable search query."""
+
+
+class ITextCriterium(ISearchCriterium):
+    """Sample full text search criterium implementation."""
+
+
+class ISearchCriteriumFactory(zope.interface.Interface):
+    """A factory for the search criterium"""
+
+    title = zope.schema.TextLine(
+        title=_('Title'),
+        description=_('A human-readable title of the criterium.'),
+        required=True)
+
+    weight = zope.schema.Int(
+        title=_('Int'),
+        description=_('The weight/importance of the factory among all '
+                      'factories.'),
+        required=True)
+
+    def __call__():
+        """Generate the criterium."""
+
+
+class ISearchFilter(zope.interface.Interface):
+    """Search criteria for position search."""
+
+    criteria = zope.interface.Attribute(
+        """Return a sequence of selected criteria.""")
+
+    criteriumFactories = zope.schema.List(
+        title=_('Criteria factories'),
+        description=_('The criteria factories.'),
+        value_type=zope.schema.Object(
+            title=_('Criterium factory'),
+            description=_('The criterium factory.'),
+            schema=ISearchCriteriumFactory,
+            required=True),
+        default=[])
+
+    def clear():
+        """Clear the criteria."""
+
+    def createCriterium(name, value=NOVALUE):
+        """Create a criterium by factory name."""
+
+    def addCriterium(criterium):
+        """Add a criterium by name at the end of the list."""
+
+    def createAndAddCriterium(name, value=NOVALUE):
+        """Create and add a criterium by name at the end of the list."""
+
+    def removeCriterium(criterium):
+        """Add a criterium by name at the end of the list."""
+
+    def getDefaultQuery():
+        """Get a query that returns the default values. 
+        
+        Override this method in your custom search filter if needed.
+        This query get used if ``NO`` criterias are available.
+        """
+
+    def getAndQuery():
+        """Return a ``And`` query which get used by default or None.
+        
+        Override this method in your custom search filter if needed.
+        This query get used if ``one or more`` criterias are available.
+        """
+
+    def getNotQuery():
+        """Return a ``Not`` query which get used as starting query or None.
+        
+        Override this method in your custom search filter if needed.
+        This query get used if ``one or more`` criterias are available.
+        """
+
+    def generateQuery():
+        """Generate a query object."""
+
+
+class IFilterForm(IForm):
+    """Filter form."""
+
+
+class ISearchForm(IForm):
+    """Search form."""
+
+
+class ISearchTable(ITable):
+    """Search table."""


Property changes on: z3c.searcher/trunk/src/z3c/searcher/interfaces.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.searcher/trunk/src/z3c/searcher/search.pt
===================================================================
--- z3c.searcher/trunk/src/z3c/searcher/search.pt	                        (rev 0)
+++ z3c.searcher/trunk/src/z3c/searcher/search.pt	2008-05-02 01:43:46 UTC (rev 86042)
@@ -0,0 +1,5 @@
+<div metal:use-macro="macro:form">
+  <div metal:fill-slot="extra-info">
+  <div tal:replace="structure view/filterForm/render" />
+  </div>
+</div>


Property changes on: z3c.searcher/trunk/src/z3c/searcher/search.pt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.searcher/trunk/src/z3c/searcher/session.py
===================================================================
--- z3c.searcher/trunk/src/z3c/searcher/session.py	                        (rev 0)
+++ z3c.searcher/trunk/src/z3c/searcher/session.py	2008-05-02 01:43:46 UTC (rev 86042)
@@ -0,0 +1,75 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""
+$Id:$
+"""
+__docformat__ = "reStructuredText"
+
+import persistent.dict
+import zope.interface
+from zope.session.session import Session
+
+from z3c.searcher import interfaces
+from z3c.searcher.interfaces import SEARCH_SESSION
+
+
+class SearchSession(Session):
+    """Search session."""
+
+    zope.interface.implementsOnly(interfaces.ISearchSession)
+
+    def __init__(self, request):
+        super(SearchSession, self).__init__(request)
+        self.searchFilters = persistent.dict.PersistentDict()
+
+    def getFilter(self, name, key='default'):
+        """Return search filter by name."""
+        spd = self.__getitem__(SEARCH_SESSION)
+        filterList = spd.get(name, None)
+        if filterList is None:
+            spd[name] = persistent.dict.PersistentDict()
+            filterList = spd.get(name)
+        return filterList.get(key)
+
+    def getFilters(self, key='default'):
+        """Return a list of search filters."""
+        spd = self.__getitem__(SEARCH_SESSION)
+        filters = []
+        append = filters.append
+        for filterList in spd.values():
+            filter = filterList.get(key)
+            if filter is not None:
+                append(filter)
+        return filters
+
+    def addFilter(self, name, searchFilter, key='default'):
+        """Add search filter.
+        
+        Note: this session doesn't know about the context, this means you need
+        to locate the added filter after you where adding it. Otherwise you 
+        will get security problems because of the missing location.
+        """
+        spd = self.__getitem__(SEARCH_SESSION)
+        filterList = spd.get(name)
+        if filterList is None:
+            spd[name] = persistent.dict.PersistentDict()
+            filterList = spd.get(name)
+        filterList[key] = searchFilter
+
+    def removeFilter(self, name, key='default'):
+        """Remove search filter."""
+        spd = self.__getitem__(SEARCH_SESSION)
+        filterList = spd.get(name)
+        if filterList is not None:
+            del filterList[key]


Property changes on: z3c.searcher/trunk/src/z3c/searcher/session.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.searcher/trunk/src/z3c/searcher/table.pt
===================================================================
--- z3c.searcher/trunk/src/z3c/searcher/table.pt	                        (rev 0)
+++ z3c.searcher/trunk/src/z3c/searcher/table.pt	2008-05-02 01:43:46 UTC (rev 86042)
@@ -0,0 +1,18 @@
+<div metal:use-macro="macro:form">
+  <div metal:fill-slot="main"
+       tal:define="batch view/renderBatch">
+    <div class="filterForm" tal:condition="nocall:view/filterForm">
+      <div tal:replace="structure view/filterForm/render" />
+    </div>
+    <div>
+      <tal:block replace="structure view/renderTable">
+        table
+      </tal:block>
+    </div>
+    <div class="batch" tal:condition="batch">
+      <tal:block replace="structure batch">
+        table
+      </tal:block>
+    </div>
+  </div>
+</div>


Property changes on: z3c.searcher/trunk/src/z3c/searcher/table.pt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.searcher/trunk/src/z3c/searcher/table.py
===================================================================
--- z3c.searcher/trunk/src/z3c/searcher/table.py	                        (rev 0)
+++ z3c.searcher/trunk/src/z3c/searcher/table.py	2008-05-02 01:43:46 UTC (rev 86042)
@@ -0,0 +1,129 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""
+$Id:$
+"""
+__docformat__ = "reStructuredText"
+
+import zope.component
+import zope.event
+import zope.lifecycleevent
+
+from zope.index.text import parsetree
+from zope.location import location
+
+from z3c.indexer.search import SearchQuery
+from z3c.template.template import getPageTemplate
+from z3c.template.template import getLayoutTemplate
+
+from z3c.i18n import MessageFactory as _
+
+import z3c.formui.form
+from z3c.table import table
+from z3c.form import button
+from z3c.searcher import interfaces
+from z3c.searcher import filter
+from z3c.searcher import form
+
+
+# conditions
+def hasContent(form):
+    return form.hasContent
+
+
+def canCancel(form):
+    return form.supportsCancel
+
+
+class SearchTable(table.Table, z3c.formui.form.Form):
+    """Search form with result table."""
+
+    zope.interface.implements(interfaces.ISearchTable)
+
+    template = getPageTemplate()
+
+    prefix = 'formTable'
+
+    # internal defaults
+    hasContent = False
+    nextURL = None
+    ignoreContext = False
+    filterForm = None
+
+    # table defaults
+    cssClasses = {'table': 'contents'}
+    cssClassEven = u'even'
+    cssClassOdd = u'odd'
+    cssClassSelected = u'selected'
+    
+    batchSize = 25
+    startBatchingAt = 25
+    
+    # customize this part
+    allowCancel = True
+
+    filterFactory = filter.SearchFilter
+
+    def setupFilterForm(self):
+        """Setup filter form before super form get updated."""
+        self.filterForm = form.FilterForm(self.context, self.request)
+        self.filterForm.filterFactory = self.filterFactory
+
+    def updateFilterForm(self):
+        """Update filter form after super form get updated."""
+        self.filterForm.update()
+
+    def setupConditions(self):
+        self.hasContent = bool(self.rows)
+        if self.allowCancel:
+            self.supportsCancel = self.hasContent
+
+    def updateAfterActionExecution(self):
+        """Update table data if subform changes soemthing."""
+        # first update table data which probably changed
+        super(SearchTable, self).update()
+        # second setup conditions
+        self.setupConditions()
+        # third update action which we have probably different conditions for
+        self.updateActions()
+
+    def update(self):
+        # 1 .setup filter form
+        self.setupFilterForm()
+        # 2. process filter form
+        self.updateFilterForm()
+        # 3. setup widgets
+        self.updateWidgets()
+        # 4. setup search values, generate rows, setup headers and columns
+        super(SearchTable, self).update()
+        # 5. setup conditions
+        self.setupConditions()
+        # 6. setup form part
+        self.updateActions()
+        self.actions.execute()
+
+    @property
+    def values(self):
+        return self.filterForm.values()
+
+    @button.buttonAndHandler(_('Cancel'), name='cancel', condition=canCancel)
+    def handleCancel(self, action):
+        self.nextURL = self.request.getURL()
+
+    def render(self):
+        """Render the template."""
+        if self.nextURL is not None:
+            self.request.response.redirect(self.nextURL)
+            return ""
+        return self.template()


Property changes on: z3c.searcher/trunk/src/z3c/searcher/table.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.searcher/trunk/src/z3c/searcher/testing.py
===================================================================
--- z3c.searcher/trunk/src/z3c/searcher/testing.py	                        (rev 0)
+++ z3c.searcher/trunk/src/z3c/searcher/testing.py	2008-05-02 01:43:46 UTC (rev 86042)
@@ -0,0 +1,55 @@
+###############################################################################
+#
+# Copyright (c) 2007 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+###############################################################################
+"""
+$Id:$
+"""
+
+import zope.component
+from zope.publisher.interfaces import IRequest
+from zope.session import session
+from zope.session.http import CookieClientIdManager
+from zope.session.interfaces import IClientId
+from zope.session.interfaces import IClientIdManager
+from zope.session.interfaces import ISession
+from zope.session.interfaces import ISessionDataContainer
+from zope.app.authentication.tests import TestClientId
+from zope.app.keyreference.testing import SimpleKeyReference
+from zope.app.testing import setup
+
+
+def setUp(test):
+    test.globs = {'root': setup.placefulSetUp(True)}
+
+    # session setup
+    zope.component.provideAdapter(TestClientId, (IRequest,), IClientId)
+    zope.component.provideAdapter(session.Session, (IRequest,), ISession)
+    zope.component.provideUtility(CookieClientIdManager(), IClientIdManager)
+    rsdc = session.RAMSessionDataContainer()
+    zope.component.provideUtility(rsdc, ISessionDataContainer, '')
+
+    # Setup simple key reference adapter
+    zope.component.provideAdapter(SimpleKeyReference)
+
+    from zope.app.pagetemplate import metaconfigure
+    from z3c.macro import tales
+    metaconfigure.registerType('macro', tales.MacroExpression)
+
+    # register provider TALES
+    from zope.app.pagetemplate import metaconfigure
+    from zope.contentprovider import tales
+    metaconfigure.registerType('provider', tales.TALESProviderExpression)
+
+
+def tearDown(test):
+    setup.placefulTearDown()


Property changes on: z3c.searcher/trunk/src/z3c/searcher/testing.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.searcher/trunk/src/z3c/searcher/tests.py
===================================================================
--- z3c.searcher/trunk/src/z3c/searcher/tests.py	                        (rev 0)
+++ z3c.searcher/trunk/src/z3c/searcher/tests.py	2008-05-02 01:43:46 UTC (rev 86042)
@@ -0,0 +1,81 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""
+$Id:$
+"""
+__docformat__ = "reStructuredText"
+
+import unittest
+from zope.testing import doctest
+
+import z3c.testing
+from z3c.searcher import interfaces
+from z3c.searcher import testing
+from z3c.searcher import criterium
+from z3c.searcher import filter
+
+
+# ISearchCriterium
+class TestSearchCriterium(z3c.testing.InterfaceBaseTest):
+
+    def getTestInterface(self):
+        return interfaces.ISearchCriterium
+
+    def getTestClass(self):
+        return criterium.SearchCriterium
+
+
+class TestSetSearchCriterium(z3c.testing.InterfaceBaseTest):
+
+    def getTestInterface(self):
+        return interfaces.ISearchCriterium
+
+    def getTestClass(self):
+        return criterium.SetSearchCriterium
+
+
+class TestTextCriterium(z3c.testing.InterfaceBaseTest):
+
+    def getTestInterface(self):
+        return interfaces.ITextCriterium
+
+    def getTestClass(self):
+        return criterium.TextCriterium
+
+
+# ISearchFilter
+class TestSearchFilter(z3c.testing.InterfaceBaseTest):
+
+    def getTestInterface(self):
+        return interfaces.ISearchFilter
+
+    def getTestClass(self):
+        return filter.SearchFilter
+
+
+def test_suite():
+    return unittest.TestSuite((
+        doctest.DocFileSuite('README.txt',
+            setUp=testing.setUp, tearDown=testing.tearDown,
+            optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+            ),
+        unittest.makeSuite(TestSearchCriterium),
+        unittest.makeSuite(TestSetSearchCriterium),
+        unittest.makeSuite(TestTextCriterium),
+        unittest.makeSuite(TestSearchFilter),
+        ))
+
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')


Property changes on: z3c.searcher/trunk/src/z3c/searcher/tests.py
___________________________________________________________________
Name: svn:eol-style
   + native



More information about the Checkins mailing list