r347 - / python-hurry.query python-hurry.query/branches python-hurry.query/branches/upstream python-hurry.query/branches/upstream/current python-hurry.query/branches/upstream/current/src python-hurry.query/branches/upstream/current/src/hurry python-hurry.query/branches/upstream/current/src/hurry/query python-hurry.query/branches/upstream/current/src/hurry.query.egg-info

Brian Sutherland jinty-guest at costa.debian.org
Wed Oct 25 11:23:38 UTC 2006


Author: jinty-guest
Date: 2006-10-25 11:23:38 +0000 (Wed, 25 Oct 2006)
New Revision: 347

Added:
   python-hurry.query/
   python-hurry.query/branches/
   python-hurry.query/branches/upstream/
   python-hurry.query/branches/upstream/current/
   python-hurry.query/branches/upstream/current/CHANGES.txt
   python-hurry.query/branches/upstream/current/CREDITS.txt
   python-hurry.query/branches/upstream/current/INSTALL.txt
   python-hurry.query/branches/upstream/current/LICENSE.txt
   python-hurry.query/branches/upstream/current/PKG-INFO
   python-hurry.query/branches/upstream/current/README.txt
   python-hurry.query/branches/upstream/current/hurry.query-configure.zcml
   python-hurry.query/branches/upstream/current/setup.py
   python-hurry.query/branches/upstream/current/src/
   python-hurry.query/branches/upstream/current/src/hurry.query.egg-info/
   python-hurry.query/branches/upstream/current/src/hurry.query.egg-info/PKG-INFO
   python-hurry.query/branches/upstream/current/src/hurry.query.egg-info/SOURCES.txt
   python-hurry.query/branches/upstream/current/src/hurry.query.egg-info/namespace_packages.txt
   python-hurry.query/branches/upstream/current/src/hurry.query.egg-info/not-zip-safe
   python-hurry.query/branches/upstream/current/src/hurry.query.egg-info/top_level.txt
   python-hurry.query/branches/upstream/current/src/hurry/
   python-hurry.query/branches/upstream/current/src/hurry/__init__.py
   python-hurry.query/branches/upstream/current/src/hurry/query/
   python-hurry.query/branches/upstream/current/src/hurry/query/__init__.py
   python-hurry.query/branches/upstream/current/src/hurry/query/configure.zcml
   python-hurry.query/branches/upstream/current/src/hurry/query/interfaces.py
   python-hurry.query/branches/upstream/current/src/hurry/query/query.py
   python-hurry.query/branches/upstream/current/src/hurry/query/query.txt
   python-hurry.query/branches/upstream/current/src/hurry/query/set.py
   python-hurry.query/branches/upstream/current/src/hurry/query/tests.py
   python-hurry.query/branches/upstream/current/src/hurry/query/value.py
   python-hurry.query/branches/upstream/current/zc.catalog-configure.zcml
   python-hurry.query/tags/
Log:
[svn-inject] Installing original source of python-hurry.query

Added: python-hurry.query/branches/upstream/current/CHANGES.txt
===================================================================
--- python-hurry.query/branches/upstream/current/CHANGES.txt	                        (rev 0)
+++ python-hurry.query/branches/upstream/current/CHANGES.txt	2006-10-25 11:23:38 UTC (rev 347)
@@ -0,0 +1,14 @@
+hurry changes
+=============
+
+0.9 (2006-05-16)
+----------------
+
+* Separate hurry.query from the other hurry packages. Eggification work.
+
+* Support for ValueIndex from zc.catalog.
+
+0.8 (2006-05-01)
+----------------
+
+Initial public release.


