Skip to content

Commit

Permalink
- Added "Finding the Root Resource" to Resources narrative chapter.
Browse files Browse the repository at this point in the history
- Added "Finding a Resource With a Class or Interface in Lineage" to
  Resources narrative chapter.
  • Loading branch information
mcdonc committed Dec 21, 2010
1 parent f4f41f3 commit b32bfd3
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 26 deletions.
5 changes: 5 additions & 0 deletions CHANGES.txt
Expand Up @@ -28,6 +28,11 @@ Documentation
- Added "Determining if a Resource is In The Lineage of Another Resource" to
Resources narrative chapter.

- Added "Finding the Root Resource" to Resources narrative chapter.

- Added "Finding a Resource With a Class or Interface in Lineage" to
Resources narrative chapter.

1.0a7 (2010-12-20)
==================

Expand Down
74 changes: 69 additions & 5 deletions docs/narr/resources.rst
Expand Up @@ -462,6 +462,35 @@ parent (or one of its parent's parents, etc.) is an ancestor.

See :func:`pyramid.location.inside` for more information.

Finding the Root Resource
-------------------------

Use the :func:`pyramid.traversal.find_root` API to find the :term:`root`
resource. The root resource is the root resource of the :term:`resource
tree`. The API accepts a single argument: ``resource``. This is a resource
that is :term:`location` aware. It can be any resource in the tree for which
you want to find the root.

For example, if the resource tree is:

.. code-block:: python
:linenos:
class Thing(object): pass
a = Thing()
b = Thing()
b.__parent__ = a
Calling ``find_root(b)`` will return ``a``.

The root resource is also available as ``request.root`` within :term:`view
callable` code.

The presence or absence of a :term:`virtual root` has no impact on the
behavior of :func:`~pyramid.traversal.find_root`. The root object returned
is always the *physical* root object.

.. index::
single: resource interfaces

Expand All @@ -472,14 +501,15 @@ Resources Which Implement Interfaces

Resources can optionally be made to implement an :term:`interface`. An
interface is used to tag a resource object with a "type" that can later be
referred to within :term:`view configuration`.
referred to within :term:`view configuration` and by
:func:`pyramid.traversal.find_interface`.

Specifying an interface instead of a class as the ``context`` or
``containment`` predicate arguments within :term:`view configuration`
statements effectively makes it possible to use a single view callable for
more than one class of resource object. If your application is simple enough
that you see no reason to want to do this, you can skip reading this section
of the chapter.
statements makes it possible to use a single view callable for more than one
class of resource object. If your application is simple enough that you see
no reason to want to do this, you can skip reading this section of the
chapter.

For example, here's some code which describes a blog entry which also
declares that the blog entry implements an :term:`interface`.
Expand Down Expand Up @@ -576,6 +606,40 @@ directly provided by an instance instead of overwriting them like
For more information about how resource interfaces can be used by view
configuration, see :ref:`using_resource_interfaces`.

Finding a Resource With a Class or Interface in Lineage
-------------------------------------------------------

Use the :func:`pyramid.traversal.find_interface` API to locate a parent that
is of a particular Python class, or which implements some :term:`interface`.

For example, if your resource tree is composed as follows:

.. code-block:: python
:linenos:
class Thing1(object): pass
class Thing2(object): pass
a = Thing1()
b = Thing2()
b.__parent__ = a
Calling ``find_interface(a, Thing1)`` will return the ``a`` resource because
``a`` is of class ``Thing1`` (the resource passed as the first argument is
considered first, and is returned if the class or interface spec matches).

Calling ``find_interface(b, Thing1)`` will return the ``a`` resource because
``a`` is of class ``Thing1`` and ``a`` is the first resource in ``b``'s
lineage of this class.

Calling ``find_interface(b, Thing2)`` will return the ``b`` resource.

The second argument to find_interface may also be a :term:`interface` instead
of a class. If it is an interface, each resource in the lineage is checked
to see if the resource implements the specificed interface (instead of seeing
if the resource is of a class). See also
:ref:`resources_which_implement_interfaces`.

.. index::
single: resource API functions
single: url generation (traversal)
Expand Down
42 changes: 21 additions & 21 deletions pyramid/traversal.py
Expand Up @@ -44,7 +44,7 @@ def find_resource(resource, path):
Rules for passing a *string* as the ``path`` argument: if the
first character in the path string is the with the ``/``
character, the path will considered absolute and the resource tree
traversal will start at the root object. If the first character
traversal will start at the root resource. If the first character
of the path string is *not* the ``/`` character, the path is
considered relative and resource tree traversal will begin at the resource
object supplied to the function as the ``resource`` argument. If an
Expand Down Expand Up @@ -86,13 +86,13 @@ def find_resource(resource, path):

def find_interface(resource, class_or_interface):
"""
Return the first object found in the parent chain of ``resource``
which, a) if ``class_or_interface`` is a Python class object, is
an instance of the class or any subclass of that class or b) if
``class_or_interface`` is a :term:`interface`, provides the
specified interface. Return ``None`` if no object providing
``interface_or_class`` can be found in the parent chain. The
``resource`` passed in *must* be :term:`location`-aware.
Return the first resource found in the :term:`lineage` of ``resource``
which, a) if ``class_or_interface`` is a Python class object, is an
instance of the class or any subclass of that class or b) if
``class_or_interface`` is a :term:`interface`, provides the specified
interface. Return ``None`` if no resource providing ``interface_or_class``
can be found in the lineage. The ``resource`` passed in *must* be
:term:`location`-aware.
"""
if IInterface.providedBy(class_or_interface):
test = class_or_interface.providedBy
Expand Down Expand Up @@ -179,7 +179,7 @@ def traverse(resource, path):
in the ``path``. The ``view_name`` will be a Unicode object or
the empty string. The ``view_name`` will be the empty string if
there is no element which follows the ``context`` path. An
example: if the path passed is ``/foo/bar``, and a context
example: if the path passed is ``/foo/bar``, and a resource
object is found at ``/foo`` (but not at ``/foo/bar``), the 'view
name' will be ``u'bar'``. If the ``resource`` was found via
urldispatch, the view_name will be the name the route found was
Expand All @@ -190,7 +190,7 @@ def traverse(resource, path):
the ``view_name`` (if any). Each of these items is a Unicode
object. If no path segments follow the ``view_name``, the
subpath will be the empty sequence. An example: if the path
passed is ``/foo/bar/baz/buz``, and a context object is found at
passed is ``/foo/bar/baz/buz``, and a resource object is found at
``/foo`` (but not ``/foo/bar``), the 'view name' will be
``u'bar'`` and the :term:`subpath` will be ``[u'baz', u'buz']``.
For a ``resource`` found via url dispatch, the subpath will be a
Expand All @@ -210,17 +210,17 @@ def traverse(resource, path):
See :ref:`vhosting_chapter` for a definition of the virtual root
object. If no virtual hosting is in effect, and the ``path``
passed in was absolute, the ``virtual_root`` will be the
*physical* root object (the object at which :term:`traversal`
*physical* root resource object (the object at which :term:`traversal`
begins). If the ``resource`` passed in was found via :term:`URL
dispatch` or if the ``path`` passed in was relative, the
``virtual_root`` will always equal the ``root`` object (the
resource passed in).
- ``virtual_root_path`` -- If :term:`traversal` was used to find
the ``resource``, this will be the sequence of path elements
traversed to find the ``virtual_root`` object. Each of these
traversed to find the ``virtual_root`` resource. Each of these
items is a Unicode object. If no path segments were traversed
to find the ``virtual_root`` object (e.g. if virtual hosting is
to find the ``virtual_root`` resource (e.g. if virtual hosting is
not in effect), the ``traversed`` value will be the empty list.
If url dispatch was used to find the ``resource``, this will be
``None``.
Expand All @@ -230,7 +230,7 @@ def traverse(resource, path):
Rules for passing a *string* as the ``path`` argument: if the
first character in the path string is the with the ``/``
character, the path will considered absolute and the resource tree
traversal will start at the root object. If the first character
traversal will start at the root resource. If the first character
of the path string is *not* the ``/`` character, the path is
considered relative and resource tree traversal will begin at the resource
object supplied to the function as the ``resource`` argument. If an
Expand Down Expand Up @@ -367,16 +367,16 @@ def virtual_root(resource, request):
the resource object representing the :term:`virtual root` of the
current :term:`request`. Using a virtual root in a
:term:`traversal` -based :app:`Pyramid` application permits
rooting, for example, the object at the traversal path ``/cms`` at
rooting, for example, the resource at the traversal path ``/cms`` at
``http://example.com/`` instead of rooting it at
``http://example.com/cms/``.
If the ``resource`` passed in is a context obtained via
:term:`traversal`, and if the ``HTTP_X_VHM_ROOT`` key is in the
WSGI environment, the value of this key will be treated as a
'virtual root path': the :func:`pyramid.traversal.find_resource`
API will be used to find the virtual root object using this path;
if the object is found, it will be returned. If the
API will be used to find the virtual root resource using this path;
if the resource is found, it will be returned. If the
``HTTP_X_VHM_ROOT`` key is is not present in the WSGI environment,
the physical :term:`root` of the resource tree will be returned instead.
Expand Down Expand Up @@ -526,8 +526,8 @@ def quote_path_segment(segment):

class ResourceTreeTraverser(object):
""" A resource tree traverser that should be used (for speed) when
every object in the tree supplies a ``__name__`` and
``__parent__`` attribute (ie. every object in the tree is
every resource in the tree supplies a ``__name__`` and
``__parent__`` attribute (ie. every resource in the tree is
:term:`location` aware) ."""

implements(ITraverser)
Expand Down Expand Up @@ -633,8 +633,8 @@ def __call__(self, request):
ModelGraphTraverser = ResourceTreeTraverser # b/w compat

class TraversalContextURL(object):
""" The IContextURL adapter used to generate URLs for a context
object obtained via resource tree traversal"""
""" The IContextURL adapter used to generate URLs for a resource in a
resource tree"""
implements(IContextURL)

vroot_varname = VH_ROOT_KEY
Expand Down

0 comments on commit b32bfd3

Please sign in to comment.