diff --git a/.travis.yml b/.travis.yml
index e002327..95faf32 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,15 +1,14 @@
language: python
sudo: false
+dist: xenial
python:
- 2.7
- - 3.4
- - 3.5
- 3.6
+ - 3.7
install:
- - pip install six==1.10.0 # force here to avoid conflict with zc.recipe.testrunner
- - pip install -U setuptools==33.1.1
+ - pip install -U setuptools pip
- pip install zc.buildout
- - buildout bootstrap
+ - buildout annotate
- buildout
script:
- bin/test -v1
diff --git a/Products/ExtendedPathIndex/ExtendedPathIndex.py b/Products/ExtendedPathIndex/ExtendedPathIndex.py
index 22087a2..6977032 100644
--- a/Products/ExtendedPathIndex/ExtendedPathIndex.py
+++ b/Products/ExtendedPathIndex/ExtendedPathIndex.py
@@ -53,6 +53,7 @@ class ExtendedPathIndex(PathIndex):
)
indexed_attrs = None
+ multi_valued = False
query_options = ("query", "level", "operator",
"depth", "navtree", "navtree_start")
@@ -62,8 +63,10 @@ def __init__(self, id, extra=None, caller=None):
if isinstance(extra, dict):
attrs = extra.get('indexed_attrs', None)
+ self.multi_valued = extra.get('multi_valued', False)
else:
attrs = getattr(extra, 'indexed_attrs', None)
+ self.multi_valued = getattr(extra, 'multi_valued', False)
if attrs is None:
return
@@ -245,7 +248,7 @@ def search(self, path, default_level=0, depth=-1, navtree=0,
# Optimized absolute path navtree and breadcrumbs cases
result = []
add = lambda x: x is not None and result.append(x)
- if depth == 1:
+ if depth == 1 and not self.multi_valued:
# Navtree case, all sibling elements along the path
convert = multiunion
index = self._index_parents
@@ -261,7 +264,7 @@ def search(self, path, default_level=0, depth=-1, navtree=0,
if not path.startswith('/'):
path = '/' + path
- if depth == 0:
+ if depth == 0 and not self.multi_valued:
# Specific object search
res = self._index_items.get(path)
return res and IISet([res]) or IISet()
diff --git a/README.rst b/README.rst
index 6780c06..a815077 100644
--- a/README.rst
+++ b/README.rst
@@ -1,21 +1,19 @@
Introduction
============
-This is an index that supports depth limiting, and the ability to build a
-structure usable for navtrees and sitemaps. The actual navtree implementations
-are not (and should not) be in this Product, this is the index implementation
-only.
+This is an Zope Catalog index to query treeish structures in the ZODB by path.
+It supports depth limiting, and has the ability to build a structure usable for navtrees and sitemaps.
+The actual navtree implementations are not (and should not) be in this package.
+This is the index implementation only.
Assumptions
===========
-EPI makes an assumption about the catalog and index being in the
-same container as all the content. This makes a lot of sense in a
-Plone setting, but might not work as expected in other scenarios.
+EPI makes an assumption about the catalog and index being in the same container as all the content.
+This makes a lot of sense in a Plone setting, but might not work as expected in other scenarios.
-A query like ``/plonesite/folder, level=0`` is transformed internally to
-``/folder, level=1``. This avoids touching the rather large plonesite set
-which contains reference to all content in your site.
+A query like ``/plonesite/folder, level=0`` is transformed internally to ``/folder, level=1``.
+This avoids touching the rather large plonesite set which contains reference to all content in your site.
Features
========
@@ -24,6 +22,44 @@ Features
- Can construct a navigation tree with a single catalog query
+Configuration
+=============
+
+In a GenericSetup profile, provide th following snippet to create an index::
+
+
+
+
+
+For multi valued paths, provide an extra
+(switches off an breaking optimization not needed for this cases)::
+
+
+
+
+
+
+An example for an index with multiple values per path element:
+Imagine to index multilingual content.
+Every item is translated and all translated items share a common unique identifier
+(this is how plone.app.multilingual works).
+Now create an indexer returing this unique identifier instead of the items ID as a path element.
+With this it is possible to query all elements of all languages in a folder in one go
+(for an advanced usage of this pattern look at ``plone.app.multilingualindexes``).
+
Usage
=====
@@ -32,45 +68,45 @@ Usage
``catalog(path=dict(query='some/path', depth=0))``
search for the object with the given path.
+ For multi valued paths, multiple objects are returned.
``catalog(path=dict(query='some/path', depth=2))``
search for all objects below some/path but only down to a depth of 2
``catalog(path=dict(query='some/path', navtree=True))``
- search for all objects below some/path for rendering a navigation tree. This
- includes all objects below some/path up to a depth of 1 and all parent
- objects.
+ search for all objects below some/path for rendering a navigation tree.
+ This includes all objects below some/path up to a depth of 1 and all parent objects.
``catalog(path=dict(query='some/path', navtree=True, depth=0))``
search for all objects below some/path for rendering a breadcrumb trail.
This includes only the parent objects themselves.
``catalog(path=dict(query='some/path', navtree=True, navtree_start=1))``
- search for all objects below some/path for rendering a partial
- navigation tree. This includes all objects below the path but stops
- 1 level above the root. The given path is included, even if it is at a
- shorter path in the portal than the level parameter would allow.
+ search for all objects below some/path for rendering a partial navigation tree.
+ This includes all objects below the path but stops 1 level above the root.
+ The given path is included,
+ even if it is at a shorter path in the portal than the level parameter would allow.
``catalog(path=dict(query='some/path', navtree=True, depth=0, navtree_start=1))``
- search for all objects below some/path for rendering a partial
- breadcrumb trail. This includes all parents below the path but stops
- 1 level above the root. The given path is included, even if it is at a
- lower level in the portal than the start parameter would allow.
+ search for all objects below some/path for rendering a partial breadcrumb trail.
+ This includes all parents below the path but stops 1 level above the root.
+ The given path is included, even if it is at a lower level in the portal than the start parameter would allow.
``catalog(path=dict(query='some/path', level=2))``
- search for all objects whose path contains some/path at level 2. This
- includes paths like /foo/bar/some/path and /spam/eggs/some/path, plus all
- children of those paths.
+ search for all objects whose path contains some/path at level 2.
+ This includes paths like /foo/bar/some/path and /spam/eggs/some/path,
+ plus all children of those paths.
``catalog(path=dict(query='some/path', level=-1, depth=0))``
- search for all objects whose path contains some/path at *any* level. This
- includes paths like /spam/some/path as well as /foo/bar/baz/some/path, but
- only those exact matches are included in the result because depth is set to
- 0.
+ search for all objects whose path contains some/path at *any* level.
+ This includes paths like /spam/some/path as well as /foo/bar/baz/some/path,
+ but only those exact matches are included in the result because depth is set to 0.
``catalog(path=dict(query=(('foo/bar', 2), ('bar/baz'), 1), depth=0))``
- search for multiple paths, each at different levels (foo/bar at level 2,
- and bar/baz at level 1), and return exact matches only.
+ search for multiple paths,
+ each at different levels
+ (foo/bar at level 2, and bar/baz at level 1),
+ and return exact matches only.
Credits
=======
@@ -87,5 +123,5 @@ Credits
License
=======
-This software is released under the GPL license.
+This software is released under the GPLv2 license.
diff --git a/news/7-feature b/news/7-feature
new file mode 100644
index 0000000..a551528
--- /dev/null
+++ b/news/7-feature
@@ -0,0 +1,2 @@
+Support allow multi value results for "virtual" paths.
+[jensens]
diff --git a/setup.py b/setup.py
index 882cd57..a3c7c1c 100644
--- a/setup.py
+++ b/setup.py
@@ -1,13 +1,16 @@
from setuptools import setup, find_packages
-version = '3.3.2.dev0'
+version = '3.4.0.dev0'
setup(
name='Products.ExtendedPathIndex',
version=version,
description="Zope catalog index for paths",
- long_description=(open("README.rst").read() + "\n" + \
- open("CHANGES.rst").read()),
+ long_description=(
+ open("README.rst").read() +
+ "\n" +
+ open("CHANGES.rst").read()
+ ),
classifiers=[
"Environment :: Web Environment",
"Framework :: Plone",
@@ -19,11 +22,9 @@
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 2.7",
- "Programming Language :: Python :: 3.4",
- "Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
- ],
+ ],
keywords='Zope catalog index',
author='Plone Foundation',
author_email='plone-developers@lists.sourceforge.net',
@@ -41,4 +42,4 @@
'Zope2 >= 2.13.0a3',
'zope.interface',
],
- )
+)