diff -r 6ed429390935 -r 5ebe61e3a965 src/source/zca.rst --- a/src/source/zca.rst Fri Apr 20 16:52:49 2018 +0200 +++ b/src/source/zca.rst Fri Apr 27 11:51:08 2018 +0200 @@ -1,7 +1,7 @@ .. _zca: Zope Component Architecture with PyAMS -====================================== +++++++++++++++++++++++++++++++++++++++ The **Zope Component Architecture** (aka **ZCA**) is used by the Pyramid framework "under the hood" to handle interfaces, adapters and utilities. You don't **have to** use it in your own applications. But you can. @@ -9,64 +9,55 @@ The ZCA is mainly adding elements like **interfaces**, **adapters** and **utilities** to the Python language. It allows you to write a framework or an application by using **components** which can be extended easily. +Interfaces + Interfaces are objects that specify (document) the external behavior + of objects that "provide" them. An interface specifies behavior through, a documentation in a doc string, + attribute definitions and conditions of attribute values. + +Components + Components are objects that are associated with interfaces. + +Utilities + Utilities are just components that provide an interface and that are looked up by an interface and a name + +Adapters + Adapters are components that are computed from other components to adapt them to some interface. + Because they are computed from other objects, they are provided as factories, usually classes. + + You will find several useful resources about ZCA concepts on the internet. - .. seealso:: Zope Documentations: - - `Components and Interfaces `_ - - `Zope component `_ - - `Zope interface `_ + - `Components and Interfaces `_ + - `Zope component `_ + - `Zope interface `_ +Utilities +--------- + Local utilities ---------------- +''''''''''''''' In ZCA, a **utility** is a **registered** component which provides an **interface**. This interface is the **contract** which defines features (list of attributes and methods) provided by the component which implements it. When a Pyramid application starts, a **global registry** is created to register a whole set of utilities and adapters; this registration can be done via ZCML directives or via native Python code. -In addition, PyAMS allows you to define **local utilities**, which are stored and registered in the ZODB via a **site -manager**. - - -Defining site root ------------------- - -One of PyAMS pre-requisites is to use the ZODB, at least to store the site root application, it's configuration and a -set of local utilities. :ref:`site` describes application startup and **local site manager** initialization process. - -This site can be used to store **local utilities** whose configuration, which is easily available to site -administrators through management interface, is stored in the ZODB. - - -Registering global utilities ----------------------------- - -**Global utilities** are components providing an interface which are registered in the global registry. -PyAMS_utils package provides custom annotations to register global utilities without using ZCML. For example, a skin -is nothing more than a simple utility providing the *ISkin* interface: - -.. code-block:: python - - from pyams_default_theme.layer import IPyAMSDefaultLayer - from pyams_skin.interfaces import ISkin - from pyams_utils.registry import utility_config - - @utility_config(name='PyAMS default skin', provides=ISkin) - class PyAMSDefaultSkin(object): - """PyAMS default skin""" - - label = _("PyAMS default skin") - layer = IPyAMSDefaultLayer - -This annotation registers a utility, named *PyAMS default skin*, providing the *ISkin* interface. It's the developer -responsibility to provide all attributes and methods required by the provided interface. +In addition, PyAMS allows you to define **local utilities**, which are stored and registered in the ZODB via a +**site manager**. Registering local utilities ---------------------------- +''''''''''''''''''''''''''' + + +.. tip:: + + :ref:`site` can be used to store **local utilities** whose configuration, which is easily + available to site administrators through management interface, is stored in the ZODB. + A local utility is a persistent object, registered in a *local site manager*, and providing a specific interface (if a component provides several interfaces, it can be registered several times). @@ -150,8 +141,32 @@ by an event is providing given interface. +Registering global utilities +'''''''''''''''''''''''''''' + +**Global utilities** are components providing an interface which are registered in the global registry. +PyAMS_utils package provides custom annotations to register global utilities without using ZCML. For example, a skin +is nothing more than a simple utility providing the *ISkin* interface: + +.. code-block:: python + + from pyams_default_theme.layer import IPyAMSDefaultLayer + from pyams_skin.interfaces import ISkin + from pyams_utils.registry import utility_config + + @utility_config(name='PyAMS default skin', provides=ISkin) + class PyAMSDefaultSkin(object): + """PyAMS default skin""" + + label = _("PyAMS default skin") + layer = IPyAMSDefaultLayer + +This annotation registers a utility, named *PyAMS default skin*, providing the *ISkin* interface. It's the developer +responsibility to provide all attributes and methods required by the provided interface. + + Looking for utilities ---------------------- +''''''''''''''''''''' ZCA provides the *getUtility* and *queryUtility* functions to look for a utility. But these methods only applies to global registry. @@ -173,8 +188,11 @@ functions API, but are looking for utilities in the local registry before looking in the global registry. +Adapters +-------- + Registering adapters --------------------- +'''''''''''''''''''' An adapter is also a kind of utility. But instead of *just* providing an interface, it adapts an input object, providing a given interface, to provide another interface. An adapter can also be named, so that you can choose which @@ -248,8 +266,11 @@ As you can see, adapted objects can be given as functions or as classes. +Vocabularies +------------ + Registering vocabularies ------------------------- +'''''''''''''''''''''''' A **vocabulary** is a custom factory which can be used as source for several field types, like *choices* or *lists*. Vocabularies have to be registered in a custom registry, so PyAMS_utils provide another annotation to register them. @@ -268,3 +289,7 @@ def __init__(self, *args, **kw): terms = [SimpleTerm(t, t, t) for t in pytz.all_timezones] super(TimezonesVocabulary, self).__init__(terms) + + + +