1 .. _zca: |
1 .. _zca: |
2 |
2 |
3 Managing ZCA with PyAMS |
3 Zope Component Architecture with PyAMS |
4 ======================= |
4 ++++++++++++++++++++++++++++++++++++++ |
5 |
5 |
6 The **Zope Component Architecture** (aka ZCA) is used by the Pyramid framework "under the hood" to handle interfaces, |
6 The **Zope Component Architecture** (aka **ZCA**) is used by the Pyramid framework "under the hood" to handle interfaces, |
7 adapters and utilities. You don't **have to** use it in your own applications. But you can. |
7 adapters and utilities. You don't **have to** use it in your own applications. But you can. |
8 |
8 |
9 The ZCA is mainly adding elements like **interfaces**, **adapters** and **utilities** to the Python language. It |
9 The ZCA is mainly adding elements like **interfaces**, **adapters** and **utilities** to the Python language. It |
10 allows you to write a framework or an application by using **components** which can be extended easily. |
10 allows you to write a framework or an application by using **components** which can be extended easily. |
11 |
11 |
|
12 Interfaces |
|
13 Interfaces are objects that specify (document) the external behavior |
|
14 of objects that "provide" them. An interface specifies behavior through, a documentation in a doc string, |
|
15 attribute definitions and conditions of attribute values. |
|
16 |
|
17 Components |
|
18 Components are objects that are associated with interfaces. |
|
19 |
|
20 Utilities |
|
21 Utilities are just components that provide an interface and that are looked up by an interface and a name |
|
22 |
|
23 Adapters |
|
24 Adapters are components that are computed from other components to adapt them to some interface. |
|
25 Because they are computed from other objects, they are provided as factories, usually classes. |
|
26 |
|
27 |
12 You will find several useful resources about ZCA concepts on the internet. |
28 You will find several useful resources about ZCA concepts on the internet. |
13 |
29 |
|
30 .. seealso:: |
|
31 Zope Documentations: |
|
32 - `Components and Interfaces <http://zope.readthedocs.io/en/latest/zdgbook/ComponentsAndInterfaces.html>`_ |
|
33 - `Zope component <http://zopecomponent.readthedocs.io/en/latest/narr.html>`_ |
|
34 - `Zope interface <https://docs.zope.org/zope.interface/README.html>`_ |
|
35 |
|
36 |
|
37 Utilities |
|
38 --------- |
14 |
39 |
15 Local utilities |
40 Local utilities |
16 --------------- |
41 ''''''''''''''' |
17 |
42 |
18 In ZCA, a **utility** is a **registered** component which provides an **interface**. This interface is the |
43 In ZCA, a **utility** is a **registered** component which provides an **interface**. This interface is the |
19 **contract** which defines features (list of attributes and methods) provided by the component which implements it. |
44 **contract** which defines features (list of attributes and methods) provided by the component which implements it. |
20 |
45 |
21 When a Pyramid application starts, a **global registry** is created to register a whole set of utilities and |
46 When a Pyramid application starts, a **global registry** is created to register a whole set of utilities and |
22 adapters; this registration can be done via ZCML directives or via native Python code. |
47 adapters; this registration can be done via ZCML directives or via native Python code. |
23 In addition, PyAMS allows you to define **local utilities**, which are stored and registered in the ZODB via a **site |
48 In addition, PyAMS allows you to define **local utilities**, which are stored and registered in the ZODB via a |
24 manager**. |
49 **site manager**. |
25 |
|
26 |
|
27 Defining site root |
|
28 ------------------ |
|
29 |
|
30 One of PyAMS pre-requisites is to use the ZODB, at least to store the site root application, it's configuration and a |
|
31 set of local utilities. :ref:`site` describes application startup and **local site manager** initialization process. |
|
32 |
|
33 This site can be used to store **local utilities** whose configuration, which is easily available to site |
|
34 administrators through management interface, is stored in the ZODB. |
|
35 |
|
36 |
|
37 Registering global utilities |
|
38 ---------------------------- |
|
39 |
|
40 **Global utilities** are components providing an interface which are registered in the global registry. |
|
41 PyAMS_utils package provides custom annotations to register global utilities without using ZCML. For example, a skin |
|
42 is nothing more than a simple utility providing the *ISkin* interface: |
|
43 |
|
44 .. code-block:: python |
|
45 |
|
46 from pyams_default_theme.layer import IPyAMSDefaultLayer |
|
47 from pyams_skin.interfaces import ISkin |
|
48 from pyams_utils.registry import utility_config |
|
49 |
|
50 @utility_config(name='PyAMS default skin', provides=ISkin) |
|
51 class PyAMSDefaultSkin(object): |
|
52 """PyAMS default skin""" |
|
53 |
|
54 label = _("PyAMS default skin") |
|
55 layer = IPyAMSDefaultLayer |
|
56 |
|
57 This annotation registers a utility, named *PyAMS default skin*, providing the *ISkin* interface. It's the developer |
|
58 responsibility to provide all attributes and methods required by the provided interface. |
|
59 |
50 |
60 |
51 |
61 Registering local utilities |
52 Registering local utilities |
62 --------------------------- |
53 ''''''''''''''''''''''''''' |
|
54 |
|
55 |
|
56 .. tip:: |
|
57 |
|
58 :ref:`site` can be used to store **local utilities** whose configuration, which is easily |
|
59 available to site administrators through management interface, is stored in the ZODB. |
|
60 |
63 |
61 |
64 A local utility is a persistent object, registered in a *local site manager*, and providing a specific interface (if |
62 A local utility is a persistent object, registered in a *local site manager*, and providing a specific interface (if |
65 a component provides several interfaces, it can be registered several times). |
63 a component provides several interfaces, it can be registered several times). |
66 |
64 |
67 Some components can be required by a given package, and created automatically via the *pyams_upgrade* command line |
65 Some components can be required by a given package, and created automatically via the *pyams_upgrade* command line |
141 |
139 |
142 *context_selector* is a custom subscriber predicate, so that subscriber event is activated only if object concerned |
140 *context_selector* is a custom subscriber predicate, so that subscriber event is activated only if object concerned |
143 by an event is providing given interface. |
141 by an event is providing given interface. |
144 |
142 |
145 |
143 |
|
144 Registering global utilities |
|
145 '''''''''''''''''''''''''''' |
|
146 |
|
147 **Global utilities** are components providing an interface which are registered in the global registry. |
|
148 PyAMS_utils package provides custom annotations to register global utilities without using ZCML. For example, a skin |
|
149 is nothing more than a simple utility providing the *ISkin* interface: |
|
150 |
|
151 .. code-block:: python |
|
152 |
|
153 from pyams_default_theme.layer import IPyAMSDefaultLayer |
|
154 from pyams_skin.interfaces import ISkin |
|
155 from pyams_utils.registry import utility_config |
|
156 |
|
157 @utility_config(name='PyAMS default skin', provides=ISkin) |
|
158 class PyAMSDefaultSkin(object): |
|
159 """PyAMS default skin""" |
|
160 |
|
161 label = _("PyAMS default skin") |
|
162 layer = IPyAMSDefaultLayer |
|
163 |
|
164 This annotation registers a utility, named *PyAMS default skin*, providing the *ISkin* interface. It's the developer |
|
165 responsibility to provide all attributes and methods required by the provided interface. |
|
166 |
|
167 |
146 Looking for utilities |
168 Looking for utilities |
147 --------------------- |
169 ''''''''''''''''''''' |
148 |
170 |
149 ZCA provides the *getUtility* and *queryUtility* functions to look for a utility. But these methods only applies to |
171 ZCA provides the *getUtility* and *queryUtility* functions to look for a utility. But these methods only applies to |
150 global registry. |
172 global registry. |
151 |
173 |
152 PyAMS package provides equivalent functions, which are looking for components into local registry before looking into |
174 PyAMS package provides equivalent functions, which are looking for components into local registry before looking into |
164 All ZCA utility functions have been ported to use local registry: *registered_utilities*, *query_utility*, |
186 All ZCA utility functions have been ported to use local registry: *registered_utilities*, *query_utility*, |
165 *get_utility*, *get_utilities_for*, *get_all_utilities_registered_for* functions all follow the equivalent ZCA |
187 *get_utility*, *get_utilities_for*, *get_all_utilities_registered_for* functions all follow the equivalent ZCA |
166 functions API, but are looking for utilities in the local registry before looking in the global registry. |
188 functions API, but are looking for utilities in the local registry before looking in the global registry. |
167 |
189 |
168 |
190 |
|
191 Adapters |
|
192 -------- |
|
193 |
169 Registering adapters |
194 Registering adapters |
170 -------------------- |
195 '''''''''''''''''''' |
171 |
196 |
172 An adapter is also a kind of utility. But instead of *just* providing an interface, it adapts an input object, |
197 An adapter is also a kind of utility. But instead of *just* providing an interface, it adapts an input object, |
173 providing a given interface, to provide another interface. An adapter can also be named, so that you can choose which |
198 providing a given interface, to provide another interface. An adapter can also be named, so that you can choose which |
174 adapter to use at a given time. |
199 adapter to use at a given time. |
175 |
200 |