Property changes on: python-hurry.query/branches/upstream/current/CHANGES.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: python-hurry.query/branches/upstream/current/CREDITS.txt
===================================================================
--- python-hurry.query/branches/upstream/current/CREDITS.txt	                        (rev 0)
+++ python-hurry.query/branches/upstream/current/CREDITS.txt	2006-10-25 11:23:38 UTC (rev 347)
@@ -0,0 +1,9 @@
+Credits
+-------
+
+Martijn Faassen - initial and main developer
+Stephan Richter - additional hurry.query index support
+Jan-Wijbrand Kolman - suggestions and feedback
+
+The hurry.query library for Zope 3 was originally developed at Infrae
+(http://www.infrae.com).


Property changes on: python-hurry.query/branches/upstream/current/CREDITS.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: python-hurry.query/branches/upstream/current/INSTALL.txt
===================================================================
--- python-hurry.query/branches/upstream/current/INSTALL.txt	                        (rev 0)
+++ python-hurry.query/branches/upstream/current/INSTALL.txt	2006-10-25 11:23:38 UTC (rev 347)
@@ -0,0 +1,14 @@
+Installation
+------------
+
+hurry.query needs Zope 3.1 or Zope 3.2. 
+
+Make sure hurry.query's src directory is on the Python path somehow,
+and then copy hurry.query-configure.zcml into your Zope's
+`etc/package-includes` directory.
+
+hurry.query also has support for zc.catalog SetIndexes in
+hurry.query.set. If you want to use this extension, you need to
+install zc.catalog. It can be found in Zope's SVN repository.  You
+then also need to copy `zc.catalog-configure.zcml` into your Zope's
+`etc/package-includes` directory.


Property changes on: python-hurry.query/branches/upstream/current/INSTALL.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: python-hurry.query/branches/upstream/current/LICENSE.txt
===================================================================
--- python-hurry.query/branches/upstream/current/LICENSE.txt	                        (rev 0)
+++ python-hurry.query/branches/upstream/current/LICENSE.txt	2006-10-25 11:23:38 UTC (rev 347)
@@ -0,0 +1,29 @@
+Copyright (c) 2005-2006 Infrae. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+
+  3. Neither the name of Infrae nor the names of its contributors may
+     be used to endorse or promote products derived from this software
+     without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS 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 INFRAE OR
+CONTRIBUTORS 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: python-hurry.query/branches/upstream/current/LICENSE.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: python-hurry.query/branches/upstream/current/PKG-INFO
===================================================================
--- python-hurry.query/branches/upstream/current/PKG-INFO	                        (rev 0)
+++ python-hurry.query/branches/upstream/current/PKG-INFO	2006-10-25 11:23:38 UTC (rev 347)
@@ -0,0 +1,13 @@
+Metadata-Version: 1.0
+Name: hurry.query
+Version: 0.9
+Summary: hurry.query is a higher level query system built on top of the Zope 3
+catalog. It makes it easy to perform catalog queries in Zope 3 code.
+
+Home-page: UNKNOWN
+Author: Infrae
+Author-email: faassen at infrae.com
+License: BSD
+Description: UNKNOWN
+Keywords: zope zope3
+Platform: UNKNOWN

Added: python-hurry.query/branches/upstream/current/README.txt
===================================================================
--- python-hurry.query/branches/upstream/current/README.txt	                        (rev 0)
+++ python-hurry.query/branches/upstream/current/README.txt	2006-10-25 11:23:38 UTC (rev 347)
@@ -0,0 +1,4 @@
+hurry.query - higher level query system built on top of the Zope 3
+              catalog. Some inspiration came from Dieter Maurer's
+              AdvancedQuery. See src/hurry/query/query.txt for
+              documentation.


Property changes on: python-hurry.query/branches/upstream/current/README.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: python-hurry.query/branches/upstream/current/hurry.query-configure.zcml
===================================================================
--- python-hurry.query/branches/upstream/current/hurry.query-configure.zcml	                        (rev 0)
+++ python-hurry.query/branches/upstream/current/hurry.query-configure.zcml	2006-10-25 11:23:38 UTC (rev 347)
@@ -0,0 +1,3 @@
+<!-- install this into your Zope 3 instance's etc/package-includes 
+     directory -->
+<include package="hurry.query"/>


Property changes on: python-hurry.query/branches/upstream/current/hurry.query-configure.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: python-hurry.query/branches/upstream/current/setup.py
===================================================================
--- python-hurry.query/branches/upstream/current/setup.py	                        (rev 0)
+++ python-hurry.query/branches/upstream/current/setup.py	2006-10-25 11:23:38 UTC (rev 347)
@@ -0,0 +1,24 @@
+from setuptools import setup, find_packages
+
+setup(
+    name="hurry.query",
+    version="0.9",
+    packages=find_packages('src', exclude=["*.tests", "*.ftests"]),
+    
+    package_dir= {'':'src'},
+    
+    namespace_packages=['hurry'],
+    package_data = {
+    '': ['*.txt', '*.zcml'],
+    },
+
+    zip_safe=False,
+    author='Infrae',
+    author_email='faassen at infrae.com',
+    description="""\
+hurry.query is a higher level query system built on top of the Zope 3
+catalog. It makes it easy to perform catalog queries in Zope 3 code.
+""",
+    license='BSD',
+    keywords="zope zope3",
+    )


Property changes on: python-hurry.query/branches/upstream/current/setup.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: python-hurry.query/branches/upstream/current/src/hurry/__init__.py
===================================================================
--- python-hurry.query/branches/upstream/current/src/hurry/__init__.py	                        (rev 0)
+++ python-hurry.query/branches/upstream/current/src/hurry/__init__.py	2006-10-25 11:23:38 UTC (rev 347)
@@ -0,0 +1,5 @@
+# this is a namespace package
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    pass


Property changes on: python-hurry.query/branches/upstream/current/src/hurry/__init__.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: python-hurry.query/branches/upstream/current/src/hurry/query/__init__.py
===================================================================
--- python-hurry.query/branches/upstream/current/src/hurry/query/__init__.py	                        (rev 0)
+++ python-hurry.query/branches/upstream/current/src/hurry/query/__init__.py	2006-10-25 11:23:38 UTC (rev 347)
@@ -0,0 +1 @@
+from query import And, Or, Eq, NotEq, Between, In, Ge, Le, Text


Property changes on: python-hurry.query/branches/upstream/current/src/hurry/query/__init__.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: python-hurry.query/branches/upstream/current/src/hurry/query/configure.zcml
===================================================================
--- python-hurry.query/branches/upstream/current/src/hurry/query/configure.zcml	                        (rev 0)
+++ python-hurry.query/branches/upstream/current/src/hurry/query/configure.zcml	2006-10-25 11:23:38 UTC (rev 347)
@@ -0,0 +1,9 @@
+<configure 
+  xmlns="http://namespaces.zope.org/zope">
+
+  <utility
+    provides=".interfaces.IQuery"
+    factory=".query.Query"
+    />
+
+</configure>


Property changes on: python-hurry.query/branches/upstream/current/src/hurry/query/configure.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: python-hurry.query/branches/upstream/current/src/hurry/query/interfaces.py
===================================================================
--- python-hurry.query/branches/upstream/current/src/hurry/query/interfaces.py	                        (rev 0)
+++ python-hurry.query/branches/upstream/current/src/hurry/query/interfaces.py	2006-10-25 11:23:38 UTC (rev 347)
@@ -0,0 +1,9 @@
+from zope.interface import Interface
+
+class IQuery(Interface):
+    def searchResults(query):
+        """Query indexes.
+
+        Argument is a query composed of terms.
+        """
+


Property changes on: python-hurry.query/branches/upstream/current/src/hurry/query/interfaces.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: python-hurry.query/branches/upstream/current/src/hurry/query/query.py
===================================================================
--- python-hurry.query/branches/upstream/current/src/hurry/query/query.py	                        (rev 0)
+++ python-hurry.query/branches/upstream/current/src/hurry/query/query.py	2006-10-25 11:23:38 UTC (rev 347)
@@ -0,0 +1,198 @@
+from zope.interface import implements
+
+from zope.app import zapi
+from zope.app.intid.interfaces import IIntIds
+from zope.app.catalog.catalog import ResultSet
+from zope.app.catalog.field import IFieldIndex
+from zope.app.catalog.text import ITextIndex
+from zope.app.catalog.interfaces import ICatalog
+
+from BTrees.IFBTree import weightedIntersection, union, difference, IFBTree
+
+from hurry.query import interfaces
+
+# XXX look into using multiunion for performance?
+
+class Query(object):
+    implements(interfaces.IQuery)
+
+    def searchResults(self, query):
+        results = query.apply()
+        if results is not None:
+            uidutil = zapi.getUtility(IIntIds)
+            results = ResultSet(results, uidutil)
+        return results
+
+class Term(object):
+    def __and__(self, other):
+        return And(self, other)
+
+    def __rand__(self, other):
+        return And(other, self)
+
+    def __or__(self, other):
+        return Or(self, other)
+
+    def __ror__(self, other):
+        return Or(other, self)
+
+    def __invert__(self):
+        return Not(self)
+
+class And(Term):
+    def __init__(self, *terms):
+        self.terms = terms
+
+    def apply(self):
+        results = []
+        for term in self.terms:
+            r = term.apply()
+            if not r:
+                # empty results
+                return r
+            results.append((len(r), r))
+
+        if not results:
+            # no applicable terms at all
+            # XXX should this be possible?
+            return IFBTree()
+
+        results.sort()
+
+        _, result = results.pop(0)
+        for _, r in results:
+            _, result = weightedIntersection(result, r)
+        return result
+
+class Or(Term):
+    def __init__(self, *terms):
+        self.terms = terms
+
+    def apply(self):
+        results = []
+        for term in self.terms:
+            r = term.apply()
+            # empty results
+            if not r:
+                continue
+            results.append(r)
+
+        if not results:
+            # no applicable terms at all
+            # XXX should this be possible?
+            return IFBTree()
+
+        result = results.pop(0)
+        for r in results:
+            result = union(result, r)
+        return result
+
+class Not(Term):
+    def __init__(self, term):
+        self.term = term
+
+    def apply(self):
+        return difference(self._all(), self.term.apply())
+
+    def _all(self):
+        # XXX may not work well/be efficient with extentcatalog
+        # XXX not very efficient in general, better to use internal
+        # IntIds datastructure but that would break abstraction..
+        intids = zapi.getUtility(IIntIds)
+        result = IFBTree()
+        for uid in intids:
+            result.insert(uid, 0)
+        return result
+
+class IndexTerm(Term):
+    def __init__(self, (catalog_name, index_name)):
+        self.catalog_name = catalog_name
+        self.index_name = index_name
+
+    def getIndex(self):
+        catalog = zapi.getUtility(ICatalog, self.catalog_name)
+        index = catalog[self.index_name]
+        return index
+
+class Text(IndexTerm):
+    def __init__(self, index_id, text):
+        super(Text, self).__init__(index_id)
+        self.text = text
+
+    def getIndex(self):
+        index = super(Text, self).getIndex()
+        assert ITextIndex.providedBy(index)
+        return index
+
+    def apply(self):
+        index = self.getIndex()
+        return index.apply(self.text)
+
+class FieldTerm(IndexTerm):
+    def getIndex(self):
+        index = super(FieldTerm, self).getIndex()
+        assert IFieldIndex.providedBy(index)
+        return index
+
+class Eq(FieldTerm):
+    def __init__(self, index_id, value):
+        assert value is not None
+        super(Eq, self).__init__(index_id)
+        self.value = value
+
+    def apply(self):
+        return self.getIndex().apply((self.value, self.value))
+
+class NotEq(FieldTerm):
+    def __init__(self, index_id, not_value):
+        super(NotEq, self).__init__(index_id)
+        self.not_value = not_value
+
+    def apply(self):
+        index = self.getIndex()
+        all = index.apply((None, None))
+        r = index.apply((self.not_value, self.not_value))
+        return difference(all, r)
+
+class Between(FieldTerm):
+    def __init__(self, index_id, min_value, max_value):
+        super(Between, self).__init__(index_id)
+        self.min_value = min_value
+        self.max_value = max_value
+
+    def apply(self):
+        return self.getIndex().apply((self.min_value, self.max_value))
+
+class Ge(Between):
+    def __init__(self, index_id, min_value):
+        super(Ge, self).__init__(index_id, min_value, None)
+
+class Le(Between):
+    def __init__(self, index_id, max_value):
+        super(Le, self).__init__(index_id, None, max_value)
+
+class In(FieldTerm):
+    def __init__(self, index_id, values):
+        assert None not in values
+        super(In, self).__init__(index_id)
+        self.values = values
+
+    def apply(self):
+        results = []
+        index = self.getIndex()
+        for value in self.values:
+            r = index.apply((value, value))
+            # empty results
+            if not r:
+                continue
+            results.append(r)
+
+        if not results:
+            # no applicable terms at all
+            return IFBTree()
+
+        result = results.pop(0)
+        for r in results:
+            result = union(result, r)
+        return result
+


Property changes on: python-hurry.query/branches/upstream/current/src/hurry/query/query.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: python-hurry.query/branches/upstream/current/src/hurry/query/query.txt
===================================================================
--- python-hurry.query/branches/upstream/current/src/hurry/query/query.txt	                        (rev 0)
+++ python-hurry.query/branches/upstream/current/src/hurry/query/query.txt	2006-10-25 11:23:38 UTC (rev 347)
@@ -0,0 +1,394 @@
+Hurry Query
+===========
+
+The hurry query system for the Zope 3 catalog builds on catalog
+indexes as defined in Zope 3 core, as well as the indexes in
+zc.catalog. It is in part inspired by AdvancedQuery for Zope 2 by
+Dieter Maurer, though has an independent origin.
+
+Setup
+-----
+
+Let's define a simple content object. First its interface::
+
+  >>> from zope.interface import Interface, Attribute, implements
+  >>> class IContent(Interface):
+  ...     f1 = Attribute('f1')
+  ...     f2 = Attribute('f2')
+  ...     f3 = Attribute('f3')
+  ...     f4 = Attribute('f4')
+  ...     t1 = Attribute('t1')
+  ...     t2 = Attribute('t2')
+
+And its implementation::
+
+  >>> from zope.app.container.contained import Contained
+  >>> class Content(Contained):
+  ...     implements(IContent)
+  ...     def __init__(self, id, f1='', f2='', f3='', f4='', t1='', t2=''):
+  ...         self.id = id
+  ...         self.f1 = f1
+  ...         self.f2 = f2
+  ...         self.f3 = f3
+  ...         self.f4 = f4
+  ...         self.t1 = t1
+  ...         self.t2 = t2
+  ...     def __cmp__(self, other):
+  ...         return cmp(self.id, other.id)
+
+The id attribute is just so we can identify objects we find again
+easily. By including the __cmp__ method we make sure search results
+can be stably sorted.
+
+We use a fake int id utility here so we can test independent of
+the full-blown zope environment::
+
+  >>> from zope.interface import verify
+  >>> from zope import interface
+  >>> import zope.app.intid.interfaces
+  >>> from zope.app.testing import ztapi
+  >>> class DummyIntId(object):
+  ...     interface.implements(zope.app.intid.interfaces.IIntIds)
+  ...     MARKER = '__dummy_int_id__'
+  ...     def __init__(self):
+  ...         self.counter = 0
+  ...         self.data = {}
+  ...     def register(self, obj):
+  ...         intid = getattr(obj, self.MARKER, None)
+  ...         if intid is None:
+  ...             setattr(obj, self.MARKER, self.counter)
+  ...             self.data[self.counter] = obj
+  ...             intid = self.counter
+  ...             self.counter += 1
+  ...         return intid
+  ...     def getObject(self, intid):
+  ...         return self.data[intid]
+  ...     def __iter__(self):
+  ...         return iter(self.data)
+  >>> intid = DummyIntId()
+  >>> ztapi.provideUtility(
+  ...     zope.app.intid.interfaces.IIntIds, intid)
+
+Now let's register a catalog::
+
+  >>> from zope.app.catalog.interfaces import ICatalog
+  >>> from zope.app.catalog.catalog import Catalog
+  >>> catalog = Catalog()
+  >>> ztapi.provideUtility(ICatalog, catalog, 'catalog1')
+
+And set it up with various indexes::
+
+  >>> from zope.app.catalog.field import FieldIndex
+  >>> from zope.app.catalog.text import TextIndex
+  >>> catalog['f1'] = FieldIndex('f1', IContent)
+  >>> catalog['f2'] = FieldIndex('f2', IContent)
+  >>> catalog['f3'] = FieldIndex('f3', IContent)
+  >>> catalog['f4'] = FieldIndex('f4', IContent)
+  >>> catalog['t1'] = TextIndex('t1', IContent)
+  >>> catalog['t2'] = TextIndex('t2', IContent)
+
+Now let's create some objects so that they'll be cataloged::
+
+  >>> content = [
+  ... Content(1, 'a', 'b', 'd'),
+  ... Content(2, 'a', 'c'),
+  ... Content(3, 'X', 'c'),
+  ... Content(4, 'a', 'b', 'e'),
+  ... Content(5, 'X', 'b', 'e'),
+  ... Content(6, 'Y', 'Z')]
+
+And catalog them now::
+
+  >>> for entry in content:
+  ...     catalog.index_doc(intid.register(entry), entry)
+
+Now let's register a query utility::
+
+  >>> from hurry.query.query import Query
+  >>> from hurry.query.interfaces import IQuery
+  >>> ztapi.provideUtility(IQuery, Query())
+
+Set up some code to make querying and display the result
+easy::
+
+  >>> from zope.app import zapi
+  >>> from hurry.query.interfaces import IQuery
+  >>> def displayQuery(q):
+  ...     query = zapi.getUtility(IQuery)
+  ...     r = query.searchResults(q)
+  ...     return [e.id for e in sorted(list(r))]
+
+FieldIndex Queries
+------------------
+
+Now for a query where f1 equals a::
+
+  >>> from hurry.query import Eq
+  >>> f1 = ('catalog1', 'f1')
+  >>> displayQuery(Eq(f1, 'a'))
+  [1, 2, 4]
+
+Not equals (this is more efficient than the generic ~ operator)::
+
+  >>> from hurry.query import NotEq
+  >>> displayQuery(NotEq(f1, 'a'))
+  [3, 5, 6]
+
+Testing whether a field is in a set::
+
+  >>> from hurry.query import In
+  >>> displayQuery(In(f1, ['a', 'X']))
+  [1, 2, 3, 4, 5]
+
+Whether documents are in a specified range::
+
+  >>> from hurry.query import Between
+  >>> displayQuery(Between(f1, 'X', 'Y'))
+  [3, 5, 6]
+
+You can leave out one end of the range::
+
+  >>> displayQuery(Between(f1, 'X', None)) # 'X' < 'a'
+  [1, 2, 3, 4, 5, 6]
+  >>> displayQuery(Between(f1, None, 'X'))
+  [3, 5]
+
+You can also use greater-equals and lesser-equals for the same purpose::
+
+  >>> from hurry.query import Ge, Le
+  >>> displayQuery(Ge(f1, 'X'))
+  [1, 2, 3, 4, 5, 6]
+  >>> displayQuery(Le(f1, 'X'))
+  [3, 5]
+
+It's also possible to use not with the ~ operator::
+
+  >>> displayQuery(~Eq(f1, 'a'))
+  [3, 5, 6]
+
+Using and (&)::
+
+  >>> f2 = ('catalog1', 'f2')
+  >>> displayQuery(Eq(f1, 'a') & Eq(f2, 'b'))
+  [1, 4]
+
+Using or (|)::
+
+  >>> displayQuery(Eq(f1, 'a') | Eq(f2, 'b'))
+  [1, 2, 4, 5]
+
+These can be chained::
+
+  >>> displayQuery(Eq(f1, 'a') & Eq(f2, 'b') & Between(f1, 'a', 'b'))
+  [1, 4]
+  >>> displayQuery(Eq(f1, 'a') | Eq(f1, 'X') | Eq(f2, 'b'))
+  [1, 2, 3, 4, 5]
+
+And nested::
+
+  >>> displayQuery((Eq(f1, 'a') | Eq(f1, 'X')) & (Eq(f2, 'b') | Eq(f2, 'c')))
+  [1, 2, 3, 4, 5]
+
+"and" and "or" can also be spelled differently::
+
+  >>> from hurry.query import And, Or
+  >>> displayQuery(And(Eq(f1, 'a'), Eq(f2, 'b')))
+  [1, 4]
+  >>> displayQuery(Or(Eq(f1, 'a'), Eq(f2, 'b')))
+  [1, 2, 4, 5]
+
+Combination of In and &
+-----------------------
+
+A combination of 'In' and '&'::
+
+  >>> displayQuery(In(f1, ['a', 'X', 'Y', 'Z']))
+  [1, 2, 3, 4, 5, 6]
+  >>> displayQuery(In(f1, ['Z']))
+  []
+  >>> displayQuery(In(f1, ['a', 'X', 'Y', 'Z']) & In(f1, ['Z']))
+  []
+
+
+SetIndex queries
+----------------
+
+The SetIndex is defined in zc.catalog. Let's make a catalog which uses
+it::
+
+  >>> intid = DummyIntId()
+  >>> ztapi.provideUtility(
+  ...     zope.app.intid.interfaces.IIntIds, intid)
+  >>> from zope.app.catalog.interfaces import ICatalog
+  >>> from zope.app.catalog.catalog import Catalog
+  >>> catalog = Catalog()
+  >>> ztapi.provideUtility(ICatalog, catalog, 'catalog1')
+  >>> from zc.catalog.catalogindex import SetIndex
+  >>> catalog['f1'] = SetIndex('f1', IContent)
+  >>> catalog['f2'] = FieldIndex('f2', IContent)
+
+First let's set up some new data::
+
+  >>> content = [
+  ... Content(1, ['a', 'b', 'c'], 1),
+  ... Content(2, ['a'], 1),
+  ... Content(3, ['b'], 1),
+  ... Content(4, ['c', 'd'], 2),
+  ... Content(5, ['b', 'c'], 2),
+  ... Content(6, ['a', 'c'], 2)]
+
+And catalog them now::
+
+  >>> for entry in content:
+  ...     catalog.index_doc(intid.register(entry), entry)
+
+Now do a a 'any of' query, which returns all documents that
+contain any of the values listed::
+
+  >>> from hurry.query.set import AnyOf
+  >>> displayQuery(AnyOf(f1, ['a', 'c']))
+  [1, 2, 4, 5, 6]
+  >>> displayQuery(AnyOf(f1, ['c', 'b']))
+  [1, 3, 4, 5, 6]
+  >>> displayQuery(AnyOf(f1, ['a']))
+  [1, 2, 6]
+
+Do a 'all of' query, which returns all documents that
+contain all of the values listed::
+
+  >>> from hurry.query.set import AllOf
+  >>> displayQuery(AllOf(f1, ['a']))
+  [1, 2, 6]
+  >>> displayQuery(AllOf(f1, ['a', 'b']))
+  [1]
+  >>> displayQuery(AllOf(f1, ['a', 'c']))
+  [1, 6]
+
+We can combine this with other queries::
+
+  >>> displayQuery(AnyOf(f1, ['a']) & Eq(f2, 1))
+  [1, 2]
+
+
+ValueIndex queries
+------------------
+
+The ``ValueIndex`` is defined in ``zc.catalog`` and provides a generalization
+of the standard field index.
+
+  >>> from hurry.query import value
+
+Let's set up a catalog that uses this index. The ``ValueIndex`` is defined in
+``zc.catalog``. Let's make a catalog which uses it:
+
+  >>> intid = DummyIntId()
+  >>> ztapi.provideUtility(zope.app.intid.interfaces.IIntIds, intid)
+
+  >>> from zope.app.catalog.interfaces import ICatalog
+  >>> from zope.app.catalog.catalog import Catalog
+  >>> catalog = Catalog()
+  >>> ztapi.provideUtility(ICatalog, catalog, 'catalog1')
+
+  >>> from zc.catalog.catalogindex import ValueIndex
+  >>> catalog['f1'] = ValueIndex('f1', IContent)
+
+Next we set up some content data to fill the indices:
+
+  >>> content = [
+  ... Content(1, 'a'),
+  ... Content(2, 'b'),
+  ... Content(3, 'c'),
+  ... Content(4, 'd'),
+  ... Content(5, 'c'),
+  ... Content(6, 'a')]
+
+And catalog them now:
+
+  >>> for entry in content:
+  ...     catalog.index_doc(intid.register(entry), entry)
+
+
+Let's now query for all objects where ``f1`` equals 'a':
+
+  >>> f1 = ('catalog1', 'f1')
+  >>> displayQuery(value.Eq(f1, 'a'))
+  [1, 6]
+
+Next, let's find all objects where ``f1`` does not equal 'a'; this is more
+efficient than the generic ``~`` operator:
+
+  >>> displayQuery(value.NotEq(f1, 'a'))
+  [2, 3, 4, 5]
+
+You can also query for all objects where the value of ``f1`` is in a set of
+values:
+
+  >>> displayQuery(value.In(f1, ['a', 'd']))
+  [1, 4, 6]
+
+The next interesting set of queries allows you to make evaluations of the
+values. For example, you can ask for all objects between a certain set of
+values:
+
+  >>> displayQuery(value.Between(f1, 'a', 'c'))
+  [1, 2, 3, 5, 6]
+
+  >>> displayQuery(value.Between(f1, 'a', 'c', exclude_min=True))
+  [2, 3, 5]
+
+  >>> displayQuery(value.Between(f1, 'a', 'c', exclude_max=True))
+  [1, 2, 6]
+
+  >>> displayQuery(value.Between(f1, 'a', 'c',
+  ...                            exclude_min=True, exclude_max=True))
+  [2]
+
+You can also leave out one end of the range:
+
+  >>> displayQuery(value.Between(f1, 'c', None))
+  [3, 4, 5]
+  >>> displayQuery(value.Between(f1, None, 'c'))
+  [1, 2, 3, 5, 6]
+
+You can also use greater-equals and lesser-equals for the same purpose:
+
+  >>> displayQuery(value.Ge(f1, 'c'))
+  [3, 4, 5]
+  >>> displayQuery(value.Le(f1, 'c'))
+  [1, 2, 3, 5, 6]
+
+Of course, you can chain those queries with the others as demonstrated before.
+
+The ``value`` module also supports ``zc.catalog`` extents. The first query is
+``ExtentAny``, which returns all douments matching the extent. If the the
+extent is ``None``, all document ids are returned:
+
+  >>> displayQuery(value.ExtentAny(f1, None))
+  [1, 2, 3, 4, 5, 6]
+
+If we now create an extent that is only in the scope of the first four
+documents,
+
+  >>> from zc.catalog.extentcatalog import FilterExtent
+  >>> extent = FilterExtent(lambda extent, uid, obj: True)
+  >>> for i in range(4):
+  ...     extent.add(i, i)
+
+then only the first four are returned:
+
+  >>> displayQuery(value.ExtentAny(f1, extent))
+  [1, 2, 3, 4]
+
+The opposite query is the ``ExtentNone`` query, which returns all ids in the
+extent that are *not* in the index:
+
+  >>> id = intid.register(Content(7, 'b'))
+  >>> id = intid.register(Content(8, 'c'))
+  >>> id = intid.register(Content(9, 'a'))
+
+  >>> extent = FilterExtent(lambda extent, uid, obj: True)
+  >>> for i in range(9):
+  ...     extent.add(i, i)
+
+  >>> displayQuery(value.ExtentNone(f1, extent))
+  [7, 8, 9]


Property changes on: python-hurry.query/branches/upstream/current/src/hurry/query/query.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: python-hurry.query/branches/upstream/current/src/hurry/query/set.py
===================================================================
--- python-hurry.query/branches/upstream/current/src/hurry/query/set.py	                        (rev 0)
+++ python-hurry.query/branches/upstream/current/src/hurry/query/set.py	2006-10-25 11:23:38 UTC (rev 347)
@@ -0,0 +1,54 @@
+from zc.catalog.interfaces import ISetIndex
+from hurry.query import query
+
+class SetTerm(query.IndexTerm):
+    def getIndex(self):
+        index = super(SetTerm, self).getIndex()
+        assert ISetIndex.providedBy(index)
+        return index
+
+class AnyOf(SetTerm):
+    def __init__(self, index_id, values):
+        super(AnyOf, self).__init__(index_id)
+        self.values = values
+
+    def apply(self):
+        return self.getIndex().apply({'any_of': self.values})
+
+class AllOf(SetTerm):
+    def __init__(self, index_id, values):
+        super(AllOf, self).__init__(index_id)
+        self.values = values
+
+    def apply(self):
+        return self.getIndex().apply({'all_of': self.values})
+
+class SetBetween(SetTerm):
+    def __init__(self, index_id,
+                 minimum=None, maximum=None,
+                 include_minimum=False, include_maximum=False):
+        super(SetBetween, self).__init__(index_id)
+        self.tuple = (minimum, maximum, include_minimum, include_maximum)
+
+    def apply(self):
+        return self.getIndex().apply({'between': self.tuple})
+
+class ExtentAny(SetTerm):
+    """Any ids in the extent that are indexed by this index.
+    """
+    def __init__(self, index_id, extent):
+        super(Any, self).__init__(index_id)
+        self.extent = extent
+
+    def apply(self):
+        return self.getIndex().apply({'any': self.extent})
+
+class ExtentNone(SetTerm):
+    """Any ids in the extent that are not indexed by this index.
+    """
+    def __init__(self, extent):
+        super(None, self).__init__(index_id)
+        self.extent = extent
+
+    def apply(self):
+        return self.getIndex().apply({'none': self.extent})


Property changes on: python-hurry.query/branches/upstream/current/src/hurry/query/set.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: python-hurry.query/branches/upstream/current/src/hurry/query/tests.py
===================================================================
--- python-hurry.query/branches/upstream/current/src/hurry/query/tests.py	                        (rev 0)
+++ python-hurry.query/branches/upstream/current/src/hurry/query/tests.py	2006-10-25 11:23:38 UTC (rev 347)
@@ -0,0 +1,10 @@
+import unittest
+from zope.testing import doctest
+
+def test_suite():
+    return unittest.TestSuite((
+        doctest.DocFileSuite('query.txt'),
+        ))
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')


Property changes on: python-hurry.query/branches/upstream/current/src/hurry/query/tests.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: python-hurry.query/branches/upstream/current/src/hurry/query/value.py
===================================================================
--- python-hurry.query/branches/upstream/current/src/hurry/query/value.py	                        (rev 0)
+++ python-hurry.query/branches/upstream/current/src/hurry/query/value.py	2006-10-25 11:23:38 UTC (rev 347)
@@ -0,0 +1,79 @@
+from zc.catalog.interfaces import IValueIndex
+from hurry.query import query
+
+class ValueTerm(query.IndexTerm):
+    def getIndex(self):
+        index = super(ValueTerm, self).getIndex()
+        assert IValueIndex.providedBy(index)
+        return index
+
+class Eq(ValueTerm):
+    def __init__(self, index_id, value):
+        assert value is not None
+        super(Eq, self).__init__(index_id)
+        self.value = value
+
+    def apply(self):
+        return self.getIndex().apply({'any_of': (self.value,)})
+
+class NotEq(ValueTerm):
+    def __init__(self, index_id, not_value):
+        super(NotEq, self).__init__(index_id)
+        self.not_value = not_value
+
+    def apply(self):
+        index = self.getIndex()
+        values = list(index.values())
+        values.remove(self.not_value)
+        return index.apply({'any_of': values})
+
+class Between(ValueTerm):
+    def __init__(self, index_id, min_value=None, max_value=None,
+                 exclude_min=False, exclude_max=False):
+        super(Between, self).__init__(index_id)
+        self.min_value = min_value
+        self.max_value = max_value
+        self.exclude_min = exclude_min
+        self.exclude_max = exclude_max
+
+    def apply(self):
+        return self.getIndex().apply(
+            {'between': (self.min_value, self.max_value,
+                         self.exclude_min, self.exclude_max)})
+
+class Ge(Between):
+    def __init__(self, index_id, min_value):
+        super(Ge, self).__init__(index_id, min_value=min_value)
+
+class Le(Between):
+    def __init__(self, index_id, max_value):
+        super(Le, self).__init__(index_id, max_value=max_value)
+
+class In(ValueTerm):
+    def __init__(self, index_id, values):
+        assert None not in values
+        super(In, self).__init__(index_id)
+        self.values = values
+
+    def apply(self):
+        return self.getIndex().apply({'any_of': self.values})
+
+class ExtentAny(ValueTerm):
+    """Any ids in the extent that are indexed by this index.
+    """
+    def __init__(self, index_id, extent):
+        super(ExtentAny, self).__init__(index_id)
+        self.extent = extent
+
+    def apply(self):
+        return self.getIndex().apply({'any': self.extent})
+
+class ExtentNone(ValueTerm):
+    """Any ids in the extent that are not indexed by this index.
+    """
+    def __init__(self, index_id, extent):
+        super(ExtentNone, self).__init__(index_id)
+        self.extent = extent
+
+    def apply(self):
+        return self.getIndex().apply({'none': self.extent})


Property changes on: python-hurry.query/branches/upstream/current/src/hurry/query/value.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: python-hurry.query/branches/upstream/current/src/hurry.query.egg-info/PKG-INFO
===================================================================
--- python-hurry.query/branches/upstream/current/src/hurry.query.egg-info/PKG-INFO	                        (rev 0)
+++ python-hurry.query/branches/upstream/current/src/hurry.query.egg-info/PKG-INFO	2006-10-25 11:23:38 UTC (rev 347)
@@ -0,0 +1,13 @@
+Metadata-Version: 1.0
+Name: hurry.query
+Version: 0.9
+Summary: hurry.query is a higher level query system built on top of the Zope 3
+catalog. It makes it easy to perform catalog queries in Zope 3 code.
+
+Home-page: UNKNOWN
+Author: Infrae
+Author-email: faassen at infrae.com
+License: BSD
+Description: UNKNOWN
+Keywords: zope zope3
+Platform: UNKNOWN

Added: python-hurry.query/branches/upstream/current/src/hurry.query.egg-info/SOURCES.txt
===================================================================
--- python-hurry.query/branches/upstream/current/src/hurry.query.egg-info/SOURCES.txt	                        (rev 0)
+++ python-hurry.query/branches/upstream/current/src/hurry.query.egg-info/SOURCES.txt	2006-10-25 11:23:38 UTC (rev 347)
@@ -0,0 +1,22 @@
+CHANGES.txt
+CREDITS.txt
+INSTALL.txt
+LICENSE.txt
+README.txt
+hurry.query-configure.zcml
+setup.py
+zc.catalog-configure.zcml
+src/hurry/__init__.py
+src/hurry.query.egg-info/PKG-INFO
+src/hurry.query.egg-info/SOURCES.txt
+src/hurry.query.egg-info/namespace_packages.txt
+src/hurry.query.egg-info/not-zip-safe
+src/hurry.query.egg-info/top_level.txt
+src/hurry/query/__init__.py
+src/hurry/query/configure.zcml
+src/hurry/query/interfaces.py
+src/hurry/query/query.py
+src/hurry/query/query.txt
+src/hurry/query/set.py
+src/hurry/query/tests.py
+src/hurry/query/value.py


Property changes on: python-hurry.query/branches/upstream/current/src/hurry.query.egg-info/SOURCES.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: python-hurry.query/branches/upstream/current/src/hurry.query.egg-info/namespace_packages.txt
===================================================================
--- python-hurry.query/branches/upstream/current/src/hurry.query.egg-info/namespace_packages.txt	                        (rev 0)
+++ python-hurry.query/branches/upstream/current/src/hurry.query.egg-info/namespace_packages.txt	2006-10-25 11:23:38 UTC (rev 347)
@@ -0,0 +1 @@
+hurry


Property changes on: python-hurry.query/branches/upstream/current/src/hurry.query.egg-info/namespace_packages.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: python-hurry.query/branches/upstream/current/src/hurry.query.egg-info/not-zip-safe
===================================================================

Added: python-hurry.query/branches/upstream/current/src/hurry.query.egg-info/top_level.txt
===================================================================
--- python-hurry.query/branches/upstream/current/src/hurry.query.egg-info/top_level.txt	                        (rev 0)
+++ python-hurry.query/branches/upstream/current/src/hurry.query.egg-info/top_level.txt	2006-10-25 11:23:38 UTC (rev 347)
@@ -0,0 +1 @@
+hurry


Property changes on: python-hurry.query/branches/upstream/current/src/hurry.query.egg-info/top_level.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: python-hurry.query/branches/upstream/current/zc.catalog-configure.zcml
===================================================================
--- python-hurry.query/branches/upstream/current/zc.catalog-configure.zcml	                        (rev 0)
+++ python-hurry.query/branches/upstream/current/zc.catalog-configure.zcml	2006-10-25 11:23:38 UTC (rev 347)
@@ -0,0 +1,5 @@
+<!-- install this into your Zope 3 instance's etc/package-includes 
+     directory. You need zc.catalog installed in your Zope 3 installation.
+     Right now you can get it from Zope 3 svn in Sandbox/zc/catalog/)
+--> 
+<include package="zc.catalog"/>


Property changes on: python-hurry.query/branches/upstream/current/zc.catalog-configure.zcml
___________________________________________________________________
Name: svn:eol-style
   + native




More information about the pkg-zope-commits mailing list