Index of /ports/www/zope210/work/Zope-2.10.5-final/lib/python/zope/app/component
Name Last modified Size Description
Parent Directory 29-Oct-2007 06:39 -
__init__.py 29-Oct-2007 06:10 2k
adapter.py 29-Oct-2007 06:10 1k
back35.py 29-Oct-2007 06:10 30k
configure.zcml 29-Oct-2007 06:10 3k
contentdirective.py 29-Oct-2007 06:10 9k
fields.py 29-Oct-2007 06:10 1k
hooks.py 29-Oct-2007 06:10 3k
interface.py 29-Oct-2007 06:10 1k
meta.zcml 29-Oct-2007 06:10 3k
metaconfigure.py 29-Oct-2007 06:10 9k
metadirectives.py 29-Oct-2007 06:10 12k
registration.py 29-Oct-2007 06:10 2k
site.py 29-Oct-2007 06:10 14k
site.txt 29-Oct-2007 06:10 10k
testing.py 29-Oct-2007 06:10 6k
vocabulary.py 29-Oct-2007 06:10 12k
browser/ 29-Oct-2007 06:39 -
interfaces/ 29-Oct-2007 06:39 -
tests/ 29-Oct-2007 06:39 -
=====================================
Zope 3's Local Component Architecture
=====================================
The local component architecture provides several packages that can be used
independent of the entire component architecture framework. Thus, I decided to
document these frameworks in different files.
o Registration Framework (`registration.txt`)
Provides an API for creating custom registries. The entries of the
registries are managed via registration components. A specific
implementation for component-based registrations is also
provided. Finally, there are some generic container classes that allow the
developer to manage the components and their registrations.
o Local Adapter Registry (`adapterregistry.txt`)
Provides a persistent adapter registry that uses the registration
framework. Local registries can be assembled to a registry tree where
nodes further down in the tree overrride registrations of higher-up nodes.
o Sites and Local Site Managers (`site.txt`)
Provides a local and persistent site manager implementation, so that one
can register local utilities and adapters. It uses local adapter
registries for its adapter and utility registry. The module also provides
some facilities to organize the local software and ensures the correct
behavior inside the ZODB.
Local Component Architecture API
--------------------------------
While the component architecture API provided by `zope.component` is
sufficient most of the time, there are a couple of functions that are useful
in the context of multiple sites.
A very common use case is to get the nearest site manager in a given
context. Sometimes, however, one wants the next higher-up site manager. First,
let's create a folder tree and create some sites from it:
>>> from zope.app.testing import setup
>>> root = setup.buildSampleFolderTree()
>>> root_sm = setup.createSiteManager(root)
>>> folder1_sm = setup.createSiteManager(root['folder1'])
If we ask `folder1` for its nearest site manager, we get
>>> from zope.app import zapi
>>> zapi.getSiteManager(root['folder1']) is folder1_sm
True
but its next site manager is
>>> from zope.app import component
>>> component.getNextSiteManager(root['folder1']) is root_sm
True
The next site manager of the local root is the global site manager:
>>> gsm = zapi.getGlobalSiteManager()
>>> component.getNextSiteManager(root) is gsm
True
If a non-location is passed into the function, a component lookup error is
raised, since there is no site manager beyond the global site manager:
>>> component.getNextSiteManager(object())
Traceback (most recent call last):
...
ComponentLookupError: No more site managers have been found.
If you use the `queryNextSiteManager()` function, you can specify a `default`
return value:
>>> component.queryNextSiteManager(object(), 'default')
'default'
A related use case to the above is to find the next available utility
providing a certain interface and name. This is often used when a utility
delegates a query to the next one. Let's start by creating a utility and
inserting it in our folder hiearchy:
>>> import zope.interface
>>> class IMyUtility(zope.interface.Interface):
... pass
>>> class MyUtility(object):
... zope.interface.implements(IMyUtility)
... def __init__(self, id):
... self.id = id
... def __repr__(self):
... return "%s('%s')" %(self.__class__.__name__, self.id)
>>> gutil = MyUtility('global')
>>> gsm.registerUtility(gutil, IMyUtility, 'myutil')
>>> util1 = setup.addUtility(folder1_sm, 'myutil', IMyUtility,
... MyUtility('one'))
>>> folder1_1_sm = setup.createSiteManager(root['folder1']['folder1_1'])
>>> util1_1 = setup.addUtility(folder1_1_sm, 'myutil', IMyUtility,
... MyUtility('one-one'))
Now, if we ask `util1_1` for its next available utility and we get
>>> component.getNextUtility(util1_1, IMyUtility, 'myutil')
MyUtility('one')
Next we ask `util1` for its next utility and we should get the global version:
>>> component.getNextUtility(util1, IMyUtility, 'myutil')
MyUtility('global')
However, if we ask the global utility for the next one, an error is raised
>>> component.getNextUtility(gutil, IMyUtility,
... 'myutil') #doctest: +NORMALIZE_WHITESPACE
Traceback (most recent call last):
...
ComponentLookupError:
No more utilities for <InterfaceClass __builtin__.IMyUtility>,
'myutil' have been found.
or you can simply use the `queryNextUtility` and specify a default:
>>> component.queryNextUtility(gutil, IMyUtility, 'myutil', 'default')
'default'
Let's now ensure that the function also works with multiple registries. First
we create another base registry:
>>> from zope.component import registry
>>> myregistry = registry.Components()
>>> custom_util = MyUtility('my_custom_util')
>>> myregistry.registerUtility(custom_util, IMyUtility, 'my_custom_util')
Now we add it as a base to the local site manager:
>>> folder1_sm.__bases__ = (myregistry,) + folder1_sm.__bases__
Both, the ``myregistry`` and global utilities should be available:
>>> component.queryNextUtility(folder1_sm, IMyUtility, 'my_custom_util')
MyUtility('my_custom_util')
>>> component.queryNextUtility(folder1_sm, IMyUtility, 'myutil')
MyUtility('global')