File: hooks.rst

package info (click to toggle)
zope.component 4.3.0-3
  • links: PTS
  • area: main
  • in suites: bookworm, bullseye, sid
  • size: 780 kB
  • sloc: python: 5,600; makefile: 130
file content (112 lines) | stat: -rw-r--r-- 2,791 bytes parent folder | download | duplicates (3)
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
==============================
The current component registry
==============================

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 ``zope.component.hooks`` module
provides an API to set and access the current site as well as manipulate the
adapter hook associated with it.

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:

.. 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``:

.. 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

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:

.. 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