diff options
| -rw-r--r-- | CHANGES.txt | 9 | ||||
| -rw-r--r-- | docs/narr/commandline.rst | 151 | ||||
| -rw-r--r-- | docs/whatsnew-1.1.rst | 3 | ||||
| -rw-r--r-- | pyramid/paster.py | 3 |
4 files changed, 166 insertions, 0 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 00ac78835..afbc12747 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,12 @@ +Next release +============ + +Documentation +------------- + +- Added a section entitled "Writing a Script" to the "Command-Line Pyramid" + chapter. + 1.1b3 (2011-07-15) ================== diff --git a/docs/narr/commandline.rst b/docs/narr/commandline.rst index 68078ab70..fccf095d3 100644 --- a/docs/narr/commandline.rst +++ b/docs/narr/commandline.rst @@ -286,3 +286,154 @@ callable could be found. If no routes are configured within your application, nothing will be printed to the console when ``paster proutes`` is executed. +.. _writing_a_script: + +Writing a Script +---------------- + +All web applications are, at their hearts, systems which accept a request and +return a response. When a request is accepted by a :app:`Pyramid` +application, the system receives state from the request which is later relied +on your application code. For example, one :term:`view callable` may assume +it's working against a request that has a ``request.matchdict`` of a +particular composition, while another assumes a different composition of the +matchdict. + +In the meantime, it's convenient to be able to write a Python script that can +work "in a Pyramid environment", for instance to update database tables used +by your :app:`Pyramid` application. But a "real" Pyramid environment doesn't +have a completely static state independent of a request; your application +(and Pyramid itself) is almost always reliant on being able to obtain +information from a request. When you run a Python script that simply imports +code from your application and tries to run it, there just is no request +data, because there isn't any real web request. Therefore some parts of your +application and some Pyramid APIs will not work. + +For this reason, :app:`Pyramid` makes it possible to run a script in an +environment much like the environment produced when a particular +:term:`request` reaches your :app:`Pyramid` application. This is achieved by +using the :func:`pyramid.paster.bootstrap` command in the body of your +script. + +In the simplest case, :func:`pyramid.paster.bootstrap` can be used with a +single argument, which accepts the :term:`PasteDeploy` ``.ini`` file +representing Pyramid your application configuration as a single argument: + +.. code-block:: python + + from pyramid.paster import bootstrap + info = bootstrap('/path/to/my/development.ini') + print info['request'].route_url('home') + +:func:`pyramid.paster.bootstrap` returns a dictionary containing +framework-related information. This dictionary will always contain a +:term:`request` object as its ``request`` key. + +The following keys are also available in the ``info`` dictionary returned by +:func:`~pyramid.paster.bootstrap`: + +request + + A :class:`pyramid.request.Request` object implying the current request + state for your script. + +app + + The :term:`WSGI` application object generated by bootstrapping. + +root + + The :term:`resource` root of your :app:`Pyramid` application. This is an + object generated by the :term:`root factory` configured in your + application. + +registry + + The :term:`application registry` of your :app:`Pyramid` application. + +closer + + A parameterless callable that can be used to pop an internal + :app:`Pyramid` threadlocal stack (used by + :func:`pyramid.threadlocal.get_current_registry` and + :func:`pyramid.threadlocal.get_current_request`) when your scripting job + is finished. + +Let's assume that the ``/path/to/my/development.ini`` file used in the +example above looks like so: + +.. code-block:: ini + + [pipeline:main] + pipeline = egg:WebError#evalerror + another + + [app:another] + use = egg:MyProject + +The configuration loaded by the above bootstrap example will use the +configuration implied by the ``[pipeline:main]`` section of your +configuration file by default. Specifying ``/path/to/my/development.ini`` is +logically equivalent to specifying ``/path/to/my/development.ini#main``. In +this case, we'll be using a configuration that includes an ``app`` object +which is wrapped in the WebError ``evalerror`` middleware. + +You can also specify a particular *section* of the PasteDeploy ``.ini`` file +to load. By default, Pyramid assumes the section name you want to load is +``main``: + +.. code-block:: python + + from pyramid.paster import bootstrap + info = bootstrap('/path/to/my/development.ini#another') + print info['request'].route_url('home') + +The above example specifies the ``another`` ``app``, ``pipeline``, or +``composite`` section of your PasteDeploy configuration file. In the case +that we're using a configuration file that looks like this: + +.. code-block:: ini + + [pipeline:main] + pipeline = egg:WebError#evalerror + another + + [app:another] + use = egg:MyProject + +It will mean that the ``/path/to/my/development.ini#another`` argument passed +to bootstrap will imply the ``[app:another]`` section in our configuration +file. Therefore, it will not wrap the WSGI application present in the info +dictionary as ``app`` using WebError's ``evalerror`` middleware. The ``app`` +object present in the info dictionary returned by +:func:`~pyramid.paster.bootstrap` will be a :app:`Pyramid` :term:`router` +instead. + +By default, Pyramid will general a suitable request object in the ``info`` +dictionary anchored at the root path (``/``). You can alternately supply +your own :class:`pyramid.request.Request` instance to the +:func:`~pyramid.paster.bootstrap` function, to set up request parameters +beforehand: + +.. code-block:: python + + from pyramid.request import Request + request = Request.blank('/another/url') + from pyramid.paster import bootstrap + info = bootstrap('/path/to/my/development.ini#another', request=request) + print info['request'].path_info # will print '/another/url' + +When your scripting logic finishes, it's good manners (but not required) to +call the ``closer`` callback: + +.. code-block:: python + + from pyramid.paster import bootstrap + info = bootstrap('/path/to/my/development.ini') + + # .. do stuff ... + + info['closer']() + + + diff --git a/docs/whatsnew-1.1.rst b/docs/whatsnew-1.1.rst index 32955ab75..a37f03a66 100644 --- a/docs/whatsnew-1.1.rst +++ b/docs/whatsnew-1.1.rst @@ -583,6 +583,9 @@ Dependency Changes Documentation Enhancements -------------------------- +- Added a section entitled :ref:`writing_a_script` to the "Command-Line + Pyramid" chapter. + - The :ref:`bfg_wiki_tutorial` was updated slightly. - The :ref:`bfg_sql_wiki_tutorial` was updated slightly. diff --git a/pyramid/paster.py b/pyramid/paster.py index b6d7777c0..048f747e8 100644 --- a/pyramid/paster.py +++ b/pyramid/paster.py @@ -70,6 +70,9 @@ def bootstrap(config_uri, request=None): parameters. For example, most people would want to specify the host, scheme and port such that their script will generate URLs in relation to those parameters. + + See :ref:`writing_a_script` for more information about how to use this + function. """ app = get_app(config_uri) info = prepare(request) |
