summaryrefslogtreecommitdiff
path: root/docs/narr/traversal.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/narr/traversal.rst')
-rw-r--r--docs/narr/traversal.rst138
1 files changed, 76 insertions, 62 deletions
diff --git a/docs/narr/traversal.rst b/docs/narr/traversal.rst
index f03a22c9e..d57cf8f02 100644
--- a/docs/narr/traversal.rst
+++ b/docs/narr/traversal.rst
@@ -62,72 +62,74 @@ When a user requests a page from your :mod:`repoze.bfg` -powered
application, the system uses this algorithm to determine which Python
code to execute:
- 1. The request for the page is presented to :mod:`repoze.bfg`'s
+#. The request for the page is presented to :mod:`repoze.bfg`'s
"router" in terms of a standard :term:`WSGI` request, which is
represented by a WSGI environment and a ``start_response``
callable.
- 2. The router creates a :term:`WebOb` request object based on the
- WSGI environment.
-
- 3. The router uses the WSGI environment's ``PATH_INFO`` variable 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, so a
- request with a ``PATH_INFO`` variable of ``/a/b/c`` maps to the
- traversal sequence ``['a', 'b', 'c']``.
-
- 4. :term:`Traversal` begins at the root object. For the traversal
- sequence ``['a', 'b', 'c']``, the root object's ``__getitem__``
- is called with the name ``a``. Traversal continues through the
- sequence. In our example, if the root object's ``__getitem__``
- called with the name ``a`` returns an object (aka "object A"),
- that object's ``__getitem__`` is called with the name ``b``. If
- object A returns an object when asked for ``b``, object B's
- ``__getitem__`` is then asked for the name ``c``, and may return
- object C.
-
- 5. Traversal ends when a) the entire path is exhausted or b) when
- any graph element raises a ``KeyError`` from its ``__getitem__``
- or c) when any non-final path element traversal does not have a
- ``__getitem__`` method (resulting in a ``NameError``) or d) when
- any path element is prefixed with the set of characters ``@@``
- (indicating that the characters following the ``@@`` token should
- be treated as a "view name").
-
- 6. When traversal ends for any of the reasons in the previous step,
- the the last object found during traversal is deemed to be the
- :term:`context`. If the path has been exhausted when traversal
- ends, the "view name" is deemed to be the empty string (``''``).
- However, if the path was *not* exhausted before traversal
- terminated, the first remaining path element is treated as the
- view name.
-
- Any subseqent path elements after the view name are deemed the
- *subpath*. For instance, if ``PATH_INFO`` was ``/a/b`` and the
- root returned an "A" object, and the "A" object returned a "B"
- object, the router deems that the context is "object B", the view
- name is the empty string, and the subpath is the empty sequence.
- On the other hand, if ``PATH_INFO`` was ``/a/b/c`` and "object A"
- was found but raised a ``KeyError`` for the name ``b``, the
- router deems that the context is object A, the view name is ``b``
- and the subpath is ``['c']``.
-
- 7. If a :term:`security policy` is configured, the router performs a
- permission lookup. If a permission declaration is found for the
- view name and context implied by the current request, the
- security policy is consulted to see if the "current user" (also
- determined by the security policy) can perform the action. If he
- can, processing continues. If he cannot, an ``HTTPUnauthorized``
- error is raised.
-
- 8. Armed with the context, the view name, and the subpath, the
- router performs a view lookup. It attemtps to look up a view
- from the :mod:`repoze.bfg` :term:`application registry` using the
- view name and the context. If a view function is found, it is
- called with the context and the request. It returns a response,
- which is fed back upstream. If a view is not found, a generic
- WSGI ``NotFound`` application is constructed.
+#. The router creates a :term:`WebOb` request object based on the
+ WSGI environment.
+
+#. The router uses the WSGI environment's ``PATH_INFO`` variable 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, so a
+ request with a ``PATH_INFO`` variable of ``/a/b/c`` maps to the
+ traversal sequence ``['a', 'b', 'c']``.
+
+#. :term:`Traversal` begins at the root object. For the traversal
+ sequence ``['a', 'b', 'c']``, the root object's ``__getitem__`` is
+ called with the name ``a``. Traversal continues through the
+ sequence. In our example, if the root object's ``__getitem__``
+ called with the name ``a`` returns an object (aka "object ``a``"),
+ that object's ``__getitem__`` is called with the name ``b``. If
+ object A returns an object when asked for ``b``, "object ``b``"'s
+ ``__getitem__`` is then asked for the name ``c``, and may return
+ "object ``c``".
+
+#. Traversal ends when a) the entire path is exhausted or b) when any
+ graph element raises a ``KeyError`` from its ``__getitem__`` or c)
+ when any non-final path element traversal does not have a
+ ``__getitem__`` method (resulting in a ``NameError``) or d) when
+ any path element is prefixed with the set of characters ``@@``
+ (indicating that the characters following the ``@@`` token should
+ be treated as a "view name").
+
+#. When traversal ends for any of the reasons in the previous step,
+ the the last object found during traversal is deemed to be the
+ :term:`context`. If the path has been exhausted when traversal
+ ends, the "view name" is deemed to be the empty string (``''``).
+ However, if the path was *not* exhausted before traversal
+ terminated, the first remaining path element is treated as the
+ view name.
+
+ Any subseqent path elements after the view name are deemed the
+ :term:`subpath`. The subpath is always a sequence of strings that
+ come from ``PATH_INFO`` that are "left over" after traversal has
+ completed. For instance, if ``PATH_INFO`` was ``/a/b`` and the
+ root returned an "object ``a``", and "object ``a``" subsequently
+ returned an "object ``b``", the router deems that the context is
+ "object ``b``", the view name is the empty string, and the subpath
+ is the empty sequence. On the other hand, if ``PATH_INFO`` was
+ ``/a/b/c`` and "object ``a``" was found but raised a ``KeyError``
+ for the name ``b``, the router deems that the context is "object
+ ``a``", the view name is ``b`` and the subpath is ``['c']``.
+
+#. If a :term:`security policy` is configured, the router performs a
+ permission lookup. If a permission declaration is found for the
+ view name and context implied by the current request, the security
+ policy is consulted to see if the "current user" (also determined
+ by the security policy) can perform the action. If he can,
+ processing continues. If he cannot, an ``HTTPUnauthorized`` error
+ is raised.
+
+#. Armed with the context, the view name, and the subpath, the router
+ performs a view lookup. It attemtps to look up a view from the
+ :mod:`repoze.bfg` :term:`application registry` using the view name
+ and the context. If a view function is found, it is called with
+ the context and the request. It returns a response, which is fed
+ back upstream. If a view is not found, a generic WSGI
+ ``NotFound`` application is constructed.
In either case, the result is returned upstream via the :term:`WSGI`
protocol.
@@ -244,3 +246,15 @@ There are two special cases:
to address views that may have the same names as model instance
names in the graph unambiguously.
+Traversal-Related Side Effects
+------------------------------
+
+The :term:`subpath` will always be available to a view as a the
+``subpath`` attribute of the :term:`request` object. It will be a
+list containing zero or more elements (which will be strings).
+
+The :term:`view name` will always be available to a view as the
+``view_name`` attribute of the :term:`request` object. It will be a
+single string (possibly the empty string if we're rendering a default
+view).
+