diff options
| author | Alexandre Bourget <alexandre.bourget@savoirfairelinux.com> | 2011-03-24 12:07:09 -0400 |
|---|---|---|
| committer | Alexandre Bourget <alexandre.bourget@savoirfairelinux.com> | 2011-03-24 12:07:09 -0400 |
| commit | 95e799d074de2e81914d513b4c331df1e738c00e (patch) | |
| tree | b3039037533610d8c86d82bb28f139d8a3777013 /docs/narr/traversal.rst | |
| parent | 22d3253a26767501827d86b56db3a9b79bef6c4e (diff) | |
| parent | b596e1812627c359908759d7a8d83c339f08e385 (diff) | |
| download | pyramid-95e799d074de2e81914d513b4c331df1e738c00e.tar.gz pyramid-95e799d074de2e81914d513b4c331df1e738c00e.tar.bz2 pyramid-95e799d074de2e81914d513b4c331df1e738c00e.zip | |
Merge remote branch 'source/master'
Conflicts:
docs/narr/hooks.rst
Diffstat (limited to 'docs/narr/traversal.rst')
| -rw-r--r-- | docs/narr/traversal.rst | 207 |
1 files changed, 100 insertions, 107 deletions
diff --git a/docs/narr/traversal.rst b/docs/narr/traversal.rst index 2d7878265..b3747be61 100644 --- a/docs/narr/traversal.rst +++ b/docs/narr/traversal.rst @@ -3,33 +3,22 @@ Traversal ========= -:term:`Traversal` provides an alternative to using :term:`URL dispatch` to -map a URL to a :term:`view callable`. It is the act of locating a -:term:`context` resource by walking over a :term:`resource tree`, starting -from a :term:`root` resource, using a :term:`request` object as a source of -path information. Once a context resource is found, a view callable is -looked up and invoked. - -Using :term:`Traversal` to map a URL to code is optional. It is often less -easy to understand than URL dispatch, so if you're a rank beginner, it -probably makes sense to use URL dispatch to map URLs to code instead of -traversal. In that case, you can skip this chapter. - -.. index:: - single: traversal overview - -A High-Level Overview of Traversal ----------------------------------- - A :term:`traversal` uses the URL (Universal Resource Locator) to find a -:term:`resource`. This is done by mapping each segment of the path portion -of the URL into a set of nested dictionary-like objects called the -:term:`resource tree`. You might think of this as looking up files and -directories in a file system. Traversal walks down the path until it finds a -published "directory" or "file". The resource we find as the result of a -traversal becomes the :term:`context`. A separate :term:`view lookup` -subsystem is used to then find some view code willing "publish" the context -resource. +:term:`resource` located in a :term:`resource tree`, which is a set of +nested dictionary-like objects. Traversal is done by using each segment +of the path portion of the URL to navigate through the :term:`resource +tree`. You might think of this as looking up files and directories in a +file system. Traversal walks down the path until it finds a published +resource, analogous to a file system "directory" or "file". The +resource found as the result of a traversal becomes the +:term:`context` of the :term:`request`. Then, the :term:`view lookup` +subsystem is used to find some view code willing "publish" this +resource by generating a :term:`response`. + +Using :term:`Traversal` to map a URL to code is optional. It is often +less easy to understand than :term:`URL dispatch`, so if you're a rank +beginner, it probably makes sense to use URL dispatch to map URLs to +code instead of traversal. In that case, you can skip this chapter. .. index:: single: traversal details @@ -37,62 +26,65 @@ resource. Traversal Details ----------------- -:term:`Traversal` is dependent on information in a :term:`request` object. -Every :term:`request` object contains URL path information in the -``PATH_INFO`` portion of the :term:`WSGI` environment. The ``PATH_INFO`` -portion of the WSGI environment is the portion of a request's URL following -the hostname and port number, but before any query string elements or +:term:`Traversal` is dependent on information in a :term:`request` +object. Every :term:`request` object contains URL path information in +the ``PATH_INFO`` portion of the :term:`WSGI` environment. The +``PATH_INFO`` string is the portion of a request's URL following the +hostname and port number, but before any query string elements or fragment element. For example the ``PATH_INFO`` portion of the URL ``http://example.com:8080/a/b/c?foo=1`` is ``/a/b/c``. -Traversal treats the ``PATH_INFO`` segment of a URL as a sequence of path -segments. For example, the ``PATH_INFO`` string ``/a/b/c`` is converted to -the sequence ``['a', 'b', 'c']``. +Traversal treats the ``PATH_INFO`` segment of a URL as a sequence of +path segments. For example, the ``PATH_INFO`` string ``/a/b/c`` is +converted to the sequence ``['a', 'b', 'c']``. -After the path info is converted, a lookup is performed against the resource -tree for each path segment. Each lookup uses the ``__getitem__`` method of a -resource in the tree. +This path sequence is then used to descend through the :term:`resource +tree`, looking up a resource for each path segment. Each lookup uses the +``__getitem__`` method of a resource in the tree. For example, if the path info sequence is ``['a', 'b', 'c']``: -- :term:`Traversal` pops the first element (``a``) from the path segment - sequence and attempts to call the root resource's ``__getitem__`` method - using that value (``a``) as an argument; we'll presume it succeeds. +- :term:`Traversal` starts by acquiring the :term:`root` resource of the + application by calling the :term:`root factory`. The :term:`root factory` + can be configured to return whatever object is appropriate as the + traversal root of your application. -- When the root resource's ``__getitem__`` succeeds it will return another - resource, which we'll call "A". The :term:`context` temporarily becomes - the "A" resource. +- Next, the first element (``a``) is popped from the path segment + sequence and is used as a key to lookup the corresponding resource + in the root. This invokes the root resource's ``__getitem__`` method + using that value (``a``) as an argument. + +- If the root resource "contains" a resource with key ``a``, its + ``__getitem__`` method will return it. The :term:`context` temporarily + becomes the "A" resource. - The next segment (``b``) is popped from the path sequence, and the "A" resource's ``__getitem__`` is called with that value (``b``) as an argument; we'll presume it succeeds. -- When the "A" resource's ``__getitem__`` succeeds it will return another - resource, which we'll call "B". The :term:`context` temporarily becomes - the "B" resource. - -This process continues until the path segment sequence is exhausted or a path -element cannot be resolved to a resource. In either case, a :term:`context` -resource is chosen. - -Traversal "stops" when it either reaches a leaf level resource in your -resource tree or when the path segments implied by the URL "run out". The -resource that traversal "stops on" becomes the :term:`context`. If at any -point during traversal any resource in the tree doesn't have a -``__getitem__`` method, or if the ``__getitem__`` method of a resource raises -a :exc:`KeyError`, traversal ends immediately, and that resource becomes the -:term:`context`. - -The results of a :term:`traversal` also include a :term:`view name`. The -:term:`view name` is the *first* URL path segment in the set of ``PATH_INFO`` -segments "left over" in the path segment list popped by the traversal process -*after* traversal finds a context resource. - -The combination of the context resource and the :term:`view name` found via -traversal is used later in the same request by a separate :app:`Pyramid` -subsystem -- the :term:`view lookup` subsystem -- to find a :term:`view -callable` later within the same request. How :app:`Pyramid` performs view -lookup is explained within the :ref:`views_chapter` chapter. +- The "A" resource's ``__getitem__`` returns another resource, which + we'll call "B". The :term:`context` temporarily becomes the "B" + resource. + +Traversal continues until the path segment sequence is exhausted or a +path element cannot be resolved to a resource. In either case, the +:term:`context` resource is the last object that the traversal +successfully resolved. If any resource found during traversal lacks a +``__getitem__`` method, or if its ``__getitem__`` method raises a +:exc:`KeyError`, traversal ends immediately, and that resource becomes +the :term:`context`. + +The results of a :term:`traversal` also include a :term:`view name`. If +traversal ends before the path segment sequence is exhausted, the +:term:`view name` is the *next* remaining path segment element. If the +:term:`traversal` expends all of the path segments, then the :term:`view +name` is the empty string (`''`). + +The combination of the context resource and the :term:`view name` found +via traversal is used later in the same request by the :term:`view +lookup` subsystem to find a :term:`view callable`. How :app:`Pyramid` +performs view lookup is explained within the :ref:`view_config_chapter` +chapter. .. index:: single: object tree @@ -104,19 +96,20 @@ lookup is explained within the :ref:`views_chapter` chapter. The Resource Tree ----------------- -When your application uses :term:`traversal` to resolve URLs to code, the -application must supply a :term:`resource tree` to :app:`Pyramid`. The -resource tree is a set of nested dictionary-like objects. The root of the -tree is represented by a :term:`root` resource. The tree is effectively a -nested set of dictionary-like objects. +The resource tree is a set of nested dictionary-like resource objects +that begins with a :term:`root` resource. In order to use +:term:`traversal` to resolve URLs to code, your application must supply +a :term:`resource tree` to :app:`Pyramid`. -In order to supply a root resource for an application, at system startup -time, the :app:`Pyramid` :term:`Router` is configured with a callback known -as a :term:`root factory`. The root factory is supplied by the application -developer as the ``root_factory`` argument to the application's -:term:`Configurator`. +In order to supply a root resource for an application the :app:`Pyramid` +:term:`Router` is configured with a callback known as a :term:`root +factory`. The root factory is supplied by the application, at startup +time, as the ``root_factory`` argument to the :term:`Configurator`. -Here's an example of a simple root factory: +The root factory is a Python callable that accepts a :term:`request` +object, and returns the root object of the :term:`resource tree`. A +function, or class is typically used as an application's root factory. +Here's an example of a simple root factory class: .. code-block:: python :linenos: @@ -133,24 +126,23 @@ passing it to an instance of a :term:`Configurator` named ``config``: config = Configurator(root_factory=Root) -Using the ``root_factory`` argument to a :class:`pyramid.config.Configurator` -constructor tells your :app:`Pyramid` application to call this root factory -to generate a root resource whenever a request enters the application. This -root factory is also known as the global root factory. A root factory can -alternately be passed to the ``Configurator`` as a :term:`dotted Python name` -which refers to a root factory defined in a different module. - -A root factory is passed a :term:`request` object and it is expected to -return an object which represents the root of the resource tree. All -:term:`traversal` will begin at this root resource. Usually a root factory -for a traversal-based application will be more complicated than the above -``Root`` class; in particular it may be associated with a database connection -or another persistence mechanism. +The ``root_factory`` argument to the +:class:`~pyramid.config.Configurator` constructor registers this root +factory to be called to generate a root resource whenever a request +enters the application. The root factory registered this way is also +known as the global root factory. A root factory can alternately be +passed to the ``Configurator`` as a :term:`dotted Python name` which can +refer to a root factory defined in a different module. If no :term:`root factory` is passed to the :app:`Pyramid` -:term:`Configurator` constructor, or the ``root_factory`` is specified as the -value ``None``, a *default* root factory is used. The default root factory -always returns a resource that has no child resources. +:term:`Configurator` constructor, or if the ``root_factory`` value +specified is ``None``, a *default* root factory is used. The default +root factory always returns a resource that has no child resources; it +is effectively empty. + +Usually a root factory for a traversal-based application will be more +complicated than the above ``Root`` class; in particular it may be +associated with a database connection or another persistence mechanism. .. sidebar:: Emulating the Default Root Factory @@ -225,13 +217,14 @@ We'll provide a description of the algorithm, a diagram of how the algorithm works, and some example traversal scenarios that might help you understand how the algorithm operates against a specific resource tree. -We'll also talk a bit about :term:`view lookup`. The :ref:`views_chapter` -chapter discusses :term:`view lookup` in detail, and it is the canonical -source for information about views. Technically, :term:`view lookup` is a -:app:`Pyramid` subsystem that is separated from traversal entirely. However, -we'll describe the fundamental behavior of view lookup in the examples in the -next few sections to give you an idea of how traversal and view lookup -cooperate, because they are almost always used together. +We'll also talk a bit about :term:`view lookup`. The +:ref:`view_config_chapter` chapter discusses :term:`view lookup` in +detail, and it is the canonical source for information about views. +Technically, :term:`view lookup` is a :app:`Pyramid` subsystem that is +separated from traversal entirely. However, we'll describe the +fundamental behavior of view lookup in the examples in the next few +sections to give you an idea of how traversal and view lookup cooperate, +because they are almost always used together. .. index:: single: view name @@ -243,8 +236,8 @@ cooperate, because they are almost always used together. A Description of The Traversal Algorithm ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -When a user requests a page from your :mod:`traversal` -powered application, -the system uses this algorithm to find a :term:`context` resource and a +When a user requests a page from your traversal-powered application, the +system uses this algorithm to find a :term:`context` resource and a :term:`view name`. #. The request for the page is presented to the :app:`Pyramid` @@ -362,7 +355,7 @@ Here's what happens: - :mod:`traversal` traverses "foo", and attempts to find "bar", which it finds. -- :mod:`traversal` traverses bar, and attempts to find "baz", which it does +- :mod:`traversal` traverses "bar", and attempts to find "baz", which it does not find (the "bar" resource raises a :exc:`KeyError` when asked for "baz"). @@ -469,7 +462,7 @@ References A tutorial showing how :term:`traversal` can be used within a :app:`Pyramid` application exists in :ref:`bfg_wiki_tutorial`. -See the :ref:`views_chapter` chapter for detailed information about +See the :ref:`view_config_chapter` chapter for detailed information about :term:`view lookup`. The :mod:`pyramid.traversal` module contains API functions that deal with |
