Chris McDonough
2010-12-18 738a2b5f3eb44da7036a31005144e5252827ac38
Merge branch 'model2resource'

Conflicts:
docs/narr/views.rst
5 files deleted
6 files added
83 files modified
2 files renamed
4729 ■■■■ changed files
CHANGES.txt 74 ●●●●● patch | view | raw | blame | history
docs/api/config.rst 6 ●●●● patch | view | raw | blame | history
docs/api/request.rst 2 ●●● patch | view | raw | blame | history
docs/api/testing.rst 4 ●●●● patch | view | raw | blame | history
docs/api/traversal.rst 6 ●●●● patch | view | raw | blame | history
docs/api/url.rst 2 ●●● patch | view | raw | blame | history
docs/designdefense.rst 123 ●●●●● patch | view | raw | blame | history
docs/glossary.rst 114 ●●●● patch | view | raw | blame | history
docs/index.rst 4 ●●●● patch | view | raw | blame | history
docs/latexindex.rst 6 ●●●● patch | view | raw | blame | history
docs/narr/MyProject/myproject/__init__.py 6 ●●●● patch | view | raw | blame | history
docs/narr/MyProject/myproject/models.py 7 ●●●●● patch | view | raw | blame | history
docs/narr/MyProject/myproject/resources.py 3 ●●●●● patch | view | raw | blame | history
docs/narr/assets.rst 198 ●●●●● patch | view | raw | blame | history
docs/narr/contextfinding.rst 18 ●●●● patch | view | raw | blame | history
docs/narr/declarative.rst 123 ●●●● patch | view | raw | blame | history
docs/narr/environment.rst 80 ●●●● patch | view | raw | blame | history
docs/narr/extending.rst 10 ●●●● patch | view | raw | blame | history
docs/narr/handlers.rst 4 ●●●● patch | view | raw | blame | history
docs/narr/hooks.rst 42 ●●●● patch | view | raw | blame | history
docs/narr/hybrid.rst 51 ●●●● patch | view | raw | blame | history
docs/narr/introduction.rst 27 ●●●● patch | view | raw | blame | history
docs/narr/models.rst 331 ●●●●● patch | view | raw | blame | history
docs/narr/project.rst 69 ●●●● patch | view | raw | blame | history
docs/narr/resources.rst 467 ●●●● patch | view | raw | blame | history
docs/narr/resourcetreetraverser.png patch | view | raw | blame | history
docs/narr/security.rst 67 ●●●● patch | view | raw | blame | history
docs/narr/static.rst 191 ●●●● patch | view | raw | blame | history
docs/narr/templates.rst 57 ●●●● patch | view | raw | blame | history
docs/narr/threadlocals.rst 8 ●●●●● patch | view | raw | blame | history
docs/narr/traversal.rst 198 ●●●● patch | view | raw | blame | history
docs/narr/unittesting.rst 37 ●●●● patch | view | raw | blame | history
docs/narr/urldispatch.rst 14 ●●●● patch | view | raw | blame | history
docs/narr/vhosting.rst 26 ●●●● patch | view | raw | blame | history
docs/narr/views.rst 267 ●●●● patch | view | raw | blame | history
docs/narr/zca.rst 2 ●●● patch | view | raw | blame | history
docs/tutorials/catalog/index.rst 4 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/basiclayout.rst 14 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/definingmodels.rst 22 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/definingviews.rst 18 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/authorization/tutorial/login.py 6 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/authorization/tutorial/tests.py 25 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/authorization/tutorial/views.py 16 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/viewdecorators/tutorial/tests.py 25 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/viewdecorators/tutorial/views.py 16 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/views/tutorial/tests.py 24 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/views/tutorial/views.py 16 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/definingmodels.rst 12 ●●●● patch | view | raw | blame | history
docs/zcml.rst 2 ●●● patch | view | raw | blame | history
docs/zcml/aclauthorizationpolicy.rst 2 ●●● patch | view | raw | blame | history
docs/zcml/asset.rst 65 ●●●●● patch | view | raw | blame | history
docs/zcml/forbidden.rst 2 ●●● patch | view | raw | blame | history
docs/zcml/handler.rst 2 ●●● patch | view | raw | blame | history
docs/zcml/notfound.rst 2 ●●● patch | view | raw | blame | history
docs/zcml/resource.rst 62 ●●●●● patch | view | raw | blame | history
docs/zcml/route.rst 4 ●●●● patch | view | raw | blame | history
docs/zcml/view.rst 12 ●●●● patch | view | raw | blame | history
pyramid/asset.py 207 ●●●●● patch | view | raw | blame | history
pyramid/authorization.py 2 ●●● patch | view | raw | blame | history
pyramid/chameleon_text.py 8 ●●●● patch | view | raw | blame | history
pyramid/chameleon_zpt.py 8 ●●●● patch | view | raw | blame | history
pyramid/config.py 118 ●●●● patch | view | raw | blame | history
pyramid/includes/meta.zcml 10 ●●●● patch | view | raw | blame | history
pyramid/interfaces.py 2 ●●● patch | view | raw | blame | history
pyramid/location.py 32 ●●●● patch | view | raw | blame | history
pyramid/mako_templating.py 23 ●●●● patch | view | raw | blame | history
pyramid/paster_templates/starter/+package+/__init__.py_tmpl 6 ●●●● patch | view | raw | blame | history
pyramid/paster_templates/starter/+package+/models.py 7 ●●●●● patch | view | raw | blame | history
pyramid/paster_templates/starter/+package+/resources.py 3 ●●●●● patch | view | raw | blame | history
pyramid/paster_templates/starter_zcml/+package+/__init__.py_tmpl 4 ●●●● patch | view | raw | blame | history
pyramid/paster_templates/starter_zcml/+package+/configure.zcml 2 ●●● patch | view | raw | blame | history
pyramid/paster_templates/starter_zcml/+package+/models.py 7 ●●●●● patch | view | raw | blame | history
pyramid/paster_templates/starter_zcml/+package+/resources.py 3 ●●●●● patch | view | raw | blame | history
pyramid/renderers.py 34 ●●●● patch | view | raw | blame | history
pyramid/request.py 48 ●●●●● patch | view | raw | blame | history
pyramid/resource.py 212 ●●●●● patch | view | raw | blame | history
pyramid/router.py 8 ●●●● patch | view | raw | blame | history
pyramid/security.py 4 ●●●● patch | view | raw | blame | history
pyramid/settings.py 12 ●●●● patch | view | raw | blame | history
pyramid/static.py 18 ●●●● patch | view | raw | blame | history
pyramid/testing.py 50 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_asset.py 82 ●●●● patch | view | raw | blame | history
pyramid/tests/test_authorization.py 2 ●●● patch | view | raw | blame | history
pyramid/tests/test_config.py 40 ●●●● patch | view | raw | blame | history
pyramid/tests/test_mako_templating.py 14 ●●●● patch | view | raw | blame | history
pyramid/tests/test_renderers.py 8 ●●●● patch | view | raw | blame | history
pyramid/tests/test_request.py 4 ●●●● patch | view | raw | blame | history
pyramid/tests/test_settings.py 36 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_testing.py 70 ●●●● patch | view | raw | blame | history
pyramid/tests/test_traversal.py 282 ●●●● patch | view | raw | blame | history
pyramid/tests/test_url.py 8 ●●●● patch | view | raw | blame | history
pyramid/tests/test_zcml.py 8 ●●●● patch | view | raw | blame | history
pyramid/traversal.py 255 ●●●● patch | view | raw | blame | history
pyramid/url.py 63 ●●●● patch | view | raw | blame | history
pyramid/view.py 10 ●●●● patch | view | raw | blame | history
pyramid/zcml.py 24 ●●●● patch | view | raw | blame | history
CHANGES.txt
@@ -1,6 +1,77 @@
Next release
============
Terminology Changes
-------------------
- The Pyramid concept previously known as "model" is now known as "resource".
  As a result:
  - The following API changes have been made::
      pyramid.url.model_url ->
                        pyramid.url.resource_url
      pyramid.traversal.find_model ->
                        pyramid.url.find_resource
      pyramid.traversal.model_path ->
                        pyramid.traversal.resource_path
      pyramid.traversal.model_path_tuple ->
                        pyramid.traversal.resource_path_tuple
      pyramid.traversal.ModelGraphTraverser ->
                        pyramid.traversal.ResourceTreeTraverser
      pyramid.config.Configurator.testing_models ->
                        pyramid.config.Configurator.testing_resources
      pyramid.testing.registerModels ->
                        pyramid.testing.registerResources
      pyramid.testing.DummyModel ->
                        pyramid.testing.DummyResource
   - All documentation which previously referred to "model" now refers to
     "resource".
   - The ``starter`` and ``starter_zcml`` paster templates now have a
     ``resources.py`` module instead of a ``models.py`` module.
  - Positional argument names of various APIs have been changed from
    ``model`` to ``resource``.
  Backwards compatibility shims have been left in place in all cases.  They
  will continue to work "forever".
- The Pyramid concept previously known as "resource" is now known as "asset".
  As a result:
  - The (non-API) module previously known as ``pyramid.resource`` is now
    known as ``pyramid.asset``.
  - All docs that previously referred to "resource specification" now refer
    to "asset specification".
  - The following API changes were made::
      pyramid.config.Configurator.absolute_resource_spec ->
                        pyramid.config.Configurator.absolute_asset_spec
      pyramid.config.Configurator.override_resource ->
                        pyramid.config.Configurator.override_asset
  - The ZCML directive previously known as ``resource`` is now known as
    ``asset``.
  - The setting previously known as ``BFG_RELOAD_RESOURCES`` (envvar) or
    ``reload_resources`` (config file) is now known, respectively, as
    ``BFG_RELOAD_ASSETS`` and ``reload_assets``.
  Backwards compatibility shims have been left in place in all cases.  They
  will continue to work "forever".
Bug Fixes
---------
@@ -30,6 +101,9 @@
- Direct Jython users to Mako rather than Jinja2 in "Install" narrative
  chapter.
- Many changes to support terminological renaming of "model" to "resource"
  and "resource" to "asset".
Paster Templates
----------------
docs/api/config.rst
@@ -32,7 +32,7 @@
     .. automethod:: maybe_dotted
     .. automethod:: absolute_resource_spec
     .. automethod:: absolute_asset_spec
     .. automethod:: setup_registry(settings=None, root_factory=None, authentication_policy=None, renderers=DEFAULT_RENDERERS, debug_logger=None, locale_negotiator=None, request_factory=None, renderer_globals_factory=None)
@@ -58,7 +58,7 @@
     .. automethod:: make_wsgi_app()
     .. automethod:: override_resource(to_override, override_with)
     .. automethod:: override_asset(to_override, override_with)
     .. automethod:: scan(package=None, categories=None)
@@ -78,7 +78,7 @@
     .. automethod:: testing_securitypolicy
     .. automethod:: testing_models
     .. automethod:: testing_resources
     .. automethod:: testing_add_subscriber
docs/api/request.rst
@@ -26,7 +26,7 @@
   .. attribute:: root
      The :term:`root` object will be available as the ``root``
      attribute of the :term:`request` object.  It will be the model
      attribute of the :term:`request` object.  It will be the resource
      object at which traversal started (the root).  See
      :ref:`traversal_chapter` for information about root objects.
docs/api/testing.rst
@@ -7,7 +7,7 @@
  .. autofunction:: registerDummySecurityPolicy
  .. autofunction:: registerModels
  .. autofunction:: registerResources
  .. autofunction:: registerEventListener
@@ -31,7 +31,7 @@
  .. autofunction:: cleanUp
  .. autoclass:: DummyModel
  .. autoclass:: DummyResource
     :members:
  .. autoclass:: DummyRequest
docs/api/traversal.rst
@@ -7,13 +7,13 @@
  .. autofunction:: find_interface
  .. autofunction:: find_model
  .. autofunction:: find_resource
  .. autofunction:: find_root
  .. autofunction:: model_path
  .. autofunction:: resource_path
  .. autofunction:: model_path_tuple
  .. autofunction:: resource_path_tuple
  .. autofunction:: quote_path_segment
docs/api/url.rst
@@ -5,7 +5,7 @@
.. automodule:: pyramid.url
  .. autofunction:: pyramid.url.model_url(context, request, *elements, query=None, anchor=None)
  .. autofunction:: pyramid.url.resource_url(context, request, *elements, query=None, anchor=None)
  .. autofunction:: route_url
docs/designdefense.rst
@@ -606,77 +606,48 @@
Pyramid Uses "Model" To Represent A Node In The Graph of Objects Traversed
--------------------------------------------------------------------------
The :app:`Pyramid` documentation refers to the graph being
traversed when :term:`traversal` is used as a "model graph".  Some of
the :app:`Pyramid` APIs also use the word "model" in them when
referring to a node in this graph (e.g. ``pyramid.url.model_url``).
A terminology overlap confuses people who write applications that
always use ORM packages such as SQLAlchemy, which has a different
notion of the definition of a "model".  When using the API of common
ORM packages, its conception of "model" is almost certainly not a
directed acyclic graph (as may be the case in many graph databases).
Often model objects must be explicitly manufactured by an ORM as a
result of some query performed by a :term:`view`.  As a result, it can
be unnatural to think of the nodes traversed as "model" objects if you
develop your application using traversal and a relational database.
When you develop such applications, the things that :app:`Pyramid`
refers to as "models" in such an application may just be stand-ins
that perform a query and generate some wrapper *for* an ORM "model"
(or set of ORM models).  The graph *might* be composed completely of
"model" objects (as defined by the ORM) but it also might not be.
The naming impedance mismatch between the way the term "model" is used
to refer to a node in a graph in :app:`Pyramid` and the way the
term "model" is used by packages like SQLAlchemy is unfortunate.  For
the purpose of avoiding confusion, if we had it to do all over again,
we might refer to the graph that :app:`Pyramid` traverses a "node
graph" or "object graph" rather than a "model graph", but since we've
baked the name into the API, it's a little late.  Sorry.
In our defense, many :app:`Pyramid` applications (especially ones
which use :term:`ZODB`) do indeed traverse a graph full of model
nodes.  Each node in the graph is a separate persistent object that is
stored within a database.  This was the use case considered when
coming up with the "model" terminology.
The ``repoze.bfg`` documentation used to refer to the graph being traversed
when :term:`traversal` is used as a "model graph".  A terminology overlap
confused people who wrote applications that always use ORM packages such as
SQLAlchemy, which has a different notion of the definition of a "model".  As
a sresult, in Pyramid 1.0a7, the tree of objects traversed is now renamed to
:term:`resource tree` and its components are now named :term:`resource`
objects.  Associated APIs have been changed.  This hopefully alleviates the
terminology confusion caused by overriding the term "model".
Pyramid Does Traversal, And I Don't Like Traversal
--------------------------------------------------
In :app:`Pyramid`, :term:`traversal` is the act of resolving a URL
path to a :term:`model` object in an object graph.  Some people are
uncomfortable with this notion, and believe it is wrong.
In :app:`Pyramid`, :term:`traversal` is the act of resolving a URL path to a
:term:`resource` object in a resource tree.  Some people are uncomfortable
with this notion, and believe it is wrong.
This is understandable.  The people who believe it is wrong almost
invariably have all of their data in a relational database.
Relational databases aren't naturally hierarchical, so "traversing"
one like a graph is not possible.  This problem is related to
:ref:`model_traversal_confusion`.
This is understandable.  The people who believe it is wrong almost invariably
have all of their data in a relational database.  Relational databases aren't
naturally hierarchical, so "traversing" one like a tree is not possible.
Folks who deem traversal unilaterally "wrong" are neglecting to take
into account that many persistence mechanisms *are* hierarchical.
Examples include a filesystem, an LDAP database, a :term:`ZODB` (or
another type of graph) database, an XML document, and the Python
module namespace.  It is often convenient to model the frontend to a
hierarchical data store as a graph, using traversal to apply views to
objects that either *are* the nodes in the graph being traversed (such
as in the case of ZODB) or at least ones which stand in for them (such
as in the case of wrappers for files from the filesystem).
Folks who deem traversal unilaterally "wrong" are neglecting to take into
account that many persistence mechanisms *are* hierarchical.  Examples
include a filesystem, an LDAP database, a :term:`ZODB` (or another type of
graph) database, an XML document, and the Python module namespace.  It is
often convenient to model the frontend to a hierarchical data store as a
graph, using traversal to apply views to objects that either *are* the
resources in the tree being traversed (such as in the case of ZODB) or at
least ones which stand in for them (such as in the case of wrappers for files
from the filesystem).
Also, many website structures are naturally hierarchical, even if the
data which drives them isn't.  For example, newspaper websites are
often extremely hierarchical: sections within sections within
sections, ad infinitum.  If you want your URLs to indicate this
structure, and the structure is indefinite (the number of nested
sections can be "N" instead of some fixed number), traversal is an
excellent way to model this, even if the backend is a relational
database.  In this situation, the graph being traversed is actually
less a "model graph" than a site structure.
Also, many website structures are naturally hierarchical, even if the data
which drives them isn't.  For example, newspaper websites are often extremely
hierarchical: sections within sections within sections, ad infinitum.  If you
want your URLs to indicate this structure, and the structure is indefinite
(the number of nested sections can be "N" instead of some fixed number), a
resource tree is an excellent way to model this, even if the backend is a
relational database.  In this situation, the resource tree a just a site
structure.
But the point is ultimately moot.  If you use :app:`Pyramid`, and
you don't want to model your application in terms of traversal, you
needn't use it at all.  Instead, use :term:`URL dispatch` to map URL
paths to views.
But the point is ultimately moot.  If you use :app:`Pyramid`, and you don't
want to model your application in terms of a resource tree, you needn't use
it at all.  Instead, use :term:`URL dispatch` to map URL paths to views.
Pyramid Does URL Dispatch, And I Don't Like URL Dispatch
--------------------------------------------------------
@@ -705,7 +676,7 @@
a route like ``<route name="manage" pattern="manage/*traverse"/>`` and then
associate "management" views in your code by using the ``route_name``
argument to a ``view`` configuration, e.g. ``<view view=".some.callable"
context=".some.Model" route_name="manage"/>``.  If you wire things up this
context=".some.Resource" route_name="manage"/>``.  If you wire things up this
way someone then walks up to for example, ``/manage/ob1/ob2``, they might be
presented with a management interface, but walking up to ``/ob1/ob2`` would
present them with the default object view.  There are other tricks you can
@@ -745,7 +716,7 @@
       return HttpResponse(poll_id)
Zope, likewise allows you to add arbitrary keyword and positional
arguments to any method of a model object found via traversal:
arguments to any method of a resource object found via traversal:
.. ignore-next-block
.. code-block:: python
@@ -993,14 +964,16 @@
detect when the model changes.  The web just has no such facility in
its current form: it's effectively pull-only.
So, in the interest of not mistaking desire with reality, and instead
of trying to jam the square peg that is the web into the round hole of
"MVC", we just punt and say there are two things: the model, and the
view. The model stores the data, the view presents it.  The templates
are really just an implementation detail of any given view: a view
doesn't need a template to return a response.  There's no
"controller": it just doesn't exist.  This seems to us like a more
reasonable model, given the current constraints of the web.
So, in the interest of not mistaking desire with reality, and instead of
trying to jam the square peg that is the web into the round hole of "MVC", we
just punt and say there are two things: resources and views. The resource
tree represents a site structure, the view presents a resource.  The
templates are really just an implementation detail of any given view: a view
doesn't need a template to return a response.  There's no "controller": it
just doesn't exist.  The "model" is either represented by the resource tree
or by a "domain model" (like a SQLAlchemy model) that is separate from the
framework entirely.  This seems to us like more reasonable terminology, given
the current constraints of the web.
.. _apps_are_extensible:
@@ -1151,9 +1124,9 @@
   permissions that the accessing user possesses with respect to a context
   object.
#) I want to also expose my model via a REST API using Twisted Web. If
#) I want to also expose my resources via a REST API using Twisted Web. If
   Pyramid performed authorization based on attribute access via Zope3's
   security proies, I could enforce my authorization policy in both
   security proxies, I could enforce my authorization policy in both
   :app:`Pyramid` and in the Twisted-based system the same way.
Defense
docs/glossary.rst
@@ -38,20 +38,20 @@
   pkg_resources
     A module which ships with :term:`setuptools` that provides an API
     for addressing "resource files" within Python packages.  Resource
     for addressing "asset files" within Python packages.  Asset
     files are static files, template files, etc; basically anything
     non-Python-source that lives in a Python package can be considered
     a resource file.  See also `PkgResources
     a asset file.  See also `PkgResources
     <http://peak.telecommunity.com/DevCenter/PkgResources>`_
   resource
   asset
     Any file contained within a Python :term:`package` which is *not*
     a Python source code file.
   resource specification
     A colon-delimited identifier for a :term:`resource`.  The colon
   asset specification
     A colon-delimited identifier for an :term:`asset`.  The colon
     separates a Python :term:`package` name from a package subpath.
     For example, the resource specification
     For example, the asset specification
     ``my.package:static/baz.css`` identifies the file named
     ``baz.css`` in the ``static`` subdirectory of the ``my.package``
     Python :term:`package`.
@@ -120,10 +120,10 @@
     string (which implies the :term:`default view`).
   Default view
     The default view of a model is the view invoked when the
     :term:`view name` is the empty string (``''``).  This is the case
     when :term:`traversal` exhausts the path elements in the PATH_INFO
     of a request before it returns a :term:`context`.
     The default view of a :term:`resource` is the view invoked when the
     :term:`view name` is the empty string (``''``).  This is the case when
     :term:`traversal` exhausts the path elements in the PATH_INFO of a
     request before it returns a :term:`context`.
   virtualenv
     An isolated Python environment.  Allows you to control which
@@ -131,25 +131,33 @@
     Python.  `virtualenv <http://pypi.python.org/pypi/virtualenv>`_
     was created by Ian Bicking.
   model
     An object representing data in the system.  If :mod:`traversal` is
     used, a model is a node in the object graph traversed by the
     system.  When traversal is used, a model instance becomes the
     :term:`context` of a :term:`view`.  If :mod:`url dispatch` is
     used, a single :term:`context` is generated for each request and
     is used as the context of a view: this object is also technically
     a "model" in :app:`Pyramid` terms, although this terminology
     can be a bit confusing: see :ref:`model_traversal_confusion`.
   resource
     An object representing a node in the :term:`resource tree` of an
     application.  If :mod:`traversal` is used, a resource is an element in
     the resource tree traversed by the system.  When traversal is used, a
     resource becomes the :term:`context` of a :term:`view`.  If :mod:`url
     dispatch` is used, a single resource is generated for each request and
     is used as the context of a view.
   resource tree
     A nested set of dictionary-like objects, each of which is a
     :term:`resource`.  The act of :term:`traversal` uses the resource tree
     to find a :term:`context`.
   domain model
     Persistent data related to your application.  For example, data stored
     in a relational database.  In some applications, the :term:`resource
     tree` acts as the domain model.
   traversal
     The act of descending "down" a graph of model objects from a root
     model in order to find a :term:`context`.  The :app:`Pyramid`
     :term:`router` performs traversal of model objects when a
     :term:`root factory` is specified.  See the
     :ref:`traversal_chapter` chapter for more information.  Traversal
     can be performed *instead* of :term:`URL dispatch` or can be
     combined *with* URL dispatch.  See :ref:`hybrid_chapter` for more
     information about combining traversal and URL dispatch (advanced).
     The act of descending "up" a tree of resource objects from a root
     resource in order to find a :term:`context`.  The :app:`Pyramid`
     :term:`router` performs traversal of resource objects when a :term:`root
     factory` is specified.  See the :ref:`traversal_chapter` chapter for
     more information.  Traversal can be performed *instead* of :term:`URL
     dispatch` or can be combined *with* URL dispatch.  See
     :ref:`hybrid_chapter` for more information about combining traversal and
     URL dispatch (advanced).
   router
     The :term:`WSGI` application created when you start a
@@ -159,7 +167,7 @@
     :app:`Pyramid` application.
   URL dispatch
     An alternative to graph traversal as a mechanism for locating a
     An alternative to :term:`traversal` as a mechanism for locating a
     :term:`context` for a :term:`view`.  When you use a :term:`route`
     in your :app:`Pyramid` application via a :term:`route
     configuration`, you are using URL dispatch. See the
@@ -167,19 +175,19 @@
   context
     An object in the system that is found during :term:`traversal` or
     :term:`URL dispatch` based on URL data; if it's found via
     traversal, it's usually a :term:`model` object that is part of an
     object graph; if it's found via :term:`URL dispatch`, it's a
     object manufactured on behalf of the route's "factory".  A context
     becomes the subject of a :term:`view`, and typically has security
     information attached to it.  See the :ref:`traversal_chapter`
     chapter and the :ref:`urldispatch_chapter` chapter for more
     information about how a URL is resolved to a context.
     :term:`URL dispatch` based on URL data; if it's found via traversal,
     it's usually a :term:`resource` object that is part of a resource tree;
     if it's found via :term:`URL dispatch`, it's a object manufactured on
     behalf of the route's "factory".  A context becomes the subject of a
     :term:`view`, and typically has security information attached to it.
     See the :ref:`traversal_chapter` chapter and the
     :ref:`urldispatch_chapter` chapter for more information about how a URL
     is resolved to a context.
   application registry
     A registry of configuration information consulted by
     :app:`Pyramid` while servicing an application.  An application
     registry maps model types to views, as well as housing other
     registry maps resource types to views, as well as housing other
     application-specific component registrations.  Every
     :app:`Pyramid` application has one (and only one) application
     registry.
@@ -189,20 +197,20 @@
     text, XML, or HTML when rendered.
   location
     The path to an object in an object graph.  See :ref:`location_aware`
     for more information about how to make a model object *location-aware*.
     The path to an object in a :term:`resource tree`.  See
     :ref:`location_aware` for more information about how to make a resource
     object *location-aware*.
   permission
     A string or unicode object that represents an action being taken
     against a context.  A permission is associated with a view name
     and a model type by the developer.  Models are decorated with
     security declarations (e.g. an :term:`ACL`), which reference these
     tokens also.  Permissions are used by the active to security
     policy to match the view permission against the model's statements
     about which permissions are granted to which principal in a
     context in order to to answer the question "is this user allowed
     to do this".  Examples of permissions: ``read``, or
     ``view_blog_entries``.
     A string or unicode object that represents an action being taken against
     a context.  A permission is associated with a view name and a resource
     type by the developer.  Resources are decorated with security
     declarations (e.g. an :term:`ACL`), which reference these tokens also.
     Permissions are used by the active to security policy to match the view
     permission against the resources's statements about which permissions
     are granted to which principal in a context in order to to answer the
     question "is this user allowed to do this".  Examples of permissions:
     ``read``, or ``view_blog_entries``.
   default permission
     A :term:`permission` which is registered as the default for an
@@ -225,9 +233,9 @@
   ACL
     An *access control list*.  An ACL is a sequence of :term:`ACE`
     tuples.  An ACL is attached to a model instance.  An example of an
     tuples.  An ACL is attached to a resource instance.  An example of an
     ACL is ``[ (Allow, 'bob', 'read'), (Deny, 'fred', 'write')]``.  If
     an ACL is attached to a model instance, and that model instance is
     an ACL is attached to a resource instance, and that resource is
     findable via the context, it will be consulted any active security
     policy to determine wither a particular request can be fulfilled
     given the :term:`authentication` information in the request.
@@ -416,7 +424,7 @@
   interface
     A `Zope interface <http://pypi.python.org/pypi/zope.interface>`_
     object.  In :app:`Pyramid`, an interface may be attached to a
     :term:`model` object or a :term:`request` object in order to
     :term:`resource` object or a :term:`request` object in order to
     identify that the object is "of a type".  Interfaces are used
     internally by :app:`Pyramid` to perform view lookups and other
     policy lookups.  The ability to make use of an interface is
@@ -476,7 +484,7 @@
     :app:`Pyramid` to form a workflow system.
   virtual root
     A model object representing the "virtual" root of a request; this
     A resource object representing the "virtual" root of a request; this
     is typically the physical root object (the object returned by the
     application root factory) unless :ref:`vhosting_chapter` is in
     use.
docs/index.rst
@@ -48,7 +48,7 @@
   narr/webob
   narr/sessions
   narr/templates
   narr/models
   narr/resources
   narr/security
   narr/i18n
   narr/vhosting
@@ -58,7 +58,7 @@
   narr/hooks
   narr/declarative
   narr/extending
   narr/resources
   narr/assets
   narr/router
   narr/threadlocals
   narr/zca
docs/latexindex.rst
@@ -41,7 +41,7 @@
   narr/webob
   narr/sessions
   narr/templates
   narr/models
   narr/resources
   narr/security
   narr/i18n
   narr/vhosting
@@ -51,7 +51,7 @@
   narr/hooks
   narr/declarative
   narr/extending
   narr/resources
   narr/assets
   narr/router
   narr/startup
   narr/threadlocals
@@ -119,6 +119,7 @@
   zcml/aclauthorizationpolicy
   zcml/adapter
   zcml/authtktauthenticationpolicy
   zcml/asset
   zcml/configure
   zcml/default_permission
   zcml/forbidden
@@ -127,7 +128,6 @@
   zcml/remoteuserauthenticationpolicy
   zcml/renderer
   zcml/repozewho1authenticationpolicy
   zcml/resource
   zcml/route
   zcml/scan
   zcml/static
docs/narr/MyProject/myproject/__init__.py
@@ -1,12 +1,12 @@
from pyramid.config import Configurator
from myproject.models import get_root
from myproject.resources import Root
def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    config = Configurator(root_factory=get_root, settings=settings)
    config = Configurator(root_factory=Root, settings=settings)
    config.add_view('myproject.views.my_view',
                    context='myproject.models.MyModel',
                    context='myproject.resources.Root',
                    renderer='myproject:templates/mytemplate.pt')
    config.add_static_view('static', 'myproject:static')
    return config.make_wsgi_app()
docs/narr/MyProject/myproject/models.py
File was deleted
docs/narr/MyProject/myproject/resources.py
New file
@@ -0,0 +1,3 @@
class Root(object):
    def __init__(self, request):
        self.request = request
docs/narr/assets.rst
New file
@@ -0,0 +1,198 @@
.. index::
   single: assets
.. _assets_chapter:
Assets
======
An :term:`asset` is any file contained within a Python :term:`package` which
is *not* a Python source code file.  For example, each of the following is an
asset:
- a :term:`Chameleon` template file contained within a Python package.
- a GIF image file contained within a Python package.
- a CSS file contained within a Python package.
- a JavaScript source file contained within a Python package.
- A directory within a package that does not have an ``__init__.py``
  in it (if it possessed an ``__init__.py`` it would *be* a package).
The use of assets is quite common in most web development projects.  For
example, when you create a :app:`Pyramid` application using one of the
available "paster" templates, as described in :ref:`creating_a_project`, the
directory representing the application contains a Python :term:`package`.
Within that Python package, there are directories full of files which are
assets.  For example, there is a ``templates`` directory which contains
``.pt`` files, and a ``static`` directory which contains ``.css``, ``.js``,
and ``.gif`` files.
.. _understanding_assets:
Understanding Assets
--------------------
Let's imagine you've created a :app:`Pyramid` application that uses a
:term:`Chameleon` ZPT template via the
:func:`pyramid.chameleon_zpt.render_template_to_response` API.  For example,
the application might address the asset named ``templates/some_template.pt``
using that API within a ``views.py`` file inside a ``myapp`` package:
.. ignore-next-block
.. code-block:: python
   :linenos:
   from pyramid.chameleon_zpt import render_template_to_response
   render_template_to_response('templates/some_template.pt')
"Under the hood", when this API is called, :app:`Pyramid` attempts
to make sense out of the string ``templates/some_template.pt``
provided by the developer.  To do so, it first finds the "current"
package.  The "current" package is the Python package in which the
``views.py`` module which contains this code lives.  This would be the
``myapp`` package, according to our example so far.  By resolving the
current package, :app:`Pyramid` has enough information to locate
the actual template file.  These are the elements it needs:
- The *package name* (``myapp``)
- The *asset name* (``templates/some_template.pt``)
:app:`Pyramid` uses the :term:`pkg_resources` API to resolve the package name
and asset name to an absolute (operating-system-specific) file name.  It
eventually passes this resolved absolute filesystem path to the Chameleon
templating engine, which then uses it to load, parse, and execute the
template file.
Package names often contain dots.  For example, ``pyramid`` is a package.
Asset names usually look a lot like relative UNIX file paths.
.. index::
   pair: overriding; assets
.. _overriding_assets_section:
Overriding Assets
-----------------
It can often be useful to override specific assets from "outside" a given
:app:`Pyramid` application.  For example, you may wish to reuse an existing
:app:`Pyramid` application more or less unchanged.  However, some specific
template file owned by the application might have inappropriate HTML, or some
static asset (such as a logo file or some CSS file) might not be appropriate.
You *could* just fork the application entirely, but it's often more
convenient to just override the assets that are inappropriate and reuse the
application "as is".  This is particularly true when you reuse some "core"
application over and over again for some set of customers (such as a CMS
application, or some bug tracking application), and you want to make
arbitrary visual modifications to a particular application deployment without
forking the underlying code.
To this end, :app:`Pyramid` contains a feature that makes it possible to
"override" one asset with one or more other assets.  In support of this
feature, a :term:`Configurator` API exists named
:meth:`pyramid.config.Configurator.override_asset`.  This API allows you to
*override* the following kinds of assets defined in any Python package:
- Individual :term:`Chameleon` templates.
- A directory containing multiple Chameleon templates.
- Individual static files served up by an instance of the
  ``pyramid.view.static`` helper class.
- A directory of static files served up by an instance of the
  ``pyramid.view.static`` helper class.
- Any other asset (or set of assets) addressed by code that uses the
  setuptools :term:`pkg_resources` API.
.. note:: The :term:`ZCML` directive named ``asset`` serves the same purpose
   as the :meth:`pyramid.config.Configurator.override_asset` method.
.. index::
   single: override_asset
.. _override_asset:
The ``override_asset`` API
~~~~~~~~~~~~~~~~~~~~~~~~~~
An individual call to :meth:`pyramid.config.Configurator.override_asset`
can override a single asset.  For example:
.. ignore-next-block
.. code-block:: python
   :linenos:
   config.override_asset(
            to_override='some.package:templates/mytemplate.pt',
            override_with='another.package:othertemplates/anothertemplate.pt')
The string value passed to both ``to_override`` and ``override_with`` sent to
the ``override_asset`` API is called an :term:`asset specification`.  The
colon separator in a specification separates the *package name* from the
*asset name*.  The colon and the following asset name are optional.  If they
are not specified, the override attempts to resolve every lookup into a
package from the directory of another package.  For example:
.. ignore-next-block
.. code-block:: python
   :linenos:
   config.override_asset(to_override='some.package',
                         override_with='another.package')
Individual subdirectories within a package can also be overridden:
.. ignore-next-block
.. code-block:: python
   :linenos:
   config.override_asset(to_override='some.package:templates/',
                         override_with='another.package:othertemplates/')
If you wish to override a directory with another directory, you *must*
make sure to attach the slash to the end of both the ``to_override``
specification and the ``override_with`` specification.  If you fail to
attach a slash to the end of a specification that points to a directory,
you will get unexpected results.
You cannot override a directory specification with a file specification, and
vice versa: a startup error will occur if you try.  You cannot override an
asset with itself: a startup error will occur if you try.
Only individual *package* assets may be overridden.  Overrides will not
traverse through subpackages within an overridden package.  This means that
if you want to override assets for both ``some.package:templates``, and
``some.package.views:templates``, you will need to register two overrides.
The package name in a specification may start with a dot, meaning that
the package is relative to the package in which the configuration
construction file resides (or the ``package`` argument to the
:class:`pyramid.config.Configurator` class construction).
For example:
.. ignore-next-block
.. code-block:: python
   :linenos:
   config.override_asset(to_override='.subpackage:templates/',
                         override_with='another.package:templates/')
Multiple calls to ``override_asset`` which name a shared ``to_override`` but
a different ``override_with`` specification can be "stacked" to form a search
path.  The first asset that exists in the search path will be used; if no
asset exists in the override path, the original asset is used.
Asset overrides can actually override assets other than templates and static
files.  Any software which uses the
:func:`pkg_resources.get_resource_filename`,
:func:`pkg_resources.get_resource_stream` or
:func:`pkg_resources.get_resource_string` APIs will obtain an overridden file
when an override is used.
docs/narr/contextfinding.rst
@@ -95,20 +95,20 @@
hierarchies.
But :term:`traversal` *does* work well for URLs that represent
arbitrary-depth hierarchies.  Since the path segments that compose a
URL are addressed separately, it becomes very easy to form URLs that
represent arbitrary depth hierarchies in a system that uses traversal.
When you're willing to treat your application models as a graph that
can be traversed, it also becomes easy to provide "instance-level
security": you just attach a security declaration to each instance in
the graph.  This is not nearly as easy to do when using URL dispatch.
arbitrary-depth hierarchies.  Since the path segments that compose a URL are
addressed separately, it becomes very easy to form URLs that represent
arbitrary depth hierarchies in a system that uses traversal.  When you're
willing to treat your application resources as a tree that can be traversed,
it also becomes easy to provide "instance-level security": you just attach a
security declaration to each instance in the tree.  This is not nearly as
easy to do when using URL dispatch.
In essence, the choice to use traversal vs. URL dispatch is largely
religious.  Traversal dispatch probably just doesn't make any sense
when you possess completely "square" data stored in a relational
database because it requires the construction and maintenance of a
graph and requires that the developer think about mapping URLs to code
in terms of traversing that graph.  However, when you have a
tree and requires that the developer think about mapping URLs to code
in terms of traversing that tree.  However, when you have a
hierarchical data store, using traversal can provide significant
advantages over using URL-based dispatch.
docs/narr/declarative.rst
@@ -557,7 +557,7 @@
   :linenos:
   <view
     context=".models.Hello"
     context=".resources.Hello"
     view=".views.hello_world"
     name="hello.html"
    />
