diff options
| author | Chris McDonough <chrism@plope.com> | 2010-11-03 23:11:07 -0400 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2010-11-03 23:11:07 -0400 |
| commit | c7c40b9b3b3c0008185f1a44a2aba4f95f29abd0 (patch) | |
| tree | 839bf0a16a3add905e58dc037703ce400f1fa43e /docs/narr/configuration.rst | |
| parent | 108698b020c4b360c180ab3faa6f11e45a51439c (diff) | |
| download | pyramid-c7c40b9b3b3c0008185f1a44a2aba4f95f29abd0.tar.gz pyramid-c7c40b9b3b3c0008185f1a44a2aba4f95f29abd0.tar.bz2 pyramid-c7c40b9b3b3c0008185f1a44a2aba4f95f29abd0.zip | |
de-zcml-ify various chapters and move ZCML to the declarative chapter
Diffstat (limited to 'docs/narr/configuration.rst')
| -rw-r--r-- | docs/narr/configuration.rst | 317 |
1 files changed, 43 insertions, 274 deletions
diff --git a/docs/narr/configuration.rst b/docs/narr/configuration.rst index cbc49d94b..82d0c8dda 100644 --- a/docs/narr/configuration.rst +++ b/docs/narr/configuration.rst @@ -6,30 +6,30 @@ Application Configuration ========================= -Each deployment of an application written using :mod:`pyramid` -implies a specific *configuration* of the framework itself. For -example, an application which serves up MP3s for user consumption -might plug code into the framework that manages songs, while an -application that manages corporate data might plug in code that -manages accounting information. :mod:`pyramid` refers to the way -in which code is plugged in to it for a specific application as -"configuration". - -Most people understand "configuration" as coarse settings that inform -the high-level operation of a specific application deployment. For -instance, it's easy to think of the values implied by a ``.ini`` file -parsed at application startup time as "configuration". -:mod:`pyramid` extends this pattern to application development, -using the term "configuration" to express standardized ways that code -gets plugged into a deployment of the framework itself. When you plug -code into the :mod:`pyramid` framework, you are "configuring" -:mod:`pyramid` for the purpose of creating a particular application -deployment. - -There are two different mechanisms you may use to configure -:mod:`pyramid` to create an application: *imperative* configuration -and *declarative* configuration. We'll examine both modes in the -sections which follow. +Each deployment of an application written using :mod:`pyramid` implies a +specific *configuration* of the framework itself. For example, an +application which serves up MP3s for user consumption might plug code into +the framework that manages songs, while an application that manages corporate +data might plug in code that manages accounting information. :mod:`pyramid` +refers to the way in which code is plugged in to it for a specific +application as "configuration". + +Most people understand "configuration" as coarse settings that inform the +high-level operation of a specific application deployment. For instance, +it's easy to think of the values implied by a ``.ini`` file parsed at +application startup time as "configuration". :mod:`pyramid` extends this +pattern to application development, using the term "configuration" to express +standardized ways that code gets plugged into a deployment of the framework +itself. When you plug code into the :mod:`pyramid` framework, you are +"configuring" :mod:`pyramid` for the purpose of creating a particular +application deployment. + +There are two different mechanisms you may use to configure :mod:`pyramid` to +create an application: *imperative* configuration and *declarative* +configuration. We'll be using primarily the *imperative* configuration +method in this book, for the sake of brevity and simplicity. For information +about how to define application configuration declaratively, see +:ref:`declarative_chapter`. .. index:: single: imperative configuration @@ -39,13 +39,6 @@ sections which follow. Imperative Configuration ------------------------ -Experienced Python programmers might find that performing -configuration "imperatively" fits their brain best. This is the -configuration mode in which a developer cedes the least amount of -control to the framework; it's "imperative" because you express the -configuration directly in Python code, and you have the full power of -Python at your disposal as you issue configuration statements. - Here's one of the simplest :mod:`pyramid` applications, configured imperatively: @@ -77,201 +70,22 @@ power of Python, including conditionals, can be employed in this mode of configuration. .. index:: - single: declarative configuration - -.. _declarative_configuration: - -Declarative Configuration -------------------------- - -A :mod:`pyramid` application can be alternately be configured -"declaratively", if so desired. Declarative configuration relies on -*declarations* made external to the code in a configuration file -format named :term:`ZCML` (Zope Configuration Markup Language), an XML -dialect. - -A :mod:`pyramid` application configured declaratively requires not -one, but two files: a Python file and a :term:`ZCML` file. - -In a file named ``helloworld.py``: - -.. code-block:: python - :linenos: - - from paste.httpserver import serve - from pyramid.response import Response - from pyramid.configuration import Configurator - - def hello_world(request): - return Response('Hello world!') - - if __name__ == '__main__': - config = Configurator() - config.begin() - config.load_zcml('configure.zcml') - config.end() - app = config.make_wsgi_app() - serve(app, host='0.0.0.0') - -In a file named ``configure.zcml`` in the same directory as the -previously created ``helloworld.py``: - -.. code-block:: xml - :linenos: - - <configure xmlns="http://pylonshq.com/pyramid"> - - <include package="pyramid.includes" /> - - <view - view="helloworld.hello_world" - /> - - </configure> - -This pair of files forms an application functionally equivalent to the -application we created earlier in :ref:`imperative_configuration`. -Let's examine the differences between that code listing and the code -above. - -In :ref:`imperative_configuration`, we had the following lines within -the ``if __name__ == '__main__'`` section of ``helloworld.py``: - -.. code-block:: python - :linenos: - - if __name__ == '__main__': - config = Configurator() - config.begin() - config.add_view(hello_world) - config.end() - app = config.make_wsgi_app() - serve(app, host='0.0.0.0') - -In our "declarative" code, we've removed the call to ``add_view`` and -replaced it with a call to the -:meth:`pyramid.configuration.Configurator.load_zcml` method so that -it now reads as: - -.. code-block:: python - :linenos: - - if __name__ == '__main__': - config = Configurator() - config.begin() - config.load_zcml('configure.zcml') - config.end() - app = config.make_wsgi_app() - serve(app, host='0.0.0.0') - -Everything else is much the same. - -The ``config.load_zcml('configure.zcml')`` line tells the configurator -to load configuration declarations from the file named -``configure.zcml`` which sits next to ``helloworld.py`` on the -filesystem. Let's take a look at that ``configure.zcml`` file again: - -.. code-block:: xml - :linenos: - - <configure xmlns="http://pylonshq.com/pyramid"> - - <include package="pyramid.includes" /> - - <view - view="helloworld.hello_world" - /> - - </configure> - -Note that this file contains some XML, and that the XML contains a -``<view>`` :term:`configuration declaration` tag that references a -:term:`dotted Python name`. This dotted name refers to the -``hello_world`` function that lives in our ``helloworld`` Python -module. - -This ``<view>`` declaration tag performs the same function as the -``add_view`` method that was employed within -:ref:`imperative_configuration`. In fact, the ``<view>`` tag is -effectively a "macro" which calls the -:meth:`pyramid.configuration.Configurator.add_view` method on your -behalf. - -The ``<view>`` tag is an example of a :mod:`pyramid` declaration -tag. Other such tags include ``<route>`` and ``<scan>``. Each of -these tags is effectively a "macro" which calls methods of a -:class:`pyramid.configuration.Configurator` object on your behalf. - -Essentially, using a :term:`ZCML` file and loading it from the -filesystem allows us to put our configuration statements within this -XML file rather as declarations, rather than representing them as -method calls to a :term:`Configurator` object. Otherwise, declarative -and imperative configuration are functionally equivalent. - -Using declarative configuration has a number of benefits, the primary -benefit being that applications configured declaratively can be -*overridden* and *extended* by third parties without requiring the -third party to change application code. If you want to build a -framework or an extensible application, using declarative -configuration is a good idea. - -Declarative configuration has an obvious downside: you can't use -plain-old-Python syntax you probably already know and understand to -configure your application; instead you need to use :term:`ZCML`. - -.. index:: - single: ZCML conflict detection - -ZCML Conflict Detection -~~~~~~~~~~~~~~~~~~~~~~~ - -A minor additional feature of ZCML is *conflict detection*. If you -define two declaration tags within the same ZCML file which logically -"collide", an exception will be raised, and the application will not -start. For example, the following ZCML file has two conflicting -``<view>`` tags: - -.. code-block:: xml - :linenos: - - <configure xmlns="http://pylonshq.com/pyramid"> - - <include package="pyramid.includes" /> - - <view - view="helloworld.hello_world" - /> - - <view - view="helloworld.hello_world" - /> - - </configure> - -If you try to use this ZCML file as the source of ZCML for an -application, an error will be raised when you attempt to start the -application. This error will contain information about which tags -might have conflicted. - -.. index:: single: view_config - single: ZCML view directive single: configuration decoration single: code scanning .. _decorations_and_code_scanning: Configuration Decorations and Code Scanning -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -An alternate mode of declarative configuration lends more *locality of -reference* to a :term:`configuration declaration`. It's sometimes -painful to have all configuration done in ZCML, or even in imperative -code, because you may need to have two files open at once to see the -"big picture": the file that represents the configuration, and the -file that contains the implementation objects referenced by the -configuration. To avoid this, :mod:`pyramid` allows you to insert -:term:`configuration decoration` statements very close to code that is +------------------------------------------- + +An alternate mode of configuration lends more *locality of reference* to a +:term:`configuration declaration`. It's sometimes painful to have all +configuration done in imperative code, because you may need to have two files +open at once to see the "big picture": the file that represents the +configuration, and the file that contains the implementation objects +referenced by the configuration. To avoid this, :mod:`pyramid` allows you to +insert :term:`configuration decoration` statements very close to code that is referred to by the declaration itself. For example: .. code-block:: python @@ -322,46 +136,6 @@ and its subpackages. For example: app = config.make_wsgi_app() serve(app, host='0.0.0.0') -:term:`ZCML` can also invoke a :term:`scan` via its ``<scan>`` -directive. If a ZCML file is processed that contains a scan -directive, the package the ZCML file points to is scanned. - -.. topic:: Declaratively Starting a Scan - - .. code-block:: python - :linenos: - - # helloworld.py - - from paste.httpserver import serve - from pyramid.response import Response - from pyramid.view import view_config - - @view_config() - def hello(request): - return Response('Hello') - - if __name__ == '__main__': - from pyramid.configuration import Configurator - config = Configurator() - config.begin() - config.load_zcml('configure.zcml') - config.end() - app = config.make_wsgi_app() - serve(app, host='0.0.0.0') - - .. code-block:: xml - :linenos: - - <configure xmlns="http://namespaces.repoze.org"> - - <!-- configure.zcml --> - - <include package="pyramid.includes"/> - <scan package="."/> - - </configure> - The scanning machinery imports each module and subpackage in a package or module recursively, looking for special attributes attached to objects defined within a module. These special attributes are @@ -384,20 +158,15 @@ method, effectively: config.add_view(hello) -Which Mode Should I Use? ------------------------- - -A combination of imperative configuration, declarative configuration -via ZCML and scanning can be used to configure any application. They -are not mutually exclusive. +Declarative Configuration +------------------------- -The :mod:`pyramid` authors often recommend using mostly declarative -configuration, because it's the more traditional form of configuration -used in :mod:`pyramid` applications, it can be overridden and -extended by third party deployers, and there are more examples for it -"in the wild". +A third mode of configuration can be employed when you create a +:mod:`pyramid` application named *declarative configuration*. This mode uses +:term:`ZCML` to represent configuration statements rather than Python. ZCML +is often used when application extensibility is important. Most of the +examples in the narrative portion of this documentation concentrate on +imperative configuration rather than ZCML, but almost everything that can be +configured imperatively can also be configured via ZCML. See +:ref:`declarative_chapter` for more information about ZCML. -However, imperative mode configuration can be simpler to understand, -and the framework is not "opinionated" about the choice. This book -presents examples in both styles, mostly interchangeably. You can -choose the mode that best fits your brain as necessary. |
