1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
==========================================================
``zope.component.hooks``: The current component registry
==========================================================
.. currentmodule:: zope.component.hooks
There can be any number of component registries in an application. One of them
is the global component registry, and there is also the concept of a currently
used component registry. Component registries other than the global one are
associated with objects called sites. The :mod:`zope.component.hooks` module
provides an API to set and access the current site as well as manipulate the
adapter hook associated with it.
.. autofunction:: getSite
As long as we haven't set a site, none is being considered current:
.. doctest::
>>> from zope.component.hooks import getSite
>>> print(getSite())
None
We can also ask for the current component registry (aka site manager
historically); it will return the global one if no current site is set:
.. autofunction:: getSiteManager
.. doctest::
>>> from zope.component.hooks import getSiteManager
>>> getSiteManager()
<BaseGlobalComponents base>
Let's set a site now. A site has to be an object that provides the
``getSiteManager`` method, which is specified by
`zope.component.interfaces.IPossibleSite`:
.. autofunction:: setSite
.. doctest::
>>> from zope.interface.registry import Components
>>> class Site(object):
... def __init__(self):
... self.registry = Components('components')
... def getSiteManager(self):
... return self.registry
>>> from zope.component.hooks import setSite
>>> site1 = Site()
>>> setSite(site1)
After this, the newly set site is considered the currently active one:
.. doctest::
>>> getSite() is site1
True
>>> getSiteManager() is site1.registry
True
If we set another site, that one will be considered current:
.. doctest::
>>> site2 = Site()
>>> site2.registry is not site1.registry
True
>>> setSite(site2)
>>> getSite() is site2
True
>>> getSiteManager() is site2.registry
True
However, the default `zope.component.getSiteManager` function isn't
yet aware of this:
.. doctest::
>>> from zope.component import getSiteManager as global_getSiteManager
>>> global_getSiteManager()
<BaseGlobalComponents base>
To integrate that with the notion of the current site, we need to call ``setHooks``:
.. autofunction:: setHooks
.. doctest::
>>> from zope.component.hooks import setHooks
>>> setHooks()
>>> getSiteManager() is site2.registry
True
>>> global_getSiteManager() is site2.registry
True
This can be reversed using ``resetHooks``:
.. autofunction:: resetHooks
.. doctest::
>>> from zope.component.hooks import resetHooks
>>> resetHooks()
>>> global_getSiteManager()
<BaseGlobalComponents base>
Finally we can unset the site and the global component registry is used again:
.. doctest::
>>> setSite()
>>> print(getSite())
None
>>> getSiteManager()
<BaseGlobalComponents base>
Context manager
===============
There also is a context manager for setting the site, which is especially
useful when writing tests:
.. autofunction:: site
.. doctest::
>>> import zope.component.hooks
>>> print(getSite())
None
>>> with zope.component.hooks.site(site2):
... getSite() is site2
True
>>> print(getSite())
None
The site is properly restored even if the body of the with statement
raises an exception:
.. doctest::
>>> print(getSite())
None
>>> with zope.component.hooks.site(site2):
... getSite() is site2
... raise ValueError('An error in the body')
Traceback (most recent call last):
...
ValueError: An error in the body
>>> print(getSite())
None
|