@@ -566,7 +566,7 @@
the following set of :term:`context finding` results:
- A :term:`context` object which is an instance (or subclass) of the
  Python class represented by ``.models.Hello``
  Python class represented by ``.resources.Hello``
- A :term:`view name` equalling ``hello.html``.
@@ -575,28 +575,27 @@
   above) mean "relative to the Python package directory in which this
   :term:`ZCML` file is stored".  So if the above ``view`` declaration
   was made inside a ``configure.zcml`` file that lived in the
   ``hello`` package, you could replace the relative ``.models.Hello``
   with the absolute ``hello.models.Hello``; likewise you could
   ``hello`` package, you could replace the relative ``.resources.Hello``
   with the absolute ``hello.resources.Hello``; likewise you could
   replace the relative ``.views.hello_world`` with the absolute
   ``hello.views.hello_world``.  Either the relative or absolute form
   is functionally equivalent.  It's often useful to use the relative
   form, in case your package's name changes.  It's also shorter to
   type.
You can also declare a *default view callable* for a :term:`model`
type:
You can also declare a *default view callable* for a :term:`resource` type:
.. code-block:: xml
   :linenos:
   <view
     context=".models.Hello"
     context=".resources.Hello"
     view=".views.hello_world"
    />
A *default view callable* simply has no ``name`` attribute.  For the
above registration, when a :term:`context` is found that is of the
type ``.models.Hello`` and there is no :term:`view name` associated
type ``.resources.Hello`` and there is no :term:`view name` associated
with the result of :term:`context finding`, the *default view
callable* will be used.  In this case, it's the view at
``.views.hello_world``.
@@ -608,7 +607,7 @@
   :linenos:
   <view
     context=".models.Hello"
     context=".resources.Hello"
     view=".views.hello_world"
     name=""
    />
@@ -721,19 +720,19 @@
.. index::
   triple: view; zcml; static resource
.. _zcml_static_resources_section:
.. _zcml_static_assets_section:
Serving Static Resources Using ZCML
------------------------------------
Serving Static Assets Using ZCML
--------------------------------
Use of the ``static`` ZCML directive makes static files available at a name
relative to the application root URL, e.g. ``/static``.
Use of the ``static`` ZCML directive makes static assets available at a name
relative to the application root URL, e.g. ``/static``.
Note that the ``path`` provided to the ``static`` ZCML directive may be a
fully qualified :term:`resource specification`, a package-relative path, or
fully qualified :term:`asset specification`, a package-relative path, or
an *absolute path*.  The ``path`` with the value ``a/b/c/static`` of a
``static`` directive in a ZCML file that resides in the "mypackage" package
will resolve to a package-qualified resource such as
will resolve to a package-qualified assets such as
``some_package:a/b/c/static``.
Here's an example of a ``static`` ZCML directive that will serve files
@@ -752,7 +751,7 @@
Here's an example of a ``static`` directive that will serve files up
under the ``/static`` URL from the ``a/b/c/static`` directory of the
Python package named ``some_package`` using a fully qualified
:term:`resource specification`.
:term:`asset specification`.
.. code-block:: xml
   :linenos:
@@ -775,7 +774,7 @@
     path="static"
    />
Whether you use for ``path`` a fully qualified resource specification,
Whether you use for ``path`` a fully qualified asset specification,
an absolute path, or a package-relative path, When you place your
static files on the filesystem in the directory represented as the
``path`` of the directive, you will then be able to view the static
@@ -792,7 +791,7 @@
``name`` argument of the ``static`` ZCML directive can also be one of
a number of things: a *view name* or a *URL*.  The above examples have
shown usage of the ``name`` argument as a view name.  When ``name`` is
a *URL* (or any string with a slash (``/``) in it), static resources
a *URL* (or any string with a slash (``/``) in it), static assets
can be served from an external webserver.  In this mode, the ``name``
is used as the URL prefix when generating a URL using
:func:`pyramid.url.static_url`.
@@ -820,8 +819,77 @@
The :meth:`pyramid.config.Configurator.add_static_view` method offers
an imperative equivalent to the ``static`` ZCML directive.  Use of the
``add_static_view`` imperative configuration method is completely equivalent
to using ZCML for the same purpose.  See :ref:`static_resources_section` for
to using ZCML for the same purpose.  See :ref:`static_assets_section` for
more information.
.. index::
   pair: ZCML directive; asset
.. _asset_zcml_directive:
The ``asset`` ZCML Directive
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Instead of using :meth:`pyramid.config.Configurator.override_asset` during
:term:`imperative configuration`, an equivalent ZCML directive can be used.
The ZCML ``asset`` tag is a frontend to using
:meth:`pyramid.config.Configurator.override_asset`.
An individual :app:`Pyramid` ``asset`` ZCML statement can override a
single asset.  For example:
.. code-block:: xml
   :linenos:
    <asset
      to_override="some.package:templates/mytemplate.pt"
      override_with="another.package:othertemplates/anothertemplate.pt"
     />
The string value passed to both ``to_override`` and ``override_with``
attached to an ``asset`` directive is called an "asset specification".  The
colon separator in a specification separates the *package name* from the
*asset name*.  The colon and the following asset name are optional.  If they
are not specified, the override attempts to resolve every lookup into a
package from the directory of another package.  For example:
.. code-block:: xml
   :linenos:
    <asset
      to_override="some.package"
      override_with="another.package"
     />
Individual subdirectories within a package can also be overridden:
.. code-block:: xml
   :linenos:
    <asset
      to_override="some.package:templates/"
      override_with="another.package:othertemplates/"
     />
If you wish to override an asset directory with another directory, you *must*
make sure to attach the slash to the end of both the ``to_override``
specification and the ``override_with`` specification.  If you fail to attach
a slash to the end of an asset specification that points to a directory, you
will get unexpected results.
The package name in an asset specification may start with a dot, meaning that
the package is relative to the package in which the ZCML file resides.  For
example:
.. code-block:: xml
   :linenos:
    <asset
      to_override=".subpackage:templates/"
      override_with="another.package:templates/"
     />
See also :ref:`asset_directive`.
.. _zcml_authorization_policy:
@@ -833,12 +901,11 @@
application (usually named ``configure.zcml``) to enable an
authorization policy.
For example, to enable a policy which compares the value of an "auth
ticket" cookie passed in the request's environment which contains a
reference to a single :term:`principal` against the principals present
in any :term:`ACL` found in model data when attempting to call some
:term:`view`, modify your ``configure.zcml`` to look something like
this:
For example, to enable a policy which compares the value of an "auth ticket"
cookie passed in the request's environment which contains a reference to a
single :term:`principal` against the principals present in any :term:`ACL`
found in the resource tree when attempting to call some :term:`view`, modify
your ``configure.zcml`` to look something like this:
.. code-block:: xml
   :linenos:
@@ -958,7 +1025,7 @@
``aclauthorizationpolicy``
When this directive is used, authorization information is obtained
from :term:`ACL` objects attached to model instances.
from :term:`ACL` objects attached to resources.
An example of its usage, with all attributes fully expanded:
@@ -1068,7 +1135,6 @@
See also :ref:`renderer_directive` and
:meth:`pyramid.config.Configurator.add_renderer`.
Overriding an Existing Renderer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1207,4 +1273,3 @@
.. - hooks chapter still has topics for ZCML
.. - resources chapter still has topics for ZCML
docs/narr/environment.rst
@@ -3,7 +3,7 @@
   single: settings
   single: reload
   single: debug_authorization
   single: reload_resources
   single: reload_assets
   single: debug_notfound
   single: debug_all
   single: reload_all
@@ -52,20 +52,24 @@
|                                 |                             |
+---------------------------------+-----------------------------+
Reloading Resources
-------------------
Reloading Assets
----------------
Don't cache any resource file data when this value is true.  See
also :ref:`overriding_resources_section`.
Don't cache any asset file data when this value is true.  See
also :ref:`overriding_assets_section`.
+---------------------------------+-----------------------------+
| Environment Variable Name       | Config File Setting Name    |
+=================================+=============================+
| ``BFG_RELOAD_RESOURCES``        |  ``reload_resources``       |
| ``BFG_RELOAD_ASSETS``           |  ``reload_assets``          |
|                                 |                             |
|                                 |                             |
|                                 |                             |
+---------------------------------+-----------------------------+
.. note:: For backwards compatibility purposes, the following aliases can be
   used for configurating asset reloading: ``BFG_RELOAD_RESOURCES`` (envvar)
   and ``reload_resources`` (config file).
Debugging Authorization
-----------------------
@@ -174,7 +178,7 @@
++++++++++++++++
The value(s) supplied here are passed in as the template directories. They
should be in :term:`resource specification` format, for example:
should be in :term:`asset specification` format, for example:
``my.package:templates``.
+-----------------------------+
@@ -333,40 +337,38 @@
.. index:: 
   single: reload_templates
   single: reload_resources
   single: reload_assets
Understanding the Distinction Between ``reload_templates`` and ``reload_resources``
-----------------------------------------------------------------------------------
Understanding the Distinction Between ``reload_templates`` and ``reload_assets``
--------------------------------------------------------------------------------
The difference between ``reload_resources`` and ``reload_templates``
is a bit subtle.  Templates are themselves also treated by
:app:`Pyramid` as :term:`pkg_resources` resource files (along with
static files and other resources), so the distinction can be
confusing.  It's helpful to read :ref:`overriding_resources_section`
for some context about resources in general.
The difference between ``reload_assets`` and ``reload_templates`` is a bit
subtle.  Templates are themselves also treated by :app:`Pyramid` as asset
files (along with other static files), so the distinction can be confusing.
It's helpful to read :ref:`overriding_assets_section` for some context
about assets in general.
When ``reload_templates`` is true, :app:`Pyramid` takes advantage
of the underlying templating systems' ability to check for file
modifications to an individual template file.  When
``reload_templates`` is true but ``reload_resources`` is *not* true,
the template filename returned by pkg_resources is cached by
:app:`Pyramid` on the first request.  Subsequent requests for the
same template file will return a cached template filename.  The
underlying templating system checks for modifications to this
particular file for every request.  Setting ``reload_templates`` to
``True`` doesn't affect performance dramatically (although it should
still not be used in production because it has some effect).
When ``reload_templates`` is true, :app:`Pyramid` takes advantage of the
underlying templating systems' ability to check for file modifications to an
individual template file.  When ``reload_templates`` is true but
``reload_assets`` is *not* true, the template filename returned by the
``pkg_resources`` package (used under the hood by asset resolution) is cached
by :app:`Pyramid` on the first request.  Subsequent requests for the same
template file will return a cached template filename.  The underlying
templating system checks for modifications to this particular file for every
request.  Setting ``reload_templates`` to ``True`` doesn't affect performance
dramatically (although it should still not be used in production because it
has some effect).
However, when ``reload_resources`` is true, :app:`Pyramid` will not
cache the template filename, meaning you can see the effect of
changing the content of an overridden resource directory for templates
without restarting the server after every change.  Subsequent requests
for the same template file may return different filenames based on the
current state of overridden resource directories. Setting
``reload_resources`` to ``True`` affects performance *dramatically*,
slowing things down by an order of magnitude for each template
rendering.  However, it's convenient to enable when moving files
around in overridden resource directories. ``reload_resources`` makes
the system *very slow* when templates are in use.  Never set
``reload_resources`` to ``True`` on a production system.
However, when ``reload_assets`` is true, :app:`Pyramid` will not cache the
template filename, meaning you can see the effect of changing the content of
an overridden asset directory for templates without restarting the server
after every change.  Subsequent requests for the same template file may
return different filenames based on the current state of overridden asset
directories. Setting ``reload_assets`` to ``True`` affects performance
*dramatically*, slowing things down by an order of magnitude for each
template rendering.  However, it's convenient to enable when moving files
around in overridden asset directories. ``reload_assets`` makes the system
*very slow* when templates are in use.  Never set ``reload_assets`` to
``True`` on a production system.
docs/narr/extending.rst
@@ -191,15 +191,15 @@
   :linenos:
    <view 
      context="theoriginalapplication.models.SomeModel"
      context="theoriginalapplication.resources.SomeResource"
      name="theview"
      view=".views.a_view_that_does_something_slightly_different"
     />
A similar pattern can be used to *extend* the application with
``<view>`` declarations.  Just register a new view against some
existing model type and make sure the URLs it implies are available on
some other page rendering.
A similar pattern can be used to *extend* the application with ``<view>``
declarations.  Just register a new view against some existing resource type
(using ``context``) and make sure the URLs it implies are available on some
other page rendering.
.. index::
   pair: overriding; routes
docs/narr/handlers.rst
@@ -100,7 +100,7 @@
When calling :meth:`~pyramid.config.Configurator.add_handler`, an
``action`` is required in either the route pattern or as a keyword argument,
but **cannot appear in both places**. A ``handler`` argument must also be
supplied, which can be either a :term:`resource specification` or a Python
supplied, which can be either a :term:`asset specification` or a Python
reference to the handler class. Additional keyword arguments are passed
directly through to :meth:`pyramid.config.Configurator.add_route`.
@@ -112,7 +112,7 @@
    config.add_handler('hello', '/hello/{action}',
                       handler='mypackage.handlers:MyHandler')
In larger applications, it is advised to use a :term:`resource specification`
In larger applications, it is advised to use a :term:`asset specification`
with :meth:`~pyramid.config.Configurator.add_handler` to avoid having
to import every handler class.
docs/narr/hooks.rst
@@ -88,11 +88,10 @@
   it is false.
.. warning:: When a NotFound view callable accepts an argument list as
   described in :ref:`request_and_context_view_definitions`, the
   ``context`` passed as the first argument to the view callable will
   be the :exc:`pyramid.exceptions.NotFound` exception instance.
   If available, the *model* context will still be available as
   ``request.context``.
   described in :ref:`request_and_context_view_definitions`, the ``context``
   passed as the first argument to the view callable will be the
   :exc:`pyramid.exceptions.NotFound` exception instance.  If available, the
   resource context will still be available as ``request.context``.
.. index::
   single: forbidden view
