summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@plope.com>2010-12-19 12:45:30 -0500
committerChris McDonough <chrism@plope.com>2010-12-19 12:45:30 -0500
commit450006eb2493833ddfd3a0f623c3295f1e8a0e47 (patch)
treecf40fddef95e0aa76fcf12c42b2ee05912b64db9
parent36cbf3a071fb76c14dde7f4c4e74cd8464e9919f (diff)
downloadpyramid-450006eb2493833ddfd3a0f623c3295f1e8a0e47.tar.gz
pyramid-450006eb2493833ddfd3a0f623c3295f1e8a0e47.tar.bz2
pyramid-450006eb2493833ddfd3a0f623c3295f1e8a0e47.zip
wording
-rw-r--r--docs/narr/traversal.rst281
1 files changed, 137 insertions, 144 deletions
diff --git a/docs/narr/traversal.rst b/docs/narr/traversal.rst
index 7b9c76581..48e90e4d9 100644
--- a/docs/narr/traversal.rst
+++ b/docs/narr/traversal.rst
@@ -3,10 +3,12 @@
Traversal
=========
-:term:`Traversal` is a :term:`resource location` mechanism. It is the act of
-finding 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.
+:term:`Traversal` It provides an alternative to using :term:`URL dispatch` to
+map a URL to a :term:`view callable`. It is a :term:`resource location`
+mechanism. It is the act of finding 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.
In this chapter, we'll provide a high-level overview of traversal, we'll
explain the concept of a resource tree, and we'll show how traversal might be
@@ -25,7 +27,7 @@ of the URL into a set of nested dictionary-like objects called the
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 code willing "publish" the context
+subsystem is used to then find some view code willing "publish" the context
resource.
.. index::
@@ -47,31 +49,30 @@ 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.
+tree 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` 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.
- 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.
-- The next segment (``b``) is popped from the path sequence, and the
- "A" resource's ``__getitem__`` is called with that value (``b``) as an
+- 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.
+ 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
-lookup for a path element fails. In either case, a :term:`context` resouce
-is found.
+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
@@ -81,10 +82,10 @@ point during traversal any resource in the tree doesn't have a
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 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`
@@ -102,10 +103,11 @@ lookup is explained within the :ref:`views_chapter` chapter.
The Resource Tree
-----------------
-When your application uses :term:`traversal` to resolve URLs to code, your
+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.
+tree is represented by a :term:`root` resource. The tree is effectively a
+nested set of dictionary-like objects.
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
@@ -138,7 +140,7 @@ 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 a resource which represents the root of the resource tree. All
+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
@@ -151,9 +153,9 @@ always returns a resource that has no child resources.
.. sidebar:: Emulating the Default Root Factory
- For purposes of understanding the default root factory better,
- we'll note that you can emulate the default root factory by using
- this code as an explicit root factory in your application setup:
+ For purposes of understanding the default root factory better, we'll note
+ that you can emulate the default root factory by using this code as an
+ explicit root factory in your application setup:
.. code-block:: python
:linenos:
@@ -190,12 +192,11 @@ whether an object is "containerish" or not (dictionary objects are
Each container resource is presumed to be willing to return a child resource
or raise a ``KeyError`` based on a name passed to its ``__getitem__``.
-Leaf-level instances must not have a ``__getitem__``. If
-instances that you'd like to be leaves already happen to have a
-``__getitem__`` through some historical inequity, you should subclass
-these resource types and cause their ``__getitem__`` methods to simply
-raise a ``KeyError``. Or just disuse them and think up another
-strategy.
+Leaf-level instances must not have a ``__getitem__``. If instances that
+you'd like to be leaves already happen to have a ``__getitem__`` through some
+historical inequity, you should subclass these resource types and cause their
+``__getitem__`` methods to simply raise a ``KeyError``. Or just disuse them
+and think up another strategy.
Usually, the traversal root is a *container* resource, and as such it
contains other resources. However, it doesn't *need* to be a container.
@@ -218,19 +219,17 @@ resource. This happens *ad infinitum* until all path segments are exhausted.
The Traversal Algorithm
-----------------------
-This section will attempt to explain the :app:`Pyramid` traversal
-algorithm. 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
+This section will attempt to explain the :app:`Pyramid` traversal algorithm.
+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.
.. index::
@@ -243,25 +242,24 @@ 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`
-and a :term:`view name`.
+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
+:term:`view name`.
#. The request for the page is presented to the :app:`Pyramid`
- :term:`router` in terms of a standard :term:`WSGI` request, which
- is represented by a WSGI environment and a WSGI ``start_response``
- callable.
+ :term:`router` in terms of a standard :term:`WSGI` request, which is
+ represented by a WSGI environment and a WSGI ``start_response`` callable.
#. The router creates a :term:`request` object based on the WSGI
environment.
-#. The :term:`root factory` is called with the :term:`request`. It
- returns a :term:`root` resource.
+#. The :term:`root factory` is called with the :term:`request`. It returns
+ a :term:`root` resource.
-#. The router uses the WSGI environment's ``PATH_INFO`` information
- to determine the path segments to traverse. The leading slash is
- stripped off ``PATH_INFO``, and the remaining path segments are
- split on the slash character to form a traversal sequence.
+#. The router uses the WSGI environment's ``PATH_INFO`` information to
+ determine the path segments to traverse. The leading slash is stripped
+ off ``PATH_INFO``, and the remaining path segments are split on the slash
+ character to form a traversal sequence.
The traversal algorithm by default attempts to first URL-unquote and then
Unicode-decode each path segment derived from ``PATH_INFO`` from its
@@ -273,18 +271,18 @@ and a :term:`view name`.
segment will be fully URL-unquoted and UTF8-decoded before it is passed
it to the ``__getitem__`` of any resource during traversal.
- Thus, a request with a ``PATH_INFO`` variable of ``/a/b/c`` maps
- to the traversal sequence ``[u'a', u'b', u'c']``.
+ Thus, a request with a ``PATH_INFO`` variable of ``/a/b/c`` maps to the
+ traversal sequence ``[u'a', u'b', u'c']``.
#. :term:`Traversal` begins at the root resource returned by the root
factory. For the traversal sequence ``[u'a', u'b', u'c']``, the root
resource's ``__getitem__`` is called with the name ``a``. Traversal
continues through the sequence. In our example, if the root resource's
``__getitem__`` called with the name ``a`` returns a resource (aka
- "resource ``a``"), that resource's ``__getitem__`` is called with the name
- ``b``. If resource A returns a resource when asked for ``b``, "resource
- ``b``"'s ``__getitem__`` is then asked for the name ``c``, and may return
- "resource ``c``".
+ "resource ``a``"), that resource's ``__getitem__`` is called with the
+ name ``b``. If resource A returns a resource when asked for ``b``,
+ "resource ``b``"'s ``__getitem__`` is then asked for the name ``c``, and
+ may return "resource ``c``".
#. Traversal ends when a) the entire path is exhausted or b) when any
resouce raises a :exc:`KeyError` from its ``__getitem__`` or c) when any
@@ -293,33 +291,31 @@ and a :term:`view name`.
with the set of characters ``@@`` (indicating that the characters
following the ``@@`` token should be treated as a :term:`view name`).
-#. When traversal ends for any of the reasons in the previous step,
- the last resource found during traversal is deemed to be the
- :term:`context`. If the path has been exhausted when traversal
- ends, the :term:`view name` is deemed to be the empty string
- (``''``). However, if the path was *not* exhausted before
- traversal terminated, the first remaining path segment is treated
- as the view name.
-
-#. Any subsequent path elements after the :term:`view name` is found
- are deemed the :term:`subpath`. The subpath is always a sequence
- of path segments that come from ``PATH_INFO`` that are "left over"
- after traversal has completed.
-
-Once :term:`context`, :term:`view name`, and associated attributes
-such as the :term:`subpath` are located, the job of :term:`traversal`
-is finished. It passes back the information it obtained to its
-caller, the :app:`Pyramid` :term:`Router`, which subsequently
-invokes :term:`view lookup` with the context and view name
-information.
+#. When traversal ends for any of the reasons in the previous step, the last
+ resource found during traversal is deemed to be the :term:`context`. If
+ the path has been exhausted when traversal ends, the :term:`view name` is
+ deemed to be the empty string (``''``). However, if the path was *not*
+ exhausted before traversal terminated, the first remaining path segment
+ is treated as the view name.
+
+#. Any subsequent path elements after the :term:`view name` is found are
+ deemed the :term:`subpath`. The subpath is always a sequence of path
+ segments that come from ``PATH_INFO`` that are "left over" after
+ traversal has completed.
+
+Once the :term:`context` resource, the :term:`view name`, and associated
+attributes such as the :term:`subpath` are located, the job of
+:term:`traversal` is finished. It passes back the information it obtained to
+its caller, the :app:`Pyramid` :term:`Router`, which subsequently invokes
+:term:`view lookup` with the context and view name information.
The traversal algorithm exposes two special cases:
-- You will often end up with a :term:`view name` that is the empty
- string as the result of a particular traversal. This indicates that
- the view lookup machinery should look up the :term:`default view`.
- The default view is a view that is registered with no name or a view
- which is registered with a name that equals the empty string.
+- You will often end up with a :term:`view name` that is the empty string as
+ the result of a particular traversal. This indicates that the view lookup
+ machinery should look up the :term:`default view`. The default view is a
+ view that is registered with no name or a view which is registered with a
+ name that equals the empty string.
- If any path segment element begins with the special characters ``@@``
(think of them as goggles), the value of that segment minus the goggle
@@ -327,10 +323,10 @@ The traversal algorithm exposes two special cases:
stops there. This allows you to address views that may have the same names
as resource names in the tree unambiguously.
-Finally, traversal is responsible for locating a :term:`virtual root`.
-A virtual root is used during "virtual hosting"; see the
-:ref:`vhosting_chapter` chapter for information. We won't speak more
-about it in this chapter.
+Finally, traversal is responsible for locating a :term:`virtual root`. A
+virtual root is used during "virtual hosting"; see the
+:ref:`vhosting_chapter` chapter for information. We won't speak more about
+it in this chapter.
.. image:: resourcetreetraverser.png
@@ -340,15 +336,14 @@ about it in this chapter.
Traversal Algorithm Examples
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-No one can be expected to understand the traversal algorithm by
-analogy and description alone, so let's examine some traversal
-scenarios that use concrete URLs and resource tree compositions.
+No one can be expected to understand the traversal algorithm by analogy and
+description alone, so let's examine some traversal scenarios that use
+concrete URLs and resource tree compositions.
Let's pretend the user asks for
-``http://example.com/foo/bar/baz/biz/buz.txt``. The request's
-``PATH_INFO`` in that case is ``/foo/bar/baz/biz/buz.txt``. Let's
-further pretend that when this request comes in that we're traversing
-the following resource tree:
+``http://example.com/foo/bar/baz/biz/buz.txt``. The request's ``PATH_INFO``
+in that case is ``/foo/bar/baz/biz/buz.txt``. Let's further pretend that
+when this request comes in that we're traversing the following resource tree:
.. code-block:: text
@@ -360,20 +355,21 @@ the following resource tree:
Here's what happens:
-- :mod:`traversal` traverses the root, and attempts to find "foo",
- which it finds.
+- :mod:`traversal` traverses the root, and attempts to find "foo", which it
+ finds.
-- :mod:`traversal` traverses "foo", and attempts to find "bar", which
- it finds.
+- :mod:`traversal` traverses "foo", and attempts to find "bar", which it
+ finds.
-- :mod:`traversal` traverses bar, and attempts to find "baz", which it
- does not find ("bar" raises a :exc:`KeyError` when asked for "baz").
+- :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").
-The fact that it does not find "baz" at this point does not signify an
-error condition. It signifies that:
+The fact that it does not find "baz" at this point does not signify an error
+condition. It signifies that:
-- the :term:`context` is "bar" (the context is the last resource found
- during traversal).
+- the :term:`context` is the "bar" resource (the context is the last resource
+ found during traversal).
- the :term:`view name` is ``baz``
@@ -387,13 +383,12 @@ to find out what "type" it is. Let's say it finds that the context is a
Using the :term:`view name` (``baz``) and the type, view lookup asks the
:term:`application registry` this question:
-- Please find me a :term:`view callable` registered using a
- :term:`view configuration` with the name "baz" that can be used for
- the class ``Bar``.
+- Please find me a :term:`view callable` registered using a :term:`view
+ configuration` with the name "baz" that can be used for the class ``Bar``.
Let's say that view lookup finds no matching view type. In this
-circumstance, the :app:`Pyramid` :term:`router` returns the result
-of the :term:`not found view` and the request ends.
+circumstance, the :app:`Pyramid` :term:`router` returns the result of the
+:term:`not found view` and the request ends.
However, for this tree:
@@ -411,23 +406,23 @@ However, for this tree:
The user asks for ``http://example.com/foo/bar/baz/biz/buz.txt``
-- :mod:`traversal` traverses "foo", and attempts to find "bar", which
- it finds.
+- :mod:`traversal` traverses "foo", and attempts to find "bar", which it
+ finds.
-- :mod:`traversal` traverses "bar", and attempts to find "baz", which
- it finds.
+- :mod:`traversal` traverses "bar", and attempts to find "baz", which it
+ finds.
-- :mod:`traversal` traverses "baz", and attempts to find "biz", which
- it finds.
+- :mod:`traversal` traverses "baz", and attempts to find "biz", which it
+ finds.
-- :mod:`traversal` traverses "biz", and attempts to find "buz.txt"
- which it does not find.
+- :mod:`traversal` traverses "biz", and attempts to find "buz.txt" which it
+ does not find.
-The fact that it does not find "buz.txt" at this point does not
-signify an error condition. It signifies that:
+The fact that it does not find a resource related to "buz.txt" at this point
+does not signify an error condition. It signifies that:
-- the :term:`context` is "biz" (the context is the last resource found
- during traversal).
+- the :term:`context` is the "biz" resource (the context is the last resource
+ found during traversal).
- the :term:`view name` is "buz.txt"
@@ -435,21 +430,20 @@ signify an error condition. It signifies that:
At this point, traversal has ended, and :term:`view lookup` begins.
-Because it's the "context" resource, the view lookup machinery examines "biz"
-to find out what "type" it is. Let's say it finds that the context is a
-``Biz`` type (because "biz" is an instance of the Python class ``Biz``).
-Using the :term:`view name` (``buz.txt``) and the type, view lookup asks the
-:term:`application registry` this question:
+Because it's the "context" resource, the view lookup machinery examines the
+"biz" resource to find out what "type" it is. Let's say it finds that the
+resource is a ``Biz`` type (because "biz" is an instance of the Python class
+``Biz``). Using the :term:`view name` (``buz.txt``) and the type, view
+lookup asks the :term:`application registry` this question:
- Please find me a :term:`view callable` registered with a :term:`view
configuration` with the name ``buz.txt`` that can be used for class
``Biz``.
-Let's say that question is answered by the application registry; in
-such a situation, the application registry returns a :term:`view
-callable`. The view callable is then called with the current
-:term:`WebOb` :term:`request` as the sole argument: ``request``; it is
-expected to return a response.
+Let's say that question is answered by the application registry; in such a
+situation, the application registry returns a :term:`view callable`. The
+view callable is then called with the current :term:`WebOb` :term:`request`
+as the sole argument: ``request``; it is expected to return a response.
.. sidebar:: The Example View Callables Accept Only a Request; How Do I Access the Context Resource?
@@ -471,16 +465,15 @@ expected to return a response.
References
----------
-A tutorial showing how :term:`traversal` can be used within a
-:app:`Pyramid` application exists in :ref:`bfg_wiki_tutorial`.
+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
:term:`view lookup`.
-The :mod:`pyramid.traversal` module contains API functions that
-deal with traversal, such as traversal invocation from within
-application code.
+The :mod:`pyramid.traversal` module contains API functions that deal with
+traversal, such as traversal invocation from within application code.
-The :func:`pyramid.url.resource_url` function generates a URL when
-given a resource retrieved from a resource tree.
+The :func:`pyramid.url.resource_url` function generates a URL when given a
+resource retrieved from a resource tree.