diff options
| author | Steve Piercy <web@stevepiercy.com> | 2015-12-04 02:17:44 -0800 |
|---|---|---|
| committer | Steve Piercy <web@stevepiercy.com> | 2015-12-04 02:17:44 -0800 |
| commit | acfdc7085b836045e41568731e5f3223f34d635d (patch) | |
| tree | 55e563a1d2892b77fa2b2787e75130151884686f /docs/narr/zca.rst | |
| parent | fd404c0dc268fe71d39875e74ea4ff5ee68489ef (diff) | |
| download | pyramid-acfdc7085b836045e41568731e5f3223f34d635d.tar.gz pyramid-acfdc7085b836045e41568731e5f3223f34d635d.tar.bz2 pyramid-acfdc7085b836045e41568731e5f3223f34d635d.zip | |
- add emphasize lines, minor grammar, rewrap 79 columns
Diffstat (limited to 'docs/narr/zca.rst')
| -rw-r--r-- | docs/narr/zca.rst | 257 |
1 files changed, 121 insertions, 136 deletions
diff --git a/docs/narr/zca.rst b/docs/narr/zca.rst index b0e9b1709..784886563 100644 --- a/docs/narr/zca.rst +++ b/docs/narr/zca.rst @@ -9,17 +9,16 @@ .. _zca_chapter: Using the Zope Component Architecture in :app:`Pyramid` -========================================================== +======================================================= -Under the hood, :app:`Pyramid` uses a :term:`Zope Component -Architecture` component registry as its :term:`application registry`. -The Zope Component Architecture is referred to colloquially as the -"ZCA." +Under the hood, :app:`Pyramid` uses a :term:`Zope Component Architecture` +component registry as its :term:`application registry`. The Zope Component +Architecture is referred to colloquially as the "ZCA." The ``zope.component`` API used to access data in a traditional Zope -application can be opaque. For example, here is a typical "unnamed -utility" lookup using the :func:`zope.component.getUtility` global API -as it might appear in a traditional Zope application: +application can be opaque. For example, here is a typical "unnamed utility" +lookup using the :func:`zope.component.getUtility` global API as it might +appear in a traditional Zope application: .. code-block:: python :linenos: @@ -28,23 +27,21 @@ as it might appear in a traditional Zope application: from zope.component import getUtility settings = getUtility(ISettings) -After this code runs, ``settings`` will be a Python dictionary. But -it's unlikely that any "civilian" will be able to figure this out just -by reading the code casually. When the ``zope.component.getUtility`` -API is used by a developer, the conceptual load on a casual reader of -code is high. +After this code runs, ``settings`` will be a Python dictionary. But it's +unlikely that any "civilian" will be able to figure this out just by reading +the code casually. When the ``zope.component.getUtility`` API is used by a +developer, the conceptual load on a casual reader of code is high. -While the ZCA is an excellent tool with which to build a *framework* -such as :app:`Pyramid`, it is not always the best tool with which -to build an *application* due to the opacity of the ``zope.component`` -APIs. Accordingly, :app:`Pyramid` tends to hide the presence of the -ZCA from application developers. You needn't understand the ZCA to -create a :app:`Pyramid` application; its use is effectively only a -framework implementation detail. +While the ZCA is an excellent tool with which to build a *framework* such as +:app:`Pyramid`, it is not always the best tool with which to build an +*application* due to the opacity of the ``zope.component`` APIs. Accordingly, +:app:`Pyramid` tends to hide the presence of the ZCA from application +developers. You needn't understand the ZCA to create a :app:`Pyramid` +application; its use is effectively only a framework implementation detail. -However, developers who are already used to writing :term:`Zope` -applications often still wish to use the ZCA while building a -:app:`Pyramid` application; :app:`Pyramid` makes this possible. +However, developers who are already used to writing :term:`Zope` applications +often still wish to use the ZCA while building a :app:`Pyramid` application. +:app:`Pyramid` makes this possible. .. index:: single: get_current_registry @@ -52,87 +49,81 @@ applications often still wish to use the ZCA while building a single: getSiteManager single: ZCA global API -Using the ZCA Global API in a :app:`Pyramid` Application ------------------------------------------------------------ - -:term:`Zope` uses a single ZCA registry -- the "global" ZCA registry --- for all Zope applications that run in the same Python process, -effectively making it impossible to run more than one Zope application -in a single process. - -However, for ease of deployment, it's often useful to be able to run more -than a single application per process. For example, use of a -:term:`PasteDeploy` "composite" allows you to run separate individual WSGI -applications in the same process, each answering requests for some URL -prefix. This makes it possible to run, for example, a TurboGears application -at ``/turbogears`` and a :app:`Pyramid` application at ``/pyramid``, both -served up using the same :term:`WSGI` server within a single Python process. - -Most production Zope applications are relatively large, making it -impractical due to memory constraints to run more than one Zope -application per Python process. However, a :app:`Pyramid` application -may be very small and consume very little memory, so it's a reasonable -goal to be able to run more than one :app:`Pyramid` application per -process. - -In order to make it possible to run more than one :app:`Pyramid` -application in a single process, :app:`Pyramid` defaults to using a -separate ZCA registry *per application*. - -While this services a reasonable goal, it causes some issues when -trying to use patterns which you might use to build a typical -:term:`Zope` application to build a :app:`Pyramid` application. -Without special help, ZCA "global" APIs such as -:func:`zope.component.getUtility` and :func:`zope.component.getSiteManager` -will use the ZCA "global" registry. Therefore, these APIs -will appear to fail when used in a :app:`Pyramid` application, -because they'll be consulting the ZCA global registry rather than the -component registry associated with your :app:`Pyramid` application. - -There are three ways to fix this: by disusing the ZCA global API -entirely, by using -:meth:`pyramid.config.Configurator.hook_zca` or by passing -the ZCA global registry to the :term:`Configurator` constructor at -startup time. We'll describe all three methods in this section. +Using the ZCA global API in a :app:`Pyramid` application +-------------------------------------------------------- + +:term:`Zope` uses a single ZCA registry—the "global" ZCA registry—for all Zope +applications that run in the same Python process, effectively making it +impossible to run more than one Zope application in a single process. + +However, for ease of deployment, it's often useful to be able to run more than +a single application per process. For example, use of a :term:`PasteDeploy` +"composite" allows you to run separate individual WSGI applications in the same +process, each answering requests for some URL prefix. This makes it possible +to run, for example, a TurboGears application at ``/turbogears`` and a +:app:`Pyramid` application at ``/pyramid``, both served up using the same +:term:`WSGI` server within a single Python process. + +Most production Zope applications are relatively large, making it impractical +due to memory constraints to run more than one Zope application per Python +process. However, a :app:`Pyramid` application may be very small and consume +very little memory, so it's a reasonable goal to be able to run more than one +:app:`Pyramid` application per process. + +In order to make it possible to run more than one :app:`Pyramid` application in +a single process, :app:`Pyramid` defaults to using a separate ZCA registry *per +application*. + +While this services a reasonable goal, it causes some issues when trying to use +patterns which you might use to build a typical :term:`Zope` application to +build a :app:`Pyramid` application. Without special help, ZCA "global" APIs +such as :func:`zope.component.getUtility` and +:func:`zope.component.getSiteManager` will use the ZCA "global" registry. +Therefore, these APIs will appear to fail when used in a :app:`Pyramid` +application, because they'll be consulting the ZCA global registry rather than +the component registry associated with your :app:`Pyramid` application. + +There are three ways to fix this: by disusing the ZCA global API entirely, by +using :meth:`pyramid.config.Configurator.hook_zca` or by passing the ZCA global +registry to the :term:`Configurator` constructor at startup time. We'll +describe all three methods in this section. .. index:: single: request.registry .. _disusing_the_global_zca_api: -Disusing the Global ZCA API +Disusing the global ZCA API +++++++++++++++++++++++++++ ZCA "global" API functions such as ``zope.component.getSiteManager``, ``zope.component.getUtility``, :func:`zope.component.getAdapter`, and :func:`zope.component.getMultiAdapter` aren't strictly necessary. Every -component registry has a method API that offers the same -functionality; it can be used instead. For example, presuming the -``registry`` value below is a Zope Component Architecture component -registry, the following bit of code is equivalent to -``zope.component.getUtility(IFoo)``: +component registry has a method API that offers the same functionality; it can +be used instead. For example, presuming the ``registry`` value below is a Zope +Component Architecture component registry, the following bit of code is +equivalent to ``zope.component.getUtility(IFoo)``: .. code-block:: python registry.getUtility(IFoo) -The full method API is documented in the ``zope.component`` package, -but it largely mirrors the "global" API almost exactly. +The full method API is documented in the ``zope.component`` package, but it +largely mirrors the "global" API almost exactly. -If you are willing to disuse the "global" ZCA APIs and use the method -interface of a registry instead, you need only know how to obtain the -:app:`Pyramid` component registry. +If you are willing to disuse the "global" ZCA APIs and use the method interface +of a registry instead, you need only know how to obtain the :app:`Pyramid` +component registry. There are two ways of doing so: -- use the :func:`pyramid.threadlocal.get_current_registry` - function within :app:`Pyramid` view or resource code. This will - always return the "current" :app:`Pyramid` application registry. +- use the :func:`pyramid.threadlocal.get_current_registry` function within + :app:`Pyramid` view or resource code. This will always return the "current" + :app:`Pyramid` application registry. -- use the attribute of the :term:`request` object named ``registry`` - in your :app:`Pyramid` view code, eg. ``request.registry``. This - is the ZCA component registry related to the running - :app:`Pyramid` application. +- use the attribute of the :term:`request` object named ``registry`` in your + :app:`Pyramid` view code, e.g., ``request.registry``. This is the ZCA + component registry related to the running :app:`Pyramid` application. See :ref:`threadlocals_chapter` for more information about :func:`pyramid.threadlocal.get_current_registry`. @@ -142,7 +133,7 @@ See :ref:`threadlocals_chapter` for more information about .. _hook_zca: -Enabling the ZCA Global API by Using ``hook_zca`` +Enabling the ZCA global API by using ``hook_zca`` +++++++++++++++++++++++++++++++++++++++++++++++++ Consider the following bit of idiomatic :app:`Pyramid` startup code: @@ -157,34 +148,31 @@ Consider the following bit of idiomatic :app:`Pyramid` startup code: config.include('some.other.package') return config.make_wsgi_app() -When the ``app`` function above is run, a :term:`Configurator` is -constructed. When the configurator is created, it creates a *new* -:term:`application registry` (a ZCA component registry). A new -registry is constructed whenever the ``registry`` argument is omitted -when a :term:`Configurator` constructor is called, or when a -``registry`` argument with a value of ``None`` is passed to a -:term:`Configurator` constructor. - -During a request, the application registry created by the Configurator -is "made current". This means calls to -:func:`~pyramid.threadlocal.get_current_registry` in the thread -handling the request will return the component registry associated -with the application. - -As a result, application developers can use ``get_current_registry`` -to get the registry and thus get access to utilities and such, as per -:ref:`disusing_the_global_zca_api`. But they still cannot use the -global ZCA API. Without special treatment, the ZCA global APIs will -always return the global ZCA registry (the one in -``zope.component.globalregistry.base``). - -To "fix" this and make the ZCA global APIs use the "current" -:app:`Pyramid` registry, you need to call -:meth:`~pyramid.config.Configurator.hook_zca` within your setup code. -For example: +When the ``app`` function above is run, a :term:`Configurator` is constructed. +When the configurator is created, it creates a *new* :term:`application +registry` (a ZCA component registry). A new registry is constructed whenever +the ``registry`` argument is omitted, when a :term:`Configurator` constructor +is called, or when a ``registry`` argument with a value of ``None`` is passed +to a :term:`Configurator` constructor. + +During a request, the application registry created by the Configurator is "made +current". This means calls to +:func:`~pyramid.threadlocal.get_current_registry` in the thread handling the +request will return the component registry associated with the application. + +As a result, application developers can use ``get_current_registry`` to get the +registry and thus get access to utilities and such, as per +:ref:`disusing_the_global_zca_api`. But they still cannot use the global ZCA +API. Without special treatment, the ZCA global APIs will always return the +global ZCA registry (the one in ``zope.component.globalregistry.base``). + +To "fix" this and make the ZCA global APIs use the "current" :app:`Pyramid` +registry, you need to call :meth:`~pyramid.config.Configurator.hook_zca` within +your setup code. For example: .. code-block:: python :linenos: + :emphasize-lines: 5 from pyramid.config import Configurator @@ -194,9 +182,9 @@ For example: config.include('some.other.application') return config.make_wsgi_app() -We've added a line to our original startup code, line number 6, which -calls ``config.hook_zca()``. The effect of this line under the hood -is that an analogue of the following code is executed: +We've added a line to our original startup code, line number 5, which calls +``config.hook_zca()``. The effect of this line under the hood is that an +analogue of the following code is executed: .. code-block:: python :linenos: @@ -205,17 +193,15 @@ is that an analogue of the following code is executed: from pyramid.threadlocal import get_current_registry getSiteManager.sethook(get_current_registry) -This causes the ZCA global API to start using the :app:`Pyramid` -application registry in threads which are running a :app:`Pyramid` -request. +This causes the ZCA global API to start using the :app:`Pyramid` application +registry in threads which are running a :app:`Pyramid` request. -Calling ``hook_zca`` is usually sufficient to "fix" the problem of -being able to use the global ZCA API within a :app:`Pyramid` -application. However, it also means that a Zope application that is -running in the same process may start using the :app:`Pyramid` -global registry instead of the Zope global registry, effectively -inverting the original problem. In such a case, follow the steps in -the next section, :ref:`using_the_zca_global_registry`. +Calling ``hook_zca`` is usually sufficient to "fix" the problem of being able +to use the global ZCA API within a :app:`Pyramid` application. However, it +also means that a Zope application that is running in the same process may +start using the :app:`Pyramid` global registry instead of the Zope global +registry, effectively inverting the original problem. In such a case, follow +the steps in the next section, :ref:`using_the_zca_global_registry`. .. index:: single: get_current_registry @@ -224,14 +210,15 @@ the next section, :ref:`using_the_zca_global_registry`. .. _using_the_zca_global_registry: -Enabling the ZCA Global API by Using The ZCA Global Registry +Enabling the ZCA global API by using the ZCA global registry ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -You can tell your :app:`Pyramid` application to use the ZCA global -registry at startup time instead of constructing a new one: +You can tell your :app:`Pyramid` application to use the ZCA global registry at +startup time instead of constructing a new one: .. code-block:: python :linenos: + :emphasize-lines: 5-7 from zope.component import getGlobalSiteManager from pyramid.config import Configurator @@ -243,16 +230,14 @@ registry at startup time instead of constructing a new one: config.include('some.other.application') return config.make_wsgi_app() -Lines 5, 6, and 7 above are the interesting ones. Line 5 retrieves -the global ZCA component registry. Line 6 creates a -:term:`Configurator`, passing the global ZCA registry into its -constructor as the ``registry`` argument. Line 7 "sets up" the global -registry with Pyramid-specific registrations; this is code that is -normally executed when a registry is constructed rather than created, +Lines 5, 6, and 7 above are the interesting ones. Line 5 retrieves the global +ZCA component registry. Line 6 creates a :term:`Configurator`, passing the +global ZCA registry into its constructor as the ``registry`` argument. Line 7 +"sets up" the global registry with Pyramid-specific registrations; this is code +that is normally executed when a registry is constructed rather than created, but we must call it "by hand" when we pass an explicit registry. -At this point, :app:`Pyramid` will use the ZCA global registry -rather than creating a new application-specific registry; since by -default the ZCA global API will use this registry, things will work as -you might expect a Zope app to when you use the global ZCA API. - +At this point, :app:`Pyramid` will use the ZCA global registry rather than +creating a new application-specific registry. Since by default the ZCA global +API will use this registry, things will work as you might expect in a Zope app +when you use the global ZCA API. |