@@ -221,14 +220,14 @@
           """ Return a dictionary with (at least) the keys ``root``,
           ``context``, ``view_name``, ``subpath``, ``traversed``,
           ``virtual_root``, and ``virtual_root_path``.  These values are
           typically the result of an object graph traversal.  ``root``
           is the physical root object, ``context`` will be a model
           typically the result of a resource tree traversal.  ``root``
           is the physical root object, ``context`` will be a resource
           object, ``view_name`` will be the view name used (a Unicode
           name), ``subpath`` will be a sequence of Unicode names that
           followed the view name but were not traversed, ``traversed``
           will be a sequence of Unicode names that were traversed
           (including the virtual root path, if any) ``virtual_root``
           will be a model object representing the virtual root (or the
           will be a resource object representing the virtual root (or the
           physical root if traversal was not performed), and
           ``virtual_root_path`` will be a sequence representing the
           virtual root path (a sequence of Unicode names) or None if
@@ -255,30 +254,29 @@
    <adapter
      factory="myapp.traversal.Traverser"
      provides="pyramid.interfaces.ITraverser"
      for="myapp.models.MyRoot"
      for="myapp.resources.MyRoot"
     />
If the above stanza was added to a ``configure.zcml`` file,
:app:`Pyramid` would use the ``myapp.traversal.Traverser`` only
when the application :term:`root factory` returned an instance of the
``myapp.models.MyRoot`` object.  Otherwise it would use the default
``myapp.resources.MyRoot`` object.  Otherwise it would use the default
:app:`Pyramid` traverser to do traversal.
.. index::
   single: url generator
Changing How :mod:`pyramid.url.model_url` Generates a URL
Changing How :mod:`pyramid.url.resource_url` Generates a URL
------------------------------------------------------------
When you add a traverser as described in
:ref:`changing_the_traverser`, it's often convenient to continue to
use the :func:`pyramid.url.model_url` API.  However, since the way
traversal is done will have been modified, the URLs it generates by
default may be incorrect.
When you add a traverser as described in :ref:`changing_the_traverser`, it's
often convenient to continue to use the :func:`pyramid.url.resource_url` API.
However, since the way traversal is done will have been modified, the URLs it
generates by default may be incorrect.
If you've added a traverser, you can change how
:func:`pyramid.url.model_url` generates a URL for a specific type
of :term:`context` by adding an adapter stanza for
:func:`pyramid.url.resource_url` generates a URL for a specific type of
resource by adding an adapter stanza for
:class:`pyramid.interfaces.IContextURL` to your application's
``configure.zcml``:
@@ -288,13 +286,13 @@
    <adapter
      factory="myapp.traversal.URLGenerator"
      provides="pyramid.interfaces.IContextURL"
      for="myapp.models.MyRoot *"
      for="myapp.resources.MyRoot *"
     />
In the above example, the ``myapp.traversal.URLGenerator`` class will
be used to provide services to :func:`pyramid.url.model_url` any
time the :term:`context` passed to ``model_url`` is of class
``myapp.models.MyRoot``.  The asterisk following represents the type
be used to provide services to :func:`pyramid.url.resource_url` any
time the :term:`context` passed to ``resource_url`` is of class
``myapp.resources.MyRoot``.  The asterisk following represents the type
of interface that must be possessed by the :term:`request` (in this
case, any interface, represented by asterisk).
docs/narr/hybrid.rst
@@ -171,7 +171,7 @@
   Root factories related to a route were explained previously within
   :ref:`route_factories`.  Both the global root factory and default
   root factory were explained previously within
   :ref:`the_object_graph`.
   :ref:`the_resource_tree`.
.. _using_traverse_in_a_route_pattern:
@@ -226,7 +226,7 @@
.. code-block:: python
   :linenos:
   class Traversable(object):
   class Resource(object):
       def __init__(self, subobjects):
          self.subobjects = subobjects
@@ -234,15 +234,15 @@
          return self.subobjects[name]
   root = Traversable(
           {'a':Traversable({'b':Traversable({'c':Traversable({})})})}
           {'a':Resource({'b':Resource({'c':Resource({})})})}
          )
   def root_factory(request):
       return root
Above, we've defined a (bogus) graph that can be traversed, and a
``root_factory`` function that can be used as part of a particular
route configuration statement:
Above, we've defined a (bogus) resource tree that can be traversed, and a
``root_factory`` function that can be used as part of a particular route
configuration statement:
.. code-block:: python
   :linenos:
@@ -250,14 +250,13 @@
   config.add_route('home', '{foo}/{bar}/*traverse', 
                    factory='mypackage.routes.root_factory')
The ``factory`` above points at the function we've defined.  It will
return an instance of the ``Traversable`` class as a root object
whenever this route is matched.  Instances of the``Traversable`` class
can be used for graph traversal because they have a ``__getitem__``
method that does something nominally useful. Since traversal uses
``__getitem__`` to walk the nodes of an object graph, using traversal
against the root object implied by our route statement is a reasonable
thing to do.
The ``factory`` above points at the function we've defined.  It will return
an instance of the ``Traversable`` class as a root object whenever this route
is matched.  Instances of the``Resource`` class can be used for tree
traversal because they have a ``__getitem__`` method that does something
nominally useful. Since traversal uses ``__getitem__`` to walk the resources
of a resource tree, using traversal against the root resource implied by our
route statement is a reasonable thing to do.
.. note::
@@ -271,12 +270,11 @@
When the route configuration named ``home`` above is matched during a
request, the matchdict generated will be based on its pattern:
``{foo}/{bar}/*traverse``.  The "capture value" implied by the
``*traverse`` element in the pattern will be used to traverse the
graph in order to find a context, starting from the root object
returned from the root factory.  In the above example, the
:term:`root` object found will be the instance named ``root`` in
``routes.py``.
``{foo}/{bar}/*traverse``.  The "capture value" implied by the ``*traverse``
element in the pattern will be used to traverse the resource tree in order to
find a context, starting from the root object returned from the root factory.
In the above example, the :term:`root` object found will be the instance
named ``root`` in ``routes.py``.
If the URL that matched a route with the pattern ``{foo}/{bar}/*traverse``,
is ``http://example.com/one/two/a/b/c``, the traversal path used
@@ -284,12 +282,11 @@
:app:`Pyramid` will attempt to traverse through the edges ``a``,
``b``, and ``c``, beginning at the root object.
In our above example, this particular set of traversal steps will mean
that the :term:`context` of the view would be the ``Traversable``
object we've named ``c`` in our bogus graph and the :term:`view name`
resulting from traversal will be the empty string; if you need a
refresher about why this outcome is presumed, see
:ref:`traversal_algorithm`.
In our above example, this particular set of traversal steps will mean that
the :term:`context` of the view would be the ``Traversable`` object we've
named ``c`` in our bogus resource tree and the :term:`view name` resulting
from traversal will be the empty string; if you need a refresher about why
this outcome is presumed, see :ref:`traversal_algorithm`.
At this point, a suitable view callable will be found and invoked
using :term:`view lookup` as described in :ref:`view_configuration`,
@@ -347,7 +344,7 @@
- the :term:`context` is any object.
For instance, if the URL ``http://example.com/one/two/a/another`` is provided
to an application that uses the previously mentioned object graph, the
to an application that uses the previously mentioned resource tree, the
``mypackage.views.another`` view callable will be called instead of the
``mypackage.views.myview`` view callable because the :term:`view name` will
be ``another`` instead of the empty string.
docs/narr/introduction.rst
@@ -144,10 +144,9 @@
with a set of conventions for calling those views.  You are free to
use third-party components that fit your needs in your applications.
The concepts of :term:`view` and :term:`model` are used by
:app:`Pyramid` mostly as they would be by Django.
:app:`Pyramid` has a documentation culture more like Django's than
like Zope's.
The concept of :term:`view` is used by :app:`Pyramid` mostly as it would be
by Django.  :app:`Pyramid` has a documentation culture more like Django's
than like Zope's.
Like :term:`Pylons` version 1.0, but unlike :term:`Zope`, a
:app:`Pyramid` application developer may use completely imperative
@@ -177,13 +176,13 @@
.. sidebar:: You Say :app:`Pyramid` is MVC, But Where's The Controller?
   The :app:`Pyramid` authors believe that the MVC pattern just
   doesn't really fit the web very well. In a :app:`Pyramid`
   application, there are models, which store data, and views, which
   present the data stored in models.  However, no facility provided
   by the framework actually maps to the concept of a "controller".
   So :app:`Pyramid` is actually an "MV" framework rather than an
   "MVC" framework.  "MVC", however, is close enough as a general
   classification moniker for purposes of comparison with other web
   frameworks.
   The :app:`Pyramid` authors believe that the MVC pattern just doesn't
   really fit the web very well. In a :app:`Pyramid` application, there is a
   resource tree, which represents the site structure, and views, which tend
   to present the data stored in the resource tree and a user-defined "domain
   model".  However, no facility provided *by the framework* actually
   necessarily maps to the concept of a "controller" or "model".  So if you
   had to give it some acronym, I guess you'd say :app:`Pyramid` is actually
   an "RV" framework rather than an "MVC" framework.  "MVC", however, is
   close enough as a general classification moniker for purposes of
   comparison with other web frameworks.
docs/narr/models.rst
File was deleted
docs/narr/project.rst
@@ -258,8 +258,8 @@
Once you've installed your program for development using ``setup.py
develop``, you can use an interactive Python shell to examine your
:app:`Pyramid` application :term:`model` and :term:`view` objects from
a Python prompt.  To do so, use the ``paster`` shell command with the
:app:`Pyramid` application :term:`resource` and :term:`view` objects from a
Python prompt.  To do so, use the ``paster`` shell command with the
``pshell`` argument:
The first argument to ``pshell`` is the path to your application's ``.ini``
@@ -290,7 +290,7 @@
   Type "help" for more information. "root" is the Pyramid app root object,
   "registry" is the Pyramid registry object.
   >>> root
   <myproject.models.MyModel object at 0x445270>
   <myproject.resources.MyResource object at 0x445270>
   >>> registry
   <Registry myproject>
   >>> registry.settings['debug_notfound']
@@ -468,7 +468,7 @@
  |-- development.ini
  |-- myproject
  |   |-- __init__.py
  |   |-- models.py
  |   |-- resources.py
  |   |-- static
  |   |   |-- favicon.ico
  |   |   |-- logo.png
@@ -738,7 +738,7 @@
   application, include a ``main`` function which is used as a Paste entry
   point.
#. A ``models.py`` module, which contains :term:`model` code.
#. A ``resources.py`` module, which contains :term:`resource` code.
#. A ``templates`` directory, which contains :term:`Chameleon` (or
   other types of) templates.
@@ -771,8 +771,8 @@
#. Line 1 imports the :term:`Configurator` class from
   :mod:`pyramid.config` that we use later.
#. Line 2 imports the ``get_root`` function from
   :mod:`myproject.models` that we use later.
#. Line 2 imports the ``Root`` class from :mod:`myproject.resources` that we
   use later.
#. Lines 4-12 define a function that returns a :app:`Pyramid`
   WSGI application.  This function is meant to be called
@@ -784,19 +784,19 @@
   Lines 8-10 register a "default view" (a view that has no ``name``
   attribute).  It is registered so that it will be found when the
   :term:`context` of the request is an instance of the
   :class:`myproject.models.MyModel` class.  The first argument to
   :class:`myproject.resources.Root` class.  The first argument to
   ``add_view`` points at a Python function that does all the work for this
   view, also known as a :term:`view callable`, via a :term:`dotted Python
   name`.  The view declaration also names a ``renderer``, which in this case
   is a template that will be used to render the result of the view callable.
   This particular view declaration points at
   ``myproject:templates/mytemplate.pt``, which is a :term:`resource
   ``myproject:templates/mytemplate.pt``, which is a :term:`asset
   specification` that specifies the ``mytemplate.pt`` file within the
   ``templates`` directory of the ``myproject`` package.  The template file
   it actually points to is a :term:`Chameleon` ZPT template file.
   Line 11 registers a static view, which will serve up the files from the
   ``mypackage:static`` :term:`resource specification` (the ``static``
   ``mypackage:static`` :term:`asset specification` (the ``static``
   directory of the ``mypackage`` package).
   Line 12 returns a :term:`WSGI` application to the caller of the function
@@ -817,7 +817,7 @@
This bit of code was registered as the view callable within ``__init__.py``
(via ``add_view``).  ``add_view`` said that the default URL for instances
that are of the class :class:`myproject.models.MyModel` should run this
that are of the class :class:`myproject.resources.Root` should run this
:func:`myproject.views.my_view` function.
This view callable function is handed a single piece of information:
@@ -846,43 +846,38 @@
   the speed at which templates may be rendered.
.. index::
   single: models.py
   single: resources.py
.. _modelspy_project_section:
.. _resourcespy_project_section:
``models.py``
~~~~~~~~~~~~~
``resources.py``
~~~~~~~~~~~~~~~~
The ``models.py`` module provides the :term:`model` data and behavior
for our application.  Models are objects which store application data
and provide APIs which mutate and return this data.  We write a class
named ``MyModel`` that provides the behavior.
The ``resources.py`` module provides the :term:`resource` data and behavior
for our application.  Resources are objects which exist to provide site
structure in applications which use :term:`traversal` to map URLs to code.
We write a class named ``Root`` that provides the behavior for the root
resource.
.. literalinclude:: MyProject/myproject/models.py
.. literalinclude:: MyProject/myproject/resources.py
   :language: python
   :linenos:
#. Lines 1-2 define the MyModel class.
#. Lines 1-3 define the Root class.  The Root class is a "root resource
   factory" function that will be called by the :app:`Pyramid` *Router* for
   each request when it wants to find the root of the resource tree.
#. Line 4 defines an instance of MyModel as the root.
#. Line 6 is a "root factory" function that will be called by the
   :app:`Pyramid` *Router* for each request when it wants to find
   the root of the object graph.  Conventionally this is called
   ``get_root``.
In a "real" application, the root object would not be such a simple
object.  Instead, it would be an object that could access some
persistent data store, such as a database.  :app:`Pyramid` doesn't
make any assumption about which sort of datastore you'll want to use,
so the sample application uses an instance of
:class:`myproject.models.MyModel` to represent the root.
In a "real" application, the Root object would not be such a simple object.
Instead, it might be an object that could access some persistent data store,
such as a database.  :app:`Pyramid` doesn't make any assumption about which
sort of datastore you'll want to use, so the sample application uses an
instance of :class:`myproject.resources.Root` to represent the root.
``static``
~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~
This directory contains static resources which support the
``mytemplate.pt`` template.  It includes CSS and images.
This directory contains static assets which support the ``mytemplate.pt``
template.  It includes CSS and images.
.. index::
   single: tests.py
docs/narr/resources.rst
@@ -1,274 +1,319 @@
.. index::
   single: resources
.. _resources_chapter:
Resources
=========
A :term:`resource` is any file contained within a Python
:term:`package` which is *not* a Python source code file.  For
example, each of the following is a resource:
A :term:`resource` is an object that represents a "place" in your
application.  Every :app:`Pyramid` application has at least one resource
object: the :term:`root` resource.  The root resource is the root of a
:term:`resource tree`.  A resource tree is a set of nested dictionary-like
objects which you may use to represent your website's structure.
- a :term:`Chameleon` template file contained within a Python package.
In an application which uses :term:`traversal` to map URLs to code, the
resource tree structure is used heavily to map a URL to a :term:`view
callable`.  :app:`Pyramid` will walk "up" the resource tree when
:term:`traversal` is used in order to find a :term:`context`.  Once a context
is found, the resource represented by the context combined with data in the
request will be used to find a :term:`view callable`.
- a GIF image file contained within a Python package.
In an application which uses :term:`URL dispatch`, the resource tree is only
used indirectly, and is often "invisible" to the developer.  In URL dispatch
applications, the resource "tree" is often composed of only the root resource
by itself.  This root resource sometimes has security declarations attached
to it, but is not required to have any.  In general, the resource tree is
much less important in applications that use URL dispatch than applications
that use traversal.
- a CSS file contained within a Python package.
In "Zope-like" :app:`Pyramid` applications, resource objects also often store
data persistently and offer methods related to mutating that persistent data.
In these kinds of applications, resources not only represent the site
structure of your website, but they become the :term:`domain model` of the
application.
- a JavaScript source file contained within a Python package.
Also:
- A directory within a package that does not have an ``__init__.py``
  in it (if it possessed an ``__init__.py`` it would *be* a package).
- The ``context`` and ``containment`` predicate arguments to
  :meth:`pyramid.config.Configurator.add_view` (or a
  :func:`pyramid.view.view_config` decorator) and reference a resource class
  or resource :term:`interface`.
The use of resources is quite common in most web development projects.
For example, when you create a :app:`Pyramid` application using one
of the available "paster" templates, as described in
:ref:`creating_a_project`, the directory representing the application
contains a Python :term:`package`.  Within that Python package, there
are directories full of files which are resources.  For example, there
is a ``templates`` directory which contains ``.pt`` files, and a
``static`` directory which contains ``.css``, ``.js``, and ``.gif``
files.
- A :term:`root factory` returns a resource.
.. _understanding_resources:
Understanding Resources
-----------------------
Let's imagine you've created a :app:`Pyramid` application that uses
a :term:`Chameleon` ZPT template via the
:func:`pyramid.chameleon_zpt.render_template_to_response` API.  For
example, the application might address the resource named
``templates/some_template.pt`` using that API within a ``views.py``
file inside a ``myapp`` package:
.. ignore-next-block
.. code-block:: python
   :linenos:
   from pyramid.chameleon_zpt import render_template_to_response
   render_template_to_response('templates/some_template.pt')
"Under the hood", when this API is called, :app:`Pyramid` attempts
to make sense out of the string ``templates/some_template.pt``
provided by the developer.  To do so, it first finds the "current"
package.  The "current" package is the Python package in which the
``views.py`` module which contains this code lives.  This would be the
``myapp`` package, according to our example so far.  By resolving the
current package, :app:`Pyramid` has enough information to locate
the actual template file.  These are the elements it needs:
- The *package name* (``myapp``)
- The *resource name* (``templates/some_template.pt``)
:app:`Pyramid` uses the :term:`pkg_resources` API to resolve the
package name and resource name to an absolute
(operating-system-specific) file name.  It eventually passes this
resolved absolute filesystem path to the Chameleon templating engine,
which then uses it to load, parse, and execute the template file.
Package names often contain dots.  For example, ``pyramid`` is a
package.  Resource names usually look a lot like relative UNIX file
paths.
- A resource is exposed to :term:`view` code as the :term:`context` of a
  view.
.. index::
   pair: overriding; resources
   single: resource constructor
.. _overriding_resources_section:
Defining a Resource Constructor
-------------------------------
Overriding Resources
--------------------
An example of a resource constructor, ``BlogEntry`` is presented below.  It
is implemented as a class which, when instantiated, becomes a resource
instance.
It can often be useful to override specific resources "from outside" a
given :app:`Pyramid` application.  For example, you may wish to
reuse an existing :app:`Pyramid` application more or less
unchanged.  However, some specific template file owned by the
application might have inappropriate HTML, or some static resource
(such as a logo file or some CSS file) might not be appropriate.  You
*could* just fork the application entirely, but it's often more
convenient to just override the resources that are inappropriate and
reuse the application "as is".  This is particularly true when you
reuse some "core" application over and over again for some set of
customers (such as a CMS application, or some bug tracking
application), and you want to make arbitrary visual modifications to a
particular application deployment without forking the underlying code.
.. code-block:: python
   :linenos:
To this end, :app:`Pyramid` contains a feature that makes it
possible to "override" one resource with one or more other resources.
In support of this feature, a :term:`ZCML` directive exists named
``resource``.  The ``resource`` directive allows you to *override* the
following kinds of resources defined in any Python package:
   import datetime
- Individual :term:`Chameleon` templates.
   class BlogEntry(object):
       def __init__(self, title, body, author):
           self.title = title
           self.body =  body
           self.author = author
           self.created = datetime.datetime.now()
- A directory containing multiple Chameleon templates.
- Individual static files served up by an instance of the
  ``pyramid.view.static`` helper class.
- A directory of static files served up by an instance of the
  ``pyramid.view.static`` helper class.
- Any other resource (or set of resources) addressed by code that uses
  the setuptools :term:`pkg_resources` API.
A resource constructor may be any Python object which is callable, and which
returns a resource instance.  In the above example, the ``BlogEntry`` class
can be "called", returning a resource instance.
.. index::
   single: override_resource
   single: resource interfaces
.. _override_resource:
.. _resources_which_implement_interfaces:
The ``override_resource`` API
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Resources Which Implement Interfaces
------------------------------------
An individual call to
:meth:`pyramid.config.Configurator.override_resource` can
override a single resource.  For example:
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`.
.. ignore-next-block
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.
For example, here's some code which describes a blog entry which also
declares that the blog entry implements an :term:`interface`.
.. code-block:: python
   :linenos:
   config.override_resource(
            to_override='some.package:templates/mytemplate.pt',
            override_with='another.package:othertemplates/anothertemplate.pt')
   import datetime
   from zope.interface import implements
   from zope.interface import Interface
The string value passed to both ``to_override`` and ``override_with``
attached to a resource directive is called a "specification".  The
colon separator in a specification separates the *package name* from
the *resource name*.  The colon and the following resource name are
optional.  If they are not specified, the override attempts to resolve
every lookup into a package from the directory of another package.
For example:
   class IBlogEntry(Interface):
       pass
.. ignore-next-block
   class BlogEntry(object):
       implements(IBlogEntry)
       def __init__(self, title, body, author):
           self.title = title
           self.body =  body
           self.author = author
           self.created = datetime.datetime.now()
This resource consists of two things: the class which defines the resource
constructor as the class ``BlogEntry``, and an :term:`interface` attached to
the class via an ``implements`` statement at class scope using the
``IBlogEntry`` interface as its sole argument.
The interface object used must be an instance of a class that inherits from
:class:`zope.interface.Interface`.
A resource class may implement zero or more interfaces.  You specify that a
resource implements an interface by using the
:func:`zope.interface.implements` function at class scope.  The above
``BlogEntry`` resource implements the ``IBlogEntry`` interface.
You can also specify that a particular resource *instance* provides an
interface, as opposed to its class.  When you declare that a class implements
an interface, all instances of that class will also provide that interface.
However, you can also just say that a single object provides the interface.
To do so, use the :func:`zope.interface.directlyProvides` function:
.. code-block:: python
   :linenos:
   config.override_resource(to_override='some.package',
                            override_with='another.package')
   from zope.interface import directlyProvides
   from zope.interface import Interface
Individual subdirectories within a package can also be overridden:
   class IBlogEntry(Interface):
       pass
.. ignore-next-block
   class BlogEntry(object):
       def __init__(self, title, body, author):
           self.title = title
           self.body =  body
           self.author = author
           self.created = datetime.datetime.now()
   entry = BlogEntry('title', 'body', 'author')
   directlyProvides(entry, IBlogEntry)
:func:`zope.interface.directlyProvides` will replace any existing interface
that was previously provided by an instance.  If a resource object already
has instance-level interface declarations that you don't want to replace, use
the :func:`zope.interface.alsoProvides` function:
.. code-block:: python
   :linenos:
   config.override_resource(to_override='some.package:templates/',
                            override_with='another.package:othertemplates/')
   from zope.interface import alsoProvides
   from zope.interface import directlyProvides
   from zope.interface import Interface
   class IBlogEntry1(Interface):
       pass
If you wish to override a directory with another directory, you *must*
make sure to attach the slash to the end of both the ``to_override``
specification and the ``override_with`` specification.  If you fail to
attach a slash to the end of a specification that points to a directory,
you will get unexpected results.
   class IBlogEntry2(Interface):
       pass
You cannot override a directory specification with a file
specification, and vice versa: a startup error will occur if you try.
You cannot override a resource with itself: a startup error will occur
if you try.
   class BlogEntry(object):
       def __init__(self, title, body, author):
           self.title = title
           self.body =  body
           self.author = author
           self.created = datetime.datetime.now()
Only individual *package* resources may be overridden.  Overrides will
not traverse through subpackages within an overridden package.  This
means that if you want to override resources for both
``some.package:templates``, and ``some.package.views:templates``, you
will need to register two overrides.
   entry = BlogEntry('title', 'body', 'author')
   directlyProvides(entry, IBlogEntry1)
   alsoProvides(entry, IBlogEntry2)
The package name in a specification may start with a dot, meaning that
the package is relative to the package in which the configuration
construction file resides (or the ``package`` argument to the
:class:`pyramid.config.Configurator` class construction).
For example:
:func:`zope.interface.alsoProvides` will augment the set of interfaces
directly provided by an instance instead of overwriting them like
:func:`zope.interface.directlyProvides` does.
.. ignore-next-block
.. code-block:: python
   :linenos:
   config.override_resource(to_override='.subpackage:templates/',
                            override_with='another.package:templates/')
Multiple ``override_resource`` statements which name a shared
``to_override`` but a different ``override_with`` specification can be
"stacked" to form a search path.  The first resource that exists in
the search path will be used; if no resource exists in the override
path, the original resource is used.
Resource overrides can actually override resources other than
templates and static files.  Any software which uses the
:func:`pkg_resources.get_resource_filename`,
:func:`pkg_resources.get_resource_stream` or
:func:`pkg_resources.get_resource_string` APIs will obtain an
overridden file when an override is used.
For more information about how resource interfaces can be used by view
configuration, see :ref:`using_resource_interfaces`.
.. index::
   pair: ZCML directive; resource
   single: resource tree
   single: traversal tree
   single: object tree
   single: container resources
   single: leaf resources
.. _resource_zcml_directive:
Defining a Resource Tree
------------------------
The ``resource`` ZCML Directive
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When :term:`traversal` is used (as opposed to a purely :term:`url dispatch`
based application), :app:`Pyramid` expects to be able to traverse a tree
composed of resources (the :term:`resource tree`).  Traversal begins at a
root resource, and descends into the tree recursively via each resource's
``__getitem__`` method.  :app:`Pyramid` imposes the following policy on
resource instances in the tree:
Instead of using
:meth:`pyramid.config.Configurator.override_resource` during
:term:`imperative configuration`, an equivalent can be used to perform
all the tasks described above within :term:`ZCML`.  The ZCML
``resource`` tag is a frontend to using ``override_resource``.
- A container resource (a resource which contains other resources) must
  supply a ``__getitem__`` method which is willing to resolve a unicode name
  to a sub-resource.  If a sub-resource by a particular name does not exist
  in a container resource, ``__getitem__`` method of the container resource
  must raise a :exc:`KeyError`.  If a sub-resource by that name *does* exist,
  the container's ``__getitem__`` should return the sub-resource.
An individual :app:`Pyramid` ``resource`` ZCML statement can
override a single resource.  For example:
- Leaf resources, which do not contain other resources, must not implement a
  ``__getitem__``, or if they do, their ``__getitem__`` method must raise a
  :exc:`KeyError`.
.. code-block:: xml
See :ref:`traversal_chapter` for more information about how traversal
works against resource instances.
.. index::
   pair: location-aware; resource
.. _location_aware:
Location-Aware Resources
------------------------
Applications which use :term:`traversal` to locate the :term:`context`
resource of a view must ensure that the resources that make up the
resource tree are "location aware".
In order for :app:`Pyramid` location, security, URL-generation, and traversal
functions (i.e., functions in :ref:`location_module`,
:ref:`traversal_module`, :ref:`url_module` and some in :ref:`security_module`
) to work properly against the resources in a resource tree, all resources in
the tree must be :term:`location` -aware.  This means they must have two
attributes: ``__parent__`` and ``__name__``.
The ``__parent__`` attribute should be a reference to the resource's parent
resource instance in the tree.  The ``__name__`` attribute should be the name
with which a resource's parent refers to the resource via ``__getitem__``.
The ``__parent__`` of the root resource should be ``None`` and its
``__name__`` should be the empty string.  For instance:
.. code-block:: python
   :linenos:
    <resource
      to_override="some.package:templates/mytemplate.pt"
      override_with="another.package:othertemplates/anothertemplate.pt"
     />
   class MyRootResource(object):
       __name__ = ''
       __parent__ = None
The string value passed to both ``to_override`` and ``override_with``
attached to a resource directive is called a "specification".  The
colon separator in a specification separates the *package name* from
the *resource name*.  The colon and the following resource name are
optional.  If they are not specified, the override attempts to resolve
every lookup into a package from the directory of another package.
For example:
A resource returned from the root resource's ``__getitem__`` method should
have a ``__parent__`` attribute that is a reference to the root resource, and
its ``__name__`` attribute should match the name by which it is reachable via
the root resource's ``__getitem__``.  A container resource within the root
resource should have a ``__getitem__`` that returns resources with a
``__parent__`` attribute that points at the container, and these subobjects
should have a ``__name__`` attribute that matches the name by which they are
retrieved from the container via ``__getitem__``.  This pattern continues
recursively "up" the tree from the root.
.. code-block:: xml
   :linenos:
The ``__parent__`` attributes of each resource form a linked list that points
"upward" toward the root. This is analogous to the `..` entry in filesystem
directories. If you follow the ``__parent__`` values from any resource in the
resource tree, you will eventually come to the root resource, just like if
you keep executing the ``cd ..`` filesystem command, eventually you will
reach the filesystem root directory.
    <resource
      to_override="some.package"
      override_with="another.package"
     />
.. warning:: If your root resource has a ``__name__`` argument
   that is not ``None`` or the empty string, URLs returned by the
   :func:`pyramid.url.resource_url` function and paths generated by
   the :func:`pyramid.traversal.resource_path` and
   :func:`pyramid.traversal.resource_path_tuple` APIs will be
   generated improperly.  The value of ``__name__`` will be prepended
   to every path and URL generated (as opposed to a single leading
   slash or empty tuple element).
Individual subdirectories within a package can also be overridden:
.. sidebar::  Using :mod:`pyramid_traversalwrapper`
.. code-block:: xml
   :linenos:
  If you'd rather not manage the ``__name__`` and ``__parent__`` attributes
  of your resources "by hand", an add-on package named
  :mod:`pyramid_traversalwrapper` can help.
    <resource
      to_override="some.package:templates/"
      override_with="another.package:othertemplates/"
     />
  In order to use this helper feature, you must first install the
  :mod:`pyramid_traversalwrapper` package (available via PyPI), then register
  its ``ModelGraphTraverser`` as the traversal policy, rather than the
  default :app:`Pyramid` traverser. The package contains instructions for
  doing so.
If you wish to override a directory with another directory, you *must*
make sure to attach the slash to the end of both the ``to_override``
specification and the ``override_with`` specification.  If you fail to
attach a slash to the end of a specification that points to a directory,
you will get unexpected results.
  Once :app:`Pyramid` is configured with this feature, you will no longer
  need to manage the ``__parent__`` and ``__name__`` attributes on resource
  objects "by hand".  Instead, as necessary, during traversal :app:`Pyramid`
  will wrap each resource (even the root resource) in a ``LocationProxy``
  which will dynamically assign a ``__name__`` and a ``__parent__`` to the
  traversed resrouce (based on the last traversed resource and the name
  supplied to ``__getitem__``).  The root resource will have a ``__name__``
  attribute of ``None`` and a ``__parent__`` attribute of ``None``.
The package name in a specification may start with a dot, meaning that
the package is relative to the package in which the ZCML file resides.
For example:
.. index::
   single: resource API functions
   single: url generation (traversal)
.. code-block:: xml
   :linenos:
:app:`Pyramid` API Functions That Act Against Resources
-------------------------------------------------------
    <resource
      to_override=".subpackage:templates/"
      override_with="another.package:templates/"
     />
A resource object is used as the :term:`context` provided to a view.  See
:ref:`traversal_chapter` and :ref:`urldispatch_chapter` for more information
about how a resource object becomes the context.
See also :ref:`resource_directive`.
The APIs provided by :ref:`traversal_module` are used against resource
objects.  These functions can be used to find the "path" of a resource, the
root resource in a resource tree, or to generate a URL for a resource.
The APIs provided by :ref:`location_module` are used against resources.
These can be used to walk down a resource tree, or conveniently locate one
resource "inside" another.
Some APIs in :ref:`security_module` accept a resource object as a parameter.
For example, the :func:`pyramid.security.has_permission` API accepts a
resource object as one of its arguments; the ACL is obtained from this
resource or one of its ancestors.  Other APIs in the :mod:`pyramid.security`
module also accept :term:`context` as an argument, and a context is always a
resource.
docs/narr/resourcetreetraverser.png

docs/narr/security.rst
@@ -92,11 +92,11 @@
   Python name` values, each representing the dotted name path to a
   suitable implementation global defined at Python module scope.
The above configuration enables a policy which compares the value of
an "auth ticket" cookie passed in the request's environment which
contains a reference to a single :term:`principal` against the
principals present in any :term:`ACL` found in model data when
attempting to call some :term:`view`.
The above configuration enables a policy which compares the value of an "auth
ticket" cookie passed in the request's environment which contains a reference
to a single :term:`principal` against the principals present in any
:term:`ACL` found in the resource tree when attempting to call some
:term:`view`.
While it is possible to mix and match different authentication and
authorization policies, it is an error to pass an authentication
@@ -136,7 +136,7 @@
   config.add_view('mypackage.views.blog_entry_add_view',
                   name='add_entry.html', 
                   context='mypackage.models.Blog',
                   context='mypackage.resources.Blog',
                   permission='add')
The equivalent view registration including the ``add`` permission name
@@ -147,7 +147,7 @@
   :linenos:
   from pyramid.view import view_config
   from models import Blog
   from resources import Blog
   @view_config(context=Blog, name='add_entry.html', permission='add')
   def blog_entry_add_view(request):
@@ -208,19 +208,18 @@
.. _assigning_acls:
Assigning ACLs to your Model Objects
------------------------------------
Assigning ACLs to your Resource Objects
---------------------------------------
When the default :app:`Pyramid` :term:`authorization policy`
determines whether a user possesses a particular permission in a
:term:`context`, it examines the :term:`ACL` associated with the
context.  An ACL is associated with a context by virtue of the
``__acl__`` attribute of the model object representing the
:term:`context`.  This attribute can be defined on the model
*instance* if you need instance-level security, or it can be defined
on the model *class* if you just need type-level security.
When the default :app:`Pyramid` :term:`authorization policy` determines
whether a user possesses a particular permission in a :term:`context`, it
examines the :term:`ACL` associated with the context.  An ACL is associated
with a context by virtue of the ``__acl__`` attribute of the resource object
representing the :term:`context`.  This attribute can be defined on the
resource *instance* if you need instance-level security, or it can be defined
on the resource *class* if you just need type-level security.
For example, an ACL might be attached to the model for a blog via its
For example, an ACL might be attached to the resource for a blog via its
class:
.. code-block:: python
@@ -236,8 +235,8 @@
           (Allow, 'group:editors', 'edit'),
           ]
Or, if your models are persistent, an ACL might be specified via the
``__acl__`` attribute of an *instance* of a model:
Or, if your resources are persistent, an ACL might be specified via the
``__acl__`` attribute of an *instance* of a resource:
.. code-block:: python
   :linenos:
@@ -256,11 +255,11 @@
           (Allow, 'group:editors', 'edit'),
           ]
Whether an ACL is attached to a model's class or an instance of the
model itself, the effect is the same.  It is useful to decorate
individual model instances with an ACL (as opposed to just decorating
their class) in applications such as "CMS" systems where fine-grained
access is required on an object-by-object basis.
Whether an ACL is attached to a resource's class or an instance of the
resource itself, the effect is the same.  It is useful to decorate individual
resource instances with an ACL (as opposed to just decorating their class) in
applications such as "CMS" systems where fine-grained access is required on
an object-by-object basis.
.. index::
   single: ACE
@@ -448,16 +447,16 @@
ACL Inheritance and Location-Awareness
--------------------------------------
While the default :term:`authorization policy` is in place, if a model
object does not have an ACL when it is the context, its *parent* is
consulted for an ACL.  If that object does not have an ACL, *its*
parent is consulted for an ACL, ad infinitum, until we've reached the
root and there are no more parents left.
While the default :term:`authorization policy` is in place, if a resource
object does not have an ACL when it is the context, its *parent* is consulted
for an ACL.  If that object does not have an ACL, *its* parent is consulted
for an ACL, ad infinitum, until we've reached the root and there are no more
parents left.
In order to allow the security machinery to perform ACL inheritance,
model objects must provide *location-awareness*.  Providing
*location-awareness* means two things: the root object in the graph
must have a ``_name__`` attribute and a ``__parent__`` attribute.
In order to allow the security machinery to perform ACL inheritance, resource
objects must provide *location-awareness*.  Providing *location-awareness*
means two things: the root object in the resource tree must have a
``_name__`` attribute and a ``__parent__`` attribute.
.. code-block:: python
   :linenos:
docs/narr/static.rst
@@ -1,26 +1,26 @@
Static Resources
================
Static Assets
=============
:app:`Pyramid` makes it possible to serve up static
resources files from a directory on a filesystem.  This chapter describes
how to configure :app:`Pyramid` to do so.
:app:`Pyramid` makes it possible to serve up static asset files from a
directory on a filesystem.  This chapter describes how to configure
:app:`Pyramid` to do so.
.. index::
   single: add_static_view
.. _static_resources_section:
.. _static_assets_section:
Serving Static Resources
------------------------
Serving Static Assets
---------------------
Use the :meth:`pyramid.config.Configurator.add_static_view` to
instruct :app:`Pyramid` to serve static resources such as JavaScript and CSS
files. This mechanism makes static files available at a name relative to the
application root URL, e.g. ``/static``.
Use the :meth:`pyramid.config.Configurator.add_static_view` to instruct
:app:`Pyramid` to serve static assets such as JavaScript and CSS files. This
mechanism makes static files available at a name relative to the application
root URL, e.g. ``/static``.
Note that the ``path`` provided to
:meth:`pyramid.config.Configurator.add_static_view` may be a fully
qualified :term:`resource specification`, or an *absolute path*.
:meth:`pyramid.config.Configurator.add_static_view` may be a fully qualified
:term:`asset specification`, or an *absolute path*.
Here's an example of a use of
:meth:`pyramid.config.Configurator.add_static_view` that will serve
@@ -34,11 +34,10 @@
   # config is an instance of pyramid.config.Configurator
   config.add_static_view(name='static', path='/var/www/static')
Here's an example of
:meth:`pyramid.config.Configurator.add_static_view` that will serve
files up under the ``/static`` URL from the ``a/b/c/static`` directory of the
Python package named ``some_package`` using a fully qualified :term:`resource
specification`.
Here's an example of :meth:`pyramid.config.Configurator.add_static_view` that
will serve files up under the ``/static`` URL from the ``a/b/c/static``
directory of the Python package named ``some_package`` using a fully
qualified :term:`asset specification`.
.. code-block:: python
   :linenos:
@@ -46,7 +45,7 @@
   # config is an instance of pyramid.config.Configurator
   config.add_static_view(name='static', path='some_package:a/b/c/static')
Whether you use for ``path`` a fully qualified resource specification, or an
Whether you use for ``path`` a fully qualified asset specification, or an
absolute path, when you place your static files on the filesystem in the
directory represented as the ``path`` of the directive, you will then be able
to view the static files in this directory via a browser at URLs prefixed
@@ -58,13 +57,12 @@
be resolved by the static view as you would expect.
While the ``path`` argument can be a number of different things, the ``name``
argument of the call to
:meth:`pyramid.config.Configurator.add_static_view` can also be one of
a number of things: a *view name* or a *URL*.  The above examples have shown
usage of the ``name`` argument as a view name.  When ``name`` is a *URL* (or
any string with a slash (``/``) in it), static resources can be served from
an external webserver.  In this mode, the ``name`` is used as the URL prefix
when generating a URL using :func:`pyramid.url.static_url`.
argument of the call to :meth:`pyramid.config.Configurator.add_static_view`
can also be one of a number of things: a *view name* or a *URL*.  The above
examples have shown usage of the ``name`` argument as a view name.  When
``name`` is a *URL* (or any string with a slash (``/``) in it), static assets
can be served from an external webserver.  In this mode, the ``name`` is used
as the URL prefix when generating a URL using :func:`pyramid.url.static_url`.
.. note::
@@ -130,18 +128,18 @@
   other than ``media_location`` could be used.
.. index::
   single: generating static resource urls
   single: static resource urls
   single: generating static asset urls
   single: static asset urls
.. _generating_static_resource_urls:
.. _generating_static_asset_urls:
Generating Static Resource URLs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Generating Static Asset URLs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When a :meth:`pyramid.config.Configurator.add_static_view` method is
used to register a static resource directory, a special helper API named
:func:`pyramid.url.static_url` can be used to generate the appropriate URL for a
package resource that lives in one of the directories named by the static
When a :meth:`pyramid.config.Configurator.add_static_view` method is used to
register a static asset directory, a special helper API named
:func:`pyramid.url.static_url` can be used to generate the appropriate URL
for an asset that lives in one of the directories named by the static
registration ``path`` attribute.
For example, let's assume you create a set of static declarations like so:
@@ -149,19 +147,19 @@
.. code-block:: python
   :linenos:
   config.add_static_view(name='static1', path='mypackage:resources/1')
   config.add_static_view(name='static2', path='mypackage:resources/2')
   config.add_static_view(name='static1', path='mypackage:assets/1')
   config.add_static_view(name='static2', path='mypackage:assets/2')
These declarations create URL-accessible directories which have URLs that
begin with ``/static1`` and ``/static2``, respectively.  The resources in
the ``resources/1`` directory of the ``mypackage`` package are consulted when
a user visits a URL which begins with ``/static1``, and the resources in the
``resources/2`` directory of the ``mypackage`` package are consulted when a
user visits a URL which begins with ``/static2``.
begin with ``/static1`` and ``/static2``, respectively.  The assets in the
``assets/1`` directory of the ``mypackage`` package are consulted when a user
visits a URL which begins with ``/static1``, and the assets in the
``assets/2`` directory of the ``mypackage`` package are consulted when a user
visits a URL which begins with ``/static2``.
You needn't generate the URLs to static resources "by hand" in such a
configuration.  Instead, use the :func:`pyramid.url.static_url` API
to generate them for you.  For example:
You needn't generate the URLs to static assets "by hand" in such a
configuration.  Instead, use the :func:`pyramid.url.static_url` API to
generate them for you.  For example:
.. code-block:: python
   :linenos:
@@ -170,8 +168,8 @@
   from pyramid.chameleon_zpt import render_template_to_response
   def my_view(request):
       css_url = static_url('mypackage:resources/1/foo.css', request)
       js_url = static_url('mypackage:resources/2/foo.js', request)
       css_url = static_url('mypackage:assets/1/foo.css', request)
       js_url = static_url('mypackage:assets/2/foo.js', request)
       return render_template_to_response('templates/my_template.pt',
                                          css_url = css_url,
                                          js_url = js_url)
@@ -186,13 +184,12 @@
of a static URL declaration, the generated URLs will continue to resolve
properly after the rename.
URLs may also be generated by :func:`pyramid.url.static_url` to static
resources that live *outside* the :app:`Pyramid` application.  This will
happen when the :meth:`pyramid.config.Configurator.add_static_view`
API associated with the path fed to :func:`pyramid.url.static_url` is a *URL*
instead of a view name.  For example, the ``name`` argument may be
``http://example.com`` while the the ``path`` given may be
``mypackage:images``:
URLs may also be generated by :func:`pyramid.url.static_url` to static assets
that live *outside* the :app:`Pyramid` application.  This will happen when
the :meth:`pyramid.config.Configurator.add_static_view` API associated with
the path fed to :func:`pyramid.url.static_url` is a *URL* instead of a view
name.  For example, the ``name`` argument may be ``http://example.com`` while
the the ``path`` given may be ``mypackage:images``:
.. code-block:: python
   :linenos:
@@ -200,7 +197,7 @@
   config.add_static_view(name='http://example.com/images', path='mypackage:images')
Under such a configuration, the URL generated by ``static_url`` for
resources which begin with ``mypackage:images`` will be prefixed with
assets which begin with ``mypackage:images`` will be prefixed with
``http://example.com/images``:
.. code-block:: python
@@ -210,25 +207,23 @@
   # -> http://example.com/images/logo.png
.. index::
   single: static resource view
   single: static assets view
Advanced: Serving Static Resources Using a View Callable
--------------------------------------------------------
Advanced: Serving Static Assets Using a View Callable
-----------------------------------------------------
For more flexibility, static resources can be served by a :term:`view
callable` which you register manually.  For example, you may want
static resources to only be available when the :term:`context` of the
view is of a particular type, or when the request is of a particular
type.
For more flexibility, static assets can be served by a :term:`view callable`
which you register manually.  For example, you may want static assets to only
be available when the :term:`context` is of a particular type, or when
certain request headers are present.
The :class:`pyramid.view.static` helper class is used to perform
this task. This class creates an object that is capable acting as a
:app:`Pyramid` view callable which serves static resources from a
directory.  For instance, to serve files within a directory located on
your filesystem at ``/path/to/static/dir`` from the URL path
``/static`` in your application, create an instance of the
:class:`pyramid.view.static` class inside a ``static.py`` file in
your application root as below.
The :class:`pyramid.view.static` helper class is used to perform this
task. This class creates an object that is capable acting as a :app:`Pyramid`
view callable which serves static assets from a directory.  For instance, to
serve files within a directory located on your filesystem at
``/path/to/static/dir`` from the URL path ``/static`` in your application,
create an instance of the :class:`pyramid.view.static` class inside a
``static.py`` file in your application root as below.
.. ignore-next-block
.. code-block:: python
@@ -240,47 +235,43 @@
.. note:: the argument to :class:`pyramid.view.static` can also be
   a "here-relative" pathname, e.g. ``my/static`` (meaning relative to the
   Python package of the module in which the view is being defined).
   It can also be a :term:`resource specification`
   It can also be a :term:`asset specification`
   (e.g. ``anotherpackage:some/subdirectory``).
 
Subsequently, you may wire this view up to be accessible as ``/static`` using
the :mod:`pyramid.config.Configurator.add_view` method in your
application's startup code against either the class or interface that
represents your root object.
the :mod:`pyramid.config.Configurator.add_view` method in your application's
startup code against either the class or interface that represents your root
resource object.
.. code-block:: python
   :linenos:
   config.add_view('mypackage.static.static_view', name='static',
                   context='mypackage.models.Root')
                   context='mypackage.resources.Root')
In this case, ``mypackage.models.Root`` refers to the class of your
:app:`Pyramid` application's traversal root object.
In this case, ``mypackage.resources.Root`` refers to the class of your
:app:`Pyramid` application's resource tree.
The context argument above limits where the static view is accessible to
URL paths directly under the root object.  If you omit the ``context``
argument, then ``static`` will be accessible as the static view against
any model object in the traversal graph.  This will allow
``/static/foo.js`` to work, but it will also allow for
``/anything/static/foo.js`` too, as long as ``anything`` can be
resolved.
The context argument above limits where the static view is accessible to URL
paths directly under the root object.  If you omit the ``context`` argument,
then ``static`` will be accessible as the static view against any resource
object in the resource tree.  This will allow ``/static/foo.js`` to work, but
it will also allow for ``/anything/static/foo.js`` too, as long as
``anything`` can be resolved.
Note that you cannot use the :func:`pyramid.url.static_url` API to generate
URLs against resources made accessible by registering a custom static view.
URLs against assets made accessible by registering a custom static view.
.. warning::
   When adding a static view to your root object, you need to be
   careful that there are no model objects contained in the
   root with the same key as the view name (e.g., ``static``).
   Model objects take precedence during traversal,
   thus such a name collision will cause the model to "shadow"
   your static view. To avoid this issue, and ensure that your
   root object's ``__getitem__`` is never
   called when a static resource is requested, you can refer to them
   unambiguously using the ``@@`` prefix (goggles) in their URLs.
   For the above examples you could use '/@@static/foo.js'
   instead of '/static/foo.js' to avoid such shadowing.
   See :ref:`traversal_chapter` for information
   about "goggles" (``@@``).
   When adding a static view to your root object, you need to be careful that
   there are no resource objects contained in the root with the same key as
   the view name (e.g., ``static``).  Resource objects take precedence during
   traversal, thus such a name collision will cause the resource to "shadow"
   your static view. To avoid this issue, and ensure that your root
   resource's ``__getitem__`` is never called when a static asset is
   requested, you can refer to them unambiguously using the ``@@`` prefix
   (goggles) in their URLs.  For the above examples you could use
   '/@@static/foo.js' instead of '/static/foo.js' to avoid such shadowing.
   See :ref:`traversal_chapter` for information about "goggles" (``@@``).
docs/narr/templates.rst
@@ -84,9 +84,9 @@
   file instead of treating relative paths as relative to the current
   view module.  See :ref:`mako_templates`.
The path can alternately be a :term:`resource specification` in the form
The path can alternately be a :term:`asset specification` in the form
``some.dotted.package_name:relative/path``. This makes it possible to
address template resources which live in another package.  For example:
address template assets which live in another package.  For example:
.. code-block:: python
   :linenos:
@@ -98,20 +98,20 @@
                                 {'foo':1, 'bar':2},
                                 request=request)
A resource specification points at a file within a Python *package*.
An asset specification points at a file within a Python *package*.
In this case, it points at a file named ``foo.pt`` within the
``templates`` directory of the ``mypackage`` package.  Using a
resource specification instead of a relative template name is usually
a good idea, because calls to ``render_to_response`` using resource
asset specification instead of a relative template name is usually
a good idea, because calls to ``render_to_response`` using asset
specifications will continue to work properly if you move the code
containing them around.
.. note::
   Mako templating system bindings also respect absolute resource
   Mako templating system bindings also respect absolute asset
   specifications as an argument to any of the ``render*`` commands.  If a
   template name defines a ``:`` (colon) character and is not an absolute
   path, it is treated as an absolute resource specification.
   path, it is treated as an absolute asset specification.
In the examples above we pass in a keyword argument named ``request``
representing the current :app:`Pyramid` request. Passing a request
@@ -187,8 +187,8 @@
   :app:`Pyramid` bindings directly within view callables, the
   auto-template-reload strategy explained in
   :ref:`reload_templates_section` will not be available, nor will the
   template resource overriding capability explained in
   :ref:`overriding_resources_section` be available, nor will it be
   template asset overriding capability explained in
   :ref:`overriding_assets_section` be available, nor will it be
   possible to use any template using that language as a
   :term:`renderer`.  However, it's reasonably easy to write custom
   templating system binding packages for use under :app:`Pyramid` so
@@ -289,7 +289,7 @@
templating languages supported by :app:`Pyramid`.
To use a renderer via view configuration, specify a template
:term:`resource specification` as the ``renderer`` argument, or
:term:`asset specification` as the ``renderer`` argument, or
attribute to the :term:`view configuration` of a :term:`view
callable`.  Then return a *dictionary* from that view callable.  The
dictionary items returned by the view callable will be made available
@@ -326,7 +326,7 @@
   we're using a Chameleon renderer, it means "relative to the directory in
   which the file which defines the view configuration lives".  In this case,
   this is the directory containing the file that defines the ``my_view``
   function.  View-configuration-relative resource specifications work only
   function.  View-configuration-relative asset specifications work only
   in Chameleon, not in Mako templates.
Similar renderer configuration can be done imperatively and via
@@ -335,9 +335,9 @@
Although a renderer path is usually just a simple relative pathname, a path
named as a renderer can be absolute, starting with a slash on UNIX or a drive
letter prefix on Windows.  The path can alternately be a :term:`resource
letter prefix on Windows.  The path can alternately be an :term:`asset
specification` in the form ``some.dotted.package_name:relative/path``, making
it possible to address template resources which live in another package.
it possible to address template assets which live in another package.
Not just any template from any arbitrary templating system may be used as a
renderer.  Bindings must exist specifically for :app:`Pyramid` to use a
@@ -468,21 +468,20 @@
Using ZPT Macros in :app:`Pyramid`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When a :term:`renderer` is used to render a template, :app:`Pyramid`
makes at least two top-level names available to the template by default:
``context`` and ``request``.  One of the common needs in ZPT-based
templates is to use one template's "macros" from within a different
template.  In Zope, this is typically handled by retrieving the template
from the ``context``.  But the context in :app:`Pyramid` is typically a
model object, and templates cannot usually be retrieved from models.  To
use macros in :app:`Pyramid`, you need to make the macro template itself
available to the rendered template by passing the macro template, or
even the macro itself, *into* the rendered template.  To do this you can
use the :func:`pyramid.renderers.get_renderer` API to retrieve the macro
template, and pass it into the template being rendered via the dictionary
returned by the view.  For example, using a :term:`view configuration` via a
:class:`pyramid.view.view_config` decorator that uses a
:term:`renderer`:
When a :term:`renderer` is used to render a template, :app:`Pyramid` makes at
least two top-level names available to the template by default: ``context``
and ``request``.  One of the common needs in ZPT-based templates is to use
one template's "macros" from within a different template.  In Zope, this is
typically handled by retrieving the template from the ``context``.  But the
context in :app:`Pyramid` is a :term:`resource` object, and templates cannot
usually be retrieved from resources.  To use macros in :app:`Pyramid`, you
need to make the macro template itself available to the rendered template by
passing the macro template, or even the macro itself, *into* the rendered
template.  To do this you can use the :func:`pyramid.renderers.get_renderer`
API to retrieve the macro template, and pass it into the template being
rendered via the dictionary returned by the view.  For example, using a
:term:`view configuration` via a :class:`pyramid.view.view_config` decorator
that uses a :term:`renderer`:
.. code-block:: python
   :linenos:
@@ -658,7 +657,7 @@
                   request: <Request - at 0x1d2ecd0>
                   project: proj
                   macros: <Macros - at 0x1d3aed0>
                   context: <MyModel None at 0x1d39130>
                   context: <MyResource None at 0x1d39130>
                   view: <function my_view at 0x1d23570>
    NameError: wrong
docs/narr/threadlocals.rst
@@ -110,11 +110,9 @@
  View callables already have access to the request (it's passed in to
  each as ``request``).
- ``get_current_request`` should never be called in :term:`model`
  code.  Model code should never require any access to the request; if
  your model code requires access to a request object, you've almost
  certainly factored something wrong, and you should change your code
  rather than using this function.
- ``get_current_request`` should never be called in :term:`resource` code.
   If a resource needs access to the request, it should be passed the request
   by a :term:`view callable`.
- ``get_current_request`` function should never be called because it's
  "easier" or "more elegant" to think about calling it than to pass a
docs/narr/traversal.rst
@@ -3,14 +3,14 @@
Traversal
=========
:term:`Traversal` is a :term:`context finding` mechanism. It is the
act of finding a :term:`context` and a :term:`view name` by walking
over an *object graph*, starting from a :term:`root` object, using a
:term:`Traversal` is a :term:`context finding` mechanism. It is the act of
finding a :term:`context` and a :term:`view name` by walking over a
:term:`resource tree`, starting from a :term:`root` resource, using a
:term:`request` object as a source of path information.
In this chapter, we'll provide a high-level overview of traversal,
we'll explain the concept of an *object graph*, and we'll show how
traversal might be used within an application.
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
used within an application.
.. index::
   single: traversal analogy
@@ -55,16 +55,16 @@
The contents of ``myfile`` are now printed on the user's behalf.
:app:`Pyramid` is very much like this inexperienced UNIX user as it
uses :term:`traversal` against an object graph.  In this analogy, we
can map the ``cat`` program to the :app:`Pyramid` concept of a
:term:`view callable`: it is a program that can be run against some
:term:`context` as the result of :term:`view lookup`.  The file being
operated on in this analogy is the :term:`context` object; the context
is the "last node found" in a traversal.  The directory structure is
the object graph being traversed.  The act of progressively changing
directories to find the file as well as the handling of a ``cd`` error
as a stop condition is analogous to :term:`traversal`.
:app:`Pyramid` is very much like this inexperienced UNIX user as it uses
:term:`traversal` against a resource tree.  In this analogy, we can map the
``cat`` program to the :app:`Pyramid` concept of a :term:`view callable`: it
is a program that can be run against some :term:`context` as the result of
:term:`view lookup`.  The file being operated on in this analogy is the
:term:`context` object; the context is the "last resource found" in a
traversal.  The directory structure is the resource tree being traversed.
The act of progressively changing directories to find the file as well as the
handling of a ``cd`` error as a stop condition is analogous to
:term:`traversal`.
The analogy we've used is not *exactly* correct, because, while the
naive user already knows which command he wants to invoke before he
@@ -94,9 +94,9 @@
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
object graph for each path segment.  Each lookup uses the
``__getitem__`` method of an object in the graph.
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
an object in the tree.
For example, if the path info sequence is ``['a', 'b', 'c']``:
@@ -121,13 +121,13 @@
a lookup for a path element fails.  In either case, a :term:`context`
is found.
Traversal "stops" when it either reaches a leaf level model instance
in your object graph or when the path segments implied by the URL "run
out".  The object that traversal "stops on" becomes the
:term:`context`.  If at any point during traversal any node in the
graph doesn't have a ``__getitem__`` method, or if the ``__getitem__``
method of a node raises a :exc:`KeyError`, traversal ends immediately,
and that node becomes the :term:`context`.
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
object 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
@@ -142,18 +142,18 @@
within the :ref:`views_chapter` chapter.
.. index::
   single: object graph
   single: traversal graph
   single: model graph
   single: object tree
   single: traversal tree
   single: resource tree
.. _the_object_graph:
.. _the_resource_tree:
The Object Graph
----------------
The Resource Tree
-----------------
When your application uses :term:`traversal` to resolve URLs to code,
your application must supply an *object graph* to :app:`Pyramid`.
This graph is represented by a :term:`root` object.
When your application uses :term:`traversal` to resolve URLs to code, your
application must supply the a resource tree to :app:`Pyramid`.  This tree is
represented by a :term:`root` object.
In order to supply a root object for an application, at system startup
time, the :app:`Pyramid` :term:`Router` is configured with a
@@ -188,19 +188,18 @@
Python name` which refers to a root factory object 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 object graph.
All :term:`traversal` will begin at this root object.  Usually a root
factory for a traversal-based application will be more complicated
than the above ``Root`` object; in particular it may be associated
with a database connection or another persistence mechanism.  A root
object is often an instance of a class which has a ``__getitem__``
method.
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 object.  Usually a root factory for
a traversal-based application will be more complicated than the above
``Root`` object; in particular it may be associated with a database
connection or another persistence mechanism.  A root object is often an
instance of a class which has a ``__getitem__`` method.
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 an object that has no child nodes.
root factory always returns an object that has no child resources.
.. sidebar:: Emulating the Default Root Factory
@@ -218,47 +217,48 @@
      config = Configurator(root_factory=Root)
   The default root factory is just a really stupid object that has no
   behavior or state.  Using :term:`traversal` against an application
   that uses the object graph supplied by the default root object is
   not very interesting, because the default root object has no
   children.  Its availability is more useful when you're developing
   an application using :term:`URL dispatch`.
   behavior or state.  Using :term:`traversal` against an application that
   uses the resource tree supplied by the default root object is not very
   interesting, because the default root object has no children.  Its
   availability is more useful when you're developing an application using
   :term:`URL dispatch`.
Items contained within the object graph are sometimes analogous to the
concept of :term:`model` objects used by many other frameworks (and
:app:`Pyramid` APIs often refers to them as "models", as well).
They are typically instances of Python classes.
.. note::
The object graph consists of *container* nodes and *leaf* nodes.
There is only one difference between a *container* node and a *leaf*
node: *container* nodes possess a ``__getitem__`` method while *leaf*
nodes do not.  The ``__getitem__`` method was chosen as the signifying
difference between the two types of nodes because the presence of this
   If the items contained within the resource tree are "persistent" (they
   have state that lasts longer than the execution of a single process), they
   become analogous to the concept of :term:`domain model` objects used by
   many other frameworks.
The resource tree consists of *container* resources and *leaf* resources.
There is only one difference between a *container* resource and a *leaf*
resource: *container* resources possess a ``__getitem__`` method while *leaf*
resources do not.  The ``__getitem__`` method was chosen as the signifying
difference between the two types of resources because the presence of this
method is how Python itself typically determines whether an object is
"containerish" or not.
Each container node is presumed to be willing to return a child node
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 node types and cause their ``__getitem__`` methods to simply
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* node, and as such it
contains other nodes.  However, it doesn't *need* to be a container.
Your object graph can be as shallow or as deep as you require.
Usually, the traversal root is a *container* resource, and as such it
contains other resources.  However, it doesn't *need* to be a container.
Your resource tree can be as shallow or as deep as you require.
In general, the object graph is traversed beginning at its root object
using a sequence of path elements described by the ``PATH_INFO`` of
the current request; if there are path segments, the root object's
``__getitem__`` is called with the next path segment, and it is
expected to return another graph object.  The resulting object's
``__getitem__`` is called with the very next path segment, and it is
expected to return another graph object.  This happens *ad infinitum*
until all path segments are exhausted.
In general, the resource tree is traversed beginning at its root object using
a sequence of path elements described by the ``PATH_INFO`` of the current
request; if there are path segments, the root object's ``__getitem__`` is
called with the next path segment, and it is expected to return another
resource object.  The resulting object's ``__getitem__`` is called with the
very next path segment, and it is expected to return another resource object.
This happens *ad infinitum* until all path segments are exhausted.
.. index::
   single: traversal algorithm
@@ -273,7 +273,7 @@
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 object graph.
specific resource tree.
We'll also talk a bit about :term:`view lookup`.  The
:ref:`views_chapter` chapter discusses :term:`view lookup` in detail,
@@ -314,17 +314,15 @@
    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 natural byte string (``str`` type)
    representation.  URL unquoting is performed using the Python
    standard library ``urllib.unquote`` function.  Conversion from a
    URL-decoded string into Unicode is attempted using the UTF-8
    encoding.  If any URL-unquoted path segment in ``PATH_INFO`` is
    not decodeable using the UTF-8 decoding, a :exc:`TypeError` is
    raised.  A segment will be fully URL-unquoted and UTF8-decoded
    before it is passed it to the ``__getitem__`` of any model object
    during traversal.
    The traversal algorithm by default attempts to first URL-unquote and then
    Unicode-decode each path segment derived from ``PATH_INFO`` from its
    natural byte string (``str`` type) representation.  URL unquoting is
    performed using the Python standard library ``urllib.unquote`` function.
    Conversion from a URL-decoded string into Unicode is attempted using the
    UTF-8 encoding.  If any URL-unquoted path segment in ``PATH_INFO`` is not
    decodeable using the UTF-8 decoding, a :exc:`TypeError` is raised.  A
    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']``.
@@ -340,12 +338,11 @@
    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 :exc:`KeyError` from its ``__getitem__`` or
    c) when any non-final path element traversal does not have a
    ``__getitem__`` method (resulting in a :exc:`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 :term:`view name`).
    resouce raises a :exc:`KeyError` from its ``__getitem__`` or c) when any
    non-final path element traversal does not have a ``__getitem__`` method
    (resulting in a :exc:`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 :term:`view name`).
#.  When traversal ends for any of the reasons in the previous step,
    the last object found during traversal is deemed to be the
@@ -375,19 +372,18 @@
  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 characters is considered the :term:`view name`
  immediately and traversal stops there.  This allows you to address
  views that may have the same names as model instance names in the
  graph unambiguously.
- If any path segment element begins with the special characters ``@@``
  (think of them as goggles), the value of that segment minus the goggle
  characters is considered the :term:`view name` immediately and traversal
  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.
.. image:: modelgraphtraverser.png
.. image:: resourcetreetraverser.png
.. index::
   single: traversal examples
@@ -397,13 +393,13 @@
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 object graph compositions.
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 object graph:
the following resource tree:
.. code-block:: text
@@ -450,7 +446,7 @@
circumstance, the :app:`Pyramid` :term:`router` returns the result
of the :term:`not found view` and the request ends.
However, for this graph:
However, for this tree:
.. code-block:: text
@@ -537,6 +533,6 @@
deal with traversal, such as traversal invocation from within
application code.
The :func:`pyramid.url.model_url` function generates a URL when
given an object retrieved from an object graph.
The :func:`pyramid.url.resource_url` function generates a URL when
given an object retrieved from an resource tree.
docs/narr/unittesting.rst
@@ -12,23 +12,22 @@
method of a class instance.  The unit is also referred to as a "unit
under test".
The goal of a single unit test is to test **only** some permutation of
the "unit under test".  If you write a unit test that aims to verify
the result of a particular codepath through a Python function, you
need only be concerned about testing the code that *lives in the
function body itself*.  If the function accepts a parameter that
represents a complex application "domain object" (such as a model, a
database connection, or an SMTP server), the argument provided to this
function during a unit test *need not be* and likely *should not be* a
"real" implementation object.  For example, although a particular
function implementation may accept an argument that represents an SMTP
server object, and the function may call a method of this object when
the system is operating normally that would result in an email being
sent, a unit test of this codepath of the function does *not* need to
test that an email is actually sent.  It just needs to make sure that
the function calls the method of the object provided as an argument
that *would* send an email if the argument happened to be the "real"
implementation of an SMTP server object.
The goal of a single unit test is to test **only** some permutation of the
"unit under test".  If you write a unit test that aims to verify the result
of a particular codepath through a Python function, you need only be
concerned about testing the code that *lives in the function body itself*.
If the function accepts a parameter that represents a complex application
"domain object" (such as a resource, a database connection, or an SMTP
server), the argument provided to this function during a unit test *need not
be* and likely *should not be* a "real" implementation object.  For example,
although a particular function implementation may accept an argument that
represents an SMTP server object, and the function may call a method of this
object when the system is operating normally that would result in an email
being sent, a unit test of this codepath of the function does *not* need to
test that an email is actually sent.  It just needs to make sure that the
function calls the method of the object provided as an argument that *would*
send an email if the argument happened to be the "real" implementation of an
SMTP server object.
An *integration test*, on the other hand, is a different form of
testing in which the interaction between two or more "units" is
@@ -298,9 +297,9 @@
See the :ref:`testing_module` chapter for the entire :app:`Pyramid`
-specific testing API.  This chapter describes APIs for registering a
security policy, registering models at paths, registering event
security policy, registering resources at paths, registering event
listeners, registering views and view permissions, and classes
representing "dummy" implementations of a request and a model.
representing "dummy" implementations of a request and a resource.
See also the various methods of the :term:`Configurator` documented in
:ref:`configuration_module` that begin with the ``testing_`` prefix.
docs/narr/urldispatch.rst
@@ -375,7 +375,7 @@
The order that routes declarations are evaluated is the order in which
they are added to the application at startup time.  This is unlike
:term:`traversal`, which depends on emergent behavior which happens as
a result of traversing a graph.
a result of traversing a resource tree.
For routes added via the :mod:`pyramid.config.Configurator.add_route`
method, the order that routes are evaluated is the order in which they are
@@ -414,7 +414,7 @@
   :linenos:
   config.add_route('abc', '/abc', view='myproject.views.theview', 
                    factory='myproject.models.root_factory')
                    factory='myproject.resources.root_factory')
The factory can either be a Python object or a :term:`dotted Python name` (a
string) which points to such a Python object, as it is above.
@@ -459,7 +459,7 @@
  A Python object (often a function or a class) or a :term:`dotted
  Python name` to such an object that will generate a
  :app:`Pyramid` :term:`context` object when this route
  matches. For example, ``mypackage.models.MyFactoryClass``.  If this
  matches. For example, ``mypackage.resources.MyFactoryClass``.  If this
  argument is not specified, the traversal root factory will be used.
``traverse``
@@ -613,7 +613,7 @@
``view_renderer``
  This is either a single string term (e.g. ``json``) or a string
  implying a path or :term:`resource specification`
  implying a path or :term:`asset specification`
  (e.g. ``templates/views.pt``).  If the renderer value is a single
  term (does not contain a dot ``.``), the specified term will be used
  to look up a renderer implementation, and that renderer
@@ -979,10 +979,10 @@
   config.add_route('idea', 'ideas/{idea}', 
                    view='myproject.views.idea_view',
                    factory='myproject.models.Idea')
                    factory='myproject.resources.Idea')
The above route will manufacture an ``Idea`` model as a
:term:`context`, assuming that ``mypackage.models.Idea`` resolves to a
The above route will manufacture an ``Idea`` resource as a
:term:`context`, assuming that ``mypackage.resources.Idea`` resolves to a
class that accepts a request in its ``__init__``.  For example:
.. code-block:: python
docs/narr/vhosting.rst
@@ -85,21 +85,19 @@
:term:`traversal` -based (but not :term:`URL dispatch` -based)
applications.
Virtual root support is useful when you'd like to host some model in a
:app:`Pyramid` object graph as an application under a URL pathname
that does not include the model path itself.  For example, you might
want to serve the object at the traversal path ``/cms`` as an
application reachable via ``http://example.com/`` (as opposed to
``http://example.com/cms``).
Virtual root support is useful when you'd like to host some resource in a
:app:`Pyramid` resource tree as an application under a URL pathname that does
not include the resource path itself.  For example, you might want to serve the
object at the traversal path ``/cms`` as an application reachable via
``http://example.com/`` (as opposed to ``http://example.com/cms``).
To specify a virtual root, cause an environment variable to be
inserted into the WSGI environ named ``HTTP_X_VHM_ROOT`` with a value
that is the absolute pathname to the model object in the traversal
graph that should behave as the "root" model.  As a result, the
traversal machinery will respect this value during traversal
(prepending it to the PATH_INFO before traversal starts), and the
:func:`pyramid.url.model_url` API will generate the "correct"
virtually-rooted URLs.
To specify a virtual root, cause an environment variable to be inserted into
the WSGI environ named ``HTTP_X_VHM_ROOT`` with a value that is the absolute
pathname to the resource object in the resource tree that should behave as
the "root" resource.  As a result, the traversal machinery will respect this
value during traversal (prepending it to the PATH_INFO before traversal
starts), and the :func:`pyramid.url.resource_url` API will generate the
"correct" virtually-rooted URLs.
An example of an Apache ``mod_proxy`` configuration that will host the
``/cms`` subobject as ``http://www.example.com/`` using this facility
docs/narr/views.rst
@@ -3,11 +3,10 @@
Views
=====
The primary job of any :app:`Pyramid` application is is to find and
invoke a :term:`view callable` when a :term:`request` reaches the
application.  View callables are bits of code written by you -- the
application developer -- which do something interesting in response to
a request made to your application.
The primary job of any :app:`Pyramid` application is is to find and invoke a
:term:`view callable` when a :term:`request` reaches the application.  View
callables are bits of code which do something interesting in response to a
request made to your application.
.. note:: 
@@ -18,11 +17,10 @@
   that implements a view *callable*, and the process of view
   *lookup*.
The chapter :ref:`contextfinding_chapter` describes how, using
information from the :term:`request`, a :term:`context` and a
:term:`view name` are computed.  But neither the context nor the view
name found are very useful unless those elements can eventually be
mapped to a :term:`view callable`.
The chapter :ref:`contextfinding_chapter` describes how, using information
from the :term:`request`, a :term:`context` and a :term:`view name` are
computed.  But neither the context nor the view name found are very useful
unless those elements can eventually be mapped to a :term:`view callable`.
The job of actually locating and invoking the "best" :term:`view
callable` is the job of the :term:`view lookup` subsystem.  The view
@@ -139,9 +137,8 @@
    function defined in this style can be defined as follows:
    context
      An instance of a :term:`context` found via graph :term:`traversal`
      or :term:`URL dispatch`.  If the context is found via traversal, it
      will be a :term:`model` object.
      The :term:`resource` object found via tree :term:`traversal`
      or :term:`URL dispatch`.
    request
      A :app:`Pyramid` Request object representing the current WSGI
@@ -476,7 +473,7 @@
   config.add_view('myproject.views.hello_world', 
                    name='hello',
                    context='myproject.models.Hello',
                    context='myproject.resources.Hello',
                    renderer='json')
    
@@ -494,22 +491,21 @@
Two built-in renderers exist for :term:`Chameleon` templates.
If the ``renderer`` attribute of a view configuration is an absolute
path, a relative path or :term:`resource specification` which has a
final path element with a filename extension of ``.pt``, the Chameleon
ZPT renderer is used.  See :ref:`chameleon_zpt_templates` for more
information about ZPT templates.
If the ``renderer`` attribute of a view configuration is an absolute path, a
relative path or :term:`asset specification` which has a final path element
with a filename extension of ``.pt``, the Chameleon ZPT renderer is used.
See :ref:`chameleon_zpt_templates` for more information about ZPT templates.
If the ``renderer`` attribute of a view configuration is an absolute path or
a :term:`resource specification` which has a final path element with a
filename extension of ``.txt``, the :term:`Chameleon` text renderer is used.
See :ref:`chameleon_zpt_templates` for more information about Chameleon text
a :term:`asset specification` which has a final path element with a filename
extension of ``.txt``, the :term:`Chameleon` text renderer is used.  See
:ref:`chameleon_zpt_templates` for more information about Chameleon text
templates.
The behavior of these renderers is the same, except for the engine
used to render the template.
When a ``renderer`` attribute that names a template path or :term:`resource
When a ``renderer`` attribute that names a template path or :term:`asset
specification` (e.g. ``myproject:templates/foo.pt`` or
``myproject:templates/foo.txt``) is used, the view must return a
:term:`Response` object or a Python *dictionary*.  If the view callable with
@@ -541,7 +537,7 @@
    config.add_view('myproject.views.hello_world',
                    name='hello',
                    context='myproject.models.Hello',
                    context='myproject.resources.Hello',
                    renderer='myproject:templates/foo.pt')
Here's an example view configuration which uses a Chameleon text
@@ -552,7 +548,7 @@
    config.add_view('myproject.views.hello_world',
                    name='hello',
                    context='myproject.models.Hello',
                    context='myproject.resources.Hello',
                    renderer='myproject:templates/foo.txt')
Views which use a Chameleon renderer can vary response attributes by
@@ -573,13 +569,13 @@
view callable returns anything but a Response object, or a dictionary, an error
will be raised.
When using a ``renderer`` argument to a :term:`view configuration` to
specify a Mako template, the value of the ``renderer`` may be a path
relative to the ``mako.directories`` setting (e.g.
``some/template.mak``) or, alternately, it may be a :term:`resource
specification` (e.g. ``apackage:templates/sometemplate.mak``).  Mako
templates may internally inherit other Mako templates using a relative
filename or a :term:`resource specification` as desired.
When using a ``renderer`` argument to a :term:`view configuration` to specify
a Mako template, the value of the ``renderer`` may be a path relative to the
``mako.directories`` setting (e.g.  ``some/template.mak``) or, alternately,
it may be a :term:`asset specification`
(e.g. ``apackage:templates/sometemplate.mak``).  Mako templates may
internally inherit other Mako templates using a relative filename or a
:term:`asset specification` as desired.
XXX Further explanation or link to mako inheritance info
@@ -592,7 +588,7 @@
    config.add_view('myproject.views.hello_world',
                    name='hello',
                    context='myproject.models.Hello',
                    context='myproject.resources.Hello',
                    renderer='foo.mak')
It's important to note that in Mako's case, the 'relative' path name
@@ -600,16 +596,15 @@
directory (or directories) configured for Mako via the ``mako.directories``
configuration file setting.
The renderer can also be provided in :term:`resource specification`
format. Here's an example view configuration which uses a :term:`resource
specification`:
The renderer can also be provided in :term:`asset specification`
format. Here's an example view configuration which uses one:
.. code-block:: python
   :linenos:
    config.add_view('myproject.views.hello_world',
                    name='hello',
                    context='myproject.models.Hello',
                    context='myproject.resources.Hello',
                    renderer='mypackage:templates/foo.mak')
The above configuration will use the file named ``foo.mak`` in the
@@ -746,26 +741,27 @@
There are essentially two different kinds of renderer factories:
- A renderer factory which expects to accept a :term:`resource specification`,
  or an absolute path, as the ``name`` attribute of the ``info`` object fed to
  its constructor.  These renderer factories are registered with a ``name``
  value that begins with a dot (``.``).  These types of renderer factories
  usually relate to a file on the filesystem, such as a template.
- A renderer factory which expects to accept a token that does not represent a
  filesystem path or a resource specification in the ``name`` attribute of the
- A renderer factory which expects to accept a :term:`asset
  specification`, or an absolute path, as the ``name`` attribute of the
  ``info`` object fed to its constructor.  These renderer factories are
  registered with a ``name`` value that does not begin with a dot.  These
  renderer factories are typically object serializers.
  registered with a ``name`` value that begins with a dot (``.``).  These
  types of renderer factories usually relate to a file on the filesystem,
  such as a template.
.. sidebar:: Resource Specifications
- A renderer factory which expects to accept a token that does not represent
  a filesystem path or a asset specification in the ``name``
  attribute of the ``info`` object fed to its constructor.  These renderer
  factories are registered with a ``name`` value that does not begin with a
  dot.  These renderer factories are typically object serializers.
   A resource specification is a colon-delimited identifier for a
   :term:`resource`.  The colon separates a Python :term:`package`
   name from a package subpath.  For example, the resource
   specification ``my.package:static/baz.css`` identifies the file
   named ``baz.css`` in the ``static`` subdirectory of the
   ``my.package`` Python :term:`package`.
.. sidebar:: Asset Specifications
   A asset specification is a colon-delimited identifier for a
   :term:`asset`.  The colon separates a Python :term:`package`
   name from a package subpath.  For example, the asset
   specification ``my.package:static/baz.css`` identifies the file named
   ``baz.css`` in the ``static`` subdirectory of the ``my.package`` Python
   :term:`package`.
Here's an example of the registration of a simple renderer factory via
:meth:`pyramid.config.Configurator.add_renderer`:
@@ -1211,30 +1207,26 @@
  itself if the view is a function, or the ``__call__`` callable
  attribute if the view is a class).
``renderer``
  This is either a single string term (e.g. ``json``) or a string
  implying a path or :term:`resource specification`
  (e.g. ``templates/views.pt``) naming a :term:`renderer`
  implementation.  If the ``renderer`` value does not contain a dot
  (``.``), the specified string will be used to look up a renderer
  implementation, and that renderer implementation will be used to
  construct a response from the view return value.  If the
  ``renderer`` value contains a dot (``.``), the specified term will
  be treated as a path, and the filename extension of the last element
  in the path will be used to look up the renderer implementation,
  which will be passed the full path.  The renderer implementation
  will be used to construct a :term:`response` from the view return
  value.
``renderer`` This is either a single string term (e.g. ``json``) or a string
  implying a path or :term:`asset specification`
  (e.g. ``templates/views.pt``) naming a :term:`renderer` implementation.  If
  the ``renderer`` value does not contain a dot (``.``), the specified string
  will be used to look up a renderer implementation, and that renderer
  implementation will be used to construct a response from the view return
  value.  If the ``renderer`` value contains a dot (``.``), the specified
  term will be treated as a path, and the filename extension of the last
  element in the path will be used to look up the renderer implementation,
  which will be passed the full path.  The renderer implementation will be
  used to construct a :term:`response` from the view return value.
  When the renderer is a path, although a path is usually just a
  simple relative pathname (e.g. ``templates/foo.pt``, implying that a
  template named "foo.pt" is in the "templates" directory relative to
  the directory of the current :term:`package`), a path can be
  absolute, starting with a slash on UNIX or a drive letter prefix on
  Windows.  The path can alternately be a :term:`resource
  specification` in the form
  ``some.dotted.package_name:relative/path``, making it possible to
  address template resources which live in a separate package.
  When the renderer is a path, although a path is usually just a simple
  relative pathname (e.g. ``templates/foo.pt``, implying that a template
  named "foo.pt" is in the "templates" directory relative to the directory of
  the current :term:`package`), a path can be absolute, starting with a slash
  on UNIX or a drive letter prefix on Windows.  The path can alternately be a
  :term:`asset specification` in the form
  ``some.dotted.package_name:relative/path``, making it possible to address
  template assets which live in a separate package.
  The ``renderer`` attribute is optional.  If it is not defined, the
  "null" renderer is assumed (no rendering is performed and the value
@@ -1276,15 +1268,15 @@
  default view).
``context``
  An object representing a Python class that the :term:`context` must be
  an instance of, *or* the :term:`interface` that the :term:`context`
  must provide in order for this view to be found and called.  This
  predicate is true when the :term:`context` is an instance of the
  represented class or if the :term:`context` provides the represented
  interface; it is otherwise false.
  An object representing a Python class that the :term:`context` resource
  must be an instance of, *or* the :term:`interface` that the :term:`context`
  must provide in order for this view to be found and called.  This predicate
  is true when the :term:`context` is an instance of the represented class or
  if the :term:`context` provides the represented interface; it is otherwise
  false.
  If ``context`` is not supplied, the value ``None``, which matches
  any model, is used.
  If ``context`` is not supplied, the value ``None``, which matches any
  resource, is used.
``route_name``
  If ``route_name`` is supplied, the view callable will be invoked
@@ -1344,7 +1336,7 @@
  This value should be a reference to a Python class or
  :term:`interface` that a parent object in the context's
  :term:`lineage` must provide in order for this view to be found and
  called.  The nodes in your object graph must be "location-aware" to
  called.  The resources in your resource tree must be "location-aware" to
  use this feature.
  If ``containment`` is not supplied, the interfaces and classes in
@@ -1469,11 +1461,11 @@
.. code-block:: python
   :linenos:
   from models import MyModel
   from resources import MyResource
   from pyramid.view import view_config
   from pyramid.chameleon_zpt import render_template_to_response
   @view_config(name='my_view', request_method='POST', context=MyModel,
   @view_config(name='my_view', request_method='POST', context=MyResource,
             permission='read', renderer='templates/my.pt')
   def my_view(request):
       return {'a':1}
@@ -1486,7 +1478,7 @@
   :linenos:
   config.add_view('.views.my_view', name='my_view', request_method='POST', 
                   context=MyModel, permission='read')
                   context=MyResource, permission='read')
All arguments to ``view_config`` may be omitted.  For example:
@@ -1503,7 +1495,7 @@
Such a registration as the one directly above implies that the view
name will be ``my_view``, registered with a ``context`` argument that
matches any model type, using no permission, registered against
matches any resource type, using no permission, registered against
requests with any request method, request type, request param,
route name, or containment.
@@ -1686,32 +1678,32 @@
information.
.. index::
   single: model interfaces
   single: resource interfaces
.. _using_model_interfaces:
.. _using_resource_interfaces:
Using Model Interfaces In View Configuration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Using Resource Interfaces In View Configuration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Instead of registering your views with a ``context`` that names a
Python model *class*, you can optionally register a view callable with
a ``context`` which is an :term:`interface`.  An interface can be
attached arbitrarily to any model instance.  View lookup treats
context interfaces specially, and therefore the identity of a model
can be divorced from that of the class which implements it.  As a
result, associating a view with an interface can provide more
flexibility for sharing a single view between two or more different
implementations of a model type.  For example, if two model object
instances of different Python class types share the same interface,
you can use the same view against each of them.
Instead of registering your views with a ``context`` that names a Python
resource *class*, you can optionally register a view callable with a
``context`` which is an :term:`interface`.  An interface can be attached
arbitrarily to any resource object.  View lookup treats context interfaces
specially, and therefore the identity of a resource can be divorced from that
of the class which implements it.  As a result, associating a view with an
interface can provide more flexibility for sharing a single view between two
or more different implementations of a resource type.  For example, if two
resource objects of different Python class types share the same interface,
you can use the same view configuration to specify both of them as a
``context``.
In order to make use of interfaces in your application during view
dispatch, you must create an interface and mark up your model classes
or instances with interface declarations that refer to this interface.
In order to make use of interfaces in your application during view dispatch,
you must create an interface and mark up your resource classes or instances
with interface declarations that refer to this interface.
To attach an interface to a model *class*, you define the interface
and use the :func:`zope.interface.implements` function to associate
the interface with the class.
To attach an interface to a resource *class*, you define the interface and
use the :func:`zope.interface.implements` function to associate the interface
with the class.
.. code-block:: python
   :linenos:
@@ -1725,10 +1717,10 @@
   class Hello(object):
       implements(IHello)
To attach an interface to a model *instance*, you define the interface
and use the :func:`zope.interface.alsoProvides` function to associate
the interface with the instance.  This function mutates the instance
in such a way that the interface is attached to it.
To attach an interface to a resource *instance*, you define the interface and
use the :func:`zope.interface.alsoProvides` function to associate the
interface with the instance.  This function mutates the instance in such a
way that the interface is attached to it.
.. code-block:: python
   :linenos:
@@ -1747,13 +1739,13 @@
       alsoProvides(hello, IHello)
       return hello
Regardless of how you associate an interface, with a model instance, or a model
class, the resulting code to associate that interface with a view callable is
the same.  Assuming the above code that defines an ``IHello`` interface lives
in the root of your application, and its module is named "models.py", the
interface declaration below will associate the
``mypackage.views.hello_world`` view with models that implement, or provide,
this interface.
Regardless of how you associate an interface, with a resource instance, or a
resource class, the resulting code to associate that interface with a view
callable is the same.  Assuming the above code that defines an ``IHello``
interface lives in the root of your application, and its module is named
"resources.py", the interface declaration below will associate the
``mypackage.views.hello_world`` view with resources that implement, or
provide, this interface.
.. code-block:: python
   :linenos:
@@ -1761,22 +1753,25 @@
   # config is an instance of pyramid.config.Configurator
   config.add_view('mypackage.views.hello_world', name='hello.html',
                   context='mypackage.models.IHello')
                   context='mypackage.resources.IHello')
Any time a model that is determined to be the :term:`context` provides this
interface, and a view named ``hello.html`` is looked up against it as per the
URL, the ``mypackage.views.hello_world`` view callable will be invoked.
Any time a resource that is determined to be the :term:`context` provides
this interface, and a view named ``hello.html`` is looked up against it as
per the URL, the ``mypackage.views.hello_world`` view callable will be
invoked.
Note, in cases where a view is registered against a model class, and a
view is also registered against an interface that the model class
implements, an ambiguity arises. Views registered for the model class
take precedence over any views registered for any interface the model
class implements. Thus, if a view is registered for both the class type
of the context and an interface implemented by the context's class, the
view registered for the context's class will "win".
Note, in cases where a view is registered against a resource class, and a
view is also registered against an interface that the resource class
implements, an ambiguity arises. Views registered for the resource class take
precedence over any views registered for any interface the resource class
implements. Thus, if one view configuration names a ``context`` of both the
class type of a resource, and another view configuration names a ``context``
of interface implemented by the resource's class, and both view
configurations are otherwise identical, the view registered for the context's
class will "win".
For more information about defining models with interfaces for use within
view configuration, see :ref:`models_which_implement_interfaces`.
For more information about defining resources with interfaces for use within
view configuration, see :ref:`resources_which_implement_interfaces`.
.. index::
   single: view security
@@ -1800,7 +1795,7 @@
   # config is an instance of pyramid.config.Configurator
   config.add_view('myproject.views.add_entry', name='add.html',
                   context='myproject.models.IBlog', permission='add')
                   context='myproject.resources.IBlog', permission='add')
When an :term:`authorization policy` is enabled, this view will be
protected with the ``add`` permission.  The view will *not be called* if
docs/narr/zca.rst
@@ -129,7 +129,7 @@
There are two ways of doing so:
- use the :func:`pyramid.threadlocal.get_current_registry`
  function within :app:`Pyramid` view or model code.  This will
  function within :app:`Pyramid` view or resource code.  This will
  always return the "current" :app:`Pyramid` application registry.
- use the attribute of the :term:`request` object named ``registry``
docs/tutorials/catalog/index.rst
@@ -88,11 +88,11 @@
       Python 2.5.4 (r254:67916, Sep  4 2009, 02:12:16) 
       [GCC 4.2.1 (Apple Inc. build 5646)] on darwin
       Type "help" for more information. "root" is the Pyramid app root object.
       >>> from pyramid.traversal import model_path
       >>> from pyramid.traversal import resource_path
       >>> from myapp.models import Document
       >>> root['name'] = Document('title')
       >>> doc = root['name']
       >>> docid = root.catalog.document_map.add(model_path(doc))
       >>> docid = root.catalog.document_map.add(resource_path(doc))
       >>> root.catalog.index_doc(docid, doc)
       >>> import transaction
       >>> transaction.commit()
docs/tutorials/wiki/basiclayout.rst
@@ -98,11 +98,15 @@
Content Models with ``models.py``
---------------------------------
:app:`Pyramid` often uses the word :term:`model` when talking about
content resources arranged in the hierarchical *object graph*
consulted by :term:`traversal`.  The ``models.py`` file is where the
``pyramid_zodb`` Paster template put the classes that implement our
model objects.
:app:`Pyramid` uses the word :term:`resource` to describe objects arranged
hierarchically in a :term:`resource tree`.  This tree is consulted by
:term:`traversal` to map URLs to code.  In this application, the resource
tree represents the site structure, but it *also* represents the
:term:`domain model` of the application, because eeach resource is a node
stored persistently in a :term:`ZODB` database.  The ``models.py`` file is
where the ``pyramid_zodb`` Paster template put the classes that implement our
resource objects, each of which happens also to be a domain model
object.
Here is the source for ``models.py``:
docs/tutorials/wiki/definingmodels.rst
@@ -1,15 +1,17 @@
===============
Defining Models
===============
=========================
Defining the Domain Model
=========================
The first change we'll make to our bone-stock ``paster`` -generated
application will be to define a number of :term:`model` constructors.
For this application, which will be a Wiki, we will need two kinds of
model constructors: a "Wiki" model constructor, and a "Page" model
constructor.  Both our Page and Wiki constructors will be class
objects.  A single instance of the "Wiki" class will serve as a
container for "Page" objects, which will be instances of the "Page"
class.
application will be to define a number of :term:`resource` constructors.
Remember that, because we're using :term:`ZODB` to represent our
:term:`resource tree`, each of these resource constructors represents a
:term:`domain model` object, so we'll call these constructors "model
constructors".  For this application, which will be a Wiki, we will need two
kinds of model constructors: a "Wiki" model constructor, and a "Page" model
constructor.  Both our Page and Wiki constructors will be class objects.  A
single instance of the "Wiki" class will serve as a container for "Page"
objects, which will be instances of the "Page" class.
The source code for this tutorial stage can be browsed via
`http://github.com/Pylons/pyramid/tree/master/docs/tutorials/wiki/src/models/
docs/tutorials/wiki/definingviews.rst
@@ -51,15 +51,15 @@
The ``view_wiki`` view function
-------------------------------
The ``view_wiki`` function will be configured to respond as the
default view of a ``Wiki`` model object.  It always redirects to the
``Page`` object named "FrontPage".  It returns an instance of the
:class:`pyramid.httpexceptions.HTTPFound` class (instances of which
implement the WebOb :term:`response` interface), and the
:func:`pyramid.url.model_url` API.  :func:`pyramid.url.model_url`
constructs a URL to the ``FrontPage`` page
(e.g. ``http://localhost:6543/FrontPage``), and uses it as the
"location" of the HTTPFound response, forming an HTTP redirect.
The ``view_wiki`` function will be configured to respond as the default view
of a ``Wiki`` model object.  It always redirects to the ``Page`` object named
"FrontPage".  It returns an instance of the
:class:`pyramid.httpexceptions.HTTPFound` class (instances of which implement
the WebOb :term:`response` interface), and the
:func:`pyramid.url.resource_url` API.  :func:`pyramid.url.resource_url`
constructs a URL to the ``FrontPage`` page resource
(e.g. ``http://localhost:6543/FrontPage``), and uses it as the "location" of
the HTTPFound response, forming an HTTP redirect.
The ``view_page`` view function
-------------------------------
docs/tutorials/wiki/src/authorization/tutorial/login.py
@@ -1,7 +1,7 @@
from pyramid.httpexceptions import HTTPFound
from pyramid.view import view_config
from pyramid.url import model_url
from pyramid.url import resource_url
from pyramid.security import remember
from pyramid.security import forget
@@ -11,7 +11,7 @@
@view_config(context=Wiki, name='login', renderer='templates/login.pt')
def login(request):
    login_url = model_url(request.context, request, 'login')
    login_url = resource_url(request.context, request, 'login')
    referrer = request.url
    if referrer == login_url:
        referrer = '/' # never use the login form itself as came_from
@@ -39,6 +39,6 @@
@view_config(context=Wiki, name='logout')
def logout(request):
    headers = forget(request)
    return HTTPFound(location = model_url(request.context, request),
    return HTTPFound(location = resource_url(request.context, request),
                     headers = headers)
    
docs/tutorials/wiki/src/authorization/tutorial/tests.py
@@ -43,7 +43,7 @@
class ViewWikiTests(unittest.TestCase):
    def test_it(self):
        from tutorial.views import view_wiki
        context = testing.DummyModel()
        context = testing.DummyResource()
        request = testing.DummyRequest()
        response = view_wiki(context, request)
        self.assertEqual(response.location, 'http://example.com/FrontPage')
@@ -54,9 +54,9 @@
        return view_page(context, request)
    def test_it(self):
        wiki = testing.DummyModel()
        wiki['IDoExist'] = testing.DummyModel()
        context = testing.DummyModel(data='Hello CruelWorld IDoExist')
        wiki = testing.DummyResource()
        wiki['IDoExist'] = testing.DummyResource()
        context = testing.DummyResource(data='Hello CruelWorld IDoExist')
        context.__parent__ = wiki
        context.__name__ = 'thepage'
        request = testing.DummyRequest()
@@ -80,17 +80,18 @@
        return add_page(context, request)
    def test_it_notsubmitted(self):
        from pyramid.url import model_url
        context = testing.DummyModel()
        from pyramid.url import resource_url
        context = testing.DummyResource()
        request = testing.DummyRequest()
        request.subpath = ['AnotherPage']
        info = self._callFUT(context, request)
        self.assertEqual(info['page'].data,'')
        self.assertEqual(info['save_url'],
                         model_url(context, request, 'add_page', 'AnotherPage'))
                         resource_url(
                             context, request, 'add_page', 'AnotherPage'))
        
    def test_it_submitted(self):
        context = testing.DummyModel()
        context = testing.DummyResource()
        request = testing.DummyRequest({'form.submitted':True,
                                        'body':'Hello yo!'})
        request.subpath = ['AnotherPage']
@@ -106,16 +107,16 @@
        return edit_page(context, request)
    def test_it_notsubmitted(self):
        from pyramid.url import model_url
        context = testing.DummyModel()
        from pyramid.url import resource_url
        context = testing.DummyResource()
        request = testing.DummyRequest()
        info = self._callFUT(context, request)
        self.assertEqual(info['page'], context)
        self.assertEqual(info['save_url'],
                         model_url(context, request, 'edit_page'))
                         resource_url(context, request, 'edit_page'))
        
    def test_it_submitted(self):
        context = testing.DummyModel()
        context = testing.DummyResource()
        request = testing.DummyRequest({'form.submitted':True,
                                        'body':'Hello yo!'})
        response = self._callFUT(context, request)
docs/tutorials/wiki/src/authorization/tutorial/views.py
@@ -2,7 +2,7 @@
import re
from pyramid.httpexceptions import HTTPFound
from pyramid.url import model_url
from pyramid.url import resource_url
from pyramid.security import authenticated_userid
@@ -16,7 +16,7 @@
@view_config(context=Wiki, permission='view')
def view_wiki(context, request):
    return HTTPFound(location = model_url(context, request, 'FrontPage'))
    return HTTPFound(location = resource_url(context, request, 'FrontPage'))
@view_config(context=Page, renderer='templates/view.pt', permission='view')
def view_page(context, request):
@@ -26,7 +26,7 @@
        word = match.group(1)
        if word in wiki:
            page = wiki[word]
            view_url = model_url(page, request)
            view_url = resource_url(page, request)
            return '<a href="%s">%s</a>' % (view_url, word)
        else:
            add_url = request.application_url + '/add_page/' + word 
@@ -34,7 +34,7 @@
    content = publish_parts(context.data, writer_name='html')['html_body']
    content = wikiwords.sub(check, content)
    edit_url = model_url(context, request, 'edit_page')
    edit_url = resource_url(context, request, 'edit_page')
    logged_in = authenticated_userid(request)
@@ -51,8 +51,8 @@
        page.__name__ = name
        page.__parent__ = context
        context[name] = page
        return HTTPFound(location = model_url(page, request))
    save_url = model_url(context, request, 'add_page', name)
        return HTTPFound(location = resource_url(page, request))
    save_url = resource_url(context, request, 'add_page', name)
    page = Page('')
    page.__name__ = name
    page.__parent__ = context
@@ -66,11 +66,11 @@
def edit_page(context, request):
    if 'form.submitted' in request.params:
        context.data = request.params['body']
        return HTTPFound(location = model_url(context, request))
        return HTTPFound(location = resource_url(context, request))
    logged_in = authenticated_userid(request)
    return dict(page = context,
                save_url = model_url(context, request, 'edit_page'),
                save_url = resource_url(context, request, 'edit_page'),
                logged_in = logged_in)
    
docs/tutorials/wiki/src/viewdecorators/tutorial/tests.py
@@ -43,7 +43,7 @@
class ViewWikiTests(unittest.TestCase):
    def test_it(self):
        from tutorial.views import view_wiki
        context = testing.DummyModel()
        context = testing.DummyResource()
        request = testing.DummyRequest()
        response = view_wiki(context, request)
        self.assertEqual(response.location, 'http://example.com/FrontPage')
@@ -54,9 +54,9 @@
        return view_page(context, request)
    def test_it(self):
        wiki = testing.DummyModel()
        wiki['IDoExist'] = testing.DummyModel()
        context = testing.DummyModel(data='Hello CruelWorld IDoExist')
        wiki = testing.DummyResource()
        wiki['IDoExist'] = testing.DummyResource()
        context = testing.DummyResource(data='Hello CruelWorld IDoExist')
        context.__parent__ = wiki
        context.__name__ = 'thepage'
        request = testing.DummyRequest()
@@ -80,17 +80,18 @@
        return add_page(context, request)
    def test_it_notsubmitted(self):
        from pyramid.url import model_url
        context = testing.DummyModel()
        from pyramid.url import resource_url
        context = testing.DummyResource()
        request = testing.DummyRequest()
        request.subpath = ['AnotherPage']
        info = self._callFUT(context, request)
        self.assertEqual(info['page'].data,'')
        self.assertEqual(info['save_url'],
                         model_url(context, request, 'add_page', 'AnotherPage'))
                         resource_url(
                             context, request, 'add_page', 'AnotherPage'))
        
    def test_it_submitted(self):
        context = testing.DummyModel()
        context = testing.DummyResource()
        request = testing.DummyRequest({'form.submitted':True,
                                        'body':'Hello yo!'})
        request.subpath = ['AnotherPage']
@@ -106,16 +107,16 @@
        return edit_page(context, request)
    def test_it_notsubmitted(self):
        from pyramid.url import model_url
        context = testing.DummyModel()
        from pyramid.url import resource_url
        context = testing.DummyResource()
        request = testing.DummyRequest()
        info = self._callFUT(context, request)
        self.assertEqual(info['page'], context)
        self.assertEqual(info['save_url'],
                         model_url(context, request, 'edit_page'))
                         resource_url(context, request, 'edit_page'))
        
    def test_it_submitted(self):
        context = testing.DummyModel()
        context = testing.DummyResource()
        request = testing.DummyRequest({'form.submitted':True,
                                        'body':'Hello yo!'})
        response = self._callFUT(context, request)
docs/tutorials/wiki/src/viewdecorators/tutorial/views.py
@@ -2,7 +2,7 @@
import re
from pyramid.httpexceptions import HTTPFound
from pyramid.url import model_url
from pyramid.url import resource_url
from pyramid.view import view_config
from tutorial.models import Page
@@ -13,7 +13,7 @@
@view_config(context=Wiki)
def view_wiki(context, request):
    return HTTPFound(location = model_url(context, request, 'FrontPage'))
    return HTTPFound(location = resource_url(context, request, 'FrontPage'))
@view_config(context=Page, renderer='templates/view.pt')
def view_page(context, request):
@@ -23,7 +23,7 @@
        word = match.group(1)
        if word in wiki:
            page = wiki[word]
            view_url = model_url(page, request)
            view_url = resource_url(page, request)
            return '<a href="%s">%s</a>' % (view_url, word)
        else:
            add_url = request.application_url + '/add_page/' + word 
@@ -31,7 +31,7 @@
    content = publish_parts(context.data, writer_name='html')['html_body']
    content = wikiwords.sub(check, content)
    edit_url = model_url(context, request, 'edit_page')
    edit_url = resource_url(context, request, 'edit_page')
    return dict(page = context, content = content, edit_url = edit_url)
    
@view_config(context=Wiki, name='add_page', renderer='templates/edit.pt')
@@ -43,8 +43,8 @@
        page.__name__ = name
        page.__parent__ = context
        context[name] = page
        return HTTPFound(location = model_url(page, request))
    save_url = model_url(context, request, 'add_page', name)
        return HTTPFound(location = resource_url(page, request))
    save_url = resource_url(context, request, 'add_page', name)
    page = Page('')
    page.__name__ = name
    page.__parent__ = context
@@ -54,9 +54,9 @@
def edit_page(context, request):
    if 'form.submitted' in request.params:
        context.data = request.params['body']
        return HTTPFound(location = model_url(context, request))
        return HTTPFound(location = resource_url(context, request))
    return dict(page = context,
                save_url = model_url(context, request, 'edit_page'))
                save_url = resource_url(context, request, 'edit_page'))
    
    
docs/tutorials/wiki/src/views/tutorial/tests.py
@@ -43,7 +43,7 @@
class ViewWikiTests(unittest.TestCase):
    def test_it(self):
        from tutorial.views import view_wiki
        context = testing.DummyModel()
        context = testing.DummyResource()
        request = testing.DummyRequest()
        response = view_wiki(context, request)
        self.assertEqual(response.location, 'http://example.com/FrontPage')
@@ -54,9 +54,9 @@
        return view_page(context, request)
    def test_it(self):
        wiki = testing.DummyModel()
        wiki['IDoExist'] = testing.DummyModel()
        context = testing.DummyModel(data='Hello CruelWorld IDoExist')
        wiki = testing.DummyResource()
        wiki['IDoExist'] = testing.DummyResource()
        context = testing.DummyResource(data='Hello CruelWorld IDoExist')
        context.__parent__ = wiki
        context.__name__ = 'thepage'
        request = testing.DummyRequest()
@@ -80,18 +80,18 @@
        return add_page(context, request)
    def test_it_notsubmitted(self):
        from pyramid.url import model_url
        context = testing.DummyModel()
        from pyramid.url import resource_url
        context = testing.DummyResource()
        request = testing.DummyRequest()
        request.subpath = ['AnotherPage']
        info = self._callFUT(context, request)
        self.assertEqual(info['page'].data,'')
        self.assertEqual(
            info['save_url'],
            model_url(context, request, 'add_page', 'AnotherPage'))
            resource_url(context, request, 'add_page', 'AnotherPage'))
        
    def test_it_submitted(self):
        context = testing.DummyModel()
        context = testing.DummyResource()
        request = testing.DummyRequest({'form.submitted':True,
                                        'body':'Hello yo!'})
        request.subpath = ['AnotherPage']
@@ -107,16 +107,16 @@
        return edit_page(context, request)
    def test_it_notsubmitted(self):
        from pyramid.url import model_url
        context = testing.DummyModel()
        from pyramid.url import resource_url
        context = testing.DummyResource()
        request = testing.DummyRequest()
        info = self._callFUT(context, request)
        self.assertEqual(info['page'], context)
        self.assertEqual(info['save_url'],
                         model_url(context, request, 'edit_page'))
                         resource_url(context, request, 'edit_page'))
        
    def test_it_submitted(self):
        context = testing.DummyModel()
        context = testing.DummyResource()
        request = testing.DummyRequest({'form.submitted':True,
                                        'body':'Hello yo!'})
        response = self._callFUT(context, request)
docs/tutorials/wiki/src/views/tutorial/views.py
@@ -2,7 +2,7 @@
import re
from pyramid.httpexceptions import HTTPFound
from pyramid.url import model_url
from pyramid.url import resource_url
from tutorial.models import Page
@@ -10,7 +10,7 @@
wikiwords = re.compile(r"\b([A-Z]\w+[A-Z]+\w+)")
def view_wiki(context, request):
    return HTTPFound(location = model_url(context, request, 'FrontPage'))
    return HTTPFound(location = resource_url(context, request, 'FrontPage'))
def view_page(context, request):
    wiki = context.__parent__
@@ -19,7 +19,7 @@
        word = match.group(1)
        if word in wiki:
            page = wiki[word]
            view_url = model_url(page, request)
            view_url = resource_url(page, request)
            return '<a href="%s">%s</a>' % (view_url, word)
        else:
            add_url = request.application_url + '/add_page/' + word 
@@ -27,7 +27,7 @@
    content = publish_parts(context.data, writer_name='html')['html_body']
    content = wikiwords.sub(check, content)
    edit_url = model_url(context, request, 'edit_page')
    edit_url = resource_url(context, request, 'edit_page')
    return dict(page = context, content = content, edit_url = edit_url)
    
def add_page(context, request):
@@ -38,8 +38,8 @@
        page.__name__ = name
        page.__parent__ = context
        context[name] = page
        return HTTPFound(location = model_url(page, request))
    save_url = model_url(context, request, 'add_page', name)
        return HTTPFound(location = resource_url(page, request))
    save_url = resource_url(context, request, 'add_page', name)
    page = Page('')
    page.__name__ = name
    page.__parent__ = context
@@ -48,9 +48,9 @@
def edit_page(context, request):
    if 'form.submitted' in request.params:
        context.data = request.params['body']
        return HTTPFound(location = model_url(context, request))
        return HTTPFound(location = resource_url(context, request))
    return dict(page = context,
                save_url = model_url(context, request, 'edit_page'))
                save_url = resource_url(context, request, 'edit_page'))
    
    
docs/tutorials/wiki2/definingmodels.rst
@@ -1,10 +1,10 @@
===============
Defining Models
===============
=========================
Defining the Domain Model
=========================
The first change we'll make to our stock paster-generated application
will be to define a :term:`model` constructor representing a wiki
page.  We'll do this inside our ``models.py`` file.
The first change we'll make to our stock paster-generated application will be
to define a :term:`domain model` constructor representing a wiki page.  We'll
do this inside our ``models.py`` file.
The source code for this tutorial stage can be browsed at
`http://github.com/Pylons/pyramid/tree/master/docs/tutorials/wiki2/src/models/
docs/zcml.rst
@@ -13,6 +13,7 @@
   zcml/aclauthorizationpolicy
   zcml/adapter
   zcml/authtktauthenticationpolicy
   zcml/asset
   zcml/configure
   zcml/default_permission
   zcml/forbidden
@@ -23,7 +24,6 @@
   zcml/remoteuserauthenticationpolicy
   zcml/renderer
   zcml/repozewho1authenticationpolicy
   zcml/resource
   zcml/route
   zcml/scan
   zcml/static
docs/zcml/aclauthorizationpolicy.rst
@@ -4,7 +4,7 @@
--------------------------
When this directive is used, authorization information is obtained
from :term:`ACL` objects attached to model instances.
from :term:`ACL` objects attached to :term:`resource` objects.
Attributes
~~~~~~~~~~
docs/zcml/asset.rst
New file
@@ -0,0 +1,65 @@
.. _asset_directive:
``asset``
---------
The ``asset`` directive adds an asset override for a single
static file/directory asset.
Attributes
~~~~~~~~~~
``to_override``
   A :term:`asset specification` specifying the asset to be
   overridden.
``override_with``
   A :term:`asset specification` specifying the asset which
   is used as the override.
Examples
~~~~~~~~
.. topic:: Overriding a Single Asset File
  .. code-block:: xml
     :linenos:
     <asset
       to_override="some.package:templates/mytemplate.pt"
       override_with="another.package:othertemplates/anothertemplate.pt"
     />
.. topic:: Overriding all Assets in a Package
  .. code-block:: xml
     :linenos:
     <asset
       to_override="some.package"
       override_with="another.package"
      />
.. topic:: Overriding all Assets in a Subdirectory of a Package
  .. code-block:: xml
     :linenos:
     <asset
       to_override="some.package:templates/"
       override_with="another.package:othertemplates/"
      />
Alternatives
~~~~~~~~~~~~
The :meth:`pyramid.config.Configurator.override_asset`
method can be used instead of the ``resource`` ZCML directive.
This directive can also be invoked as the ``resource`` ZCML directive for
backwards compatibility purposes.
See Also
~~~~~~~~
See also :ref:`asset_zcml_directive`.
docs/zcml/forbidden.rst
@@ -35,7 +35,7 @@
``renderer``
  This is either a single string term (e.g. ``json``) or a string
  implying a path or :term:`resource specification`
  implying a path or :term:`asset specification`
  (e.g. ``templates/views.pt``) used when the view returns a
  non-:term:`response` object.  This attribute has the same meaning as
  it would in the context of :ref:`view_directive`; see the
docs/zcml/handler.rst
@@ -28,7 +28,7 @@
``factory``
  The :term:`dotted Python name` to a function that will generate a
  :app:`Pyramid` context object when the associated route matches.
  e.g. ``mypackage.models.MyFactoryClass``.  If this argument is not
  e.g. ``mypackage.resources.MyResource``.  If this argument is not
  specified, a default root factory will be used.
``xhr``
docs/zcml/notfound.rst
@@ -34,7 +34,7 @@
``renderer``
  This is either a single string term (e.g. ``json``) or a string
  implying a path or :term:`resource specification`
  implying a path or :term:`asset specification`
  (e.g. ``templates/views.pt``) used when the view returns a
  non-:term:`response` object.  This attribute has the same meaning as
  it would in the context of :ref:`view_directive`; see the
docs/zcml/resource.rst
File was deleted
docs/zcml/route.rst
@@ -25,7 +25,7 @@
``factory``
  The :term:`dotted Python name` to a function that will generate a
  :app:`Pyramid` context object when this route matches.
  e.g. ``mypackage.models.MyFactoryClass``.  If this argument is not
  e.g. ``mypackage.resources.MyResource``.  If this argument is not
  specified, a default root factory will be used.
``view``
@@ -172,7 +172,7 @@
``view_renderer``
  This is either a single string term (e.g. ``json``) or a string
  implying a path or :term:`resource specification`
  implying a path or :term:`asset specification`
  (e.g. ``templates/views.pt``).  If the renderer value is a single
  term (does not contain a dot ``.``), the specified term will be used
  to look up a renderer implementation, and that renderer
docs/zcml/view.rst
@@ -51,7 +51,7 @@
``renderer``
  This is either a single string term (e.g. ``json``) or a string
  implying a path or :term:`resource specification`
  implying a path or :term:`asset specification`
  (e.g. ``templates/views.pt``).  If the renderer value is a single
  term (does not contain a dot ``.``), the specified term will be used
  to look up a renderer implementation, and that renderer
@@ -72,10 +72,10 @@
  template named "foo.pt" is in the "templates" directory relative to
  the directory in which the ZCML file is defined), a path can be
  absolute, starting with a slash on UNIX or a drive letter prefix on
  Windows.  The path can alternately be a :term:`resource
  Windows.  The path can alternately be a :term:`asset
  specification` in the form
  ``some.dotted.package_name:relative/path``, making it possible to
  address template resources which live in a separate package.
  address template assets which live in a separate package.
  The ``renderer`` attribute is optional.  If it is not defined, the
  "null" renderer is assumed (no rendering is performed and the value
@@ -157,7 +157,7 @@
  representing the class that a graph traversal parent object of the
  :term:`context` must be an instance of (or :term:`interface` that a
  parent object must provide) in order for this view to be found and
  called.  Your models must be "location-aware" to use this feature.
  called.  Your resources must be "location-aware" to use this feature.
  See :ref:`location_aware` for more information about
  location-awareness.
@@ -222,7 +222,7 @@
     :linenos:
        <view
           context=".models.MyModel"
           context=".resources.MyResource"
           view=".views.hello_world"
         />
@@ -232,7 +232,7 @@
     :linenos:
        <view
           context=".models.MyModel"
           context=".resources.MyResource"
           view=".views.hello_world_post"
           request_method="POST"
         />
pyramid/asset.py
New file
@@ -0,0 +1,207 @@
import os
import pkg_resources
from zope.interface import implements
from pyramid.interfaces import IPackageOverrides
from pyramid.path import package_path
from pyramid.path import package_name
from pyramid.threadlocal import get_current_registry
class OverrideProvider(pkg_resources.DefaultProvider):
    def __init__(self, module):
        pkg_resources.DefaultProvider.__init__(self, module)
        self.module_name = module.__name__
    def _get_overrides(self):
        reg = get_current_registry()
        overrides = reg.queryUtility(IPackageOverrides, self.module_name)
        return overrides
    def get_resource_filename(self, manager, resource_name):
        """ Return a true filesystem path for resource_name,
        co-ordinating the extraction with manager, if the resource
        must be unpacked to the filesystem.
        """
        overrides = self._get_overrides()
        if overrides is not None:
            filename = overrides.get_filename(resource_name)
            if filename is not None:
                return filename
        return pkg_resources.DefaultProvider.get_resource_filename(
            self, manager, resource_name)
    def get_resource_stream(self, manager, resource_name):
        """ Return a readable file-like object for resource_name."""
        overrides = self._get_overrides()
        if overrides is not None:
            stream =  overrides.get_stream(resource_name)
            if stream is not None:
                return stream
        return pkg_resources.DefaultProvider.get_resource_stream(
            self, manager, resource_name)
    def get_resource_string(self, manager, resource_name):
        """ Return a string containing the contents of resource_name."""
        overrides = self._get_overrides()
        if overrides is not None:
            string = overrides.get_string(resource_name)
            if string is not None:
                return string
        return pkg_resources.DefaultProvider.get_resource_string(
            self, manager, resource_name)
    def has_resource(self, resource_name):
        overrides = self._get_overrides()
        if overrides is not None:
            result = overrides.has_resource(resource_name)
            if result is not None:
                return result
        return pkg_resources.DefaultProvider.has_resource(
            self, resource_name)
    def resource_isdir(self, resource_name):
        overrides = self._get_overrides()
        if overrides is not None:
            result = overrides.isdir(resource_name)
            if result is not None:
                return result
        return pkg_resources.DefaultProvider.resource_isdir(
            self, resource_name)
    def resource_listdir(self, resource_name):
        overrides = self._get_overrides()
        if overrides is not None:
            result = overrides.listdir(resource_name)
            if result is not None:
                return result
        return pkg_resources.DefaultProvider.resource_listdir(
            self, resource_name)
class PackageOverrides:
    implements(IPackageOverrides)
    # pkg_resources arg in kw args below for testing
    def __init__(self, package, pkg_resources=pkg_resources):
        if hasattr(package, '__loader__') and not isinstance(package.__loader__,
                                                             self.__class__):
            raise TypeError('Package %s already has a non-%s __loader__ '
                            '(probably a module in a zipped egg)' %
                            (package, self.__class__))
        # We register ourselves as a __loader__ *only* to support the
        # setuptools _find_adapter adapter lookup; this class doesn't
        # actually support the PEP 302 loader "API".  This is
        # excusable due to the following statement in the spec:
        # ... Loader objects are not
        # required to offer any useful functionality (any such functionality,
        # such as the zipimport get_data() method mentioned above, is
        # optional)...
        # A __loader__ attribute is basically metadata, and setuptools
        # uses it as such.
        package.__loader__ = self
        # we call register_loader_type for every instantiation of this
        # class; that's OK, it's idempotent to do it more than once.
        pkg_resources.register_loader_type(self.__class__, OverrideProvider)
        self.overrides = []
        self.overridden_package_name = package.__name__
    def insert(self, path, package, prefix):
        if not path or path.endswith('/'):
            override = DirectoryOverride(path, package, prefix)
        else:
            override = FileOverride(path, package, prefix)
        self.overrides.insert(0, override)
        return override
    def search_path(self, resource_name):
        for override in self.overrides:
            o = override(resource_name)
            if o is not None:
                package, name = o
                yield package, name
    def get_filename(self, resource_name):
        for package, rname in self.search_path(resource_name):
            if pkg_resources.resource_exists(package, rname):
                return pkg_resources.resource_filename(package, rname)
    def get_stream(self, resource_name):
        for package, rname in self.search_path(resource_name):
            if pkg_resources.resource_exists(package, rname):
                return pkg_resources.resource_stream(package, rname)
    def get_string(self, resource_name):
        for package, rname in self.search_path(resource_name):
            if pkg_resources.resource_exists(package, rname):
                return pkg_resources.resource_string(package, rname)
    def has_resource(self, resource_name):
        for package, rname in self.search_path(resource_name):
            if pkg_resources.resource_exists(package, rname):
                return True
    def isdir(self, resource_name):
        for package, rname in self.search_path(resource_name):
            if pkg_resources.resource_exists(package, rname):
                return pkg_resources.resource_isdir(package, rname)
    def listdir(self, resource_name):
        for package, rname in self.search_path(resource_name):
            if pkg_resources.resource_exists(package, rname):
                return pkg_resources.resource_listdir(package, rname)
class DirectoryOverride:
    def __init__(self, path, package, prefix):
        self.path = path
        self.package = package
        self.prefix = prefix
        self.pathlen = len(self.path)
    def __call__(self, resource_name):
        if resource_name.startswith(self.path):
            name = '%s%s' % (self.prefix, resource_name[self.pathlen:])
            return self.package, name
class FileOverride:
    def __init__(self, path, package, prefix):
        self.path = path
        self.package = package
        self.prefix = prefix
    def __call__(self, resource_name):
        if resource_name == self.path:
            return self.package, self.prefix
def resolve_asset_spec(spec, pname='__main__'):
    if pname and not isinstance(pname, basestring):
        pname = pname.__name__ # as package
    if os.path.isabs(spec):
        return None, spec
    filename = spec
    if ':' in spec:
        pname, filename = spec.split(':', 1)
    elif pname is None:
        pname, filename = None, spec
    return pname, filename
def asset_spec_from_abspath(abspath, package):
    """ Try to convert an absolute path to a resource in a package to
    a resource specification if possible; otherwise return the
    absolute path.  """
    if getattr(package, '__name__', None) == '__main__':
        return abspath
    pp = package_path(package) + os.path.sep
    if abspath.startswith(pp):
        relpath = abspath[len(pp):]
        return '%s:%s' % (package_name(package),
                          relpath.replace(os.path.sep, '/'))
    return abspath
def abspath_from_asset_spec(spec, pname='__main__'):
    if pname is None:
        return spec
    pname, filename = resolve_asset_spec(spec, pname)
    if pname is None:
        return filename
    return pkg_resources.resource_filename(pname, filename)
pyramid/authorization.py
@@ -65,7 +65,7 @@
        permits access, return an instance of
        :class:`pyramid.security.ACLDenied` if not."""
        acl = '<No ACL found on any object in model lineage>'
        acl = '<No ACL found on any object in resource lineage>'
        
        for location in lineage(context):
            try:
