======= Changes ======= 1.0 (2008-04-23) ================ This is the initial release of the zc.relation package. However, it represents a refactoring of another package, zc.relationship. This package contains only a modified version of the relation(ship) index, now called a catalog. The refactored version of zc.relationship index relies on (subclasses) this catalog. zc.relationship also maintains a backwards-compatible subclass. This package only relies on the ZODB, zope.interface, and zope.testing software, and can be used inside or outside of a standard ZODB database. The software does have to be there, though (the package relies heavily on the ZODB BTrees package). If you would like to switch a legacy zc.relationship index to a zc.relation catalog, try this trick in your generations script. Assuming the old index is ``old``, the following line should create a new zc.relation catalog with your legacy data: >>> new = old.copy(zc.relation.Catalog) Why is the same basic data structure called a catalog now? Because we exposed the ability to mutate the data structure, and what you are really adding and removing are indexes. It didn't make sense to put an index in an index, but it does make sense to put an index in a catalog. Thus, a name change was born. The catalog in this package has several incompatibilities from the earlier zc.relationship index, and many new features. The zc.relationship package maintains a backwards-compatible subclass. The following discussion compares the zc.relation catalog with the zc.relationship 1.x index. Incompatibilities with zc.relationship 1.x index ------------------------------------------------ The two big changes are that method names now refer to ``Relation`` rather than ``Relationship``; and the catalog is instantiated slightly differently from the index. A few other changes are worth your attention. The following list attempts to highlight all incompatibilities. :Big incompatibilities: - ``findRelationshipTokenSet`` and ``findValueTokenSet`` are renamed, with some slightly different semantics, as ``getRelationTokens`` and ``getValueTokens``. The exact same result as ``findRelationTokenSet(query)`` can be obtained with ``findRelationTokens(query, 1)`` (where 1 is maxDepth). The same result as ``findValueTokenSet(reltoken, name)`` can be obtained with ``findValueTokens(name, {zc.relation.RELATION: reltoken}, 1)``. - ``findRelations`` replaces ``findRelatonships``. The new method will use the defaultTransitiveQueriesFactory if it is set and maxDepth is not 1. It shares the call signature of ``findRelationChains``. - ``isLinked`` is now ``canFind``. - The catalog instantiation arguments have changed from the old index. * ``load`` and ``dump`` (formerly ``loadRel`` and ``dumpRel``, respectively) are now required arguments for instantiation. * The only other optional arguments are ``btree`` (was ``relFamily``) and ``family``. You now specify what elements to index with ``addValueIndex`` * Note also that ``addValueIndex`` defaults to no load and dump function, unlike the old instantiation options. - query factories are different. See ``IQueryFactory`` in the interfaces. * they first get (query, catalog, cache) and then return a getQueries callable that gets relchains and yields queries; OR None if they don't match. * They must also handle an empty relchain. Typically this should return the original query, but may also be used to mutate the original query. * They are no longer thought of as transitive query factories, but as general query mutators. :Medium: - The catalog no longer inherits from zope.app.container.contained.Contained. - The index requires ZODB 3.8 or higher. :Small: - ``deactivateSets`` is no longer an instantiation option (it was broken because of a ZODB bug anyway, as had been described in the documentation). Changes and new features ------------------------ - The catalog now offers the ability to index certain searches. The indexes must be explicitly instantiated and registered you want to optimize. This can be used when searching for values, when searching for relations, or when determining if two objects are linked. It cannot be used for relation chains. Requesting an index has the usual trade-offs of greater storage space and slower write speed for faster search speed. Registering a search index is done after instantiation time; you can iteratate over the current settings used, and remove them. (The code path expects to support legacy zc.relationship index instances for all of these APIs.) - You can now specify new values after the catalog has been created, iterate over the settings used, and remove values. - The catalog has a copy method, to quickly make new copies without actually having to reindex the relations. - query arguments can now specify multiple values for a given name by using zc.relation.catalog.any(1, 2, 3, 4) or zc.relation.catalog.Any((1, 2, 3, 4)). - The catalog supports specifying indexed values by passing callables rather than interface elements (which are also still supported). - ``findRelations`` and new method ``findRelationTokens`` can find relations transitively and intransitively. ``findRelationTokens`` when used intransitively repeats the legacy zc.relationship index behavior of ``findRelationTokenSet``. (``findRelationTokenSet`` remains in the API, not deprecated, a companion to ``findValueTokenSet``.) - in findValues and findValueTokens, ``query`` argument is now optional. If the query evaluates to False in a boolean context, all values, or value tokens, are returned. Value tokens are explicitly returned using the underlying BTree storage. This can then be used directly for other BTree operations. - Completely new docs. Unfortunately, still really not good enough. - The package has drastically reduced direct dependecies from zc.relationship: it is now more clearly a ZODB tool, with no other Zope dependencies than zope.testing and zope.interface. - Listeners allow objects to listen to messages from the catalog (which can be used directly or, for instance, to fire off events). - You can search for relations, using a key of zc.relation.RELATION...which is really an alias for None. Sorry. But hey, use the constant! I think it is more readable. - tokenizeQuery (and resolveQuery) now accept keyword arguments as an alternative to a normal dict query. This can make constructing the query a bit more attractive (i.e., ``query = catalog.tokenizeQuery; res = catalog.findValues('object', query(subject=joe, predicate=OWNS))``).