[Checkins] SVN: z3c.multifieldindex/trunk/ Initial import.
Dan Korostelev
nadako at gmail.com
Thu Oct 15 11:57:42 EDT 2009
Log message for revision 105085:
Initial import.
Changed:
_U z3c.multifieldindex/trunk/
A z3c.multifieldindex/trunk/CHANGES.txt
A z3c.multifieldindex/trunk/bootstrap.py
A z3c.multifieldindex/trunk/buildout.cfg
A z3c.multifieldindex/trunk/setup.py
A z3c.multifieldindex/trunk/src/
A z3c.multifieldindex/trunk/src/z3c/
A z3c.multifieldindex/trunk/src/z3c/__init__.py
A z3c.multifieldindex/trunk/src/z3c/multifieldindex/
A z3c.multifieldindex/trunk/src/z3c/multifieldindex/README.txt
A z3c.multifieldindex/trunk/src/z3c/multifieldindex/__init__.py
A z3c.multifieldindex/trunk/src/z3c/multifieldindex/configure.zcml
A z3c.multifieldindex/trunk/src/z3c/multifieldindex/index.py
A z3c.multifieldindex/trunk/src/z3c/multifieldindex/interfaces.py
A z3c.multifieldindex/trunk/src/z3c/multifieldindex/subindex.py
A z3c.multifieldindex/trunk/src/z3c/multifieldindex/tests.py
-=-
Property changes on: z3c.multifieldindex/trunk
___________________________________________________________________
Added: svn:ignore
+ bin
parts
eggs
develop-eggs
.installed.cfg
coverage
Added: z3c.multifieldindex/trunk/CHANGES.txt
===================================================================
--- z3c.multifieldindex/trunk/CHANGES.txt (rev 0)
+++ z3c.multifieldindex/trunk/CHANGES.txt 2009-10-15 15:57:42 UTC (rev 105085)
@@ -0,0 +1,8 @@
+=======
+CHANGES
+=======
+
+3.4.0 (unreleased)
+------------------
+
+- Initial release (using Zope 3.4 dependencies).
Added: z3c.multifieldindex/trunk/bootstrap.py
===================================================================
--- z3c.multifieldindex/trunk/bootstrap.py (rev 0)
+++ z3c.multifieldindex/trunk/bootstrap.py 2009-10-15 15:57:42 UTC (rev 105085)
@@ -0,0 +1,69 @@
+##############################################################################
+#
+# Copyright (c) 2006 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$
+"""
+
+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
+
+is_jython = sys.platform.startswith('java')
+
+if is_jython:
+ import subprocess
+
+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
+
+if is_jython:
+ assert subprocess.Popen(
+ [sys.executable] + ['-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout'],
+ env = dict(os.environ,
+ PYTHONPATH =
+ ws.find(pkg_resources.Requirement.parse('setuptools')).location
+ ),
+ ).wait() == 0
+
+else:
+ 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.multifieldindex/trunk/bootstrap.py
___________________________________________________________________
Added: svn:keywords
+ Id
Added: z3c.multifieldindex/trunk/buildout.cfg
===================================================================
--- z3c.multifieldindex/trunk/buildout.cfg (rev 0)
+++ z3c.multifieldindex/trunk/buildout.cfg 2009-10-15 15:57:42 UTC (rev 105085)
@@ -0,0 +1,27 @@
+[buildout]
+develop = .
+parts = test coverage-test coverage-report pydev python
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = z3c.multifieldindex [test]
+
+[coverage-test]
+recipe = zc.recipe.testrunner
+eggs = z3c.multifieldindex [test]
+defaults = ['--coverage', '../../coverage']
+
+[coverage-report]
+recipe = zc.recipe.egg
+eggs = z3c.coverage
+scripts = coverage=coverage-report
+arguments = ('coverage', 'coverage/report')
+
+[pydev]
+recipe = pb.recipes.pydev
+eggs = z3c.multifieldindex [test]
+
+[python]
+recipe = zc.recipe.egg
+eggs = z3c.multifieldindex
+interpreter = python
Added: z3c.multifieldindex/trunk/setup.py
===================================================================
--- z3c.multifieldindex/trunk/setup.py (rev 0)
+++ z3c.multifieldindex/trunk/setup.py 2009-10-15 15:57:42 UTC (rev 105085)
@@ -0,0 +1,58 @@
+##############################################################################
+#
+# Copyright (c) 2009 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 for z3c.multifieldindex package
+
+$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.multifieldindex',
+ version='3.4.0dev',
+ url='http://pypi.python.org/pypi/z3c.multifieldindex',
+ license='ZPL 2.1',
+ description='Multi-field index for zope catalog',
+ author='Dan Korostelev and Zope Community',
+ author_email='zope-dev at zope.org',
+ long_description=\
+ read('src', 'z3c', 'multifieldindex', 'README.txt') + \
+ '\n\n' + \
+ read('CHANGES.txt'),
+ packages=find_packages('src'),
+ package_dir={'': 'src'},
+ namespace_packages=['z3c'],
+ install_requires=[
+ 'setuptools',
+ 'zc.catalog',
+ 'ZODB3',
+ 'zope.app.catalog',
+ 'zope.app.container',
+ 'zope.component',
+ 'zope.index',
+ 'zope.interface',
+ 'zope.schema',
+ ],
+ extras_require = dict(
+ test=[
+ 'zope.testing',
+ ],
+ ),
+ include_package_data=True,
+ zip_safe=False,
+ )
Property changes on: z3c.multifieldindex/trunk/setup.py
___________________________________________________________________
Added: svn:keywords
+ Id
Property changes on: z3c.multifieldindex/trunk/src
___________________________________________________________________
Added: svn:ignore
+ *.egg-info
Added: z3c.multifieldindex/trunk/src/z3c/__init__.py
===================================================================
--- z3c.multifieldindex/trunk/src/z3c/__init__.py (rev 0)
+++ z3c.multifieldindex/trunk/src/z3c/__init__.py 2009-10-15 15:57:42 UTC (rev 105085)
@@ -0,0 +1 @@
+__import__('pkg_resources').declare_namespace(__name__)
\ No newline at end of file
Property changes on: z3c.multifieldindex/trunk/src/z3c/__init__.py
___________________________________________________________________
Added: svn:keywords
+ Id
Added: z3c.multifieldindex/trunk/src/z3c/multifieldindex/README.txt
===================================================================
--- z3c.multifieldindex/trunk/src/z3c/multifieldindex/README.txt (rev 0)
+++ z3c.multifieldindex/trunk/src/z3c/multifieldindex/README.txt 2009-10-15 15:57:42 UTC (rev 105085)
@@ -0,0 +1,124 @@
+===================
+z3c.multifieldindex
+===================
+
+This package provides an index for zope catalog that can index multiple fields.
+It is useful in cases when field set are dynamic (for example with customizable
+persistent fields).
+
+Actually, this package provides a base class for custom multi-field indexes and
+to make it work, you need to override some methods in it. But first, let's
+create a content schema and interface we will use:
+
+ >>> from zope.interface import Interface, implements
+ >>> from zope.schema import Text, Int, List, TextLine
+
+ >>> class IPerson(Interface):
+ ...
+ ... age = Int()
+ ... info = Text()
+ ... skills = List(value_type=TextLine())
+
+ >>> class Person(object):
+ ...
+ ... implements(IPerson)
+ ...
+ ... def __init__(self, age, info, skills):
+ ... self.age = age
+ ... self.info = info
+ ... self.skills = skills
+
+Let's create a set of person objects:
+
+ >>> dataset = [
+ ... (1, Person(20, u'Sweet and cute', ['dancing', 'singing'])),
+ ... (2, Person(33, u'Smart and sweet', ['math', 'dancing'])),
+ ... (3, Person(6, u'Young and cute', ['singing', 'painting'])),
+ ... ]
+
+We have choose exactly those different types of fields to illustrate that the
+index is smart enough to know how to index each type of value. We'll return
+back to this topic later in this document.
+
+Now, we need to create an multi-field index class that will be used to index our
+person objects. We'll override two methods in it to make it functional:
+
+ >>> from z3c.multifieldindex.index import MultiFieldIndexBase
+ >>> from zope.schema import getFields
+
+ >>> class PersonIndex(MultiFieldIndexBase):
+ ...
+ ... def _fields(self):
+ ... return getFields(IPerson).items()
+ ...
+ ... def _getData(self, object):
+ ... return {
+ ... 'age': object.age,
+ ... 'info': object.info,
+ ... 'skills': object.skills,
+ ... }
+
+The "_fields" method should return an iterable of (name, field) pairs of fields
+that should be indexed. The sub-indexes will be created for those fields.
+
+The "_getData" method returns a dictionary of data to be indexed using given
+object. The keys of the dictionary should match field names.
+
+Sub-indexes are created automatically by looking up an index factory for each
+field. Three most-used factories are provided by this package. Let's register
+them to continue (it's also done in this package's configure.zcml file):
+
+ >>> from z3c.multifieldindex.subindex import DefaultIndexFactory
+ >>> from z3c.multifieldindex.subindex import CollectionIndexFactory
+ >>> from z3c.multifieldindex.subindex import TextIndexFactory
+ >>> from zope.component import provideAdapter
+
+ >>> provideAdapter(DefaultIndexFactory)
+ >>> provideAdapter(CollectionIndexFactory)
+ >>> provideAdapter(TextIndexFactory)
+
+The default index factory creates zc.catalog's ValueIndex, the collection index
+factory creates zc.catalog's SetIndex and the text index factory creates
+zope.index's TextIndex. This is needed to know when you'll be doing queries.
+
+Okay, now let's create an instance of index and prepare it to be used.
+
+ >>> index = PersonIndex()
+ >>> index.recreateIndexes()
+
+The "recreateIndexes" does re-creation of sub-indexes. It is normally called
+by a subscriber to IObjectAddedEvent, provided by this package, but we simply
+call it by hand for this test.
+
+Now, let's finally index our person objects:
+
+ >>> for docid, person in dataset:
+ ... index.index_doc(docid, person)
+
+Let's do a query now. The query format is quite simple. It is a dictionary, where
+keys are names of fields and values are queries for sub-indexes.
+
+ >>> results = index.apply({
+ ... 'skills': {'any_of': ('singing', 'painting')},
+ ... })
+ >>> list(results)
+ [1, 3]
+
+ >>> results = index.apply({
+ ... 'info': 'sweet',
+ ... })
+ >>> list(results)
+ [1, 2]
+
+ >>> results = index.apply({
+ ... 'age': {'between': (1, 30)},
+ ... })
+ >>> list(results)
+ [1, 3]
+
+ >>> results = index.apply({
+ ... 'age': {'between': (1, 30)},
+ ... 'skills': {'any_of': ('dancing', )},
+ ... })
+ >>> list(results)
+ [1]
Property changes on: z3c.multifieldindex/trunk/src/z3c/multifieldindex/__init__.py
___________________________________________________________________
Added: svn:keywords
+ Id
Added: z3c.multifieldindex/trunk/src/z3c/multifieldindex/configure.zcml
===================================================================
--- z3c.multifieldindex/trunk/src/z3c/multifieldindex/configure.zcml (rev 0)
+++ z3c.multifieldindex/trunk/src/z3c/multifieldindex/configure.zcml 2009-10-15 15:57:42 UTC (rev 105085)
@@ -0,0 +1,9 @@
+<configure xmlns="http://namespaces.zope.org/zope">
+
+ <subscriber handler=".index.multiFieldIndexAdded" />
+
+ <adapter factory=".subindex.DefaultIndexFactory" />
+ <adapter factory=".subindex.TextIndexFactory" />
+ <adapter factory=".subindex.CollectionIndexFactory" />
+
+</configure>
Added: z3c.multifieldindex/trunk/src/z3c/multifieldindex/index.py
===================================================================
--- z3c.multifieldindex/trunk/src/z3c/multifieldindex/index.py (rev 0)
+++ z3c.multifieldindex/trunk/src/z3c/multifieldindex/index.py 2009-10-15 15:57:42 UTC (rev 105085)
@@ -0,0 +1,93 @@
+##############################################################################
+#
+# Copyright (c) 2009 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.
+#
+##############################################################################
+"""Multi-field index implementation
+
+$Id$
+"""
+from BTrees.IFBTree import weightedIntersection
+from zope.app.container.btree import BTreeContainer
+from zope.app.container.interfaces import IObjectAddedEvent
+from zope.component import adapter
+from zope.interface import implements
+
+from z3c.multifieldindex.interfaces import IMultiFieldIndex
+from z3c.multifieldindex.interfaces import ISubIndexFactory
+
+
+class MultiFieldIndexBase(BTreeContainer):
+ implements(IMultiFieldIndex)
+
+ def _fields(self):
+ """To be overriden. Should return an iterable of (name, field) pairs."""
+ raise NotImplemented('_fields method should be provided by subclass.')
+
+ def _getData(self, object):
+ """To be overriden. Should return a dictionary of data for given object.
+
+ Dictionary keys are the same as field/index names and values are actual
+ values to be indexed by according index.
+ """
+ raise NotImplemented('_getData method should be provided by subclass.')
+
+ def recreateIndexes(self):
+ # 1. Remove all indexes
+ for name in list(self.keys()):
+ del self[name]
+
+ # 2. Create new indexes for fields that want to be indexed
+ for name, field in self._fields():
+ factory = ISubIndexFactory(field)
+ self[name] = factory()
+
+ def index_doc(self, docid, value):
+ data = self._getData(value)
+ for name in self:
+ value = data.get(name)
+ if value is not None:
+ self[name].index_doc(docid, value)
+
+ def unindex_doc(self, docid):
+ for index in self.values():
+ index.unindex_doc(docid)
+
+ def clear(self):
+ for index in self.values():
+ index.clear()
+
+ def apply(self, query):
+ results = []
+ for name, subquery in query.items():
+ if name not in self:
+ continue
+ r = self[name].apply(subquery)
+ if r is None:
+ continue
+ if not r:
+ return r
+ results.append((len(r), r))
+
+ if not results:
+ return None
+
+ results.sort()
+ _, result = results.pop(0)
+ for _, r in results:
+ _, result = weightedIntersection(result, r)
+
+ return result
+
+
+ at adapter(IMultiFieldIndex, IObjectAddedEvent)
+def multiFieldIndexAdded(index, event):
+ index.recreateIndexes()
Property changes on: z3c.multifieldindex/trunk/src/z3c/multifieldindex/index.py
___________________________________________________________________
Added: svn:keywords
+ Id
Added: z3c.multifieldindex/trunk/src/z3c/multifieldindex/interfaces.py
===================================================================
--- z3c.multifieldindex/trunk/src/z3c/multifieldindex/interfaces.py (rev 0)
+++ z3c.multifieldindex/trunk/src/z3c/multifieldindex/interfaces.py 2009-10-15 15:57:42 UTC (rev 105085)
@@ -0,0 +1,44 @@
+##############################################################################
+#
+# Copyright (c) 2009 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.
+#
+##############################################################################
+"""Interfaces for multi-field index
+
+$Id$
+"""
+from zope.app.catalog.interfaces import ICatalogIndex
+from zope.interface import Interface
+
+
+class IMultiFieldIndex(ICatalogIndex):
+ """An index for multiple fields"""
+
+ def apply(query):
+ """See IIndexSearch for the purpose of this method.
+
+ query is the dictionary which keys are names of sub-indexes
+ and values are queries for those indexes.
+ """
+
+ def recreateIndexes():
+ """Clear and recreate sub-indexes.
+
+ Note that after using this method, newly created sub-indexes won't
+ reindex current content. This may change in future.
+ """
+
+
+class ISubIndexFactory(Interface):
+ """A factory of sub-index for multi-field index"""
+
+ def __call__():
+ """Return an index instance to be added to multi-field index"""
Property changes on: z3c.multifieldindex/trunk/src/z3c/multifieldindex/interfaces.py
___________________________________________________________________
Added: svn:keywords
+ Id
Added: z3c.multifieldindex/trunk/src/z3c/multifieldindex/subindex.py
===================================================================
--- z3c.multifieldindex/trunk/src/z3c/multifieldindex/subindex.py (rev 0)
+++ z3c.multifieldindex/trunk/src/z3c/multifieldindex/subindex.py 2009-10-15 15:57:42 UTC (rev 105085)
@@ -0,0 +1,51 @@
+##############################################################################
+#
+# Copyright (c) 2009 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.
+#
+##############################################################################
+"""Sub-index factories for mult-field index
+
+$Id$
+"""
+from zc.catalog.index import ValueIndex, SetIndex
+from zope.component import adapts
+from zope.index.text import TextIndex
+from zope.interface import implements
+from zope.schema.interfaces import IField, ICollection, IText
+
+from z3c.multifieldindex.interfaces import ISubIndexFactory
+
+
+class SubIndexFactoryBase(object):
+ implements(ISubIndexFactory)
+
+ factory = None
+
+ def __init__(self, field):
+ self.field = field
+
+ def __call__(self):
+ return self.factory()
+
+
+class DefaultIndexFactory(SubIndexFactoryBase):
+ adapts(IField)
+ factory = ValueIndex
+
+
+class CollectionIndexFactory(SubIndexFactoryBase):
+ adapts(ICollection)
+ factory = SetIndex
+
+
+class TextIndexFactory(SubIndexFactoryBase):
+ adapts(IText)
+ factory = TextIndex
Property changes on: z3c.multifieldindex/trunk/src/z3c/multifieldindex/subindex.py
___________________________________________________________________
Added: svn:keywords
+ Id
Added: z3c.multifieldindex/trunk/src/z3c/multifieldindex/tests.py
===================================================================
--- z3c.multifieldindex/trunk/src/z3c/multifieldindex/tests.py (rev 0)
+++ z3c.multifieldindex/trunk/src/z3c/multifieldindex/tests.py 2009-10-15 15:57:42 UTC (rev 105085)
@@ -0,0 +1,25 @@
+##############################################################################
+#
+# Copyright (c) 2009 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.
+#
+##############################################################################
+"""Tests for z3c.multifieldindex functionality.
+
+$Id$
+"""
+import unittest
+from zope.testing import doctest
+
+def test_suite():
+ return unittest.TestSuite(
+ doctest.DocFileSuite('README.txt',
+ optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS)
+ )
Property changes on: z3c.multifieldindex/trunk/src/z3c/multifieldindex/tests.py
___________________________________________________________________
Added: svn:keywords
+ Id
More information about the checkins
mailing list