pyramid/chameleon_text.py
@@ -71,7 +71,7 @@
    """ Return a callable object which can be used to render a
    :term:`Chameleon` text template using the template implied by the
    ``path`` argument.  The ``path`` argument may be a
    package-relative path, an absolute path, or a :term:`resource
    package-relative path, an absolute path, or a :term:`asset
    specification`.
    
    .. warning:: This API is deprecated in :app:`Pyramid` 1.0.  Use
@@ -90,7 +90,7 @@
    """ Return the underyling object representing a :term:`Chameleon`
    text template using the template implied by the ``path`` argument.
    The ``path`` argument may be a package-relative path, an absolute
    path, or a :term:`resource specification`.
    path, or a :term:`asset specification`.
    .. warning:: This API is deprecated in :app:`Pyramid` 1.0.  Use
       the ``implementation()`` method of a template renderer retrieved via
@@ -109,7 +109,7 @@
def render_template(path, **kw):
    """ Render a :term:`Chameleon` text template using the template
    implied by the ``path`` argument.  The ``path`` argument may be a
    package-relative path, an absolute path, or a :term:`resource
    package-relative path, an absolute path, or a :term:`asset
    specification`.  The arguments in ``*kw`` are passed as top-level
    names to the template, and so may be used within the template
    itself.  Returns a string.
@@ -130,7 +130,7 @@
def render_template_to_response(path, **kw):
    """ Render a :term:`Chameleon` text template using the template
    implied by the ``path`` argument.  The ``path`` argument may be a
    package-relative path, an absolute path, or a :term:`resource
    package-relative path, an absolute path, or a :term:`asset
    specification`.  The arguments in ``*kw`` are passed as top-level
    names to the template, and so may be used within the template
    itself.  Returns a :term:`Response` object with the body as the
pyramid/chameleon_zpt.py
@@ -56,7 +56,7 @@
    """ Return a callable object which can be used to render a
    :term:`Chameleon` ZPT template using the template implied by the
    ``path`` argument.  The ``path`` argument may be a
    package-relative path, an absolute path, or a :term:`resource
    package-relative path, an absolute path, or a :term:`asset
    specification`.
    
    .. warning:: This API is deprecated in :app:`Pyramid` 1.0.  Use
