diff options
| -rw-r--r-- | CHANGES.txt | 5 | ||||
| -rw-r--r-- | docs/narr/resources.rst | 74 | ||||
| -rw-r--r-- | pyramid/traversal.py | 42 |
3 files changed, 95 insertions, 26 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index e5b46678c..b4f367607 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -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) ================== diff --git a/docs/narr/resources.rst b/docs/narr/resources.rst index 1e54f9eef..fe1f760bb 100644 --- a/docs/narr/resources.rst +++ b/docs/narr/resources.rst @@ -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 @@ -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`. @@ -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) diff --git a/pyramid/traversal.py b/pyramid/traversal.py index 73878022c..f3377b0d0 100644 --- a/pyramid/traversal.py +++ b/pyramid/traversal.py @@ -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 @@ -86,13 +86,13 @@ find_model = find_resource # b/w compat 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 @@ -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 @@ -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 @@ -210,7 +210,7 @@ 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 @@ -218,9 +218,9 @@ def traverse(resource, path): - ``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``. @@ -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 @@ -367,7 +367,7 @@ 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/``. @@ -375,8 +375,8 @@ def virtual_root(resource, request): :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. @@ -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) @@ -633,8 +633,8 @@ class ResourceTreeTraverser(object): 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 |
