[Checkins] SVN: zc.relation/trunk/ be a better license citizen;
more README tweaks; add DEVELOP.txt instructions.
Gary Poster
gary at zope.com
Wed Apr 23 20:54:23 EDT 2008
Log message for revision 85674:
be a better license citizen; more README tweaks; add DEVELOP.txt instructions.
Changed:
A zc.relation/trunk/DEVELOP.txt
A zc.relation/trunk/LICENSE.txt
U zc.relation/trunk/setup.py
U zc.relation/trunk/src/zc/__init__.py
U zc.relation/trunk/src/zc/relation/README.txt
U zc.relation/trunk/src/zc/relation/__init__.py
U zc.relation/trunk/src/zc/relation/catalog.py
U zc.relation/trunk/src/zc/relation/interfaces.py
U zc.relation/trunk/src/zc/relation/queryfactory.py
U zc.relation/trunk/src/zc/relation/searchindex.py
U zc.relation/trunk/src/zc/relation/tests.py
-=-
Added: zc.relation/trunk/DEVELOP.txt
===================================================================
--- zc.relation/trunk/DEVELOP.txt (rev 0)
+++ zc.relation/trunk/DEVELOP.txt 2008-04-24 00:54:21 UTC (rev 85674)
@@ -0,0 +1,31 @@
+To develop this package from source:
+
+- check out the software from the repository
+
+- ``cd`` to the checkout
+
+- Ideally with a clean, non-system python, run
+ ``python bootstrap/bootstrap.py``
+
+- run ``./bin/buildout``
+
+To run tests, run *both* of the following:
+
+- ``./bin/test``: this tests zc.relation alone
+
+- ``./bin/testall``: this tests zc.relation and zc.relationship, to make sure
+ that zc.relation changes do not break zc.relationship tests.
+
+Changes should be documented in CHANGES.txt *in the package*.
+
+Before making a release that registers the software to PyPI, run the following:
+
+- ``./bin/py setup.py``
+
+This then creates a file with the following silly name:
+``TEST_THIS_REST_BEFORE_REGISTERING.txt``
+
+As the name suggests, test the file in a ReST tool to make sure docutils
+parses it correctly.
+
+Once this works, go ahead and ``./bin/py setup.py sdist register upload``.
\ No newline at end of file
Property changes on: zc.relation/trunk/DEVELOP.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: zc.relation/trunk/LICENSE.txt
===================================================================
--- zc.relation/trunk/LICENSE.txt (rev 0)
+++ zc.relation/trunk/LICENSE.txt 2008-04-24 00:54:21 UTC (rev 85674)
@@ -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.
\ No newline at end of file
Property changes on: zc.relation/trunk/LICENSE.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: zc.relation/trunk/setup.py
===================================================================
--- zc.relation/trunk/setup.py 2008-04-24 00:52:48 UTC (rev 85673)
+++ zc.relation/trunk/setup.py 2008-04-24 00:54:21 UTC (rev 85674)
@@ -11,7 +11,7 @@
setup(
name="zc.relation",
- version="1.0b1",
+ version="1.0",
packages=find_packages('src'),
include_package_data=True,
package_dir= {'':'src'},
@@ -19,8 +19,8 @@
namespace_packages=['zc'],
zip_safe=False,
- author='Zope Project',
- author_email='zope3-dev at zope.org',
+ author='Gary Poster',
+ author_email='gary at zope.com',
description=open("README.txt").read(),
long_description=long_description,
license='ZPL 2.1',
Modified: zc.relation/trunk/src/zc/__init__.py
===================================================================
--- zc.relation/trunk/src/zc/__init__.py 2008-04-24 00:52:48 UTC (rev 85673)
+++ zc.relation/trunk/src/zc/__init__.py 2008-04-24 00:54:21 UTC (rev 85674)
@@ -1,3 +1,16 @@
+##############################################################################
+#
+# Copyright (c) 2006-2008 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.
+#
+##############################################################################
# this is a namespace package
try:
import pkg_resources
Modified: zc.relation/trunk/src/zc/relation/README.txt
===================================================================
--- zc.relation/trunk/src/zc/relation/README.txt 2008-04-24 00:52:48 UTC (rev 85673)
+++ zc.relation/trunk/src/zc/relation/README.txt 2008-04-24 00:54:21 UTC (rev 85674)
@@ -34,6 +34,9 @@
zc.relationship will continue to be maintained, though active development is
expected to go into zc.relation.
+Many of the ideas come from discussions with and code from Casey Duncan, Tres
+Seaver, Ken Manheimer, and more.
+
Setting Up a Relation Catalog
=============================
@@ -58,9 +61,9 @@
- Relations are indexed with ``index``.
-We will use a simple two way relationship as our example here. A brief
-introduction to a more complex RDF-style subject-predicate-object set up
-can be found later in the document.
+We will use a simple two way relation as our example here. A brief introduction
+to a more complex RDF-style subject-predicate-object set up can be found later
+in the document.
Creating the Catalog
--------------------
@@ -135,7 +138,7 @@
The "load" functions get the token to be resolved; the catalog, for
context; and a dict cache, for optimizations of subsequent calls.
-You might have noticed in our Employee __init__ that we keep a mapping
+You might have noticed in our ``Employee.__init__`` that we keep a mapping
of name to object in the ``employees`` global dict (defined right above
the class definition). We'll use that for resolving the tokens.
@@ -149,19 +152,23 @@
How do you pick BTree modules?
-- If the tokens are 32-bit ints, choose BTrees.family32.II, BTrees.family32.IF
- or BTrees.family32.IO.
+- If the tokens are 32-bit ints, choose ``BTrees.family32.II``,
+ ``BTrees.family32.IF`` or ``BTrees.family32.IO``.
-- If the tokens are 64 bit ints, choose BTrees.family64.II, BTrees.family64.IF
- or BTrees.family64.IO.
+- If the tokens are 64 bit ints, choose ``BTrees.family64.II``,
+ ``BTrees.family64.IF`` or ``BTrees.family64.IO``.
-- If they are anything else, choose BTrees.family32.OI, BTrees.family64.OI, or
- BTrees.family32.OO (or BTrees.family64.OO--they are the same).
+- If they are anything else, choose ``BTrees.family32.OI``,
+ ``BTrees.family64.OI``, or ``BTrees.family32.OO`` (or
+ ``BTrees.family64.OO``--they are the same).
Within these rules, the choice is somewhat arbitrary unless you plan to merge
these results with that of another source that is using a particular BTree
-module. BTree set operations only work within the same module, so you must
-match module to module.
+module. BTree set operations only work within the same module, so you must
+match module to module. The catalog defaults to IF trees, because that's what
+standard zope catalogs use. That's as reasonable a choice as any, and will
+potentially come in handy if your tokens are in fact the same as those used by
+the zope catalog and you want to do some set operations.
In this example, our tokens are strings, so we want OO or an OI variant. We'll
choose BTrees.family32.OI, arbitrarily.
@@ -171,30 +178,31 @@
>>> catalog = zc.relation.catalog.Catalog(dumpEmployees, loadEmployees,
... btree=BTrees.family32.OI)
-[#verifyObjectICatalog]_ [#legacy]_ Look! A relation catalog!
+[#verifyObjectICatalog]_ [#legacy]_ Look! A relation catalog! We can't do very
+much searching with it so far though, because the catalog doesn't have any
+indexes.
-We can't do very much searching with it so far though, because the catalog
-doesn't have any indexes. In this example, the relationship itself represents
-the employee, so we won't need to index that separately.
+In this example, the relation itself represents the employee, so we won't need
+to index that separately.
But we do need a way to tell the catalog how to find the other end of the
-relationship, the supervisor. You can specify this to the catalog with an
-attribute or method specified from zope.interface Interface, or with a
-callable. We'll use a callable for now. The callable will receive the indexed
-relation and the catalog for context.
+relation, the supervisor. You can specify this to the catalog with an attribute
+or method specified from ``zope.interface Interface``, or with a callable.
+We'll use a callable for now. The callable will receive the indexed relation
+and the catalog for context.
>>> def supervisor(emp, catalog):
... return emp.supervisor # None or another employee
...
-We'll also specify need to specify how to tokenize (dump and load) those
-values. In this case, we're able to use the same functions as the relations
-themselves. However, do note that we can specify a completely different way to
-dump and load for each "value index," or relation element.
+We'll also need to specify how to tokenize (dump and load) those values. In
+this case, we're able to use the same functions as the relations themselves.
+However, do note that we can specify a completely different way to dump and
+load for each "value index," or relation element.
We could also specify the name to call the index, but it will default to the
-__name__ of the function (or interface element), which will work just fine for
-us now.
+``__name__`` of the function (or interface element), which will work just fine
+for us now.
Now we can add the "supervisor" value index.
@@ -210,7 +218,7 @@
----------------
Now let's create a few employees. All but one will have supervisors.
-If you recall our toy Employee class, the first argument to the
+If you recall our toy ``Employee`` class, the first argument to the
constructor is the employee name (and therefore the token), and the
optional second argument is the supervisor.
@@ -241,8 +249,8 @@
... catalog.index(emp)
...
-We've now created the relation catalog and added relations to it. We're
-ready to search!
+We've now created the relation catalog and added relations to it. We're ready
+to search!
Searching
=========
@@ -252,13 +260,13 @@
- Queries to the relation catalog are formed with dicts.
- Query keys are the names of the indexes you want to search, or, for the
- special case of precise relations, the zc.relation.RELATION constant.
+ special case of precise relations, the ``zc.relation.RELATION`` constant.
-- Query values are the tokens of the results you want to match; or None,
- indicating relations that have None as a value (or an empty collection, if it
- is a multiple). Search values can use zc.relation.catalog.any(\*args) or
- zc.relation.catalog.Any(args) to specify multiple (non-None) results to match
- for a given key.
+- Query values are the tokens of the results you want to match; or ``None``,
+ indicating relations that have ``None`` as a value (or an empty collection,
+ if it is a multiple). Search values can use
+ ``zc.relation.catalog.any(args)`` or ``zc.relation.catalog.Any(args)`` to
+ specify multiple (non-``None``) results to match for a given key.
- The index has a variety of methods to help you work with tokens.
``tokenizeQuery`` is typically the most used, though others are available.
@@ -269,10 +277,10 @@
- To find values that match a query, use ``findValues`` or ``findValueTokens``.
- You search transitively by using a query factory. The
- zc.relation.queryfactory.TransposingTransitive is a good common case factory
- that lets you walk up and down a hierarchy. A query factory can be passed in
- as an argument to search methods as a ``queryFactory``, or installed as a
- default behavior using ``addDefaultQueryFactory``.
+ ``zc.relation.queryfactory.TransposingTransitive`` is a good common case
+ factory that lets you walk up and down a hierarchy. A query factory can be
+ passed in as an argument to search methods as a ``queryFactory``, or
+ installed as a default behavior using ``addDefaultQueryFactory``.
- To find how a query is related, use ``findRelationChains`` or
``findRelationTokenChains``.
@@ -285,17 +293,17 @@
- search methods share the following arguments:
- * maxDepth, limiting the transitive depth for searches;
+ * ``maxDepth``, limiting the transitive depth for searches;
- * filter, allowing code to filter transitive paths;
+ * ``filter``, allowing code to filter transitive paths;
- * targetQuery, allowing a query to filter transitive paths on the basis of
- the endpoint;
+ * ``targetQuery``, allowing a query to filter transitive paths on the basis
+ of the endpoint;
- * targetFilter, allowing code to filter transitive paths on the basis of the
- endpoint; and
+ * ``targetFilter``, allowing code to filter transitive paths on the basis of
+ the endpoint; and
- * queryFactory, mentioned above.
+ * ``queryFactory``, mentioned above.
- You can set up search indexes to speed up specific transitive searches.
@@ -356,20 +364,20 @@
you actually might want a catalog to find it!
However, we will explore the syntax very briefly, because it introduces an
-important pair of search methods, and because it is a a stepping stone
+important pair of search methods, and because it is a stepping stone
to our first transitive search.
So, o relation catalog, who is Howie's supervisor?
-To ask this question we want to get the indexed values off of the
-relations: ``findValues``. In its simplest form, the arguments are the
-index name of the values you want, and a query to find the relationships
-that have the desired values.
+To ask this question we want to get the indexed values off of the relations:
+``findValues``. In its simplest form, the arguments are the index name of the
+values you want, and a query to find the relations that have the desired
+values.
-What about the query? Above, we noted that the keys in a query are the
-names of the indexes to search. However, in this case, we don't want to
-search one or more indexes for matching relationships, as usual, but
-actually specify a relationship: Howie.
+What about the query? Above, we noted that the keys in a query are the names of
+the indexes to search. However, in this case, we don't want to search one or
+more indexes for matching relations, as usual, but actually specify a relation:
+Howie.
We do not have a value index name: we are looking for a relation. The query
key, then, should be the constant ``zc.relation.RELATION``. For our current
@@ -400,10 +408,10 @@
------
As mentioned above, the catalog provides several helpers to work with tokens.
-The most frequently used is ``tokenizeQuery``, which takes a query with
-object values and converts them to tokens using the "dump" functions registered
-for the relationships and indexed values. Here are alternate spellings of some
-of the queries we've encountered above.
+The most frequently used is ``tokenizeQuery``, which takes a query with object
+values and converts them to tokens using the "dump" functions registered for
+the relations and indexed values. Here are alternate spellings of some of the
+queries we've encountered above.
>>> catalog.tokenizeQuery({'supervisor': a})
{'supervisor': 'Alice'}
@@ -436,9 +444,9 @@
Here's a quick example of some queries above, getting tokens rather than
objects.
-You can also spell a query in tokenizeQuery with keyword arguments. This
-won't work if your key is zc.relation.RELATION, but otherwise it can improve
-readability. We'll see some examples of this below as well.
+You can also spell a query in ``tokenizeQuery`` with keyword arguments. This
+won't work if your key is ``zc.relation.RELATION``, but otherwise it can
+improve readability. We'll see some examples of this below as well.
>>> sorted(catalog.findRelationTokens(query(supervisor=a)))
['Betty', 'Chuck']
@@ -484,18 +492,18 @@
So, we've seen a lot of one-level, intransitive searching. What about
transitive searching? Well, you need to tell the catalog how to walk the tree.
In simple (and very common) cases like this, the
-zc.relation.queryfactory.TransposingTransitive will do the trick.
+``zc.relation.queryfactory.TransposingTransitive`` will do the trick.
A transitive query factory is just a callable that the catalog uses to
ask "I got this query, and here are the results I found. I'm supposed to
walk another step transitively, so what query should I search for next?"
Writing a factory is more complex than we want to talk about right now,
-but using the TransposingTransitiveQueryFactory is easy. You just tell
+but using the ``TransposingTransitiveQueryFactory`` is easy. You just tell
it the two query names it should transpose for walking in either
direction.
-For instance, here we just want to tell the factory to transpose the two
-keys we've used, zc.relation.RELATION and 'supervisor'. Let's make a factory,
+For instance, here we just want to tell the factory to transpose the two keys
+we've used, ``zc.relation.RELATION`` and 'supervisor'. Let's make a factory,
use it in a query for a couple of transitive searches, and then, if you want,
you can read through a footnote to talk through what is happening.
@@ -550,7 +558,7 @@
<Employee instance "Howie">
We can force a non-transitive search, or a specific search depth, with
-maxDepth [#needs_a_transitive_queries_factory]_.
+``maxDepth`` [#needs_a_transitive_queries_factory]_.
>>> list(catalog.findValues(
... 'supervisor', {zc.relation.RELATION: 'Howie'}, maxDepth=1))
@@ -568,8 +576,8 @@
``findRelations`` methods help you ask what is related. But what if you
want to know *how* things are transitively related?
-``findRelationshipChains`` and ``targetQuery``
-----------------------------------------------
+``findRelationChains`` and ``targetQuery``
+------------------------------------------
Another search method, ``findRelationChains``, helps you discover how
things are transitively related.
@@ -632,7 +640,7 @@
-------------------------------
We can take a quick look now at the last of the two shared search arguments:
-filter and targetFilter. These two are similar in that they both are
+``filter`` and ``targetFilter``. These two are similar in that they both are
callables that can approve or reject given relations in a search based on
whatever logic you can code. They differ in that ``filter`` stops any further
transitive searches from the relation, while ``targetFilter`` merely omits the
@@ -689,19 +697,20 @@
>>> len(list(res)) # iterator is exhausted
0
-The brute force of this aproach can be sufficient in many cases, but
+The brute force of this approach can be sufficient in many cases, but
sometimes speed for these searches is critical. In these cases, you can
add a "search index". A search index speeds up the result of one or
more precise searches by indexing the results. Search indexes can
-affect the results of searches with a queryFactory in ``findRelations``,
+affect the results of searches with a ``queryFactory`` in ``findRelations``,
``findValues``, and the soon-to-be-introduced ``canFind``, but they do not
affect ``findRelationChains``.
The zc.relation package currently includes two kinds of search indexes, one for
-indexing transitive membership searches in a hierarchy and one very
-experimental one explored in tokens.txt in this package (which can effectively
-change the meaning of an intransitive search). Other search index
-implementations and approaches may be added in the future.
+indexing transitive membership searches in a hierarchy and one for intransitive
+searches explored in tokens.txt in this package, which can optimize frequent
+searches on complex queries or can effectively change the meaning of an
+intransitive search. Other search index implementations and approaches may be
+added in the future.
Here's a very brief example of adding a search index for the transitive
searches seen above that specify a 'supervisor'.
@@ -775,8 +784,8 @@
... 'supervisor', {zc.relation.RELATION: 'Frank'}))
['Chuck', 'Alice', 'Zane', 'Betty']
-Paths returned by ``findRelationChains`` are marked with special interfaces, and
-special metadata, to show the chain.
+Paths returned by ``findRelationChains`` are marked with special interfaces,
+and special metadata, to show the chain.
>>> res = list(catalog.findRelationChains({zc.relation.RELATION: 'Frank'}))
>>> len(res)
@@ -910,19 +919,20 @@
attribute or callable.
- The ``family`` argument in instantiating the catalog lets you change the
- default btree family for relations and value indexes from BTrees.family32.IF
- to BTrees.family64.IF.
+ default btree family for relations and value indexes from
+ ``BTrees.family32.IF`` to ``BTrees.family64.IF``.
-Extrinsic Two-Way Relationship
-------------------------------
+Extrinsic Two-Way Relations
+---------------------------
A simple variation of our current story is this: what if the indexed relation
were between two other objects--that is, what if the relation were extrinsic to
both participants?
-Let's imagine we have relations that show biological parentage. We'll want
-a "Person" and a "Parentage" relation. We'll define an interface for IParentage
-so we can see how using an interface to define a value index works.
+Let's imagine we have relations that show biological parentage. We'll want a
+"Person" and a "Parentage" relation. We'll define an interface for
+``IParentage`` so we can see how using an interface to define a value index
+works.
>>> class Person(object):
... def __init__(self, name):
@@ -1083,13 +1093,13 @@
... self.predicate = predicate
... self.objects = objects
... self._contextual = Contextual()
- ...
+ ...
... def __conform__(self, iface):
... if iface is IContextual:
... return self._contextual
...
-(When using zope.component, the __conform__ would normally be unnecessary;
+(When using zope.component, the ``__conform__`` would normally be unnecessary;
however, this package does not depend on zope.component.)
>>> def dumpPersistent(obj, catalog, cache):
@@ -1117,11 +1127,11 @@
>>> import transaction
>>> transaction.commit()
-The dumpPersistent and loadPersistent is a bit of a toy, as warned above.
-Also, while our predicate will be stored as a string, some programmers may
-prefer to have a dump in such a case verify that the string has been explicitly
-registered in some way, to prevent typos. Obviously, we are not bothering
-with this for our example.
+The ``dumpPersistent`` and ``loadPersistent`` is a bit of a toy, as warned
+above. Also, while our predicate will be stored as a string, some programmers
+may prefer to have a dump in such a case verify that the string has been
+explicitly registered in some way, to prevent typos. Obviously, we are not
+bothering with this for our example.
We make some objects, and then we make some relations with those objects and
index them.
@@ -1187,6 +1197,13 @@
causes the search to ignore search indexes, even if there is an appropriate
one.
+- ``findRelationTokens()`` (without arguments) returns the BTree set of all
+ relation tokens in the catalog.
+
+- ``findValueTokens(INDEX_NAME)`` (where "INDEX_NAME" should be replaced with
+ an index name) returns the BTree set of all value tokens in the catalog for
+ the given index name.
+
Listeners
---------
@@ -1412,7 +1429,7 @@
The five methods that can use search indexes, ``findValues``,
``findValueTokens``, ``findRelations``, ``findRelationTokens``, and
-``canFind``, can be explictly requested to ignore any pertinent search index
+``canFind``, can be explicitly requested to ignore any pertinent search index
using the ``ignoreSearchIndex`` argument.
We can see this easily with the token-related methods: the search index result
@@ -1470,6 +1487,33 @@
... query(subject=jack, predicate=BEGAT), ignoreSearchIndex=True)
True
+``findRelationTokens()``
+------------------------
+
+If you call ``findRelationTokens`` without any arguments, you will get the
+BTree set of all relation tokens in the catalog. This can be handy for tests
+and for advanced uses of the catalog.
+
+ >>> newcat.findRelationTokens() # doctest: +ELLIPSIS
+ <BTrees.LFBTree.LFTreeSet object at ...>
+ >>> len(newcat.findRelationTokens())
+ 8
+ >>> set(newcat.resolveRelationTokens(newcat.findRelationTokens())) == set(
+ ... (rel1, rel2, rel3, rel4, rel5, rel6, rel7, rel8))
+ True
+
+``findValueTokens(INDEX_NAME)``
+-------------------------------
+
+If you call ``findValueTokens`` with only an index name, you will get the BTree
+structure of all tokens for that value in the index. This can be handy for
+tests and for advanced uses of the catalog.
+
+ >>> newcat.findValueTokens('predicate') # doctest: +ELLIPSIS
+ <BTrees.OOBTree.OOBTree object at ...>
+ >>> list(newcat.findValueTokens('predicate'))
+ ['BEGAT', 'BUYS', 'OBSERVES', 'SELLS']
+
Conclusion
==========
@@ -1493,14 +1537,14 @@
- Token type determines the BTree module needed.
- - If the tokens are 32-bit ints, choose BTrees.family32.II,
- BTrees.family32.IF or BTrees.family32.IO.
+ - If the tokens are 32-bit ints, choose ``BTrees.family32.II``,
+ ``BTrees.family32.IF`` or ``BTrees.family32.IO``.
- - If the tokens are 64 bit ints, choose BTrees.family64.II,
- BTrees.family64.IF or BTrees.family64.IO.
+ - If the tokens are 64 bit ints, choose ``BTrees.family64.II``,
+ ``BTrees.family64.IF`` or ``BTrees.family64.IO``.
- - If they are anything else, choose BTrees.family32.OI,
- BTrees.family64.OI, or BTrees.family32.OO (or
+ - If they are anything else, choose ``BTrees.family32.OI``,
+ ``BTrees.family64.OI``, or ``BTrees.family32.OO`` (or
BTrees.family64.OO--they are the same).
Within these rules, the choice is somewhat arbitrary unless you plan to
@@ -1510,7 +1554,7 @@
- The ``family`` argument in instantiating the catalog lets you change the
default btree family for relations and value indexes from
- BTrees.family32.IF to BTrees.family64.IF.
+ ``BTrees.family32.IF`` to ``BTrees.family64.IF``.
- You must define your own functions for tokenizing and resolving tokens.
These functions are registered with the catalog for the relations and for
@@ -1539,44 +1583,49 @@
* Catalog Management:
- - Relations are indexed with ``index(relation)``, and removed from the catalog with
- ``unindex(relation)``. ``index_doc(relation_token, relation)`` and
- ``unindex_doc(relation_token)`` also work.
+ - Relations are indexed with ``index(relation)``, and removed from the
+ catalog with ``unindex(relation)``. ``index_doc(relation_token,
+ relation)`` and ``unindex_doc(relation_token)`` also work.
- The ``clear`` method clears the relations in the catalog.
- - The ``copy`` method makes a copy of the current catalog by copying internal
- data structures, rather than reindexing the relations, which can be a
- significant optimization opportunity. This copies value indexes and search
- indexes; and gives listeners an opportunity to specify what, if anything,
- should be included in the new copy.
+ - The ``copy`` method makes a copy of the current catalog by copying
+ internal data structures, rather than reindexing the relations, which can
+ be a significant optimization opportunity. This copies value indexes and
+ search indexes; and gives listeners an opportunity to specify what, if
+ anything, should be included in the new copy.
* Searching a catalog:
- Queries to the relation catalog are formed with dicts.
- Query keys are the names of the indexes you want to search, or, for the
- special case of precise relations, the zc.relation.RELATION constant.
+ special case of precise relations, the ``zc.relation.RELATION`` constant.
- - Query values are the tokens of the results you want to match; or None,
- indicating relations that have None as a value (or an empty collection, if it
- is a multiple). Search values can use zc.relation.catalog.any(\*args) or
- zc.relation.catalog.Any(args) to specify multiple (non-None) results to match
- for a given key.
+ - Query values are the tokens of the results you want to match; or
+ ``None``, indicating relations that have ``None`` as a value (or an empty
+ collection, if it is a multiple). Search values can use
+ ``zc.relation.catalog.any(args)`` or ``zc.relation.catalog.Any(args)`` to
+ specify multiple (non-``None``) results to match for a given key.
- The index has a variety of methods to help you work with tokens.
- ``tokenizeQuery`` is typically the most used, though others are available.
+ ``tokenizeQuery`` is typically the most used, though others are
+ available.
- To find relations that match a query, use ``findRelations`` or
- ``findRelationTokens``.
+ ``findRelationTokens``. Calling ``findRelationTokens`` without any
+ arguments returns the BTree set of all relation tokens in the catalog.
- - To find values that match a query, use ``findValues`` or ``findValueTokens``.
+ - To find values that match a query, use ``findValues`` or
+ ``findValueTokens``. Calling ``findValueTokens`` with only the name
+ of a value index returns the BTree set of all tokens in the catalog for
+ that value index.
- You search transitively by using a query factory. The
- zc.relation.queryfactory.TransposingTransitive is a good common case factory
- that lets you walk up and down a hierarchy. A query factory can be passed in
- as an argument to search methods as a ``queryFactory``, or installed as a
- default behavior using ``addDefaultQueryFactory``.
+ ``zc.relation.queryfactory.TransposingTransitive`` is a good common case
+ factory that lets you walk up and down a hierarchy. A query factory can
+ be passed in as an argument to search methods as a ``queryFactory``, or
+ installed as a default behavior using ``addDefaultQueryFactory``.
- To find how a query is related, use ``findRelationChains`` or
``findRelationTokenChains``.
@@ -1584,27 +1633,27 @@
- To find out if a query is related, use ``canFind``.
- Circular transitive relations are handled to prevent infinite loops. They
- are identified in ``findRelationChains`` and ``findRelationTokenChains`` with
- a ``zc.relation.interfaces.ICircularRelationPath`` marker interface.
+ are identified in ``findRelationChains`` and ``findRelationTokenChains``
+ with a ``zc.relation.interfaces.ICircularRelationPath`` marker interface.
- search methods share the following arguments:
- * maxDepth, limiting the transitive depth for searches;
+ * ``maxDepth``, limiting the transitive depth for searches;
- * filter, allowing code to filter transitive paths;
+ * ``filter``, allowing code to filter transitive paths;
- * targetQuery, allowing a query to filter transitive paths on the basis of
- the endpoint;
+ * ``targetQuery``, allowing a query to filter transitive paths on the
+ basis of the endpoint;
- * targetFilter, allowing code to filter transitive paths on the basis of the
- endpoint; and
+ * ``targetFilter``, allowing code to filter transitive paths on the basis
+ of the endpoint; and
- * queryFactory, mentioned above.
+ * ``queryFactory``, mentioned above.
In addition, the ``ignoreSearchIndex`` argument to ``findRelations``,
- ``findRelationTokens``, ``findValues``, ``findValueTokens``, and ``canFind``
- causes the search to ignore search indexes, even if there is an appropriate
- one.
+ ``findRelationTokens``, ``findValues``, ``findValueTokens``, and
+ ``canFind`` causes the search to ignore search indexes, even if there is
+ an appropriate one.
Next Steps
----------
@@ -1684,8 +1733,8 @@
...
ValueError: ('name already used', 'supervisor')
- Finally, if your function does not have a __name__ and you do not provide
- one, you may not add an index.
+ Finally, if your function does not have a ``__name__`` and you do not
+ provide one, you may not add an index.
>>> class Supervisor3(object):
... __name__ = None
@@ -1701,7 +1750,7 @@
...
ValueError: no name specified
-.. [#any] Any can be compared.
+.. [#any] ``Any`` can be compared.
>>> zc.relation.catalog.any('foo', 'bar', 'baz')
<zc.relation.catalog.Any instance ('bar', 'baz', 'foo')>
@@ -1723,7 +1772,7 @@
>>> list(catalog.findValueTokens('supervisor',
... {zc.relation.RELATION: 'Howie'}))
['Diane']
-
+
While we're down here in the footnotes, I'll mention that you can
search for relations that haven't been indexed.
@@ -1732,8 +1781,8 @@
>>> list(catalog.findRelations({zc.relation.RELATION: 'Ygritte'}))
[]
-.. [#findValuesExceptions] If you use findValues or findValueTokens and try
- to specify a value name that is not indexed, you get a ValueError.
+.. [#findValuesExceptions] If you use ``findValues`` or ``findValueTokens`` and
+ try to specify a value name that is not indexed, you get a ValueError.
>>> catalog.findValues('foo')
Traceback (most recent call last):
@@ -1756,15 +1805,15 @@
OK, the next part is where your brain hurts. Hang on.
In our case, the factory sees that the query was for supervisor. Its
- other key, the one it transposes with, is zc.relation.RELATION. *The
+ other key, the one it transposes with, is ``zc.relation.RELATION``. *The
factory gets the transposing key's result for the current token.* So, for
- us, a key of zc.relation.RELATION is actually a no-op: the result *is* the
- current token, Diane. Then, the factory has its answer: replace the old
+ us, a key of ``zc.relation.RELATION`` is actually a no-op: the result *is*
+ the current token, Diane. Then, the factory has its answer: replace the old
value of supervisor in the query, Betty, with the result, Diane. The next
transitive query should be {'supervisor', 'Diane'}. Ta-da.
-.. [#needs_a_transitive_queries_factory] A search with a maxDepth > 1 but
- no queryFactory raises an error.
+.. [#needs_a_transitive_queries_factory] A search with a ``maxDepth`` > 1 but
+ no ``queryFactory`` raises an error.
>>> catalog.removeDefaultQueryFactory(factory)
>>> catalog.findRelationTokens({'supervisor': 'Diane'}, maxDepth=3)
@@ -1774,14 +1823,14 @@
>>> catalog.addDefaultQueryFactory(factory)
-.. [#maxDepthExceptions] maxDepth must be None or a positive integer, or
+.. [#maxDepthExceptions] ``maxDepth`` must be None or a positive integer, or
else you'll get a value error.
>>> catalog.findRelations({'supervisor': 'Betty'}, maxDepth=0)
Traceback (most recent call last):
...
ValueError: maxDepth must be None or a positive integer
-
+
>>> catalog.findRelations({'supervisor': 'Betty'}, maxDepth=-1)
Traceback (most recent call last):
...
@@ -1804,7 +1853,6 @@
... filter=arbitrary_filter,
... targetFilter=female_filter))
['Betty', 'Galyn']
-
.. [#updates] The scenario we are looking at in this document shows a case
in which special logic in the search index needs to address updates.
Modified: zc.relation/trunk/src/zc/relation/__init__.py
===================================================================
--- zc.relation/trunk/src/zc/relation/__init__.py 2008-04-24 00:52:48 UTC (rev 85673)
+++ zc.relation/trunk/src/zc/relation/__init__.py 2008-04-24 00:54:21 UTC (rev 85674)
@@ -1 +1,14 @@
+##############################################################################
+#
+# Copyright (c) 2006-2008 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.
+#
+##############################################################################
from zc.relation.catalog import RELATION
Modified: zc.relation/trunk/src/zc/relation/catalog.py
===================================================================
--- zc.relation/trunk/src/zc/relation/catalog.py 2008-04-24 00:52:48 UTC (rev 85673)
+++ zc.relation/trunk/src/zc/relation/catalog.py 2008-04-24 00:54:21 UTC (rev 85674)
@@ -1,3 +1,16 @@
+##############################################################################
+#
+# Copyright (c) 2006-2008 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.
+#
+##############################################################################
import sys
import copy
Modified: zc.relation/trunk/src/zc/relation/interfaces.py
===================================================================
--- zc.relation/trunk/src/zc/relation/interfaces.py 2008-04-24 00:52:48 UTC (rev 85673)
+++ zc.relation/trunk/src/zc/relation/interfaces.py 2008-04-24 00:54:21 UTC (rev 85674)
@@ -1,6 +1,6 @@
##############################################################################
#
-# Copyright (c) 2004 Zope Corporation and Contributors.
+# Copyright (c) 2006-2008 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
Modified: zc.relation/trunk/src/zc/relation/queryfactory.py
===================================================================
--- zc.relation/trunk/src/zc/relation/queryfactory.py 2008-04-24 00:52:48 UTC (rev 85673)
+++ zc.relation/trunk/src/zc/relation/queryfactory.py 2008-04-24 00:54:21 UTC (rev 85674)
@@ -1,3 +1,16 @@
+##############################################################################
+#
+# Copyright (c) 2006-2008 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.
+#
+##############################################################################
import persistent
import BTrees
import zope.interface
Modified: zc.relation/trunk/src/zc/relation/searchindex.py
===================================================================
--- zc.relation/trunk/src/zc/relation/searchindex.py 2008-04-24 00:52:48 UTC (rev 85673)
+++ zc.relation/trunk/src/zc/relation/searchindex.py 2008-04-24 00:54:21 UTC (rev 85674)
@@ -1,3 +1,16 @@
+##############################################################################
+#
+# Copyright (c) 2006-2008 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.
+#
+##############################################################################
import copy
import itertools
Modified: zc.relation/trunk/src/zc/relation/tests.py
===================================================================
--- zc.relation/trunk/src/zc/relation/tests.py 2008-04-24 00:52:48 UTC (rev 85673)
+++ zc.relation/trunk/src/zc/relation/tests.py 2008-04-24 00:54:21 UTC (rev 85674)
@@ -1,6 +1,6 @@
##############################################################################
#
-# Copyright (c) 2004 Zope Corporation and Contributors.
+# Copyright (c) 2006-2008 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
More information about the Checkins
mailing list