@@ -75,7 +75,7 @@
    """ Return the underyling object representing a :term:`Chameleon`
    ZPT template using the template implied by the ``path`` argument.
    The ``path`` argument may be a package-relative path, an absolute
    path, or a :term:`resource specification`.
    path, or a :term:`asset specification`.
    .. warning:: This API is deprecated in :app:`Pyramid` 1.0.  Use
       the ``implementation()`` method of a template renderer retrieved via
@@ -94,7 +94,7 @@
def render_template(path, **kw):
    """ Render a :term:`Chameleon` ZPT template using the template
    implied by the ``path`` argument.  The ``path`` argument may be a
    package-relative path, an absolute path, or a :term:`resource
    package-relative path, an absolute path, or a :term:`asset
    specification`.  The arguments in ``*kw`` are passed as top-level
    names to the template, and so may be used within the template
    itself.  Returns a string.
@@ -115,7 +115,7 @@
def render_template_to_response(path, **kw):
    """ Render a :term:`Chameleon` ZPT template using the template
    implied by the ``path`` argument.  The ``path`` argument may be a
    package-relative path, an absolute path, or a :term:`resource
    package-relative path, an absolute path, or a :term:`asset
    specification`.  The arguments in ``*kw`` are passed as top-level
    names to the template, and so may be used within the template
    itself.  Returns a :term:`Response` object with the body as the
pyramid/config.py
@@ -73,8 +73,8 @@
from pyramid.registry import Registry
from pyramid.renderers import RendererHelper
from pyramid.request import route_request_iface
from pyramid.resource import PackageOverrides
from pyramid.resource import resolve_resource_spec
from pyramid.asset import PackageOverrides
from pyramid.asset import resolve_asset_spec
from pyramid.settings import Settings
from pyramid.static import StaticURLInfo
from pyramid.threadlocal import get_current_registry
@@ -327,14 +327,14 @@
        self.action(IAuthorizationPolicy, None)
            
    def _make_spec(self, path_or_spec):
        package, filename = resolve_resource_spec(path_or_spec,
                                                  self.package_name)
        package, filename = resolve_asset_spec(path_or_spec,
                                               self.package_name)
        if package is None:
            return filename # absolute filename
        return '%s:%s' % (package, filename)
    def _split_spec(self, path_or_spec):
        return resolve_resource_spec(path_or_spec, self.package_name)
        return resolve_asset_spec(path_or_spec, self.package_name)
    def _derive_view(self, view, permission=None, predicates=(),
                     attr=None, renderer=None, wrapper_viewname=None,
@@ -570,18 +570,20 @@
        this Configurator's constructor."""
        return self.name_resolver.maybe_resolve(dotted)
    def absolute_resource_spec(self, relative_spec):
        """ Resolve the potentially relative :term:`resource
    def absolute_asset_spec(self, relative_spec):
        """ Resolve the potentially relative :term:`asset
        specification` string passed as ``relative_spec`` into an
        absolute resource specification string and return the string.
        absolute asset specification string and return the string.
        Use the ``package`` of this configurator as the package to
        which the resource specification will be considered relative
        when generating an absolute resource specification.  If the
        which the asset specification will be considered relative
        when generating an absolute asset specification.  If the
        provided ``relative_spec`` argument is already absolute, or if
        the ``relative_spec`` is not a string, it is simply returned."""
        if not isinstance(relative_spec, basestring):
            return relative_spec
        return self._make_spec(relative_spec)
    absolute_resource_spec = absolute_asset_spec # b/w compat forever
    def setup_registry(self, settings=None, root_factory=None,
                       authentication_policy=None, authorization_policy=None,
@@ -848,7 +850,7 @@
    def load_zcml(self, spec='configure.zcml', lock=threading.Lock()):
        """ Load configuration from a :term:`ZCML` file into the
        current configuration state.  The ``spec`` argument is an
        absolute filename, a relative filename, or a :term:`resource
        absolute filename, a relative filename, or a :term:`asset
        specification`, defaulting to ``configure.zcml`` (relative to
        the package of the configurator's caller)."""
        package_name, filename = self._split_spec(spec)
@@ -1061,7 +1063,7 @@
        renderer
          This is either a single string term (e.g. ``json``) or a
          string implying a path or :term:`resource specification`
          string implying a path or :term:`asset specification`
          (e.g. ``templates/views.pt``) naming a :term:`renderer`
          implementation.  If the ``renderer`` value does not contain
          a dot ``.``, the specified string will be used to look up a
@@ -1086,9 +1088,9 @@
          current :term:`package` of the Configurator), a path can be
          absolute, starting with a slash on UNIX or a drive letter
          prefix on Windows.  The path can alternately be a
          :term:`resource specification` in the form
          :term:`asset specification` in the form
          ``some.dotted.package_name:relative/path``, making it
          possible to address template resources which live in a
          possible to address template assets which live in a
          separate package.
          The ``renderer`` attribute is optional.  If it is not
@@ -1472,11 +1474,10 @@
        factory
          A Python object (often a function or a class) or a
          :term:`dotted Python name` which refers to the same object
          that will generate a :app:`Pyramid` :term:`context`
          object when this route matches. For example,
          ``mypackage.models.MyFactoryClass``.  If this argument is
          A Python object (often a function or a class) or a :term:`dotted
          Python name` which refers to the same object that will generate a
          :app:`Pyramid` root resource object when this route matches. For
          example, ``mypackage.resources.MyFactory``.  If this argument is
          not specified, a default root factory will be used.
        traverse
@@ -1677,7 +1678,7 @@
        view_renderer
          This is either a single string term (e.g. ``json``) or a
          string implying a path or :term:`resource specification`
          string implying a path or :term:`asset specification`
          (e.g. ``templates/views.pt``).  If the renderer value is a
          single term (does not contain a dot ``.``), the specified
          term will be used to look up a renderer implementation, and
@@ -1858,20 +1859,20 @@
        self.action((IRendererFactory, name), None)
    @action_method
    def override_resource(self, to_override, override_with, _override=None):
        """ Add a :app:`Pyramid` resource override to the current
    def override_asset(self, to_override, override_with, _override=None):
        """ Add a :app:`Pyramid` asset override to the current
        configuration state.
        ``to_override`` is a :term:`resource specification` to the
        resource being overridden.
        ``to_override`` is a :term:`asset specification` to the
        asset being overridden.
        ``override_with`` is a :term:`resource specification` to the
        resource that is performing the override.
        ``override_with`` is a :term:`asset specification` to the
        asset that is performing the override.
        See :ref:`resources_chapter` for more
        information about resource overrides."""
        See :ref:`assets_chapter` for more
        information about asset overrides."""
        if to_override == override_with:
            raise ConfigurationError('You cannot override a resource with '
            raise ConfigurationError('You cannot override an asset with '
                                     'itself')
        package = to_override
@@ -1904,6 +1905,8 @@
            to_package = sys.modules[override_package]
            override(from_package, path, to_package, override_prefix)
        self.action(None, register)
    override_resource = override_asset # bw compat
    @action_method
    def set_forbidden_view(self, view=None, attr=None, renderer=None,
@@ -2094,7 +2097,7 @@
        """ Add one or more :term:`translation directory` paths to the
        current configuration state.  The ``specs`` argument is a
        sequence that may contain absolute directory paths
        (e.g. ``/usr/share/locale``) or :term:`resource specification`
        (e.g. ``/usr/share/locale``) or :term:`asset specification`
        names naming a directory path (e.g. ``some.package:locale``)
        or a combination of the two.
@@ -2143,7 +2146,7 @@
    @action_method
    def add_static_view(self, name, path, **kw):
        """ Add a view used to render static resources such as images
        """ Add a view used to render static assets such as images
        and CSS files.
        The ``name`` argument is a string representing :term:`view
@@ -2152,40 +2155,39 @@
        The ``path`` argument is the path on disk where the static
        files reside.  This can be an absolute path, a
        package-relative path, or a :term:`resource specification`.
        package-relative path, or a :term:`asset specification`.
        The ``cache_max_age`` keyword argument is input to set the
        ``Expires`` and ``Cache-Control`` headers for static resources
        ``Expires`` and ``Cache-Control`` headers for static assets
        served.  Note that this argument has no effect when the
        ``name`` is a *url prefix*.  By default, this argument is
        ``None``, meaning that no particular Expires or Cache-Control
        headers are set in the response.
        The ``permission`` keyword argument is used to specify the
        :term:`permission` required by a user to execute the static
        view.  By default, it is the string
        ``__no_permission_required__``.  The
        ``__no_permission_required__`` string is a special sentinel
        which indicates that, even if a :term:`default permission`
        exists for the current application, the static view should be
        renderered to completely anonymous users.  This default value
        is permissive because, in most web apps, static resources
        seldom need protection from viewing.
        :term:`permission` required by a user to execute the static view.  By
        default, it is the string ``__no_permission_required__``.  The
        ``__no_permission_required__`` string is a special sentinel which
        indicates that, even if a :term:`default permission` exists for the
        current application, the static view should be renderered to
        completely anonymous users.  This default value is permissive
        because, in most web apps, static assets seldom need protection from
        viewing.
        *Usage*
        The ``add_static_view`` function is typically used in
        conjunction with the :func:`pyramid.url.static_url`
        function.  ``add_static_view`` adds a view which renders a
        static resource when some URL is visited;
        static asset when some URL is visited;
        :func:`pyramid.url.static_url` generates a URL to that
        resource.
        asset.
        The ``name`` argument to ``add_static_view`` is usually a
        :term:`view name`.  When this is the case, the
        :func:`pyramid.url.static_url` API will generate a URL
        which points to a Pyramid view, which will serve up a set of
        resources that live in the package itself. For example:
        assets that live in the package itself. For example:
        .. code-block:: python
@@ -2208,7 +2210,7 @@
        be served.
        ``add_static_view`` can alternately be used with a ``name``
        argument which is a *URL*, causing static resources to be
        argument which is a *URL*, causing static assets to be
        served from an external webserver.  This happens when the
        ``name`` argument is a URL (detected as any string with a
        slash in it).  In this mode, the ``name`` is used as the URL
@@ -2237,7 +2239,7 @@
        listening on ``example.com`` must be itself configured to
        respond properly to such a request.
        See :ref:`static_resources_section` for more information.
        See :ref:`static_assets_section` for more information.
        """
        spec = self._make_spec(path)
        info = self.registry.queryUtility(IStaticURLInfo)
@@ -2281,18 +2283,18 @@
        self.registry.registerUtility(policy, IAuthorizationPolicy)
        self.registry.registerUtility(policy, IAuthenticationPolicy)
    def testing_models(self, models):
    def testing_resources(self, resources):
        """Unit/integration testing helper: registers a dictionary of
        :term:`model` objects that can be resolved via the
        :func:`pyramid.traversal.find_model` API.
        :term:`resource` objects that can be resolved via the
        :func:`pyramid.traversal.find_resource` API.
        The :func:`pyramid.traversal.find_model` API is called with
        The :func:`pyramid.traversal.find_resource` API is called with
        a path as one of its arguments.  If the dictionary you
        register when calling this method contains that path as a
        string key (e.g. ``/foo/bar`` or ``foo/bar``), the
        corresponding value will be returned to ``find_model`` (and
        corresponding value will be returned to ``find_resource`` (and
        thus to your code) when
        :func:`pyramid.traversal.find_model` is called with an
        :func:`pyramid.traversal.find_resource` is called with an
        equivalent path string or tuple.
        """
        class DummyTraverserFactory:
@@ -2301,14 +2303,16 @@
            def __call__(self, request):
                path = request['PATH_INFO']
                ob = models[path]
                ob = resources[path]
                traversed = traversal_path(path)
                return {'context':ob, 'view_name':'','subpath':(),
                        'traversed':traversed, 'virtual_root':ob,
                        'virtual_root_path':(), 'root':ob}
        self.registry.registerAdapter(DummyTraverserFactory, (Interface,),
                                      ITraverser)
        return models
        return resources
    testing_models = testing_resources # b/w compat
    @action_method
    def testing_add_subscriber(self, event_iface=None):
@@ -2339,7 +2343,7 @@
    def testing_add_renderer(self, path, renderer=None):
        """Unit/integration testing helper: register a renderer at
        ``path`` (usually a relative filename ala ``templates/foo.pt``
        or a resource specification) and return the renderer object.
        or an asset specification) and return the renderer object.
        If the ``renderer`` argument is None, a 'dummy' renderer will
        be used.  This function is useful when testing code that calls
        the :func:`pyramid.renderers.render` function or
@@ -2507,7 +2511,7 @@
    if traverse is not None:
        # ``traverse`` can only be used as a *route* "predicate"; it
        # adds 'traverse' to the matchdict if it's specified in the
        # routing args.  This causes the ModelGraphTraverser to use
        # routing args.  This causes the ResourceTreeTraverser to use
        # the resolved traverse pattern as the traversal path.
        from pyramid.urldispatch import _compile_route
        _, tgenerate = _compile_route(traverse)
pyramid/includes/meta.zcml
@@ -41,9 +41,15 @@
        />
    <meta:directive
        name="asset"
        schema="pyramid.zcml.IAssetDirective"
        handler="pyramid.zcml.asset"
        />
    <meta:directive
        name="resource"
        schema="pyramid.zcml.IResourceDirective"
        handler="pyramid.zcml.resource"
        schema="pyramid.zcml.IAssetDirective"
        handler="pyramid.zcml.asset"
        />
    <meta:directive
pyramid/interfaces.py
@@ -163,7 +163,7 @@
        """ Return a set of principal identifiers allowed by the permission """
class IStaticURLInfo(Interface):
    """ A policy for generating URLs to static resources """
    """ A policy for generating URLs to static assets """
    def add(name, spec, **extra):
        """ Add a new static info registration """
pyramid/location.py
@@ -12,29 +12,29 @@
#
##############################################################################
def inside(model1, model2):
    """Is ``model1`` 'inside' ``model2``?  Return ``True`` if so, else
def inside(resource1, resource2):
    """Is ``resource1`` 'inside' ``resource2``?  Return ``True`` if so, else
    ``False``.
    ``model1`` is 'inside' ``model2`` if ``model2`` is a
    :term:`lineage` ancestor of ``model1``.  It is a lineage ancestor
    ``resource1`` is 'inside' ``resource2`` if ``resource2`` is a
    :term:`lineage` ancestor of ``resource1``.  It is a lineage ancestor
    if its parent (or one of its parent's parents, etc.) is an
    ancestor.
    """
    while model1 is not None:
        if model1 is model2:
    while resource1 is not None:
        if resource1 is resource2:
            return True
        model1 = model1.__parent__
        resource1 = resource1.__parent__
    return False
def lineage(model):
def lineage(resource):
    """
    Return a generator representing the :term:`lineage` of the
    :term:`model` object implied by the ``model`` argument.  The
    generator first returns ``model`` unconditionally.  Then, if
    ``model`` supplies a ``__parent__`` attribute, return the object
    represented by ``model.__parent__``.  If *that* object has a
    :term:`resource` object implied by the ``resource`` argument.  The
    generator first returns ``resource`` unconditionally.  Then, if
    ``resource`` supplies a ``__parent__`` attribute, return the object
    represented by ``resource.__parent__``.  If *that* object has a
    ``__parent__`` attribute, return that object's parent, and so on,
    until the object being inspected either has no ``__parent__``
    attribute or which has a ``__parent__`` attribute of ``None``.
@@ -50,8 +50,8 @@
      list(lineage(thing2))
      [ <Thing object at thing2>, <Thing object at thing1> ]
    """
    while model is not None:
        yield model
    while resource is not None:
        yield resource
        # The common case is that the AttributeError exception below
        # is exceptional as long as the developer is a "good citizen"
        # who has a root object with a __parent__ of None.  Using an
@@ -60,7 +60,7 @@
        # called in any non-trivial application over and over again to
        # generate URLs and paths.
        try:
            model = model.__parent__
            resource = resource.__parent__
        except AttributeError:
            model = None
            resource = None
pyramid/mako_templating.py
@@ -4,10 +4,10 @@
from zope.interface import implements
from zope.interface import Interface
from pyramid.interfaces import ITemplateRenderer
from pyramid.asset import resolve_asset_spec
from pyramid.asset import abspath_from_asset_spec
from pyramid.exceptions import ConfigurationError
from pyramid.resource import resolve_resource_spec
from pyramid.resource import abspath_from_resource_spec
from pyramid.interfaces import ITemplateRenderer
from pyramid.settings import asbool
from pyramid.util import DottedNameResolver
@@ -18,12 +18,11 @@
    pass
class PkgResourceTemplateLookup(TemplateLookup):
    """TemplateLookup subclass that handles resource specification
    uri's"""
    """TemplateLookup subclass that handles asset specification URIs"""
    def adjust_uri(self, uri, relativeto):
        """Called from within a Mako template, avoids adjusting the
        uri if it looks like a resource specification"""
        # Don't adjust pkg resource spec names
        uri if it looks like an asset specification"""
        # Don't adjust asset spec names
        if ':' in uri:
            return uri
        return TemplateLookup.adjust_uri(self, uri, relativeto)
@@ -33,7 +32,7 @@
        for it
        
        In addition to the basic filesystem lookup, this subclass will
        use pkg_resource to load a file using the resource
        use pkg_resource to load a file using the asset
        specification syntax.
        
        """
@@ -45,8 +44,8 @@
                else:
                    return self._collection[uri]
            except KeyError:
                pname, path = resolve_resource_spec(uri)
                srcfile = abspath_from_resource_spec(path, pname)
                pname, path = resolve_asset_spec(uri)
                srcfile = abspath_from_asset_spec(path, pname)
                if os.path.isfile(srcfile):
                    return self._load(srcfile, uri)
                raise exceptions.TopLevelLookupException(
@@ -75,9 +74,9 @@
                'Mako template used without a ``mako.directories`` setting')
        if not hasattr(directories, '__iter__'):
            directories = filter(None, directories.splitlines())
        directories = [ abspath_from_resource_spec(d) for d in directories ]
        directories = [ abspath_from_asset_spec(d) for d in directories ]
        if module_directory is not None:
            module_directory = abspath_from_resource_spec(module_directory)
            module_directory = abspath_from_asset_spec(module_directory)
        if error_handler is not None:
            dotted = DottedNameResolver(info.package)
            error_handler = dotted.maybe_resolve(error_handler)
pyramid/paster_templates/starter/+package+/__init__.py_tmpl
@@ -1,12 +1,12 @@
from pyramid.config import Configurator
from {{package}}.models import get_root
from {{package}}.resources import Root
def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    config = Configurator(root_factory=get_root, settings=settings)
    config = Configurator(root_factory=Root, settings=settings)
    config.add_view('{{package}}.views.my_view',
                    context='{{package}}.models.MyModel',
                    context='{{package}}:resources.Root"
                    renderer='{{package}}:templates/mytemplate.pt')
    config.add_static_view('static', '{{package}}:static')
    return config.make_wsgi_app()
pyramid/paster_templates/starter/+package+/models.py
File was deleted
pyramid/paster_templates/starter/+package+/resources.py
New file
@@ -0,0 +1,3 @@
class Root(object):
    def __init__(self, request):
        self.request = request
pyramid/paster_templates/starter_zcml/+package+/__init__.py_tmpl
@@ -1,11 +1,11 @@
from pyramid.config import Configurator
from {{package}}.models import get_root
from {{package}}.models import Root
def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    zcml_file = settings.get('configure_zcml', 'configure.zcml')
    config = Configurator(root_factory=get_root, settings=settings)
    config = Configurator(root_factory=Root, settings=settings)
    config.load_zcml(zcml_file)
    return config.make_wsgi_app()
pyramid/paster_templates/starter_zcml/+package+/configure.zcml
@@ -4,7 +4,7 @@
  <include package="pyramid.includes" />
  <view
     context=".models.MyModel"
     context=".resources.Root"
     view=".views.my_view"
     renderer="templates/mytemplate.pt"
     />
pyramid/paster_templates/starter_zcml/+package+/models.py
File was deleted
pyramid/paster_templates/starter_zcml/+package+/resources.py
New file
@@ -0,0 +1,3 @@
class Root(object):
    def __init__(self, request):
        self.request = request
pyramid/renderers.py
@@ -12,13 +12,13 @@
from pyramid.interfaces import ITemplateRenderer
from pyramid.interfaces import IRendererInfo
from pyramid.asset import asset_spec_from_abspath
from pyramid.compat import json
from pyramid.decorator import reify
from pyramid.events import BeforeRender
from pyramid.path import caller_package
from pyramid.path import package_path
from pyramid.response import Response
from pyramid.resource import resource_spec_from_abspath
from pyramid.threadlocal import get_current_registry
# API
@@ -31,14 +31,14 @@
    If the renderer name refers to a file on disk (such as when the
    renderer is a template), it's usually best to supply the name as a
    :term:`resource specification`
    :term:`asset specification`
    (e.g. ``packagename:path/to/template.pt``).
    You may supply a relative resource spec as ``renderer_name``.  If
    You may supply a relative asset spec as ``renderer_name``.  If
    the ``package`` argument is supplied, a relative renderer path
    will be converted to an absolute resource specification by
    will be converted to an absolute asset specification by
    combining the package supplied as ``package`` with the relative
    resource specification supplied as ``renderer_name``.  If you do
    asset specification supplied as ``renderer_name``.  If you do
    not supply a ``package`` (or ``package`` is ``None``) the package
    name of the *caller* of this function will be used as the package.
@@ -75,13 +75,13 @@
    If the renderer name refers to a file on disk (such as when the
    renderer is a template), it's usually best to supply the name as a
    :term:`resource specification`.
    :term:`asset specification`.
    You may supply a relative resource spec as ``renderer_name``.  If
    You may supply a relative asset spec as ``renderer_name``.  If
    the ``package`` argument is supplied, a relative renderer name
    will be converted to an absolute resource specification by
    will be converted to an absolute asset specification by
    combining the package supplied as ``package`` with the relative
    resource specification supplied as ``renderer_name``.  If you do
    asset specification supplied as ``renderer_name``.  If you do
    not supply a ``package`` (or ``package`` is ``None``) the package
    name of the *caller* of this function will be used as the package.
@@ -114,11 +114,11 @@
    """ Return the renderer object for the renderer named as
    ``renderer_name``.
    You may supply a relative resource spec as ``renderer_name``.  If
    You may supply a relative asset spec as ``renderer_name``.  If
    the ``package`` argument is supplied, a relative renderer name
    will be converted to an absolute resource specification by
    will be converted to an absolute asset specification by
    combining the package supplied as ``package`` with the relative
    resource specification supplied as ``renderer_name``.  If you do
    asset specification supplied as ``renderer_name``.  If you do
    not supply a ``package`` (or ``package`` is ``None``) the package
    name of the *caller* of this function will be used as the package.
    """
@@ -164,11 +164,11 @@
        isabs = os.path.isabs(name)
        if (not isabs) and (not ':' in name) and package:
            # relative resource spec
            # relative asset spec
            if not isabs:
                pp = package_path(package)
                spec = os.path.join(pp, spec)
            spec = resource_spec_from_abspath(spec, package)
            spec = asset_spec_from_abspath(spec, package)
        return spec
    @property # wait until completely necessary to look up translator
@@ -204,7 +204,7 @@
                finally:
                    self.lock.release()
        else:
            # spec is a package:relpath resource spec
            # spec is a package:relpath asset spec
            renderer = registry.queryUtility(ITemplateRenderer, name=spec)
            if renderer is None:
                try:
@@ -218,10 +218,10 @@
                                                          filename)
                if not pkg_resources.resource_exists(package_name, filename):
                    raise ValueError(
                        'Missing template resource: %s (%s)' % (spec, abspath))
                        'Missing template asset: %s (%s)' % (spec, abspath))
                renderer = self.impl(abspath, self)
                settings = info.settings or {}
                if not settings.get('reload_resources'):
                if not settings.get('reload_assets'):
                    # cache the template
                    self.lock.acquire()
                    try:
pyramid/request.py
@@ -8,7 +8,7 @@
from pyramid.exceptions import ConfigurationError
from pyramid.decorator import reify
from pyramid.url import model_url
from pyramid.url import resource_url
from pyramid.url import route_url
from pyramid.url import static_url
from pyramid.url import route_path
@@ -195,39 +195,45 @@
        """
        return route_url(route_name, self, *elements, **kw)
    def model_url(self, model, *elements, **kw):
        """ Return the URL for the model object named ``model``, using
        ``*elements`` and ``**kw`` as modifiers.
    def resource_url(self, resource, *elements, **kw):
        """ Return the URL for the :term:`resource` object named ``resource``,
        using ``*elements`` and ``**kw`` as modifiers.
        This is a convenience method.  The result of calling
        :meth:`pyramid.request.Request.model_url` is the same as calling
        :func:`pyramid.url.model_url` with an explicit ``request`` parameter.
        :meth:`pyramid.request.Request.resource_url` is the same as calling
        :func:`pyramid.url.resource_url` with an explicit ``request`` parameter.
        The :meth:`pyramid.request.Request.model_url` method calls the
        :func:`pyramid.url.model_url` function using the Request object as
        the ``request`` argument.  The ``model``, ``*elements`` and ``*kw``
        arguments passed to :meth:`pyramid.request.Request.model_url` are
        passed through to :func:`pyramid.url.model_url` unchanged and its
        The :meth:`pyramid.request.Request.resource_url` method calls the
        :func:`pyramid.url.resource_url` function using the Request object as
        the ``request`` argument.  The ``resource``, ``*elements`` and ``*kw``
        arguments passed to :meth:`pyramid.request.Request.resource_url` are
        passed through to :func:`pyramid.url.resource_url` unchanged and its
        result is returned.
        This call to :meth:`pyramid.request.Request.model_url`::
        This call to :meth:`pyramid.request.Request.resource_url`::
          request.model_url(mymodel)
          request.resource_url(myresource)
        Is completely equivalent to calling :func:`pyramid.url.model_url`
        Is completely equivalent to calling :func:`pyramid.url.resource_url`
        like this::
          from pyramid.url import model_url
          model_url(model, request)
          from pyramid.url import resource_url
          resource_url(resource, request)
        .. note:: For backwards compatibility purposes, this method can also
                  be called as :meth:`pyramid.request.Request.model_url`.
        """
        return model_url(model, self, *elements, **kw)
        return resource_url(resource, self, *elements, **kw)
    model_url = resource_url # b/w compat forever
    def static_url(self, path, **kw):
        """ Generates a fully qualified URL for a static :term:`resource`.
        The resource must live within a location defined via the
        """
        Generates a fully qualified URL for a static :term:`asset`.  The
        asset must live within a location defined via the
        :meth:`pyramid.config.Configurator.add_static_view`
        :term:`configuration declaration` or the ``<static>`` ZCML
        directive (see :ref:`static_resources_section`).
        :term:`configuration declaration` or the ``<static>`` ZCML directive
        (see :ref:`static_assets_section`).
        This is a convenience method.  The result of calling
        :meth:`pyramid.request.Request.static_url` is the same as calling
pyramid/resource.py
@@ -1,207 +1,5 @@
import os
import pkg_resources
from zope.interface import implements
from pyramid.interfaces import IPackageOverrides
from pyramid.path import package_path
from pyramid.path import package_name
from pyramid.threadlocal import get_current_registry
class OverrideProvider(pkg_resources.DefaultProvider):
    def __init__(self, module):
        pkg_resources.DefaultProvider.__init__(self, module)
        self.module_name = module.__name__
    def _get_overrides(self):
        reg = get_current_registry()
        overrides = reg.queryUtility(IPackageOverrides, self.module_name)
        return overrides
    def get_resource_filename(self, manager, resource_name):
        """ Return a true filesystem path for resource_name,
        co-ordinating the extraction with manager, if the resource
        must be unpacked to the filesystem.
        """
        overrides = self._get_overrides()
        if overrides is not None:
            filename = overrides.get_filename(resource_name)
            if filename is not None:
                return filename
        return pkg_resources.DefaultProvider.get_resource_filename(
            self, manager, resource_name)
    def get_resource_stream(self, manager, resource_name):
        """ Return a readable file-like object for resource_name."""
        overrides = self._get_overrides()
        if overrides is not None:
            stream =  overrides.get_stream(resource_name)
            if stream is not None:
                return stream
        return pkg_resources.DefaultProvider.get_resource_stream(
            self, manager, resource_name)
    def get_resource_string(self, manager, resource_name):
        """ Return a string containing the contents of resource_name."""
        overrides = self._get_overrides()
        if overrides is not None:
            string = overrides.get_string(resource_name)
            if string is not None:
                return string
        return pkg_resources.DefaultProvider.get_resource_string(
            self, manager, resource_name)
    def has_resource(self, resource_name):
        overrides = self._get_overrides()
        if overrides is not None:
            result = overrides.has_resource(resource_name)
            if result is not None:
                return result
        return pkg_resources.DefaultProvider.has_resource(
            self, resource_name)
    def resource_isdir(self, resource_name):
        overrides = self._get_overrides()
        if overrides is not None:
            result = overrides.isdir(resource_name)
            if result is not None:
                return result
        return pkg_resources.DefaultProvider.resource_isdir(
            self, resource_name)
    def resource_listdir(self, resource_name):
        overrides = self._get_overrides()
        if overrides is not None:
            result = overrides.listdir(resource_name)
            if result is not None:
                return result
        return pkg_resources.DefaultProvider.resource_listdir(
            self, resource_name)
class PackageOverrides:
    implements(IPackageOverrides)
    # pkg_resources arg in kw args below for testing
    def __init__(self, package, pkg_resources=pkg_resources):
        if hasattr(package, '__loader__') and not isinstance(package.__loader__,
                                                             self.__class__):
            raise TypeError('Package %s already has a non-%s __loader__ '
                            '(probably a module in a zipped egg)' %
                            (package, self.__class__))
        # We register ourselves as a __loader__ *only* to support the
        # setuptools _find_adapter adapter lookup; this class doesn't
        # actually support the PEP 302 loader "API".  This is
        # excusable due to the following statement in the spec:
        # ... Loader objects are not
        # required to offer any useful functionality (any such functionality,
        # such as the zipimport get_data() method mentioned above, is
        # optional)...
        # A __loader__ attribute is basically metadata, and setuptools
        # uses it as such.
        package.__loader__ = self
        # we call register_loader_type for every instantiation of this
        # class; that's OK, it's idempotent to do it more than once.
        pkg_resources.register_loader_type(self.__class__, OverrideProvider)
        self.overrides = []
        self.overridden_package_name = package.__name__
    def insert(self, path, package, prefix):
        if not path or path.endswith('/'):
            override = DirectoryOverride(path, package, prefix)
        else:
            override = FileOverride(path, package, prefix)
        self.overrides.insert(0, override)
        return override
    def search_path(self, resource_name):
        for override in self.overrides:
            o = override(resource_name)
            if o is not None:
                package, name = o
                yield package, name
    def get_filename(self, resource_name):
        for package, rname in self.search_path(resource_name):
            if pkg_resources.resource_exists(package, rname):
                return pkg_resources.resource_filename(package, rname)
    def get_stream(self, resource_name):
        for package, rname in self.search_path(resource_name):
            if pkg_resources.resource_exists(package, rname):
                return pkg_resources.resource_stream(package, rname)
    def get_string(self, resource_name):
        for package, rname in self.search_path(resource_name):
            if pkg_resources.resource_exists(package, rname):
                return pkg_resources.resource_string(package, rname)
    def has_resource(self, resource_name):
        for package, rname in self.search_path(resource_name):
            if pkg_resources.resource_exists(package, rname):
                return True
    def isdir(self, resource_name):
        for package, rname in self.search_path(resource_name):
            if pkg_resources.resource_exists(package, rname):
                return pkg_resources.resource_isdir(package, rname)
    def listdir(self, resource_name):
        for package, rname in self.search_path(resource_name):
            if pkg_resources.resource_exists(package, rname):
                return pkg_resources.resource_listdir(package, rname)
class DirectoryOverride:
    def __init__(self, path, package, prefix):
        self.path = path
        self.package = package
        self.prefix = prefix
        self.pathlen = len(self.path)
    def __call__(self, resource_name):
        if resource_name.startswith(self.path):
            name = '%s%s' % (self.prefix, resource_name[self.pathlen:])
            return self.package, name
class FileOverride:
    def __init__(self, path, package, prefix):
        self.path = path
        self.package = package
        self.prefix = prefix
    def __call__(self, resource_name):
        if resource_name == self.path:
            return self.package, self.prefix
def resolve_resource_spec(spec, pname='__main__'):
    if pname and not isinstance(pname, basestring):
        pname = pname.__name__ # as package
    if os.path.isabs(spec):
        return None, spec
    filename = spec
    if ':' in spec:
        pname, filename = spec.split(':', 1)
    elif pname is None:
        pname, filename = None, spec
    return pname, filename
def resource_spec_from_abspath(abspath, package):
    """ Try to convert an absolute path to a resource in a package to
    a resource specification if possible; otherwise return the
    absolute path.  """
    if getattr(package, '__name__', None) == '__main__':
        return abspath
    pp = package_path(package) + os.path.sep
    if abspath.startswith(pp):
        relpath = abspath[len(pp):]
        return '%s:%s' % (package_name(package),
                          relpath.replace(os.path.sep, '/'))
    return abspath
def abspath_from_resource_spec(spec, pname='__main__'):
    if pname is None:
        return spec
    pname, filename = resolve_resource_spec(spec, pname)
    if pname is None:
        return filename
    return pkg_resources.resource_filename(pname, filename)
""" Backwards compatibility shim module (forever). """
from asset import * # b/w compat
resolve_resource_spec = resolve_asset_spec
resource_spec_from_abspath = asset_spec_from_abspath
abspath_from_resource_spec = abspath_from_asset_spec
pyramid/router.py
@@ -22,7 +22,7 @@
from pyramid.request import Request
from pyramid.threadlocal import manager
from pyramid.traversal import DefaultRootFactory
from pyramid.traversal import ModelGraphTraverser
from pyramid.traversal import ResourceTreeTraverser
from pyramid.config import Configurator # b/c
@@ -127,7 +127,7 @@
                    # find a context
                    traverser = adapters.queryAdapter(root, ITraverser)
                    if traverser is None:
                        traverser = ModelGraphTraverser(root)
                        traverser = ResourceTreeTraverser(root)
                    tdict = traverser(request)
                    context, view_name, subpath, traversed, vroot, vroot_path =(
                        tdict['context'], tdict['view_name'], tdict['subpath'],
@@ -239,13 +239,13 @@
    ``filename`` passed or the value in the ``options`` dictionary
    named ``configure_zcml`` must be a) absolute pathname to a
    :term:`ZCML` file that represents the application's configuration
    *or* b) a :term:`resource specification` to a :term:`ZCML` file in
    *or* b) a :term:`asset specification` to a :term:`ZCML` file in
    the form ``dotted.package.name:relative/file/path.zcml``.
    ``filename`` is the filesystem path to a ZCML file (optionally
    relative to the package path) that should be parsed to create the
    application registry.  It defaults to ``configure.zcml``.  It can
    also be a ;term:`resource specification` in the form
    also be a ;term:`asset specification` in the form
    ``dotted_package_name:relative/file/path.zcml``. Note that if any
    value for ``configure_zcml`` is passed within the ``settings``
    dictionary, the value passed as ``filename`` will be ignored,
pyramid/security.py
@@ -26,7 +26,7 @@
def has_permission(permission, context, request):
    """ Provided a permission (a string or unicode object), a context
    (a :term:`model` instance) and a request object, return an
    (a :term:`resource` instance) and a request object, return an
    instance of :data:`pyramid.security.Allowed` if the permission
    is granted in this context to the user implied by the
    request. Return an instance of :mod:`pyramid.security.Denied`
@@ -81,7 +81,7 @@
    return policy.effective_principals(request)
def principals_allowed_by_permission(context, permission):
    """ Provided a ``context`` (a model object), and a ``permission``
    """ Provided a ``context`` (a resource object), and a ``permission``
    (a string or unicode object), if a :term:`authorization policy` is
    in effect, return a sequence of :term:`principal` ids that possess
    the permission in the ``context``.  If no authorization policy is
pyramid/settings.py
@@ -38,9 +38,14 @@
        config_reload_templates = self.get('reload_templates', '')
        eff_reload_templates = asbool(eget('BFG_RELOAD_TEMPLATES',
                                           config_reload_templates))
        config_reload_assets = self.get('reload_assets', '')
        config_reload_resources = self.get('reload_resources', '')
        eff_reload_resources = asbool(eget('BFG_RELOAD_RESOURCES',
                                           config_reload_resources))
        reload_assets = asbool(eget('BFG_RELOAD_ASSETS',
                                    config_reload_assets))
        reload_resources = asbool(eget('BFG_RELOAD_RESOURCES',
                                    config_reload_resources))
        # reload_resources is an older alias for reload_assets
        eff_reload_assets = reload_assets or reload_resources
        configure_zcml = self.get('configure_zcml', '')
        eff_configure_zcml = eget('BFG_CONFIGURE_ZCML', configure_zcml)
        locale_name = self.get('default_locale_name', 'en')
@@ -52,7 +57,8 @@
            'debug_routematch': eff_debug_all or eff_debug_routematch,
            'debug_templates': eff_debug_all or eff_debug_templates,
            'reload_templates': eff_reload_all or eff_reload_templates,
            'reload_resources':eff_reload_all or eff_reload_resources,
            'reload_resources':eff_reload_all or eff_reload_assets,
            'reload_assets':eff_reload_all or eff_reload_assets,
            'configure_zcml':eff_configure_zcml,
            'default_locale_name':eff_locale_name,
            }
pyramid/static.py
@@ -10,9 +10,9 @@
from zope.interface import implements
from pyramid.asset import resolve_asset_spec
from pyramid.interfaces import IStaticURLInfo
from pyramid.path import caller_package
from pyramid.resource import resolve_resource_spec
from pyramid.url import route_url
class PackageURLParser(StaticURLParser):
@@ -108,7 +108,7 @@
    def add(self, name, spec, **extra):
        # This feature only allows for the serving of a directory and
        # the files contained within, not of a single resource;
        # the files contained within, not of a single asset;
        # appending a slash here if the spec doesn't have one is
        # required for proper prefix matching done in ``generate``
        # (``subpath = path[len(spec):]``).
@@ -162,7 +162,7 @@
    path into a response.
    You may pass an absolute or relative filesystem path or a
    :term:`resource specification` representing the directory
    :term:`asset specification` representing the directory
    containing static files as the ``root_dir`` argument to this
    class' constructor.
@@ -179,13 +179,13 @@
    five minutes).
    .. note:: If the ``root_dir`` is relative to a :term:`package`, or
         is a :term:`resource specification` the :app:`Pyramid`
         ``resource`` ZCML directive or
         is a :term:`asset specification` the :app:`Pyramid`
         ``asset`` ZCML directive or
         :class:`pyramid.config.Configurator` method can be
         used to override resources within the named ``root_dir``
         used to override assets within the named ``root_dir``
         package-relative directory.  However, if the ``root_dir`` is
         absolute, the ``resource`` directive will not be able to
         override the resources it contains.  """
         absolute, configuration will not be able to
         override the assets it contains.  """
    
    def __init__(self, root_dir, cache_max_age=3600, package_name=None):
        # package_name is for bw compat; it is preferred to pass in a
@@ -193,7 +193,7 @@
        # (e.g. ``anotherpackage:foo/static``).
        caller_package_name = caller_package().__name__
        package_name = package_name or caller_package_name
        package_name, root_dir = resolve_resource_spec(root_dir, package_name)
        package_name, root_dir = resolve_asset_spec(root_dir, package_name)
        if package_name is None:
            app = StaticURLParser(root_dir, cache_max_age=cache_max_age)
        else:
pyramid/testing.py
@@ -62,28 +62,33 @@
    config.commit()
    return result
def registerModels(models):
    """ Registers a dictionary of :term:`model` objects that can be
    resolved via the :func:`pyramid.traversal.find_model` API.
def registerResources(resources):
    """ Registers a dictionary of :term:`resource` objects that can be
    resolved via the :func:`pyramid.traversal.find_resource` API.
    The :func:`pyramid.traversal.find_model` API is called with a
    The :func:`pyramid.traversal.find_resource` API is called with a
    path as one of its arguments.  If the dictionary you register when
    calling this method contains that path as a string key
    (e.g. ``/foo/bar`` or ``foo/bar``), the corresponding value will
    be returned to ``find_model`` (and thus to your code) when
    :func:`pyramid.traversal.find_model` is called with an
    be returned to ``find_resource`` (and thus to your code) when
    :func:`pyramid.traversal.find_resource` is called with an
    equivalent path string or tuple.
    .. warning:: This API is deprecated as of :app:`Pyramid` 1.0.
       Instead use the
       :meth:`pyramid.config.Configurator.testing_models`
       :meth:`pyramid.config.Configurator.testing_resources`
       method in your unit and integration tests.
    .. note:: For ancient backward compatibility purposes, this API can also
       be accessed as :func:`pyramid.testing.registerModels`.
    """
    registry = get_current_registry()
    config = Configurator(registry=registry)
    result = config.testing_models(models)
    result = config.testing_resources(resources)
    config.commit()
    return result
registerModels = registerResources
def registerEventListener(event_iface=None):
    """ Registers an :term:`event` listener (aka :term:`subscriber`)
@@ -412,19 +417,19 @@
                    v, k, myval))
        return True
class DummyModel:
    """ A dummy :app:`Pyramid` :term:`model` object."""
class DummyResource:
    """ A dummy :app:`Pyramid` :term:`resource` object."""
    def __init__(self, __name__=None, __parent__=None, __provides__=None,
                 **kw):
        """ The model's ``__name__`` attribute will be set to the
        value of the ``__name__`` argument, and the model's
        """ The resource's ``__name__`` attribute will be set to the
        value of the ``__name__`` argument, and the resource's
        ``__parent__`` attribute will be set to the value of the
        ``__parent__`` argument.  If ``__provides__`` is specified, it
        should be an interface object or tuple of interface objects
        that will be attached to the resulting model via
        that will be attached to the resulting resource via
        :func:`zope.interface.alsoProvides`. Any extra keywords passed
        in the ``kw`` argumnent will be set as direct attributes of
        the model object."""
        the resource object."""
        self.__name__ = __name__
        self.__parent__ = __parent__
        if __provides__ is not None:
@@ -436,9 +441,9 @@
    def __setitem__(self, name, val):
        """ When the ``__setitem__`` method is called, the object
        passed in as ``val`` will be decorated with a ``__parent__``
        attribute pointing at the dummy model and a ``__name__``
        attribute pointing at the dummy resource and a ``__name__``
        attribute that is the value of ``name``.  The value will then
        be returned when dummy model's ``__getitem__`` is called with
        be returned when dummy resource's ``__getitem__`` is called with
        the name ``name```."""
        val.__name__ = name
        val.__parent__ = self
@@ -479,12 +484,12 @@
        return name in self.subs
    def clone(self, __name__=_marker, __parent__=_marker, **kw):
        """ Create a clone of the model object.  If ``__name__`` or
        """ Create a clone of the resource object.  If ``__name__`` or
        ``__parent__`` arguments are passed, use these values to
        override the existing ``__name__`` or ``__parent__`` of the
        model.  If any extra keyword args are passed in via the ``kw``
        resource.  If any extra keyword args are passed in via the ``kw``
        argument, use these keywords to add to or override existing
        model keywords (attributes)."""
        resource keywords (attributes)."""
        oldkw = self.kw.copy()
        oldkw.update(kw)
        inst = self.__class__(self.__name__, self.__parent__, **oldkw)
@@ -494,6 +499,8 @@
        if __parent__ is not _marker:
            inst.__parent__ = __parent__
        return inst
DummyModel = DummyResource # b/w compat (forever)
class DummyRequest(object):
    """ A dummy request object (imitates a :term:`request` object).
@@ -509,6 +516,9 @@
    Extra keyword arguments are assigned as attributes of the request
    itself.
    .. note:: For backwards compatibility purposes, this class can also be
       imported as :class:`pyramid.testing.DummyModel`.
    """
    implements(IRequest)
    method = 'GET'
@@ -571,7 +581,7 @@
    which directly or indirectly uses:
    - any of the ``register*`` functions in :mod:`pyramid.testing`
      (such as :func:`pyramid.testing.registerModels`)
      (such as :func:`pyramid.testing.registerResources`)
    - any method of the :class:`pyramid.config.Configurator`
      object returned by this function.
pyramid/tests/test_asset.py
File was renamed from pyramid/tests/test_resource.py
@@ -9,7 +9,7 @@
        cleanUp()
    def _getTargetClass(self):
        from pyramid.resource import OverrideProvider
        from pyramid.asset import OverrideProvider
        return OverrideProvider
    def _makeOne(self, module):
@@ -24,7 +24,7 @@
    def test_get_resource_filename_no_overrides(self):
        import os
        resource_name = 'test_resource.py'
        resource_name = 'test_asset.py'
        import pyramid.tests
        provider = self._makeOne(pyramid.tests)
        here = os.path.dirname(os.path.abspath(__file__))
@@ -34,7 +34,7 @@
    def test_get_resource_stream_no_overrides(self):
        import os
        resource_name = 'test_resource.py'
        resource_name = 'test_asset.py'
        import pyramid.tests
        provider = self._makeOne(pyramid.tests)
        here = os.path.dirname(os.path.abspath(__file__))
@@ -44,7 +44,7 @@
    def test_get_resource_string_no_overrides(self):
        import os
        resource_name = 'test_resource.py'
        resource_name = 'test_asset.py'
        import pyramid.tests
        provider = self._makeOne(pyramid.tests)
        here = os.path.dirname(os.path.abspath(__file__))
@@ -53,14 +53,14 @@
        self.assertEqual(result, expected)
    def test_has_resource_no_overrides(self):
        resource_name = 'test_resource.py'
        resource_name = 'test_asset.py'
        import pyramid.tests
        provider = self._makeOne(pyramid.tests)
        result = provider.has_resource(resource_name)
        self.assertEqual(result, True)
    def test_resource_isdir_no_overrides(self):
        file_resource_name = 'test_resource.py'
        file_resource_name = 'test_asset.py'
        directory_resource_name = 'fixtures'
        import pyramid.tests
        provider = self._makeOne(pyramid.tests)
@@ -80,7 +80,7 @@
        overrides = DummyOverrides(None)
        self._registerOverrides(overrides)
        import os
        resource_name = 'test_resource.py'
        resource_name = 'test_asset.py'
        import pyramid.tests
        provider = self._makeOne(pyramid.tests)
        here = os.path.dirname(os.path.abspath(__file__))
@@ -92,7 +92,7 @@
        overrides = DummyOverrides(None)
        self._registerOverrides(overrides)
        import os
        resource_name = 'test_resource.py'
        resource_name = 'test_asset.py'
        import pyramid.tests
        provider = self._makeOne(pyramid.tests)
        here = os.path.dirname(os.path.abspath(__file__))
@@ -104,7 +104,7 @@
        overrides = DummyOverrides(None)
        self._registerOverrides(overrides)
        import os
        resource_name = 'test_resource.py'
        resource_name = 'test_asset.py'
        import pyramid.tests
        provider = self._makeOne(pyramid.tests)
        here = os.path.dirname(os.path.abspath(__file__))
@@ -115,7 +115,7 @@
    def test_has_resource_override_returns_None(self):
        overrides = DummyOverrides(None)
        self._registerOverrides(overrides)
        resource_name = 'test_resource.py'
        resource_name = 'test_asset.py'
        import pyramid.tests
        provider = self._makeOne(pyramid.tests)
        result = provider.has_resource(resource_name)
@@ -144,7 +144,7 @@
        import pyramid.tests
        self._registerOverrides(overrides)
        provider = self._makeOne(pyramid.tests)
        result = provider.get_resource_filename(None, 'test_resource.py')
        result = provider.get_resource_filename(None, 'test_asset.py')
        self.assertEqual(result, 'value')
    def test_get_resource_stream_override_returns_value(self):
@@ -152,7 +152,7 @@
        import pyramid.tests
        self._registerOverrides(overrides)
        provider = self._makeOne(pyramid.tests)
        result = provider.get_resource_stream(None, 'test_resource.py')
        result = provider.get_resource_stream(None, 'test_asset.py')
        self.assertEqual(result, 'value')
    def test_get_resource_string_override_returns_value(self):
@@ -160,7 +160,7 @@
        import pyramid.tests
        self._registerOverrides(overrides)
        provider = self._makeOne(pyramid.tests)
        result = provider.get_resource_string(None, 'test_resource.py')
        result = provider.get_resource_string(None, 'test_asset.py')
        self.assertEqual(result, 'value')
    def test_has_resource_override_returns_True(self):
@@ -168,7 +168,7 @@
        import pyramid.tests
        self._registerOverrides(overrides)
        provider = self._makeOne(pyramid.tests)
        result = provider.has_resource('test_resource.py')
        result = provider.has_resource('test_asset.py')
        self.assertEqual(result, True)
    def test_resource_isdir_override_returns_False(self):
@@ -189,7 +189,7 @@
class TestPackageOverrides(unittest.TestCase):
    def _getTargetClass(self):
        from pyramid.resource import PackageOverrides
        from pyramid.asset import PackageOverrides
        return PackageOverrides
    def _makeOne(self, package, pkg_resources=None):
@@ -259,39 +259,39 @@
    def test_get_filename(self):
        import os
        overrides = [ DummyOverride(None), DummyOverride(
            ('pyramid.tests', 'test_resource.py'))]
            ('pyramid.tests', 'test_asset.py'))]
        package = DummyPackage('package')
        po = self._makeOne(package)
        po.overrides= overrides
        here = os.path.dirname(os.path.abspath(__file__))
        expected = os.path.join(here, 'test_resource.py')
        expected = os.path.join(here, 'test_asset.py')
        self.assertEqual(po.get_filename('whatever'), expected)
        
    def test_get_stream(self):
        import os
        overrides = [ DummyOverride(None), DummyOverride(
            ('pyramid.tests', 'test_resource.py'))]
            ('pyramid.tests', 'test_asset.py'))]
        package = DummyPackage('package')
        po = self._makeOne(package)
        po.overrides= overrides
        here = os.path.dirname(os.path.abspath(__file__))
        expected = open(os.path.join(here, 'test_resource.py')).read()
        expected = open(os.path.join(here, 'test_asset.py')).read()
        self.assertEqual(po.get_stream('whatever').read(), expected)
        
    def test_get_string(self):
        import os
        overrides = [ DummyOverride(None), DummyOverride(
            ('pyramid.tests', 'test_resource.py'))]
            ('pyramid.tests', 'test_asset.py'))]
        package = DummyPackage('package')
        po = self._makeOne(package)
        po.overrides= overrides
        here = os.path.dirname(os.path.abspath(__file__))
        expected = open(os.path.join(here, 'test_resource.py')).read()
        expected = open(os.path.join(here, 'test_asset.py')).read()
        self.assertEqual(po.get_string('whatever'), expected)
        
    def test_has_resource(self):
        overrides = [ DummyOverride(None), DummyOverride(
            ('pyramid.tests', 'test_resource.py'))]
            ('pyramid.tests', 'test_asset.py'))]
        package = DummyPackage('package')
        po = self._makeOne(package)
        po.overrides= overrides
@@ -299,7 +299,7 @@
    def test_isdir_false(self):
        overrides = [ DummyOverride(
            ('pyramid.tests', 'test_resource.py'))]
            ('pyramid.tests', 'test_asset.py'))]
        package = DummyPackage('package')
        po = self._makeOne(package)
        po.overrides= overrides
@@ -323,7 +323,7 @@
class TestDirectoryOverride(unittest.TestCase):
    def _getTargetClass(self):
        from pyramid.resource import DirectoryOverride
        from pyramid.asset import DirectoryOverride
        return DirectoryOverride
    def _makeOne(self, path, package, prefix):
@@ -340,10 +340,10 @@
        result = o('baz/notfound.pt')
        self.assertEqual(result, None)
class Test_resolve_resource_spec(unittest.TestCase):
class Test_resolve_asset_spec(unittest.TestCase):
    def _callFUT(self, spec, package_name='__main__'):
        from pyramid.resource import resolve_resource_spec
        return resolve_resource_spec(spec, package_name)
        from pyramid.resource import resolve_asset_spec
        return resolve_asset_spec(spec, package_name)
    def test_abspath(self):
        import os
@@ -355,37 +355,37 @@
    def test_rel_spec(self):
        pkg = 'pyramid.tests'
        path = 'test_resource.py'
        path = 'test_asset.py'
        package_name, filename = self._callFUT(path, pkg)
        self.assertEqual(package_name, 'pyramid.tests')
        self.assertEqual(filename, 'test_resource.py')
        self.assertEqual(filename, 'test_asset.py')
        
    def test_abs_spec(self):
        pkg = 'pyramid.tests'
        path = 'pyramid.nottests:test_resource.py'
        path = 'pyramid.nottests:test_asset.py'
        package_name, filename = self._callFUT(path, pkg)
        self.assertEqual(package_name, 'pyramid.nottests')
        self.assertEqual(filename, 'test_resource.py')
        self.assertEqual(filename, 'test_asset.py')
    def test_package_name_is_None(self):
        pkg = None
        path = 'test_resource.py'
        path = 'test_asset.py'
        package_name, filename = self._callFUT(path, pkg)
        self.assertEqual(package_name, None)
        self.assertEqual(filename, 'test_resource.py')
        self.assertEqual(filename, 'test_asset.py')
    def test_package_name_is_package_object(self):
        import pyramid.tests
        pkg = pyramid.tests
        path = 'test_resource.py'
        path = 'test_asset.py'
        package_name, filename = self._callFUT(path, pkg)
        self.assertEqual(package_name, 'pyramid.tests')
        self.assertEqual(filename, 'test_resource.py')
        self.assertEqual(filename, 'test_asset.py')
class TestFileOverride(unittest.TestCase):
    def _getTargetClass(self):
        from pyramid.resource import FileOverride
        from pyramid.asset import FileOverride
        return FileOverride
    def _makeOne(self, path, package, prefix):
@@ -402,16 +402,16 @@
        result = o('notfound.pt')
        self.assertEqual(result, None)
class Test_abspath_from_resource_spec(unittest.TestCase):
class Test_abspath_from_asset_spec(unittest.TestCase):
    def _callFUT(self, spec, pname='__main__'):
        from pyramid.resource import abspath_from_resource_spec
        return abspath_from_resource_spec(spec, pname)
        from pyramid.resource import abspath_from_asset_spec
        return abspath_from_asset_spec(spec, pname)
    def test_pname_is_None_before_resolve_resource_spec(self):
    def test_pname_is_None_before_resolve_asset_spec(self):
        result = self._callFUT('abc', None)
        self.assertEqual(result, 'abc')
    def test_pname_is_None_after_resolve_resource_spec(self):
    def test_pname_is_None_after_resolve_asset_spec(self):
        result = self._callFUT('/abc', '__main__')
        self.assertEqual(result, '/abc')
pyramid/tests/test_authorization.py
@@ -117,7 +117,7 @@
        self.assertEqual(result.ace, '<default deny>')
        self.assertEqual(
            result.acl,
            '<No ACL found on any object in model lineage>')
            '<No ACL found on any object in resource lineage>')
    def test_principals_allowed_by_permission_direct(self):
        from pyramid.security import Allow
pyramid/tests/test_config.py
@@ -226,22 +226,22 @@
        result = config.maybe_dotted(pyramid.tests)
        self.assertEqual(result, pyramid.tests)
    def test_absolute_resource_spec_already_absolute(self):
    def test_absolute_asset_spec_already_absolute(self):
        import pyramid.tests
        config = self._makeOne(package=pyramid.tests)
        result = config.absolute_resource_spec('already:absolute')
        result = config.absolute_asset_spec('already:absolute')
        self.assertEqual(result, 'already:absolute')
    def test_absolute_resource_spec_notastring(self):
    def test_absolute_asset_spec_notastring(self):
        import pyramid.tests
        config = self._makeOne(package=pyramid.tests)
        result = config.absolute_resource_spec(None)
        result = config.absolute_asset_spec(None)
        self.assertEqual(result, None)
    def test_absolute_resource_spec_relative(self):
    def test_absolute_asset_spec_relative(self):
        import pyramid.tests
        config = self._makeOne(package=pyramid.tests)
        result = config.absolute_resource_spec('templates')
        result = config.absolute_asset_spec('templates')
        self.assertEqual(result, 'pyramid.tests:templates')
    def test_setup_registry_fixed(self):
@@ -2541,7 +2541,7 @@
                          config.add_translation_dirs,
                          '/wont/exist/on/my/system')
    def test_add_translation_dirs_resource_spec(self):
    def test_add_translation_dirs_asset_spec(self):
        import os
        from pyramid.interfaces import ITranslationDirectories
        config = self._makeOne(autocommit=True)
@@ -2972,27 +2972,27 @@
            inner_view, viewname='inner', wrapper_viewname='owrap')
        self.assertRaises(ValueError, wrapped, None, request)
    def test_override_resource_samename(self):
    def test_override_asset_samename(self):
        from pyramid.exceptions import ConfigurationError
        config = self._makeOne()
        self.assertRaises(ConfigurationError, config.override_resource,'a', 'a')
        self.assertRaises(ConfigurationError, config.override_asset,'a', 'a')
    def test_override_resource_directory_with_file(self):
    def test_override_asset_directory_with_file(self):
        from pyramid.exceptions import ConfigurationError
        config = self._makeOne()
        self.assertRaises(ConfigurationError, config.override_resource,
        self.assertRaises(ConfigurationError, config.override_asset,
                          'a:foo/', 'a:foo.pt')
    def test_override_resource_file_with_directory(self):
    def test_override_asset_file_with_directory(self):
        from pyramid.exceptions import ConfigurationError
        config = self._makeOne()
        self.assertRaises(ConfigurationError, config.override_resource,
        self.assertRaises(ConfigurationError, config.override_asset,
                          'a:foo.pt', 'a:foo/')
    def test_override_resource_success(self):
    def test_override_asset_success(self):
        config = self._makeOne(autocommit=True)
        override = DummyUnderOverride()
        config.override_resource(
        config.override_asset(
            'pyramid.tests.fixtureapp:templates/foo.pt',
            'pyramid.tests.fixtureapp.subpackage:templates/bar.pt',
            _override=override)
@@ -3153,14 +3153,14 @@
        self.assertEqual(ut.groupids, ('group1', 'group2'))
        self.assertEqual(ut.permissive, False)
    def test_testing_models(self):
        from pyramid.traversal import find_model
    def test_testing_resources(self):
        from pyramid.traversal import find_resource
        from pyramid.interfaces import ITraverser
        ob1 = object()
        ob2 = object()
        models = {'/ob1':ob1, '/ob2':ob2}
        resources = {'/ob1':ob1, '/ob2':ob2}
        config = self._makeOne(autocommit=True)
        config.testing_models(models)
        config.testing_resources(resources)
        adapter = config.registry.getAdapter(None, ITraverser)
        result = adapter({'PATH_INFO':'/ob1'})
        self.assertEqual(result['context'], ob1)
@@ -3179,7 +3179,7 @@
        self.assertRaises(KeyError, adapter, {'PATH_INFO':'/ob3'})
        try:
            config.begin()
            self.assertEqual(find_model(None, '/ob1'), ob1)
            self.assertEqual(find_resource(None, '/ob1'), ob1)
        finally:
            config.end()
pyramid/tests/test_mako_templating.py
@@ -77,7 +77,7 @@
            os.path.join(module_path, 'a'),
            os.path.join(module_path, 'b')])
    def test_with_module_directory_resource_spec(self):
    def test_with_module_directory_asset_spec(self):
        import os
        from pyramid.mako_templating import IMakoLookup
        module_directory = 'pyramid.tests:fixtures'
@@ -94,7 +94,7 @@
        fixtures = os.path.join(os.path.dirname(__file__), 'fixtures')
        self.assertEqual(lookup.module_directory, fixtures)
    def test_with_module_directory_resource_abspath(self):
    def test_with_module_directory_asset_abspath(self):
        import os
        from pyramid.mako_templating import IMakoLookup
        fixtures = os.path.join(os.path.dirname(__file__), 'fixtures')
@@ -364,28 +364,28 @@
        import pyramid.tests
        return os.path.join(os.path.dirname(pyramid.tests.__file__), 'fixtures')
    def test_adjust_uri_not_resource_spec(self):
    def test_adjust_uri_not_asset_spec(self):
        inst = self._makeOne()
        result = inst.adjust_uri('a', None)
        self.assertEqual(result, '/a')
    def test_adjust_uri_resource_spec(self):
    def test_adjust_uri_asset_spec(self):
        inst = self._makeOne()
        result = inst.adjust_uri('a:b', None)
        self.assertEqual(result, 'a:b')
    def test_get_template_not_resource_spec(self):
    def test_get_template_not_asset_spec(self):
        fixturedir = self.get_fixturedir()
        inst = self._makeOne(directories=[fixturedir])
        result = inst.get_template('helloworld.mak')
        self.failIf(result is None)
        
    def test_get_template_resource_spec_with_filesystem_checks(self):
    def test_get_template_asset_spec_with_filesystem_checks(self):
        inst = self._makeOne(filesystem_checks=True)
        result = inst.get_template('pyramid.tests:fixtures/helloworld.mak')
        self.failIf(result is None)
    def test_get_template_resource_spec_missing(self):
    def test_get_template_asset_spec_missing(self):
        from mako.exceptions import TopLevelLookupException
        fixturedir = self.get_fixturedir()
        inst = self._makeOne(filesystem_checks=True, directories=[fixturedir])
pyramid/tests/test_renderers.py
@@ -143,11 +143,11 @@
        self.failUnless(factory.path.startswith(path))
        self.assertEqual(factory.kw, {})
    def test_reload_resources_true(self):
    def test_reload_assets_true(self):
        import pyramid.tests
        from pyramid.interfaces import ISettings
        from pyramid.interfaces import ITemplateRenderer
        settings = {'reload_resources':True}
        settings = {'reload_assets':True}
        testing.registerUtility(settings, ISettings)
        renderer = {}
        factory = DummyFactory(renderer)
@@ -166,10 +166,10 @@
        self.assertEqual(reg.queryUtility(ITemplateRenderer, name=spec),
                         None)
    def test_reload_resources_false(self):
    def test_reload_assets_false(self):
        import pyramid.tests
        from pyramid.interfaces import ITemplateRenderer
        settings = {'reload_resources':False}
        settings = {'reload_assets':False}
        renderer = {}
        factory = DummyFactory(renderer)
        spec = 'test_renderers.py'
pyramid/tests/test_request.py
@@ -241,11 +241,11 @@
        self.assertEqual(inst.called2, True)
        self.assertEqual(inst.finished_callbacks, [])
    def test_model_url(self):
    def test_resource_url(self):
        self._registerContextURL()
        inst = self._makeOne({})
        root = DummyContext()
        result = inst.model_url(root)
        result = inst.resource_url(root)
        self.assertEqual(result, 'http://example.com/context/')
    def test_route_url(self):
pyramid/tests/test_settings.py
@@ -45,40 +45,76 @@
        self.assertEqual(result['reload_templates'], True)
    def test_reload_resources(self):
        # alias for reload_assets
        result = self._makeOne({})
        self.assertEqual(result['reload_resources'], False)
        self.assertEqual(result['reload_assets'], False)
        result = self._makeOne({'reload_resources':'false'})
        self.assertEqual(result['reload_resources'], False)
        self.assertEqual(result['reload_assets'], False)
        result = self._makeOne({'reload_resources':'t'})
        self.assertEqual(result['reload_resources'], True)
        self.assertEqual(result['reload_assets'], True)
        result = self._makeOne({'reload_resources':'1'})
        self.assertEqual(result['reload_resources'], True)
        self.assertEqual(result['reload_assets'], True)
        result = self._makeOne({}, {'BFG_RELOAD_RESOURCES':'1'})
        self.assertEqual(result['reload_resources'], True)
        self.assertEqual(result['reload_assets'], True)
        result = self._makeOne({'reload_resources':'false'},
                             {'BFG_RELOAD_RESOURCES':'1'})
        self.assertEqual(result['reload_resources'], True)
        self.assertEqual(result['reload_assets'], True)
    def test_reload_assets(self):
        # alias for reload_resources
        result = self._makeOne({})
        self.assertEqual(result['reload_assets'], False)
        self.assertEqual(result['reload_resources'], False)
        result = self._makeOne({'reload_assets':'false'})
        self.assertEqual(result['reload_resources'], False)
        self.assertEqual(result['reload_assets'], False)
        result = self._makeOne({'reload_assets':'t'})
        self.assertEqual(result['reload_assets'], True)
        self.assertEqual(result['reload_resources'], True)
        result = self._makeOne({'reload_assets':'1'})
        self.assertEqual(result['reload_assets'], True)
        self.assertEqual(result['reload_resources'], True)
        result = self._makeOne({}, {'BFG_RELOAD_ASSETS':'1'})
        self.assertEqual(result['reload_assets'], True)
        self.assertEqual(result['reload_resources'], True)
        result = self._makeOne({'reload_assets':'false'},
                             {'BFG_RELOAD_ASSETS':'1'})
        self.assertEqual(result['reload_assets'], True)
        self.assertEqual(result['reload_resources'], True)
    def test_reload_all(self):
        result = self._makeOne({})
        self.assertEqual(result['reload_templates'], False)
        self.assertEqual(result['reload_resources'], False)
        self.assertEqual(result['reload_assets'], False)
        result = self._makeOne({'reload_all':'false'})
        self.assertEqual(result['reload_templates'], False)
        self.assertEqual(result['reload_resources'], False)
        self.assertEqual(result['reload_assets'], False)
        result = self._makeOne({'reload_all':'t'})
        self.assertEqual(result['reload_templates'], True)
        self.assertEqual(result['reload_resources'], True)
        self.assertEqual(result['reload_assets'], True)
        result = self._makeOne({'reload_all':'1'})
        self.assertEqual(result['reload_templates'], True)
        self.assertEqual(result['reload_resources'], True)
        self.assertEqual(result['reload_assets'], True)
        result = self._makeOne({}, {'BFG_RELOAD_ALL':'1'})
        self.assertEqual(result['reload_templates'], True)
        self.assertEqual(result['reload_resources'], True)
        self.assertEqual(result['reload_assets'], True)
        result = self._makeOne({'reload_all':'false'},
                             {'BFG_RELOAD_ALL':'1'})
        self.assertEqual(result['reload_templates'], True)
        self.assertEqual(result['reload_resources'], True)
        self.assertEqual(result['reload_assets'], True)
    def test_debug_authorization(self):
        result = self._makeOne({})
pyramid/tests/test_testing.py
@@ -33,13 +33,13 @@
        self.assertEqual(ut.groupids, ('group1', 'group2'))
        self.assertEqual(ut.permissive, False)
class Test_registerModels(TestBase):
    def test_registerModels(self):
class Test_registerResources(TestBase):
    def test_it(self):
        ob1 = object()
        ob2 = object()
        models = {'/ob1':ob1, '/ob2':ob2}
        resources = {'/ob1':ob1, '/ob2':ob2}
        from pyramid import testing
        testing.registerModels(models)
        testing.registerResources(resources)
        from pyramid.interfaces import ITraverser
        adapter = self.registry.getAdapter(None, ITraverser)
        result = adapter({'PATH_INFO':'/ob1'})
@@ -57,8 +57,8 @@
        self.assertEqual(result['virtual_root'], ob2)
        self.assertEqual(result['virtual_root_path'], ())
        self.assertRaises(KeyError, adapter, {'PATH_INFO':'/ob3'})
        from pyramid.traversal import find_model
        self.assertEqual(find_model(None, '/ob1'), ob1)
        from pyramid.traversal import find_resource
        self.assertEqual(find_resource(None, '/ob1'), ob1)
class Test_registerTemplateRenderer(TestBase):
    def test_registerTemplateRenderer(self):
@@ -331,10 +331,10 @@
        
        
class TestDummyModel(unittest.TestCase):
class TestDummyResource(unittest.TestCase):
    def _getTargetClass(self):
        from pyramid.testing import DummyModel
        return DummyModel
        from pyramid.testing import DummyResource
        return DummyResource
    def _makeOne(self, name=None, parent=None, **kw):
        klass = self._getTargetClass()
@@ -344,26 +344,26 @@
        class Dummy:
            pass
        dummy = Dummy()
        model = self._makeOne()
        model['abc'] = dummy
        resource = self._makeOne()
        resource['abc'] = dummy
        self.assertEqual(dummy.__name__, 'abc')
        self.assertEqual(dummy.__parent__, model)
        self.assertEqual(model['abc'], dummy)
        self.assertEqual(model.get('abc'), dummy)
        self.assertRaises(KeyError, model.__getitem__, 'none')
        self.failUnless('abc' in model)
        del model['abc']
        self.failIf('abc' in model)
        self.assertEqual(model.get('abc', 'foo'), 'foo')
        self.assertEqual(model.get('abc'), None)
        self.assertEqual(dummy.__parent__, resource)
        self.assertEqual(resource['abc'], dummy)
        self.assertEqual(resource.get('abc'), dummy)
        self.assertRaises(KeyError, resource.__getitem__, 'none')
        self.failUnless('abc' in resource)
        del resource['abc']
        self.failIf('abc' in resource)
        self.assertEqual(resource.get('abc', 'foo'), 'foo')
        self.assertEqual(resource.get('abc'), None)
    def test_extra_params(self):
        model = self._makeOne(foo=1)
        self.assertEqual(model.foo, 1)
        resource = self._makeOne(foo=1)
        self.assertEqual(resource.foo, 1)
        
    def test_clone(self):
        model = self._makeOne('name', 'parent', foo=1, bar=2)
        clone = model.clone('name2', 'parent2', bar=1)
        resource = self._makeOne('name', 'parent', foo=1, bar=2)
        clone = resource.clone('name2', 'parent2', bar=1)
        self.assertEqual(clone.bar, 1)
        self.assertEqual(clone.__name__, 'name2')
        self.assertEqual(clone.__parent__, 'parent2')
@@ -372,21 +372,21 @@
    def test_keys_items_values_len(self):
        class Dummy:
            pass
        model = self._makeOne()
        model['abc'] = Dummy()
        model['def'] = Dummy()
        self.assertEqual(model.values(), model.subs.values())
        self.assertEqual(model.items(), model.subs.items())
        self.assertEqual(model.keys(), model.subs.keys())
        self.assertEqual(len(model), 2)
        resource = self._makeOne()
        resource['abc'] = Dummy()
        resource['def'] = Dummy()
        self.assertEqual(resource.values(), resource.subs.values())
        self.assertEqual(resource.items(), resource.subs.items())
        self.assertEqual(resource.keys(), resource.subs.keys())
        self.assertEqual(len(resource), 2)
    def test_nonzero(self):
        model = self._makeOne()
        self.assertEqual(model.__nonzero__(), True)
        resource = self._makeOne()
        self.assertEqual(resource.__nonzero__(), True)
    def test_ctor_with__provides__(self):
        model = self._makeOne(__provides__=IDummy)
        self.failUnless(IDummy.providedBy(model))
        resource = self._makeOne(__provides__=IDummy)
        self.failUnless(IDummy.providedBy(resource))
class TestDummyRequest(unittest.TestCase):
    def _getTargetClass(self):
pyramid/tests/test_traversal.py
@@ -62,7 +62,7 @@
        path = unicode('/La Pe\xc3\xb1a', 'utf-8')
        self.assertRaises(UnicodeEncodeError, self._callFUT, path)
class ModelGraphTraverserTests(unittest.TestCase):
class ResourceTreeTraverserTests(unittest.TestCase):
    def setUp(self):
        cleanUp()
@@ -70,8 +70,8 @@
        cleanUp()
    def _getTargetClass(self):
        from pyramid.traversal import ModelGraphTraverser
        return ModelGraphTraverser
        from pyramid.traversal import ResourceTreeTraverser
        return ResourceTreeTraverser
    def _makeOne(self, *arg, **kw):
        klass = self._getTargetClass()
@@ -272,68 +272,68 @@
        self.assertRaises(URLDecodeError, policy, environ)
    def test_withroute_nothingfancy(self):
        model = DummyContext()
        traverser = self._makeOne(model)
        resource = DummyContext()
        traverser = self._makeOne(resource)
        environ = {'bfg.routes.matchdict': {}}
        result = traverser(environ)
        self.assertEqual(result['context'], model)
        self.assertEqual(result['context'], resource)
        self.assertEqual(result['view_name'], '')
        self.assertEqual(result['subpath'], ())
        self.assertEqual(result['traversed'], ())
        self.assertEqual(result['root'], model)
        self.assertEqual(result['virtual_root'], model)
        self.assertEqual(result['root'], resource)
        self.assertEqual(result['virtual_root'], resource)
        self.assertEqual(result['virtual_root_path'], ())
    def test_withroute_with_subpath_string(self):
        model = DummyContext()
        traverser = self._makeOne(model)
        resource = DummyContext()
        traverser = self._makeOne(resource)
        environ = {'bfg.routes.matchdict': {'subpath':'/a/b/c'}}
        result = traverser(environ)
        self.assertEqual(result['context'], model)
        self.assertEqual(result['context'], resource)
        self.assertEqual(result['view_name'], '')
        self.assertEqual(result['subpath'], ('a', 'b','c'))
        self.assertEqual(result['traversed'], ())
        self.assertEqual(result['root'], model)
        self.assertEqual(result['virtual_root'], model)
        self.assertEqual(result['root'], resource)
        self.assertEqual(result['virtual_root'], resource)
        self.assertEqual(result['virtual_root_path'], ())
    def test_withroute_with_subpath_tuple(self):
        model = DummyContext()
        traverser = self._makeOne(model)
        resource = DummyContext()
        traverser = self._makeOne(resource)
        environ = {'bfg.routes.matchdict': {'subpath':('a', 'b', 'c')}}
        result = traverser(environ)
        self.assertEqual(result['context'], model)
        self.assertEqual(result['context'], resource)
        self.assertEqual(result['view_name'], '')
        self.assertEqual(result['subpath'], ('a', 'b','c'))
        self.assertEqual(result['traversed'], ())
        self.assertEqual(result['root'], model)
        self.assertEqual(result['virtual_root'], model)
        self.assertEqual(result['root'], resource)
        self.assertEqual(result['virtual_root'], resource)
        self.assertEqual(result['virtual_root_path'], ())
    def test_withroute_and_traverse_string(self):
        model = DummyContext()
        traverser = self._makeOne(model)
        resource = DummyContext()
        traverser = self._makeOne(resource)
        environ = {'bfg.routes.matchdict': {'traverse':'foo/bar'}}
        result = traverser(environ)
        self.assertEqual(result['context'], model)
        self.assertEqual(result['context'], resource)
        self.assertEqual(result['view_name'], 'foo')
        self.assertEqual(result['subpath'], ('bar',))
        self.assertEqual(result['traversed'], ())
        self.assertEqual(result['root'], model)
        self.assertEqual(result['virtual_root'], model)
        self.assertEqual(result['root'], resource)
        self.assertEqual(result['virtual_root'], resource)
        self.assertEqual(result['virtual_root_path'], ())
    def test_withroute_and_traverse_tuple(self):
        model = DummyContext()
        traverser = self._makeOne(model)
        resource = DummyContext()
        traverser = self._makeOne(resource)
        environ = {'bfg.routes.matchdict': {'traverse':('foo', 'bar')}}
        result = traverser(environ)
        self.assertEqual(result['context'], model)
        self.assertEqual(result['context'], resource)
        self.assertEqual(result['view_name'], 'foo')
        self.assertEqual(result['subpath'], ('bar',))
        self.assertEqual(result['traversed'], ())
        self.assertEqual(result['root'], model)
        self.assertEqual(result['virtual_root'], model)
        self.assertEqual(result['root'], resource)
        self.assertEqual(result['virtual_root'], resource)
        self.assertEqual(result['virtual_root_path'], ())
class FindInterfaceTests(unittest.TestCase):
@@ -396,10 +396,10 @@
        result = self._callFUT(baz)
        self.assertEqual(result, dummy)
class FindModelTests(unittest.TestCase):
class FindResourceTests(unittest.TestCase):
    def _callFUT(self, context, name):
        from pyramid.traversal import find_model
        return find_model(context, name)
        from pyramid.traversal import find_resource
        return find_resource(context, name)
    def _registerTraverser(self, traverser):
        from pyramid.threadlocal import get_current_registry
@@ -409,124 +409,124 @@
        reg.registerAdapter(traverser, (Interface,), ITraverser)
    def test_list(self):
        model = DummyContext()
        traverser = make_traverser({'context':model, 'view_name':''})
        resource = DummyContext()
        traverser = make_traverser({'context':resource, 'view_name':''})
        self._registerTraverser(traverser)
        result = self._callFUT(model, [''])
        self.assertEqual(result, model)
        self.assertEqual(model.request.environ['PATH_INFO'], '/')
        result = self._callFUT(resource, [''])
        self.assertEqual(result, resource)
        self.assertEqual(resource.request.environ['PATH_INFO'], '/')
    def test_generator(self):
        model = DummyContext()
        traverser = make_traverser({'context':model, 'view_name':''})
        resource = DummyContext()
        traverser = make_traverser({'context':resource, 'view_name':''})
        self._registerTraverser(traverser)
        def foo():
            yield ''
        result = self._callFUT(model, foo())
        self.assertEqual(result, model)
        self.assertEqual(model.request.environ['PATH_INFO'], '/')
        result = self._callFUT(resource, foo())
        self.assertEqual(result, resource)
        self.assertEqual(resource.request.environ['PATH_INFO'], '/')
    def test_self_string_found(self):
        model = DummyContext()
        traverser = make_traverser({'context':model, 'view_name':''})
        resource = DummyContext()
        traverser = make_traverser({'context':resource, 'view_name':''})
        self._registerTraverser(traverser)
        result = self._callFUT(model, '')
        self.assertEqual(result, model)
        self.assertEqual(model.request.environ['PATH_INFO'], '')
        result = self._callFUT(resource, '')
        self.assertEqual(result, resource)
        self.assertEqual(resource.request.environ['PATH_INFO'], '')
    def test_self_tuple_found(self):
        model = DummyContext()
        traverser = make_traverser({'context':model, 'view_name':''})
        resource = DummyContext()
        traverser = make_traverser({'context':resource, 'view_name':''})
        self._registerTraverser(traverser)
        result = self._callFUT(model, ())
        self.assertEqual(result, model)
        self.assertEqual(model.request.environ['PATH_INFO'], '')
        result = self._callFUT(resource, ())
        self.assertEqual(result, resource)
        self.assertEqual(resource.request.environ['PATH_INFO'], '')
    def test_relative_string_found(self):
        model = DummyContext()
        resource = DummyContext()
        baz = DummyContext()
        traverser = make_traverser({'context':baz, 'view_name':''})
        self._registerTraverser(traverser)
        result = self._callFUT(model, 'baz')
        result = self._callFUT(resource, 'baz')
        self.assertEqual(result, baz)
        self.assertEqual(model.request.environ['PATH_INFO'], 'baz')
        self.assertEqual(resource.request.environ['PATH_INFO'], 'baz')
    def test_relative_tuple_found(self):
        model = DummyContext()
        resource = DummyContext()
        baz = DummyContext()
        traverser = make_traverser({'context':baz, 'view_name':''})
        self._registerTraverser(traverser)
        result = self._callFUT(model, ('baz',))
        result = self._callFUT(resource, ('baz',))
        self.assertEqual(result, baz)
        self.assertEqual(model.request.environ['PATH_INFO'], 'baz')
        self.assertEqual(resource.request.environ['PATH_INFO'], 'baz')
    def test_relative_string_notfound(self):
        model = DummyContext()
        resource = DummyContext()
        baz = DummyContext()
        traverser = make_traverser({'context':baz, 'view_name':'bar'})
        self._registerTraverser(traverser)
        self.assertRaises(KeyError, self._callFUT, model, 'baz')
        self.assertEqual(model.request.environ['PATH_INFO'], 'baz')
        self.assertRaises(KeyError, self._callFUT, resource, 'baz')
        self.assertEqual(resource.request.environ['PATH_INFO'], 'baz')
    def test_relative_tuple_notfound(self):
        model = DummyContext()
        resource = DummyContext()
        baz = DummyContext()
        traverser = make_traverser({'context':baz, 'view_name':'bar'})
        self._registerTraverser(traverser)
        self.assertRaises(KeyError, self._callFUT, model, ('baz',))
        self.assertEqual(model.request.environ['PATH_INFO'], 'baz')
        self.assertRaises(KeyError, self._callFUT, resource, ('baz',))
        self.assertEqual(resource.request.environ['PATH_INFO'], 'baz')
    def test_absolute_string_found(self):
        root = DummyContext()
        model = DummyContext()
        model.__parent__ = root
        model.__name__ = 'baz'
        resource = DummyContext()
        resource.__parent__ = root
        resource.__name__ = 'baz'
        traverser = make_traverser({'context':root, 'view_name':''})
        self._registerTraverser(traverser)
        result = self._callFUT(model, '/')
        result = self._callFUT(resource, '/')
        self.assertEqual(result, root)
        self.assertEqual(root.wascontext, True)
        self.assertEqual(root.request.environ['PATH_INFO'], '/')
    def test_absolute_tuple_found(self):
        root = DummyContext()
        model = DummyContext()
        model.__parent__ = root
        model.__name__ = 'baz'
        resource = DummyContext()
        resource.__parent__ = root
        resource.__name__ = 'baz'
        traverser = make_traverser({'context':root, 'view_name':''})
        self._registerTraverser(traverser)
        result = self._callFUT(model, ('',))
        result = self._callFUT(resource, ('',))
        self.assertEqual(result, root)
        self.assertEqual(root.wascontext, True)
        self.assertEqual(root.request.environ['PATH_INFO'], '/')
    def test_absolute_string_notfound(self):
        root = DummyContext()
        model = DummyContext()
        model.__parent__ = root
        model.__name__ = 'baz'
        resource = DummyContext()
        resource.__parent__ = root
        resource.__name__ = 'baz'
        traverser = make_traverser({'context':root, 'view_name':'fuz'})
        self._registerTraverser(traverser)
        self.assertRaises(KeyError, self._callFUT, model, '/')
        self.assertRaises(KeyError, self._callFUT, resource, '/')
        self.assertEqual(root.wascontext, True)
        self.assertEqual(root.request.environ['PATH_INFO'], '/')
    def test_absolute_tuple_notfound(self):
        root = DummyContext()
        model = DummyContext()
        model.__parent__ = root
        model.__name__ = 'baz'
        resource = DummyContext()
        resource.__parent__ = root
        resource.__name__ = 'baz'
        traverser = make_traverser({'context':root, 'view_name':'fuz'})
        self._registerTraverser(traverser)
        self.assertRaises(KeyError, self._callFUT, model, ('',))
        self.assertRaises(KeyError, self._callFUT, resource, ('',))
        self.assertEqual(root.wascontext, True)
        self.assertEqual(root.request.environ['PATH_INFO'], '/')
    def test_absolute_unicode_found(self):
        # test for bug wiggy found in wild, traceback stack:
        # root = u'/%E6%B5%81%E8%A1%8C%E8%B6%8B%E5%8A%BF'
        # wiggy's code: section=find_model(page, root)
        # find_model L76: D = traverse(model, path)
        # wiggy's code: section=find_resource(page, root)
        # find_resource L76: D = traverse(resource, path)
        # traverse L291: return traverser(request)
        # __call__ line 568: vpath_tuple = traversal_path(vpath)
        # lru_cached line 91: f(*arg)
@@ -536,7 +536,7 @@
        #
        # solution: encode string to ascii in pyramid.traversal.traverse
        # before passing it along to webob as path_info
        from pyramid.traversal import ModelGraphTraverser
        from pyramid.traversal import ResourceTreeTraverser
        unprintable = DummyContext()
        root = DummyContext(unprintable)
        unprintable.__parent__ = root
@@ -544,15 +544,15 @@
            '/\xe6\xb5\x81\xe8\xa1\x8c\xe8\xb6\x8b\xe5\x8a\xbf', 'utf-8')
        root.__parent__ = None
        root.__name__ = None
        traverser = ModelGraphTraverser
        traverser = ResourceTreeTraverser
        self._registerTraverser(traverser)
        result = self._callFUT(root, u'/%E6%B5%81%E8%A1%8C%E8%B6%8B%E5%8A%BF')
        self.assertEqual(result, unprintable)
class ModelPathTests(unittest.TestCase):
    def _callFUT(self, model, *elements):
        from pyramid.traversal import model_path
        return model_path(model, *elements)
class ResourcePathTests(unittest.TestCase):
    def _callFUT(self, resource, *elements):
        from pyramid.traversal import resource_path
        return resource_path(resource, *elements)
    def test_it(self):
        baz = DummyContext()
@@ -624,10 +624,10 @@
        result = self._callFUT(other2)
        self.assertEqual(result, '//other2')
class ModelPathTupleTests(unittest.TestCase):
    def _callFUT(self, model, *elements):
        from pyramid.traversal import model_path_tuple
        return model_path_tuple(model, *elements)
class ResourcePathTupleTests(unittest.TestCase):
    def _callFUT(self, resource, *elements):
        from pyramid.traversal import resource_path_tuple
        return resource_path_tuple(resource, *elements)
    def test_it(self):
        baz = DummyContext()
@@ -745,7 +745,7 @@
        result = context_url()
        self.assertEqual(result, 'http://example.com:5432/')
    def test_call_unicode_mixed_with_bytes_in_model_names(self):
    def test_call_unicode_mixed_with_bytes_in_resource_names(self):
        root = DummyContext()
        root.__parent__ = None
        root.__name__ = None
@@ -836,9 +836,9 @@
    def tearDown(self):
        cleanUp()
    def _callFUT(self, model, request):
    def _callFUT(self, resource, request):
        from pyramid.traversal import virtual_root
        return virtual_root(model, request)
        return virtual_root(resource, request)
    def test_registered(self):
        from pyramid.interfaces import IContextURL
@@ -885,96 +885,96 @@
    def test_request_has_registry(self):
        from pyramid.threadlocal import get_current_registry
        model = DummyContext()
        traverser = make_traverser({'context':model, 'view_name':''})
        resource = DummyContext()
        traverser = make_traverser({'context':resource, 'view_name':''})
        self._registerTraverser(traverser)
        self._callFUT(model, [''])
        self.assertEqual(model.request.registry, get_current_registry())
        self._callFUT(resource, [''])
        self.assertEqual(resource.request.registry, get_current_registry())
    def test_list(self):
        model = DummyContext()
        traverser = make_traverser({'context':model, 'view_name':''})
        resource = DummyContext()
        traverser = make_traverser({'context':resource, 'view_name':''})
        self._registerTraverser(traverser)
        self._callFUT(model, [''])
        self.assertEqual(model.request.environ['PATH_INFO'], '/')
        self._callFUT(resource, [''])
        self.assertEqual(resource.request.environ['PATH_INFO'], '/')
    def test_generator(self):
        model = DummyContext()
        traverser = make_traverser({'context':model, 'view_name':''})
        resource = DummyContext()
        traverser = make_traverser({'context':resource, 'view_name':''})
        self._registerTraverser(traverser)
        def foo():
            yield ''
        self._callFUT(model, foo())
        self.assertEqual(model.request.environ['PATH_INFO'], '/')
        self._callFUT(resource, foo())
        self.assertEqual(resource.request.environ['PATH_INFO'], '/')
    def test_self_string_found(self):
        model = DummyContext()
        traverser = make_traverser({'context':model, 'view_name':''})
        resource = DummyContext()
        traverser = make_traverser({'context':resource, 'view_name':''})
        self._registerTraverser(traverser)
        self._callFUT(model, '')
        self.assertEqual(model.request.environ['PATH_INFO'], '')
        self._callFUT(resource, '')
        self.assertEqual(resource.request.environ['PATH_INFO'], '')
    def test_self_tuple_found(self):
        model = DummyContext()
        traverser = make_traverser({'context':model, 'view_name':''})
        resource = DummyContext()
        traverser = make_traverser({'context':resource, 'view_name':''})
        self._registerTraverser(traverser)
        self._callFUT(model, ())
        self.assertEqual(model.request.environ['PATH_INFO'], '')
        self._callFUT(resource, ())
        self.assertEqual(resource.request.environ['PATH_INFO'], '')
    def test_relative_string_found(self):
        model = DummyContext()
        resource = DummyContext()
        baz = DummyContext()
        traverser = make_traverser({'context':baz, 'view_name':''})
        self._registerTraverser(traverser)
        self._callFUT(model, 'baz')
        self.assertEqual(model.request.environ['PATH_INFO'], 'baz')
        self._callFUT(resource, 'baz')
        self.assertEqual(resource.request.environ['PATH_INFO'], 'baz')
    def test_relative_tuple_found(self):
        model = DummyContext()
        resource = DummyContext()
        baz = DummyContext()
        traverser = make_traverser({'context':baz, 'view_name':''})
        self._registerTraverser(traverser)
        self._callFUT(model, ('baz',))
        self.assertEqual(model.request.environ['PATH_INFO'], 'baz')
        self._callFUT(resource, ('baz',))
        self.assertEqual(resource.request.environ['PATH_INFO'], 'baz')
    def test_absolute_string_found(self):
        root = DummyContext()
        model = DummyContext()
        model.__parent__ = root
        model.__name__ = 'baz'
        resource = DummyContext()
        resource.__parent__ = root
        resource.__name__ = 'baz'
        traverser = make_traverser({'context':root, 'view_name':''})
        self._registerTraverser(traverser)
        self._callFUT(model, '/')
        self._callFUT(resource, '/')
        self.assertEqual(root.wascontext, True)
        self.assertEqual(root.request.environ['PATH_INFO'], '/')
    def test_absolute_tuple_found(self):
        root = DummyContext()
        model = DummyContext()
        model.__parent__ = root
        model.__name__ = 'baz'
        resource = DummyContext()
        resource.__parent__ = root
        resource.__name__ = 'baz'
        traverser = make_traverser({'context':root, 'view_name':''})
        self._registerTraverser(traverser)
        self._callFUT(model, ('',))
        self._callFUT(resource, ('',))
        self.assertEqual(root.wascontext, True)
        self.assertEqual(root.request.environ['PATH_INFO'], '/')
    def test_empty_sequence(self):
        root = DummyContext()
        model = DummyContext()
        model.__parent__ = root
        model.__name__ = 'baz'
        resource = DummyContext()
        resource.__parent__ = root
        resource.__name__ = 'baz'
        traverser = make_traverser({'context':root, 'view_name':''})
        self._registerTraverser(traverser)
        self._callFUT(model, [])
        self.assertEqual(model.wascontext, True)
        self.assertEqual(model.request.environ['PATH_INFO'], '')
        self._callFUT(resource, [])
        self.assertEqual(resource.wascontext, True)
        self.assertEqual(resource.request.environ['PATH_INFO'], '')
    def test_default_traverser(self):
        model = DummyContext()
        result = self._callFUT(model, '')
        resource = DummyContext()
        result = self._callFUT(resource, '')
        self.assertEqual(result['view_name'], '')
        self.assertEqual(result['context'], model)
        self.assertEqual(result['context'], resource)
    def test_requestfactory_overridden(self):
        from pyramid.interfaces import IRequestFactory
@@ -984,11 +984,11 @@
        class MyRequest(Request):
            pass
        reg.registerUtility(MyRequest, IRequestFactory)
        model = DummyContext()
        traverser = make_traverser({'context':model, 'view_name':''})
        resource = DummyContext()
        traverser = make_traverser({'context':resource, 'view_name':''})
        self._registerTraverser(traverser)
        self._callFUT(model, [''])
        self.assertEqual(model.request.__class__, MyRequest)
        self._callFUT(resource, [''])
        self.assertEqual(resource.request.__class__, MyRequest)
class TestDefaultRootFactory(unittest.TestCase):
    def _getTargetClass(self):
pyramid/tests/test_url.py
@@ -2,16 +2,16 @@
from pyramid.testing import cleanUp
class ModelURLTests(unittest.TestCase):
class ResourceURLTests(unittest.TestCase):
    def setUp(self):
        cleanUp()
    def tearDown(self):
        cleanUp()
        
    def _callFUT(self, model, request, *elements, **kw):
        from pyramid.url import model_url
        return model_url(model, request, *elements, **kw)
    def _callFUT(self, resource, request, *elements, **kw):
        from pyramid.url import resource_url
        return resource_url(resource, request, *elements, **kw)
    def _registerContextURL(self, reg):
        from pyramid.interfaces import IContextURL
pyramid/tests/test_zcml.py
@@ -815,7 +815,7 @@
        request = DummyRequest()
        self.assertRaises(Forbidden, view, None, request)
class TestResourceDirective(unittest.TestCase):
class TestAssetDirective(unittest.TestCase):
    def setUp(self):
        self.config = testing.setUp(autocommit=False)
        self.config._ctx = self.config._make_context()
@@ -824,8 +824,8 @@
        testing.tearDown()
    def _callFUT(self, *arg, **kw):
        from pyramid.zcml import resource
        return resource(*arg, **kw)
        from pyramid.zcml import asset
        return asset(*arg, **kw)
    def test_it(self):
        import pyramid.tests
@@ -1302,7 +1302,7 @@
        result = self._callFUT(context, '/foo.pt')
        self.assertEqual(result, '/foo.pt')
    def test_path_is_already_resource_spec(self):
    def test_path_is_already_asset_spec(self):
        context = DummyContext()
        result = self._callFUT(context, 'pyramid.tests:foo.pt')
        self.assertEqual(result, 'pyramid.tests:foo.pt')
pyramid/traversal.py
@@ -15,31 +15,31 @@
from pyramid.location import lineage
from pyramid.threadlocal import get_current_registry
def find_root(model):
    """ Find the root node in the graph to which ``model``
    belongs. Note that ``model`` should be :term:`location`-aware.
    Note that the root node is available in the request object by
def find_root(resource):
    """ Find the root node in the graph to which ``resource``
    belongs. Note that ``resource`` should be :term:`location`-aware.
    Note that the root resource is available in the request object by
    accessing the ``request.root`` attribute.
    """
    for location in lineage(model):
    for location in lineage(resource):
        if location.__parent__ is None:
            model = location
            resource = location
            break
    return model
    return resource
def find_model(model, path):
    """ Given a model object and a string or tuple representing a path
def find_resource(resource, path):
    """ Given a resource object and a string or tuple representing a path
    (such as the return value of
    :func:`pyramid.traversal.model_path` or
    :func:`pyramid.traversal.model_path_tuple`), return a context
    in this application's model graph at the specified path.  The
    model passed in *must* be :term:`location`-aware.  If the path
    :func:`pyramid.traversal.resource_path` or
    :func:`pyramid.traversal.resource_path_tuple`), return a context
    in this application's resource tree at the specified path.  The
    resource passed in *must* be :term:`location`-aware.  If the path
    cannot be resolved (if the respective node in the graph does not
    exist), a :exc:`KeyError` will be raised.
    This function is the logical inverse of
    :func:`pyramid.traversal.model_path` and
    :func:`pyramid.traversal.model_path_tuple`; it can resolve any
    :func:`pyramid.traversal.resource_path` and
    :func:`pyramid.traversal.resource_path_tuple`; it can resolve any
    path string or tuple generated by either of those functions.
    Rules for passing a *string* as the ``path`` argument: if the
@@ -47,15 +47,15 @@
    character, the path will considered absolute and the graph
    traversal will start at the root object.  If the first character
    of the path string is *not* the ``/`` character, the path is
    considered relative and graph traversal will begin at the model
    object supplied to the function as the ``model`` argument.  If an
    empty string is passed as ``path``, the ``model`` passed in will
    be returned.  Model path strings must be escaped in the following
    considered relative and graph traversal will begin at the resource
    object supplied to the function as the ``resource`` argument.  If an
    empty string is passed as ``path``, the ``resource`` passed in will
    be returned.  Resource path strings must be escaped in the following
    manner: each Unicode path segment must be encoded as UTF-8 and as
    each path segment must escaped via Python's :mod:`urllib.quote`.
    For example, ``/path/to%20the/La%20Pe%C3%B1a`` (absolute) or
    ``to%20the/La%20Pe%C3%B1a`` (relative).  The
    :func:`pyramid.traversal.model_path` function generates strings
    :func:`pyramid.traversal.resource_path` function generates strings
    which follow these rules (albeit only absolute ones).
    Rules for passing a *tuple* as the ``path`` argument: if the first
@@ -64,108 +64,117 @@
    traversal will start at the graph root object.  If the first
    element in the path tuple is not the empty string (for example
    ``('a', 'b', 'c')``), the path is considered relative and graph
    traversal will begin at the model object supplied to the function
    as the ``model`` argument.  If an empty sequence is passed as
    ``path``, the ``model`` passed in itself will be returned.  No
    traversal will begin at the resource object supplied to the function
    as the ``resource`` argument.  If an empty sequence is passed as
    ``path``, the ``resource`` passed in itself will be returned.  No
    URL-quoting or UTF-8-encoding of individual path segments within
    the tuple is required (each segment may be any string or unicode
    object representing a model name).  Model path tuples generated by
    :func:`pyramid.traversal.model_path_tuple` can always be
    resolved by ``find_model``.
    object representing a resource name).  Resource path tuples generated by
    :func:`pyramid.traversal.resource_path_tuple` can always be
    resolved by ``find_resource``.
    .. note:: For backwards compatibility purposes, this function can also
       be imported as :func:`pyramid.traversal.find_model`.
    """
    D = traverse(model, path)
    D = traverse(resource, path)
    view_name = D['view_name']
    context = D['context']
    if view_name:
        raise KeyError('%r has no subelement %s' % (context, view_name))
    return context
def find_interface(model, class_or_interface):
find_model = find_resource # b/w compat
def find_interface(resource, class_or_interface):
    """
    Return the first object found in the parent chain of ``model``
    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
    ``model`` passed in *must* be :term:`location`-aware.
    ``resource`` passed in *must* be :term:`location`-aware.
    """
    if IInterface.providedBy(class_or_interface):
        test = class_or_interface.providedBy
    else:
        test = lambda arg: isinstance(arg, class_or_interface)
    for location in lineage(model):
    for location in lineage(resource):
        if test(location):
            return location
def model_path(model, *elements):
    """ Return a string object representing the absolute physical path
    of the model object based on its position in the model graph, e.g
    ``/foo/bar``.  Any positional arguments passed in as ``elements``
    will be appended as path segments to the end of the model path.
    For instance, if the model's path is ``/foo/bar`` and ``elements``
    equals ``('a', 'b')``, the returned string will be
    ``/foo/bar/a/b``.  The first character in the string will always
    be the ``/`` character (a leading ``/`` character in a path string
    represents that the path is absolute).
def resource_path(resource, *elements):
    """ Return a string object representing the absolute physical path of the
    resource object based on its position in the resource tree, e.g
    ``/foo/bar``.  Any positional arguments passed in as ``elements`` will be
    appended as path segments to the end of the resource path.  For instance,
    if the resource's path is ``/foo/bar`` and ``elements`` equals ``('a',
    'b')``, the returned string will be ``/foo/bar/a/b``.  The first
    character in the string will always be the ``/`` character (a leading
    ``/`` character in a path string represents that the path is absolute).
    Model path strings returned will be escaped in the following
    Resource path strings returned will be escaped in the following
    manner: each unicode path segment will be encoded as UTF-8 and
    each path segment will be escaped via Python's :mod:`urllib.quote`.
    For example, ``/path/to%20the/La%20Pe%C3%B1a``.
    This function is a logical inverse of
    :mod:`pyramid.traversal.find_model`: it can be used to generate
    :mod:`pyramid.traversal.find_resource`: it can be used to generate
    path references that can later be resolved via that function.
    The ``model`` passed in *must* be :term:`location`-aware.
    The ``resource`` passed in *must* be :term:`location`-aware.
    .. note:: Each segment in the path string returned will use the
              ``__name__`` attribute of the model it represents within
              ``__name__`` attribute of the resource it represents within
              the graph.  Each of these segments *should* be a unicode
              or string object (as per the contract of
              :term:`location`-awareness).  However, no conversion or
              safety checking of model names is performed.  For
              instance, if one of the models in your graph has a
              safety checking of resource names is performed.  For
              instance, if one of the resources in your tree has a
              ``__name__`` which (by error) is a dictionary, the
              :func:`pyramid.traversal.model_path` function will
              :func:`pyramid.traversal.resource_path` function will
              attempt to append it to a string and it will cause a
              :exc:`pyramid.exceptions.URLDecodeError`.
    .. note:: The :term:`root` model *must* have a ``__name__``
    .. note:: The :term:`root` resource *must* have a ``__name__``
              attribute with a value of either ``None`` or the empty
              string for paths to be generated properly.  If the root
              model has a non-null ``__name__`` attribute, its name
              resource has a non-null ``__name__`` attribute, its name
              will be prepended to the generated path rather than a
              single leading '/' character.
    .. note:: For backwards compatibility purposes, this function can also
       be imported as ``model_path``.
    """
    # joining strings is a bit expensive so we delegate to a function
    # which caches the joined result for us
    return _join_path_tuple(model_path_tuple(model, *elements))
    return _join_path_tuple(resource_path_tuple(resource, *elements))
def traverse(model, path):
    """Given a model object as ``model`` and a string or tuple
model_path = resource_path # b/w compat
def traverse(resource, path):
    """Given a resource object as ``resource`` and a string or tuple
    representing a path as ``path`` (such as the return value of
    :func:`pyramid.traversal.model_path` or
    :func:`pyramid.traversal.model_path_tuple` or the value of
    :func:`pyramid.traversal.resource_path` or
    :func:`pyramid.traversal.resource_path_tuple` or the value of
    ``request.environ['PATH_INFO']``), return a dictionary with the
    keys ``context``, ``root``, ``view_name``, ``subpath``,
    ``traversed``, ``virtual_root``, and ``virtual_root_path``.
    A definition of each value in the returned dictionary:
    - ``context``: The :term:`context` (a :term:`model` object) found
    - ``context``: The :term:`context` (a :term:`resource` object) found
      via traversal or url dispatch.  If the ``path`` passed in is the
      empty string, the value of the ``model`` argument passed to this
      empty string, the value of the ``resource`` argument passed to this
      function is returned.
    - ``root``: The model object at which :term:`traversal` begins.
      If the ``model`` passed in was found via url dispatch or if the
    - ``root``: The resource object at which :term:`traversal` begins.
      If the ``resource`` passed in was found via url dispatch or if the
      ``path`` passed in was relative (non-absolute), the value of the
      ``model`` argument passed to this function is returned.
      ``resource`` argument passed to this function is returned.
    - ``view_name``: The :term:`view name` found during
      :term:`traversal` or :term:`url dispatch`; if the ``model`` was
      :term:`traversal` or :term:`url dispatch`; if the ``resource`` was
      found via traversal, this is usually a representation of the
      path segment which directly follows the path to the ``context``
      in the ``path``.  The ``view_name`` will be a Unicode object or
@@ -173,11 +182,11 @@
      there is no element which follows the ``context`` path.  An
      example: if the path passed is ``/foo/bar``, and a context
      object is found at ``/foo`` (but not at ``/foo/bar``), the 'view
      name' will be ``u'bar'``.  If the ``model`` was found via
      name' will be ``u'bar'``.  If the ``resource`` was found via
      urldispatch, the view_name will be the name the route found was
      registered with.
    - ``subpath``: For a ``model`` found via :term:`traversal`, this
    - ``subpath``: For a ``resource`` found via :term:`traversal`, this
      is a sequence of path segments found in the ``path`` that follow
      the ``view_name`` (if any).  Each of these items is a Unicode
      object.  If no path segments follow the ``view_name``, the
@@ -185,7 +194,7 @@
      passed is ``/foo/bar/baz/buz``, and a context 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 ``model`` found via url dispatch, the subpath will be a
      For a ``resource`` found via url dispatch, the subpath will be a
      sequence of values discerned from ``*subpath`` in the route
      pattern matched or the empty sequence.
@@ -194,27 +203,27 @@
      Each of these items is a Unicode object.  If no path segments
      were traversed to find the ``context`` object (e.g. if the
      ``path`` provided is the empty string), the ``traversed`` value
      will be the empty sequence.  If the ``model`` is a model found
      will be the empty sequence.  If the ``resource`` is a resource found
      via :term:`url dispatch`, traversed will be None.
    - ``virtual_root``: A model object representing the 'virtual' root
    - ``virtual_root``: A resource object representing the 'virtual' root
      of the object graph being traversed during :term:`traversal`.
      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`
      begins).  If the ``model`` passed in was found via :term:`URL
      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
      model passed in).
      resource passed in).
    - ``virtual_root_path`` -- If :term:`traversal` was used to find
      the ``model``, this will be the sequence of path elements
      the ``resource``, this will be the sequence of path elements
      traversed to find the ``virtual_root`` object.  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
      not in effect), the ``traversed`` value will be the empty list.
      If url dispatch was used to find the ``model``, this will be
      If url dispatch was used to find the ``resource``, this will be
      ``None``.
    If the path cannot be resolved, a :exc:`KeyError` will be raised.
@@ -224,15 +233,15 @@
    character, the path will considered absolute and the graph
    traversal will start at the root object.  If the first character
    of the path string is *not* the ``/`` character, the path is
    considered relative and graph traversal will begin at the model
    object supplied to the function as the ``model`` argument.  If an
    empty string is passed as ``path``, the ``model`` passed in will
    be returned.  Model path strings must be escaped in the following
    considered relative and graph traversal will begin at the resource
    object supplied to the function as the ``resource`` argument.  If an
    empty string is passed as ``path``, the ``resource`` passed in will
    be returned.  Resource path strings must be escaped in the following
    manner: each Unicode path segment must be encoded as UTF-8 and
    each path segment must escaped via Python's :mod:`urllib.quote`.
    For example, ``/path/to%20the/La%20Pe%C3%B1a`` (absolute) or
    ``to%20the/La%20Pe%C3%B1a`` (relative).  The
    :func:`pyramid.traversal.model_path` function generates strings
    :func:`pyramid.traversal.resource_path` function generates strings
    which follow these rules (albeit only absolute ones).
    Rules for passing a *tuple* as the ``path`` argument: if the first
@@ -241,12 +250,12 @@
    traversal will start at the graph root object.  If the first
    element in the path tuple is not the empty string (for example
    ``('a', 'b', 'c')``), the path is considered relative and graph
    traversal will begin at the model object supplied to the function
    as the ``model`` argument.  If an empty sequence is passed as
    ``path``, the ``model`` passed in itself will be returned.  No
    traversal will begin at the resource object supplied to the function
    as the ``resource`` argument.  If an empty sequence is passed as
    ``path``, the ``resource`` passed in itself will be returned.  No
    URL-quoting or UTF-8-encoding of individual path segments within
    the tuple is required (each segment may be any string or unicode
    object representing a model name).
    object representing a resource name).
    Explanation of the conversion of ``path`` segment values to
    Unicode during traversal: Each segment is URL-unquoted, and
@@ -284,7 +293,7 @@
        path = path.encode('ascii')
    if path and path[0] == '/':
        model = find_root(model)
        resource = find_root(resource)
    reg = get_current_registry()
    
@@ -295,19 +304,19 @@
    request = request_factory.blank(path)
    request.registry = reg
    traverser = reg.queryAdapter(model, ITraverser)
    traverser = reg.queryAdapter(resource, ITraverser)
    if traverser is None:
        traverser = ModelGraphTraverser(model)
        traverser = ResourceTreeTraverser(resource)
    return traverser(request)
def model_path_tuple(model, *elements):
def resource_path_tuple(resource, *elements):
    """
    Return a tuple representing the absolute physical path of the
    ``model`` object based on its position in an object graph, e.g
    ``resource`` object based on its position in an object graph, e.g
    ``('', 'foo', 'bar')``.  Any positional arguments passed in as
    ``elements`` will be appended as elements in the tuple
    representing the model path.  For instance, if the model's
    representing the resource path.  For instance, if the resource's
    path is ``('', 'foo', 'bar')`` and elements equals ``('a', 'b')``,
    the returned tuple will be ``('', 'foo', 'bar', 'a', b')``.  The
    first element of this tuple will always be the empty string (a
@@ -315,52 +324,58 @@
    path is absolute).
    This function is a logical inverse of
    :func:`pyramid.traversal.find_model`: it can be used to
    :func:`pyramid.traversal.find_resource`: it can be used to
    generate path references that can later be resolved that function.
    The ``model`` passed in *must* be :term:`location`-aware.
    The ``resource`` passed in *must* be :term:`location`-aware.
    .. note:: Each segment in the path tuple returned will equal the
              ``__name__`` attribute of the model it represents within
              ``__name__`` attribute of the resource it represents within
              the graph.  Each of these segments *should* be a unicode
              or string object (as per the contract of
              :term:`location`-awareness).  However, no conversion or
              safety checking of model names is performed.  For
              instance, if one of the models in your graph has a
              safety checking of resource names is performed.  For
              instance, if one of the resources in your tree has a
              ``__name__`` which (by error) is a dictionary, that
              dictionary will be placed in the path tuple; no warning
              or error will be given.
    .. note:: The :term:`root` model *must* have a ``__name__``
    .. note:: The :term:`root` resource *must* have a ``__name__``
              attribute with a value of either ``None`` or the empty
              string for path tuples to be generated properly.  If
              the root model has a non-null ``__name__`` attribute,
              the root resource has a non-null ``__name__`` attribute,
              its name will be the first element in the generated
              path tuple rather than the empty string.
    """
    return tuple(_model_path_list(model, *elements))
def _model_path_list(model, *elements):
    """ Implementation detail shared by model_path and model_path_tuple """
    path = [loc.__name__ or '' for loc in lineage(model)]
    .. note:: For backwards compatibility purposes, this function can also
       be imported as ``model_path_tuple``.
    """
    return tuple(_resource_path_list(resource, *elements))
def _resource_path_list(resource, *elements):
    """ Implementation detail shared by resource_path and resource_path_tuple"""
    path = [loc.__name__ or '' for loc in lineage(resource)]
    path.reverse()
    path.extend(elements)
    return path
def virtual_root(model, request):
_model_path_list = _resource_path_list # b/w compat
def virtual_root(resource, request):
    """
    Provided any :term:`model` and a :term:`request` object, return
    the model object representing the :term:`virtual root` of the
    Provided any :term:`resource` and a :term:`request` object, return
    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
    ``http://example.com/`` instead of rooting it at
    ``http://example.com/cms/``.
    If the ``model`` passed in is a context obtained via
    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_model`
    '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
    ``HTTP_X_VHM_ROOT`` key is is not present in the WSGI environment,
@@ -370,16 +385,16 @@
    :term:`URL dispatch`. Contexts obtained via URL dispatch don't
    really support being virtually rooted (each URL dispatch context
    is both its own physical and virtual root).  However if this API
    is called with a ``model`` argument which is a context obtained
    via URL dispatch, the model passed in will be returned
    is called with a ``resource`` argument which is a context obtained
    via URL dispatch, the resource passed in will be returned
    unconditionally."""
    try:
        reg = request.registry
    except AttributeError:
        reg = get_current_registry() # b/c
    urlgenerator = reg.queryMultiAdapter((model, request), IContextURL)
    urlgenerator = reg.queryMultiAdapter((resource, request), IContextURL)
    if urlgenerator is None:
        urlgenerator = TraversalContextURL(model, request)
        urlgenerator = TraversalContextURL(resource, request)
    return urlgenerator.virtual_root()
@lru_cache(1000)
@@ -438,13 +453,13 @@
        (u'archives', u'<unprintable unicode>')
    .. note:: This function does not generate the same type of tuples
              that :func:`pyramid.traversal.model_path_tuple` does.
              that :func:`pyramid.traversal.resource_path_tuple` does.
              In particular, the leading empty string is not present
              in the tuple it returns, unlike tuples returned by
              :func:`pyramid.traversal.model_path_tuple`.  As a
              :func:`pyramid.traversal.resource_path_tuple`.  As a
              result, tuples generated by ``traversal_path`` are not
              resolveable by the
              :func:`pyramid.traversal.find_model` API.
              :func:`pyramid.traversal.find_resource` API.
              ``traversal_path`` is a function mostly used by the
              internals of :app:`Pyramid` and by people writing
              their own traversal machinery, as opposed to users
@@ -474,7 +489,7 @@
def quote_path_segment(segment):
    """ Return a quoted representation of a 'path segment' (such as
    the string ``__name__`` attribute of a model) as a string.  If the
    the string ``__name__`` attribute of a resource) as a string.  If the
    ``segment`` passed in is a unicode object, it is converted to a
    UTF-8 string, then it is URL-quoted using Python's
    ``urllib.quote``.  If the ``segment`` passed in is a string, it is
@@ -510,10 +525,10 @@
        _segment_cache[segment] = result
        return result
class ModelGraphTraverser(object):
    """ A model graph traverser that should be used (for speed) when
    every object in the graph supplies a ``__name__`` and
    ``__parent__`` attribute (ie. every object in the graph is
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
    :term:`location` aware) ."""
    implements(ITraverser)
@@ -616,9 +631,11 @@
                'traversed':vpath_tuple, 'virtual_root':vroot,
                'virtual_root_path':vroot_tuple, 'root':root}
ModelGraphTraverser = ResourceTreeTraverser # b/w compat
class TraversalContextURL(object):
    """ The IContextURL adapter used to generate URLs for a context
    object obtained via graph traversal"""
    object obtained via resource tree traversal"""
    implements(IContextURL)
    vroot_varname = VH_ROOT_KEY
@@ -631,7 +648,7 @@
        environ = self.request.environ
        vroot_varname = self.vroot_varname
        if vroot_varname in environ:
            return find_model(self.context, environ[vroot_varname])
            return find_resource(self.context, environ[vroot_varname])
        # shortcut instead of using find_root; we probably already
        # have it on the request
        try:
@@ -641,15 +658,15 @@
    def __call__(self):
        """ Generate a URL based on the :term:`lineage` of a
        :term:`model` object obtained via :term:`traversal`.  If any
        model in the context lineage has a Unicode name, it will be
        :term:`resource` object obtained via :term:`traversal`.  If any
        resource in the context lineage has a Unicode name, it will be
        converted to a UTF-8 string before being attached to the URL.
        If a ``HTTP_X_VHM_ROOT`` key is present in the WSGI
        environment, its value will be treated as a 'virtual root
        path': the path of the URL generated by this will be
        left-stripped of this virtual root path value.
        """
        path = model_path(self.context)
        path = resource_path(self.context)
        if path != '/':
            path = path + '/'
        request = self.request
pyramid/url.py
@@ -73,9 +73,9 @@
    If a keyword argument ``_anchor`` is present, its string
    representation will be used as a named anchor in the generated URL
    (e.g. if ``_anchor`` is passed as ``foo`` and the model URL is
    ``http://example.com/model/url``, the resulting generated URL will
    be ``http://example.com/model/url#foo``).
    (e.g. if ``_anchor`` is passed as ``foo`` and the route URL is
    ``http://example.com/route/url``, the resulting generated URL will
    be ``http://example.com/route/url#foo``).
    .. note:: If ``_anchor`` is passed as a string, it should be UTF-8
              encoded. If ``_anchor`` is passed as a Unicode object, it
@@ -181,42 +181,42 @@
    kw['_app_url'] = ''
    return route_url(route_name, request, *elements, **kw)
def model_url(model, request, *elements, **kw):
def resource_url(resource, request, *elements, **kw):
    """
    Generate a string representing the absolute URL of the ``model``
    Generate a string representing the absolute URL of the :term:`resource`
    object based on the ``wsgi.url_scheme``, ``HTTP_HOST`` or
    ``SERVER_NAME`` in the ``request``, plus any ``SCRIPT_NAME``.  The
    overall result of this function is always a UTF-8 encoded string
    (never Unicode).
    .. note:: Calling :meth:`pyramid.Request.model_url` can be used to
              achieve the same result as :func:`pyramid.url.model_url`.
    .. note:: Calling :meth:`pyramid.Request.resource_url` can be used to
              achieve the same result as :func:`pyramid.url.resource_url`.
    Examples::
        model_url(context, request) =>
        resource_url(context, request) =>
                                   http://example.com/
        model_url(context, request, 'a.html') =>
        resource_url(context, request, 'a.html') =>
                                   http://example.com/a.html
        model_url(context, request, 'a.html', query={'q':'1'}) =>
        resource_url(context, request, 'a.html', query={'q':'1'}) =>
                                   http://example.com/a.html?q=1
        model_url(context, request, 'a.html', anchor='abc') =>
        resource_url(context, request, 'a.html', anchor='abc') =>
                                   http://example.com/a.html#abc
    Any positional arguments passed in as ``elements`` must be strings
    or Unicode objects.  These will be joined by slashes and appended
    to the generated model URL.  Each of the elements passed in is
    to the generated resource URL.  Each of the elements passed in is
    URL-quoted before being appended; if any element is Unicode, it
    will converted to a UTF-8 bytestring before being URL-quoted.
    .. warning:: if no ``elements`` arguments are specified, the model
    .. warning:: if no ``elements`` arguments are specified, the resource
                 URL will end with a trailing slash.  If any
                 ``elements`` are used, the generated URL will *not*
                 end in trailing a slash.
@@ -241,9 +241,9 @@
    If a keyword argument ``anchor`` is present, its string
    representation will be used as a named anchor in the generated URL
    (e.g. if ``anchor`` is passed as ``foo`` and the model URL is
    ``http://example.com/model/url``, the resulting generated URL will
    be ``http://example.com/model/url#foo``).
    (e.g. if ``anchor`` is passed as ``foo`` and the resource URL is
    ``http://example.com/resource/url``, the resulting generated URL will
    be ``http://example.com/resource/url#foo``).
    .. note:: If ``anchor`` is passed as a string, it should be UTF-8
              encoded. If ``anchor`` is passed as a Unicode object, it
@@ -255,28 +255,31 @@
    will always follow the query element,
    e.g. ``http://example.com?foo=1#bar``.
    .. note:: If the ``model`` used is the result of a
    .. note:: If the :term:`resource` used is the result of a
             :term:`traversal`, it must be :term:`location`-aware.
             The ``model`` can also be the context of a :term:`URL
             The resource can also be the context of a :term:`URL
             dispatch`; contexts found this way do not need to be
             location-aware.
    .. note:: If a 'virtual root path' is present in the request
              environment (the value of the WSGI environ key
              ``HTTP_X_VHM_ROOT``), and the ``model`` was obtained via
              ``HTTP_X_VHM_ROOT``), and the resource was obtained via
              :term:`traversal`, the URL path will not include the
              virtual root prefix (it will be stripped off the
              left hand side of the generated URL).
    .. note:: For backwards compatibility purposes, this function can also
       be imported as ``model_url``.
    """
    try:
        reg = request.registry
    except AttributeError:
        reg = get_current_registry() # b/c
    
    context_url = reg.queryMultiAdapter((model, request), IContextURL)
    context_url = reg.queryMultiAdapter((resource, request), IContextURL)
    if context_url is None:
        context_url = TraversalContextURL(model, request)
    model_url = context_url()
        context_url = TraversalContextURL(resource, request)
    resource_url = context_url()
    qs = ''
    anchor = ''
@@ -295,15 +298,17 @@
    else:
        suffix = ''
    return model_url + suffix + qs + anchor
    return resource_url + suffix + qs + anchor
model_url = resource_url # b/w compat (forever)
def static_url(path, request, **kw):
    """
    Generates a fully qualified URL for a static :term:`resource`.
    The resource must live within a location defined via the
    Generates a fully qualified URL for a static :term:`asset`.
    The asset must live within a location defined via the
    :meth:`pyramid.config.Configurator.add_static_view`
    :term:`configuration declaration` or the ``<static>`` ZCML
    directive (see :ref:`static_resources_section`).
    directive (see :ref:`static_assets_section`).
    .. note:: Calling :meth:`pyramid.Request.static_url` can be used to
              achieve the same result as :func:`pyramid.url.static_url`.
@@ -317,7 +322,7 @@
    The ``path`` argument points at a file or directory on disk which
    a URL should be generated for.  The ``path`` may be either a
    relative path (e.g. ``static/foo.css``) or a :term:`resource
    relative path (e.g. ``static/foo.css``) or a :term:`asset
    specification` (e.g. ``mypackage:static/foo.css``).  A ``path``
    may not be an absolute filesystem path (a :exc:`ValueError` will
    be raised if this function is supplied with an absolute path).
@@ -328,7 +333,7 @@
    the :func:`pyramid.url.route_url` ``**kw`` argument.  See the
    documentation for that function to understand the arguments which
    you can provide to it.  However, typically, you don't need to pass
    anything as ``*kw`` when generating a static resource URL.
    anything as ``*kw`` when generating a static asset URL.
    This function raises a :exc:`ValueError` if a static view
    definition cannot be found which matches the path specification.
@@ -336,7 +341,7 @@
    """
    if os.path.isabs(path):
        raise ValueError('Absolute paths cannot be used to generate static '
                         'urls (use a package-relative path or a resource '
                         'urls (use a package-relative path or an asset '
                         'specification).')
    if not ':' in path:
        # if it's not a package:relative/name and it's not an
pyramid/view.py
@@ -147,9 +147,9 @@
    For example, this code in a module ``views.py``::
      from models import MyModel
      from resources import MyResource
      @view_config(name='my_view', context=MyModel, permission='read',
      @view_config(name='my_view', context=MyResource, permission='read',
                   route_name='site1')
      def my_view(context, request):
          return 'OK'
@@ -158,14 +158,14 @@
    :meth:`pyramid.config.Configurator.add_view` method::
       import views
       import models
       config.add_view(views.my_view, context=models.MyModel, name='my_view',
       from resources import MyResource
       config.add_view(views.my_view, context=MyResource, name='my_view',
                       permission='read', 'route_name='site1')
    Or might replace the following ZCML ``view`` declaration::
      <view
       for='.models.MyModel'
       for='.resources.MyResource'
       view='.views.my_view'
       name='my_view'
       permission='read'
pyramid/zcml.py
@@ -21,7 +21,7 @@
from pyramid.authorization import ACLAuthorizationPolicy
from pyramid.config import Configurator
from pyramid.exceptions import ConfigurationError
from pyramid.resource import resource_spec_from_abspath
from pyramid.asset import asset_spec_from_abspath
from pyramid.threadlocal import get_current_registry
###################### directives ##########################
@@ -402,23 +402,23 @@
                             wrapper=wrapper)
    
class IResourceDirective(Interface):
class IAssetDirective(Interface):
    """
    Directive for specifying that one package may override resources from
    Directive for specifying that one package may override assets from
    another package.
    """
    to_override = TextLine(
        title=u"Override spec",
        description=u'The spec of the resource to override.',
        description=u'The spec of the asset to override.',
        required=True)
    override_with = TextLine(
        title=u"With spec",
        description=u"The spec of the resource providing the override.",
        description=u"The spec of the asset providing the override.",
        required=True)
def resource(_context, to_override, override_with, _override=None):
def asset(_context, to_override, override_with, _override=None):
    config = Configurator.with_context(_context)
    config.override_resource(to_override, override_with, _override=_override)
    config.override_asset(to_override, override_with, _override=_override)
class IRepozeWho1AuthenticationPolicyDirective(Interface):
    identifier_name = TextLine(title=u'identitfier_name', required=False,
@@ -524,7 +524,7 @@
        required=True)
    path = TextLine(
        title=u'Path to the directory which contains resources',
        title=u'Path to the directory which contains assets',
        description=u'May be package-relative by using a colon to '
        'separate package name and path relative to the package directory.',
        required=True)
@@ -807,14 +807,14 @@
    config.set_default_permission(name)
def path_spec(context, path):
    # we prefer registering resource specifications over absolute
    # paths because these can be overridden by the resource directive.
    # we prefer registering asset specifications over absolute
    # paths because these can be overridden by the asset directive.
    if ':' in path and not os.path.isabs(path):
        # it's already a resource specification
        # it's already an asset specification
        return path
    abspath = context.path(path)
    if hasattr(context, 'package') and context.package:
        return resource_spec_from_abspath(abspath, context.package)
        return asset_spec_from_abspath(abspath, context.package)
    return abspath
def zcml_configure(name, package):