summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorChris McDonough <chrism@plope.com>2010-12-18 15:53:49 -0500
committerChris McDonough <chrism@plope.com>2010-12-18 15:53:49 -0500
commit738a2b5f3eb44da7036a31005144e5252827ac38 (patch)
tree80e10d2ae215b2e0e1f248354b6c9a5e11406cd5 /docs
parentaa6c4267b330a5665dcb7c98d75fe21f8eeececb (diff)
parent70119302324e5bf5627344f90c62ef31b6e43005 (diff)
downloadpyramid-738a2b5f3eb44da7036a31005144e5252827ac38.tar.gz
pyramid-738a2b5f3eb44da7036a31005144e5252827ac38.tar.bz2
pyramid-738a2b5f3eb44da7036a31005144e5252827ac38.zip
Merge branch 'model2resource'
Conflicts: docs/narr/views.rst
Diffstat (limited to 'docs')
-rw-r--r--docs/api/config.rst6
-rw-r--r--docs/api/request.rst2
-rw-r--r--docs/api/testing.rst4
-rw-r--r--docs/api/traversal.rst6
-rw-r--r--docs/api/url.rst2
-rw-r--r--docs/designdefense.rst131
-rw-r--r--docs/glossary.rst114
-rw-r--r--docs/index.rst4
-rw-r--r--docs/latexindex.rst6
-rw-r--r--docs/narr/MyProject/myproject/__init__.py6
-rw-r--r--docs/narr/MyProject/myproject/models.py7
-rw-r--r--docs/narr/MyProject/myproject/resources.py3
-rw-r--r--docs/narr/assets.rst198
-rw-r--r--docs/narr/contextfinding.rst18
-rw-r--r--docs/narr/declarative.rst123
-rw-r--r--docs/narr/environment.rst88
-rw-r--r--docs/narr/extending.rst10
-rw-r--r--docs/narr/handlers.rst4
-rw-r--r--docs/narr/hooks.rst42
-rw-r--r--docs/narr/hybrid.rst51
-rw-r--r--docs/narr/introduction.rst27
-rw-r--r--docs/narr/models.rst331
-rw-r--r--docs/narr/project.rst69
-rw-r--r--docs/narr/resources.rst465
-rw-r--r--docs/narr/resourcetreetraverser.png (renamed from docs/narr/modelgraphtraverser.png)bin232233 -> 232233 bytes
-rw-r--r--docs/narr/security.rst67
-rw-r--r--docs/narr/static.rst197
-rw-r--r--docs/narr/templates.rst57
-rw-r--r--docs/narr/threadlocals.rst8
-rw-r--r--docs/narr/traversal.rst202
-rw-r--r--docs/narr/unittesting.rst37
-rw-r--r--docs/narr/urldispatch.rst14
-rw-r--r--docs/narr/vhosting.rst28
-rw-r--r--docs/narr/views.rst269
-rw-r--r--docs/narr/zca.rst2
-rw-r--r--docs/tutorials/catalog/index.rst4
-rw-r--r--docs/tutorials/wiki/basiclayout.rst14
-rw-r--r--docs/tutorials/wiki/definingmodels.rst22
-rw-r--r--docs/tutorials/wiki/definingviews.rst18
-rw-r--r--docs/tutorials/wiki/src/authorization/tutorial/login.py6
-rw-r--r--docs/tutorials/wiki/src/authorization/tutorial/tests.py25
-rw-r--r--docs/tutorials/wiki/src/authorization/tutorial/views.py16
-rw-r--r--docs/tutorials/wiki/src/viewdecorators/tutorial/tests.py25
-rw-r--r--docs/tutorials/wiki/src/viewdecorators/tutorial/views.py16
-rw-r--r--docs/tutorials/wiki/src/views/tutorial/tests.py24
-rw-r--r--docs/tutorials/wiki/src/views/tutorial/views.py16
-rw-r--r--docs/tutorials/wiki2/definingmodels.rst12
-rw-r--r--docs/zcml.rst2
-rw-r--r--docs/zcml/aclauthorizationpolicy.rst2
-rw-r--r--docs/zcml/asset.rst (renamed from docs/zcml/resource.rst)33
-rw-r--r--docs/zcml/forbidden.rst2
-rw-r--r--docs/zcml/handler.rst2
-rw-r--r--docs/zcml/notfound.rst2
-rw-r--r--docs/zcml/route.rst4
-rw-r--r--docs/zcml/view.rst12
55 files changed, 1393 insertions, 1462 deletions
diff --git a/docs/api/config.rst b/docs/api/config.rst
index 64dc4d0dd..fd8e1042d 100644
--- a/docs/api/config.rst
+++ b/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
diff --git a/docs/api/request.rst b/docs/api/request.rst
index acd66ccf8..13b434a51 100644
--- a/docs/api/request.rst
+++ b/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.
diff --git a/docs/api/testing.rst b/docs/api/testing.rst
index fc4b76cc7..fdcdadee8 100644
--- a/docs/api/testing.rst
+++ b/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
diff --git a/docs/api/traversal.rst b/docs/api/traversal.rst
index b89691847..cd4765e04 100644
--- a/docs/api/traversal.rst
+++ b/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
diff --git a/docs/api/url.rst b/docs/api/url.rst
index 8c702a3fb..1aa3082b7 100644
--- a/docs/api/url.rst
+++ b/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
diff --git a/docs/designdefense.rst b/docs/designdefense.rst
index 1a8868883..5aa149824 100644
--- a/docs/designdefense.rst
+++ b/docs/designdefense.rst
@@ -606,77 +606,48 @@ folks that haven't yet spent that 30 minutes.
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.
-
-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`.
-
-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).
-
-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.
-
-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.
+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 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
+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), 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 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 @@ top of your object graph (or any administrative interface), you can register
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 @@ which match information in an associated "urlconf" such as
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 @@ frameworks have some sort of event system hooked up that lets the view
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 @@ access. I like this, because it means:
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
diff --git a/docs/glossary.rst b/docs/glossary.rst
index 2494a6cdf..a27d73766 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -38,20 +38,20 @@ Glossary
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 @@ Glossary
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 @@ Glossary
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 @@ Glossary
: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 @@ Glossary
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 @@ Glossary
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 @@ Glossary
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 @@ Glossary
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 @@ Glossary
: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.
diff --git a/docs/index.rst b/docs/index.rst
index 073a562ca..3add95117 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -48,7 +48,7 @@ Narrative documentation in chapter form explaining how to use
narr/webob
narr/sessions
narr/templates
- narr/models
+ narr/resources
narr/security
narr/i18n
narr/vhosting
@@ -58,7 +58,7 @@ Narrative documentation in chapter form explaining how to use
narr/hooks
narr/declarative
narr/extending
- narr/resources
+ narr/assets
narr/router
narr/threadlocals
narr/zca
diff --git a/docs/latexindex.rst b/docs/latexindex.rst
index 0ef67248b..09e449fe3 100644
--- a/docs/latexindex.rst
+++ b/docs/latexindex.rst
@@ -41,7 +41,7 @@ Narrative Documentation
narr/webob
narr/sessions
narr/templates
- narr/models
+ narr/resources
narr/security
narr/i18n
narr/vhosting
@@ -51,7 +51,7 @@ Narrative Documentation
narr/hooks
narr/declarative
narr/extending
- narr/resources
+ narr/assets
narr/router
narr/startup
narr/threadlocals
@@ -119,6 +119,7 @@ ZCML Directive Reference
zcml/aclauthorizationpolicy
zcml/adapter
zcml/authtktauthenticationpolicy
+ zcml/asset
zcml/configure
zcml/default_permission
zcml/forbidden
@@ -127,7 +128,6 @@ ZCML Directive Reference
zcml/remoteuserauthenticationpolicy
zcml/renderer
zcml/repozewho1authenticationpolicy
- zcml/resource
zcml/route
zcml/scan
zcml/static
diff --git a/docs/narr/MyProject/myproject/__init__.py b/docs/narr/MyProject/myproject/__init__.py
index 05730a115..813028704 100644
--- a/docs/narr/MyProject/myproject/__init__.py
+++ b/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()
diff --git a/docs/narr/MyProject/myproject/models.py b/docs/narr/MyProject/myproject/models.py
deleted file mode 100644
index 75dec7505..000000000
--- a/docs/narr/MyProject/myproject/models.py
+++ /dev/null
@@ -1,7 +0,0 @@
-class MyModel(object):
- pass
-
-root = MyModel()
-
-def get_root(request):
- return root
diff --git a/docs/narr/MyProject/myproject/resources.py b/docs/narr/MyProject/myproject/resources.py
new file mode 100644
index 000000000..3d811895c
--- /dev/null
+++ b/docs/narr/MyProject/myproject/resources.py
@@ -0,0 +1,3 @@
+class Root(object):
+ def __init__(self, request):
+ self.request = request
diff --git a/docs/narr/assets.rst b/docs/narr/assets.rst
new file mode 100644
index 000000000..1932e19ff
--- /dev/null
+++ b/docs/narr/assets.rst
@@ -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.
+
diff --git a/docs/narr/contextfinding.rst b/docs/narr/contextfinding.rst
index 691ad7b8e..ad0d1f9da 100644
--- a/docs/narr/contextfinding.rst
+++ b/docs/narr/contextfinding.rst
@@ -95,20 +95,20 @@ don't deal very well with URLs that represent arbitrary-depth
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.
diff --git a/docs/narr/declarative.rst b/docs/narr/declarative.rst
index 99c5a75ac..28dec4ff1 100644
--- a/docs/narr/declarative.rst
+++ b/docs/narr/declarative.rst
@@ -557,7 +557,7 @@ example of a view declaration in ZCML is as follows:
:linenos:
<view
- context=".models.Hello"
+ context=".resources.Hello"
view=".views.hello_world"
name="hello.html"
/>
@@ -566,7 +566,7 @@ The above maps the ``.views.hello_world`` view callable function to
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 @@ the following set of :term:`context finding` results:
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 @@ string as its ``name`` attribute:
:linenos:
<view
- context=".models.Hello"
+ context=".resources.Hello"
view=".views.hello_world"
name=""
/>
@@ -721,19 +720,19 @@ documentation.
.. 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 @@ absolute path.
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 @@ package-relative path.
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 @@ While the ``path`` argument can be a number of different things, the
``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,9 +819,78 @@ detail later in this chapter.
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:
Enabling an Authorization Policy Via ZCML
@@ -833,12 +901,11 @@ than imperative configuration, modify the ZCML file loaded by your
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 @@ Built-In Authorization Policy ZCML Directives
``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:
@@ -1069,7 +1136,6 @@ with ``.jinja2`` as its ``renderer`` value. The ``name`` passed to the
See also :ref:`renderer_directive` and
:meth:`pyramid.config.Configurator.add_renderer`.
-
Overriding an Existing Renderer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1207,4 +1273,3 @@ See also :ref:`subscriber_directive` and :ref:`events_chapter`.
.. - hooks chapter still has topics for ZCML
-.. - resources chapter still has topics for ZCML
diff --git a/docs/narr/environment.rst b/docs/narr/environment.rst
index 08fa7af44..0c6f3dd03 100644
--- a/docs/narr/environment.rst
+++ b/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,21 +52,25 @@ template rendering extensions.
| | |
+---------------------------------+-----------------------------+
-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 @@ Mako Directories
++++++++++++++++
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 @@ affect settings that do not start with ``reload_*`` such as
.. index::
single: reload_templates
- single: reload_resources
-
-Understanding the Distinction Between ``reload_templates`` and ``reload_resources``
------------------------------------------------------------------------------------
-
-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.
-
-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).
-
-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.
+ single: reload_assets
+
+Understanding the Distinction Between ``reload_templates`` and ``reload_assets``
+--------------------------------------------------------------------------------
+
+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_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_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.
diff --git a/docs/narr/extending.rst b/docs/narr/extending.rst
index 1f9fd1288..9802a01f6 100644
--- a/docs/narr/extending.rst
+++ b/docs/narr/extending.rst
@@ -191,15 +191,15 @@ the original application with slight tweaks. For example:
: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
diff --git a/docs/narr/handlers.rst b/docs/narr/handlers.rst
index f6e658cf0..5b6f71984 100644
--- a/docs/narr/handlers.rst
+++ b/docs/narr/handlers.rst
@@ -100,7 +100,7 @@ Using :meth:`~pyramid.config.Configurator.add_handler`
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 @@ For example:
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.
diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst
index 10f463a17..006f5d5cb 100644
--- a/docs/narr/hooks.rst
+++ b/docs/narr/hooks.rst
@@ -88,11 +88,10 @@ callable:
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 @@ a class that implements the following interface:
""" 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 @@ traverser would be used. For example:
<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 @@ of :term:`context` by adding an adapter stanza for
<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).
diff --git a/docs/narr/hybrid.rst b/docs/narr/hybrid.rst
index da77a28f0..f9dab9ff6 100644
--- a/docs/narr/hybrid.rst
+++ b/docs/narr/hybrid.rst
@@ -171,7 +171,7 @@ match is straightforward. When a route is matched:
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 @@ we've created a root factory that looks like so in a module named
.. code-block:: python
:linenos:
- class Traversable(object):
+ class Resource(object):
def __init__(self, subobjects):
self.subobjects = subobjects
@@ -234,15 +234,15 @@ we've created a root factory that looks like so in a module named
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 @@ route configuration statement:
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 @@ thing to do.
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 @@ against the root object will be ``a/b/c``. As a result,
: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 @@ above ``mypackage.views.another_view`` view will be invoked when:
- 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.
diff --git a/docs/narr/introduction.rst b/docs/narr/introduction.rst
index 7c725690d..3ade3726c 100644
--- a/docs/narr/introduction.rst
+++ b/docs/narr/introduction.rst
@@ -144,10 +144,9 @@ it only supplies a mechanism to map URLs to :term:`view` code, along
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 @@ frameworks, :app:`Pyramid` also generally fits into this class.
.. 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.
diff --git a/docs/narr/models.rst b/docs/narr/models.rst
deleted file mode 100644
index 91828287f..000000000
--- a/docs/narr/models.rst
+++ /dev/null
@@ -1,331 +0,0 @@
-Models
-======
-
-A :term:`model` class is typically a simple Python class defined in a module.
-References to these classes and instances of such classes are omnipresent in
-:app:`Pyramid` when :term:`traversal` is used to build an application:
-
-- Model instances make up the object graph that :app:`Pyramid`
- will walk over when :term:`traversal` is used.
-
-- The ``context`` and ``containment`` arguments to
- :meth:`pyramid.config.Configurator.add_view` often
- reference a model class.
-
-- A :term:`root factory` returns a model instance.
-
-- A model instance is exposed to :term:`view` code as the :term:`context` of
- a view.
-
-In many :term:`traversal` based applications (particularly ones that use
-Zope-like patterns), model objects often store data and offer methods related
-to mutating that data.
-
-.. note::
-
- A terminology overlap confuses people who write applications that
- always use ORM packages such as SQLAlchemy, which has a very
- different notion of the definition of a "model". When using the API
- of common ORM packages, its conception of "model" is almost
- certainly not the same conception of "model" used by
- :app:`Pyramid`. In particular, it can be unnatural to think of
- :app:`Pyramid` model objects as "models" if you develop your
- application using :term:`traversal` and a relational database. When
- you develop such applications, the object graph *might* be composed
- completely of "model" objects (as defined by the ORM) but it also
- might not be. The things that :app:`Pyramid` refers to as
- "models" in such an application may instead just be stand-ins that
- perform a query and generate some wrapper *for* an ORM "model" or
- set of ORM models. This naming overlap is slightly unfortunate.
- However, many :app:`Pyramid` applications (especially ones which
- use :term:`ZODB`) do indeed traverse a graph full of literal 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. However, if we had it to do
- all over again, we'd probably call these objects something
- different to avoid confusion.
-
-.. index::
- single: model constructor
-
-Defining a Model Constructor
-----------------------------
-
-An example of a model constructor, ``BlogEntry`` is presented below.
-It is implemented as a class which, when instantiated, becomes a model
-instance.
-
-.. code-block:: python
- :linenos:
-
- import datetime
-
- class BlogEntry(object):
- def __init__(self, title, body, author):
- self.title = title
- self.body = body
- self.author = author
- self.created = datetime.datetime.now()
-
-A model constructor may be essentially any Python object which is
-callable, and which returns a model instance. In the above example,
-the ``BlogEntry`` class can be called, returning a model instance.
-
-.. index::
- single: model interfaces
-
-.. _models_which_implement_interfaces:
-
-Model Instances Which Implement Interfaces
-------------------------------------------
-
-Model instances can optionally be made to implement an
-:term:`interface`. An interface is used to tag a model object with a
-"type" that can later be referred to within :term:`view
-configuration`.
-
-Specifying an interface instead of a class as the ``context`` or
-``containment`` arguments within :term:`view configuration` statements
-effectively makes it possible to use a single view callable for more
-than one class of 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:
-
- import datetime
- from zope.interface import implements
- from zope.interface import Interface
-
- class IBlogEntry(Interface):
- pass
-
- 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 model consists of two things: the class which defines the model
-constructor (above 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 model class may *implement* zero or more interfaces. You specify
-that a model implements an interface by using the
-:func:`zope.interface.implements` function at class scope. The above
-``BlogEntry`` model implements the ``IBlogEntry`` interface.
-
-You can also specify that a *particular* model instance provides an
-interface, as opposed to its class as above, which implies that all
-instances do. To do so, use the :func:`zope.interface.directlyProvides`
-function:
-
-.. code-block:: python
- :linenos:
-
- from zope.interface import directlyProvides
- from zope.interface import Interface
-
- class IBlogEntry(Interface):
- pass
-
- 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 model
-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:
-
- from zope.interface import alsoProvides
- from zope.interface import directlyProvides
- from zope.interface import Interface
-
- class IBlogEntry1(Interface):
- pass
-
- class IBlogEntry2(Interface):
- pass
-
- 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, IBlogEntry1)
- alsoProvides(entry, IBlogEntry2)
-
-: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.
-
-For more information about how model interfaces can be used by view
-configuration, see :ref:`using_model_interfaces`.
-
-.. index::
- single: model graph
- single: traversal graph
- single: object graph
- single: container nodes
- single: leaf nodes
-
-Defining a Graph of Model Instances for Traversal
--------------------------------------------------
-
-When :term:`traversal` is used (as opposed to a purely :term:`url
-dispatch` based application), :app:`Pyramid` expects to be able to
-traverse a graph composed of model instances. Traversal begins at a
-root model instance, and descends into the graph recursively via each
-found model's ``__getitem__`` method. :app:`Pyramid` imposes the
-following policy on model instance nodes in the graph:
-
-- Container nodes (i.e., nodes which contain other nodes) must supply
- a ``__getitem__`` method which is willing to resolve a unicode name
- to a subobject. If a subobject by that name does not exist in the
- container, ``__getitem__`` must raise a :exc:`KeyError`. If a
- subobject by that name *does* exist, the container should return the
- subobject (another model instance).
-
-- Leaf nodes, which do not contain other nodes, must not
- implement a ``__getitem__``, or if they do, their ``__getitem__``
- method must raise a :exc:`KeyError`.
-
-See :ref:`traversal_chapter` for more information about how traversal
-works against model instances.
-
-.. index::
- pair: location-aware; model
-
-.. _location_aware:
-
-Location-Aware Model Instances
-------------------------------
-
-Applications which use :term:`traversal` to locate the :term:`context`
-of a view must ensure that the model instances that make up the model
-graph 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 model instances in
-an object graph, all nodes in the graph must be :term:`location` -aware.
-This means they must have two attributes: ``__parent__`` and
-``__name__``.
-
-The ``__parent__`` attribute should be a reference to the node's
-parent model instance in the graph. The ``__name__`` attribute should
-be the name that a node's parent refers to the node via
-``__getitem__``.
-
-The ``__parent__`` of the root object should be ``None`` and its
-``__name__`` should be the empty string. For instance:
-
-.. code-block:: python
- :linenos:
-
- class MyRootObject(object):
- __name__ = ''
- __parent__ = None
-
-A node returned from the root item's ``__getitem__`` method should have
-a ``__parent__`` attribute that is a reference to the root object, and
-its ``__name__`` attribute should match the name by which it is
-reachable via the root object's ``__getitem__``. A container under the
-root should have a ``__getitem__`` that returns objects 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 down the graph.
-
-The ``__parent__`` attributes of each node 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 node in the traversal graph, you will eventually
-come to the root node, just like if you keep executing the
-``cd ..`` filesystem command, eventually you will reach the
-filesystem root directory.
-
-.. warning:: If your root model object has a ``__name__`` argument
- that is not ``None`` or the empty string, URLs returned by the
- :func:`pyramid.url.model_url` function and paths generated by
- the :func:`pyramid.traversal.model_path` and
- :func:`pyramid.traversal.model_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).
-
-.. sidebar:: Using :mod:`pyramid_traversalwrapper`
-
- If you'd rather not manage the ``__name__`` and ``__parent__``
- attributes of your models "by hand", an add-on package named
- :mod:`pyramid_traversalwrapper` can help.
-
- 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.
-
- Once :app:`Pyramid` is configured with this feature, you will no
- longer need to manage the ``__parent__`` and ``__name__`` attributes
- on graph objects "by hand". Instead, as necessary, during traversal
- :app:`Pyramid` will wrap each object (even the root object) in a
- ``LocationProxy`` which will dynamically assign a ``__name__`` and a
- ``__parent__`` to the traversed object (based on the last traversed
- object and the name supplied to ``__getitem__``). The root object
- will have a ``__name__`` attribute of ``None`` and a ``__parent__``
- attribute of ``None``.
-
-.. index::
- single: model API functions
- single: url generation (traversal)
-
-:app:`Pyramid` API Functions That Act Against Models
--------------------------------------------------------
-
-A model instance is used as the :term:`context` provided to a view. See
-:ref:`traversal_chapter` and :ref:`urldispatch_chapter` for more information
-about how a model instance becomes the context.
-
-The APIs provided by :ref:`traversal_module` are used against model
-instances. These functions can be used to find the "path" of a model,
-the root model in an object graph, or generate a URL to a model.
-
-The APIs provided by :ref:`location_module` are used against model
-instances. These can be used to walk down an object graph, or
-conveniently locate one object "inside" another.
-
-Some APIs in :ref:`security_module` accept a model object as a
-parameter. For example, the
-:func:`pyramid.security.has_permission` API accepts a "context" (a
-model object) as one of its arguments; the ACL is obtained from this
-model 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 model.
-
diff --git a/docs/narr/project.rst b/docs/narr/project.rst
index 2b03f7373..ff03a57b8 100644
--- a/docs/narr/project.rst
+++ b/docs/narr/project.rst
@@ -258,8 +258,8 @@ The Interactive Shell
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 @@ the name ``MyProject`` as a section name:
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 @@ structure:
|-- development.ini
|-- myproject
| |-- __init__.py
- | |-- models.py
+ | |-- resources.py
| |-- static
| | |-- favicon.ico
| | |-- logo.png
@@ -738,7 +738,7 @@ The ``myproject`` :term:`package` lives inside the ``MyProject``
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 @@ also informs Python that the directory which contains it is a *package*.
#. 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 @@ also informs Python that the directory which contains it is a *package*.
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 @@ code which accepts a :term:`request` and which returns a
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 @@ renderers, and templates relate and cooperate.
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.
-
-#. 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``.
+#. 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.
-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
diff --git a/docs/narr/resources.rst b/docs/narr/resources.rst
index c87157472..21ba97c9e 100644
--- a/docs/narr/resources.rst
+++ b/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:`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).
+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.
+
+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`.
+
+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.
+
+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.
+
+Also:
+
+- 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`.
+
+- A :term:`root factory` returns a resource.
+
+- A resource is exposed to :term:`view` code as the :term:`context` of a
+ view.
-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.
-
-.. _understanding_resources:
+.. index::
+ single: resource constructor
-Understanding Resources
------------------------
+Defining a Resource Constructor
+-------------------------------
-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:
+An example of a resource constructor, ``BlogEntry`` is presented below. It
+is implemented as a class which, when instantiated, becomes a resource
+instance.
-.. 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``)
+ import datetime
-- The *resource name* (``templates/some_template.pt``)
+ class BlogEntry(object):
+ def __init__(self, title, body, author):
+ self.title = title
+ self.body = body
+ self.author = author
+ self.created = datetime.datetime.now()
-: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 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::
- pair: overriding; resources
+ single: resource interfaces
-.. _overriding_resources_section:
+.. _resources_which_implement_interfaces:
-Overriding Resources
---------------------
+Resources Which Implement Interfaces
+------------------------------------
-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.
+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`.
-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:
+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.
-- Individual :term:`Chameleon` templates.
+For example, here's some code which describes a blog entry which also
+declares that the blog entry implements an :term:`interface`.
-- A directory containing multiple Chameleon templates.
+.. code-block:: python
+ :linenos:
-- Individual static files served up by an instance of the
- ``pyramid.view.static`` helper class.
+ import datetime
+ from zope.interface import implements
+ from zope.interface import Interface
-- A directory of static files served up by an instance of the
- ``pyramid.view.static`` helper class.
+ class IBlogEntry(Interface):
+ pass
-- Any other resource (or set of resources) addressed by code that uses
- the setuptools :term:`pkg_resources` API.
+ 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()
-.. index::
- single: override_resource
+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.
-.. _override_resource:
+The interface object used must be an instance of a class that inherits from
+:class:`zope.interface.Interface`.
-The ``override_resource`` API
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+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.
-An individual call to
-:meth:`pyramid.config.Configurator.override_resource` can
-override a single resource. For example:
+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:
-.. ignore-next-block
.. code-block:: python
:linenos:
- config.override_resource(
- to_override='some.package:templates/mytemplate.pt',
- override_with='another.package:othertemplates/anothertemplate.pt')
+ from zope.interface import directlyProvides
+ 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
-.. code-block:: python
- :linenos:
+ class BlogEntry(object):
+ def __init__(self, title, body, author):
+ self.title = title
+ self.body = body
+ self.author = author
+ self.created = datetime.datetime.now()
- config.override_resource(to_override='some.package',
- override_with='another.package')
+ entry = BlogEntry('title', 'body', 'author')
+ directlyProvides(entry, IBlogEntry)
-Individual subdirectories within a package can also be overridden:
+: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:
-.. ignore-next-block
.. 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
-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 IBlogEntry1(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 IBlogEntry2(Interface):
+ pass
-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.
-
-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:
+ class BlogEntry(object):
+ def __init__(self, title, body, author):
+ self.title = title
+ self.body = body
+ self.author = author
+ self.created = datetime.datetime.now()
- config.override_resource(to_override='.subpackage:templates/',
- override_with='another.package:templates/')
+ entry = BlogEntry('title', 'body', 'author')
+ directlyProvides(entry, IBlogEntry1)
+ alsoProvides(entry, IBlogEntry2)
-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.
+: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.
-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
+
+Defining a Resource Tree
+------------------------
+
+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:
+
+- 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.
+
+- 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`.
+
+See :ref:`traversal_chapter` for more information about how traversal
+works against resource instances.
-.. _resource_zcml_directive:
+.. index::
+ pair: location-aware; resource
-The ``resource`` ZCML Directive
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.. _location_aware:
-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``.
+Location-Aware Resources
+------------------------
-An individual :app:`Pyramid` ``resource`` ZCML statement can
-override a single resource. For example:
+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".
-.. code-block:: xml
- :linenos:
+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__``.
- <resource
- to_override="some.package:templates/mytemplate.pt"
- override_with="another.package:othertemplates/anothertemplate.pt"
- />
+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 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:
+The ``__parent__`` of the root resource should be ``None`` and its
+``__name__`` should be the empty string. For instance:
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <resource
- to_override="some.package"
- override_with="another.package"
- />
-
-Individual subdirectories within a package can also be overridden:
+ class MyRootResource(object):
+ __name__ = ''
+ __parent__ = None
+
+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.
+
+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.
+
+.. 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).
+
+.. sidebar:: Using :mod:`pyramid_traversalwrapper`
+
+ 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.
+
+ 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.
+
+ 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``.
-.. code-block:: xml
- :linenos:
+.. index::
+ single: resource API functions
+ single: url generation (traversal)
- <resource
- to_override="some.package:templates/"
- override_with="another.package:othertemplates/"
- />
+:app:`Pyramid` API Functions That Act Against Resources
+-------------------------------------------------------
-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.
+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.
-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:
+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.
-.. code-block:: xml
- :linenos:
+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.
- <resource
- to_override=".subpackage:templates/"
- override_with="another.package:templates/"
- />
+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.
-See also :ref:`resource_directive`.
diff --git a/docs/narr/modelgraphtraverser.png b/docs/narr/resourcetreetraverser.png
index 037d12b18..037d12b18 100644
--- a/docs/narr/modelgraphtraverser.png
+++ b/docs/narr/resourcetreetraverser.png
Binary files differ
diff --git a/docs/narr/security.rst b/docs/narr/security.rst
index 5edbc3ec3..469d3d298 100644
--- a/docs/narr/security.rst
+++ b/docs/narr/security.rst
@@ -92,11 +92,11 @@ For example:
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 @@ permission using the :meth:`pyramid.config.Configurator.add_view` API:
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 @@ may be performed via the ``@view_config`` decorator:
: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 @@ When a default permission is registered:
.. _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 @@ class:
(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 @@ Or, if your models are persistent, an ACL might be specified via the
(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 @@ the following:
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:
diff --git a/docs/narr/static.rst b/docs/narr/static.rst
index 172fb08d4..6b03b2349 100644
--- a/docs/narr/static.rst
+++ b/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 @@ path.
# 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 @@ specification`.
# 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 @@ subdirectories recursively, and any subdirectories may hold files; these will
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 @@ imperative configuration for the same purpose.
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 @@ For example, let's assume you create a set of static declarations like so:
.. 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 @@ to generate them for you. For example:
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 @@ constructing static URLs "by hand" is that if you need to change the ``name``
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 @@ instead of a view name. For example, the ``name`` argument may be
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 @@ resources which begin with ``mypackage:images`` will be prefixed with
# -> http://example.com/images/logo.png
.. index::
- single: static resource view
-
-Advanced: Serving Static Resources 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.
-
-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.
+ single: static assets view
+
+Advanced: Serving Static Assets Using a View Callable
+-----------------------------------------------------
+
+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 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 @@ your application root as below.
.. 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" (``@@``).
diff --git a/docs/narr/templates.rst b/docs/narr/templates.rst
index 09b9bfc51..adec9aa0c 100644
--- a/docs/narr/templates.rst
+++ b/docs/narr/templates.rst
@@ -84,9 +84,9 @@ prefix on Windows.
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 @@ address template resources which live in another package. For example:
{'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 @@ combination as shown above.
: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 @@ to specify the template as a :term:`renderer` in your
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 @@ template renderer:
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 @@ Similar renderer configuration can be done imperatively and via
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 @@ works in these templates.
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 @@ on, an exception resulting from the same problem might end like so:
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
diff --git a/docs/narr/threadlocals.rst b/docs/narr/threadlocals.rst
index f540fa255..171eaa1c7 100644
--- a/docs/narr/threadlocals.rst
+++ b/docs/narr/threadlocals.rst
@@ -110,11 +110,9 @@ follows:
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
diff --git a/docs/narr/traversal.rst b/docs/narr/traversal.rst
index 01729c4bd..9bc6014cd 100644
--- a/docs/narr/traversal.rst
+++ b/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 @@ can run the ``cat`` command:
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 @@ Traversal treats the ``PATH_INFO`` segment of a URL as a sequence of
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 @@ This process continues until the path segment sequence is exhausted or
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 @@ request. How :app:`Pyramid` performs view lookup is explained
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 @@ alternately be passed to the ``Configurator`` as a :term:`dotted
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 @@ root factory always returns an object that has no child nodes.
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`.
-
-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.
-
-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
+ 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`.
+
+.. note::
+
+ 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 @@ This section will attempt to explain the :app:`Pyramid` traversal
algorithm. We'll provide a description of the algorithm, a diagram of
how the algorithm works, and some example traversal scenarios that
might help you understand how the algorithm operates against a
-specific 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 @@ and a :term:`view name`.
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 @@ and a :term:`view name`.
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 traversal algorithm exposes two special cases:
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 @@ Traversal Algorithm Examples
No one can be expected to understand the traversal algorithm by
analogy and description alone, so let's examine some traversal
-scenarios that use concrete URLs and 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 @@ Let's say that view lookup finds no matching view type. In this
circumstance, the :app:`Pyramid` :term:`router` returns the result
of the :term:`not found view` and the request ends.
-However, for this graph:
+However, for this tree:
.. code-block:: text
@@ -537,6 +533,6 @@ The :mod:`pyramid.traversal` module contains API functions that
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.
diff --git a/docs/narr/unittesting.rst b/docs/narr/unittesting.rst
index 3c31f69b6..6a721f403 100644
--- a/docs/narr/unittesting.rst
+++ b/docs/narr/unittesting.rst
@@ -12,23 +12,22 @@ your application. In this context, a "unit" is often a function or a
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 @@ sure to use this pattern in your test case's ``setUp`` and
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.
diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst
index f0ace76ba..739a826c1 100644
--- a/docs/narr/urldispatch.rst
+++ b/docs/narr/urldispatch.rst
@@ -375,7 +375,7 @@ order of route configuration declarations is very important.
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 @@ found via :term:`view lookup`.
: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 @@ represent neither predicates nor view configuration information.
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 @@ represent neither predicates nor view configuration information.
``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 @@ An example of using a route with a factory:
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
diff --git a/docs/narr/vhosting.rst b/docs/narr/vhosting.rst
index d1fd1b382..65168806e 100644
--- a/docs/narr/vhosting.rst
+++ b/docs/narr/vhosting.rst
@@ -85,21 +85,19 @@ Virtual Root Support
: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``).
-
-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.
+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 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
diff --git a/docs/narr/views.rst b/docs/narr/views.rst
index ce2884599..cda6de48b 100644
--- a/docs/narr/views.rst
+++ b/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 @@ a request made to your application.
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 @@ represent the method expected to return a response, you can use an
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 @@ You can configure a view to use the JSON renderer by naming ``json`` as the
config.add_view('myproject.views.hello_world',
name='hello',
- context='myproject.models.Hello',
+ context='myproject.resources.Hello',
renderer='json')
@@ -494,22 +491,21 @@ attributes by attaching properties to the request. See
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 @@ renderer:
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 @@ renderer:
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 @@ The dictionary items will then be used in the global template space. If the
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 @@ Here's an example view configuration which uses a relative path:
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 @@ It's important to note that in Mako's case, the 'relative' path name
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 @@ factory constructor is available as :class:`pyramid.interfaces.IRendererInfo`.
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.
+
+- 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.
-.. sidebar:: Resource Specifications
+.. sidebar:: Asset Specifications
- 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`.
+ 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 @@ Non-Predicate Arguments
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.
-
- 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.
+``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:`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 @@ the usage of the configured view.
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 @@ the usage of the configured view.
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 @@ reside in a :app:`Pyramid` application module ``views.py``:
.. 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 @@ configuration stanza:
: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 @@ All arguments to ``view_config`` may be omitted. For example:
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 @@ such an object. All other arguments are optional. See
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 @@ the interface with the class.
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 @@ in such a way that the interface is attached to it.
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 @@ this interface.
# 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 @@ using :meth:`pyramid.config.Configurator.add_view`:
# 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
diff --git a/docs/narr/zca.rst b/docs/narr/zca.rst
index c930ecc50..f330fd551 100644
--- a/docs/narr/zca.rst
+++ b/docs/narr/zca.rst
@@ -129,7 +129,7 @@ interface of a registry instead, you need only know how to obtain the
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``
diff --git a/docs/tutorials/catalog/index.rst b/docs/tutorials/catalog/index.rst
index 43b078edc..e4e5bd720 100644
--- a/docs/tutorials/catalog/index.rst
+++ b/docs/tutorials/catalog/index.rst
@@ -88,11 +88,11 @@ want the application to be based on :term:`traversal`.
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()
diff --git a/docs/tutorials/wiki/basiclayout.rst b/docs/tutorials/wiki/basiclayout.rst
index 3dbf10bd8..c7c722f70 100644
--- a/docs/tutorials/wiki/basiclayout.rst
+++ b/docs/tutorials/wiki/basiclayout.rst
@@ -98,11 +98,15 @@ following:
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``:
diff --git a/docs/tutorials/wiki/definingmodels.rst b/docs/tutorials/wiki/definingmodels.rst
index 097485047..f317d31dd 100644
--- a/docs/tutorials/wiki/definingmodels.rst
+++ b/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/
diff --git a/docs/tutorials/wiki/definingviews.rst b/docs/tutorials/wiki/definingviews.rst
index 97314fb77..5250cb5e5 100644
--- a/docs/tutorials/wiki/definingviews.rst
+++ b/docs/tutorials/wiki/definingviews.rst
@@ -51,15 +51,15 @@ wiki itself (it will answer on the root URL), another named
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
-------------------------------
diff --git a/docs/tutorials/wiki/src/authorization/tutorial/login.py b/docs/tutorials/wiki/src/authorization/tutorial/login.py
index 60e69fddf..a1194feb0 100644
--- a/docs/tutorials/wiki/src/authorization/tutorial/login.py
+++ b/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 @@ from tutorial.security import USERS
@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 @@ def login(request):
@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)
diff --git a/docs/tutorials/wiki/src/authorization/tutorial/tests.py b/docs/tutorials/wiki/src/authorization/tutorial/tests.py
index d082fb84d..aaf753816 100644
--- a/docs/tutorials/wiki/src/authorization/tutorial/tests.py
+++ b/docs/tutorials/wiki/src/authorization/tutorial/tests.py
@@ -43,7 +43,7 @@ class AppmakerTests(unittest.TestCase):
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 @@ class ViewPageTests(unittest.TestCase):
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 @@ class AddPageTests(unittest.TestCase):
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 @@ class EditPageTests(unittest.TestCase):
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)
diff --git a/docs/tutorials/wiki/src/authorization/tutorial/views.py b/docs/tutorials/wiki/src/authorization/tutorial/views.py
index 48e4e2b43..3143ab552 100644
--- a/docs/tutorials/wiki/src/authorization/tutorial/views.py
+++ b/docs/tutorials/wiki/src/authorization/tutorial/views.py
@@ -2,7 +2,7 @@ from docutils.core import publish_parts
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 @@ wikiwords = re.compile(r"\b([A-Z]\w+[A-Z]+\w+)")
@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 @@ def view_page(context, request):
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 @@ def view_page(context, request):
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 @@ def add_page(context, request):
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 add_page(context, request):
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)
diff --git a/docs/tutorials/wiki/src/viewdecorators/tutorial/tests.py b/docs/tutorials/wiki/src/viewdecorators/tutorial/tests.py
index d082fb84d..aaf753816 100644
--- a/docs/tutorials/wiki/src/viewdecorators/tutorial/tests.py
+++ b/docs/tutorials/wiki/src/viewdecorators/tutorial/tests.py
@@ -43,7 +43,7 @@ class AppmakerTests(unittest.TestCase):
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 @@ class ViewPageTests(unittest.TestCase):
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 @@ class AddPageTests(unittest.TestCase):
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 @@ class EditPageTests(unittest.TestCase):
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)
diff --git a/docs/tutorials/wiki/src/viewdecorators/tutorial/views.py b/docs/tutorials/wiki/src/viewdecorators/tutorial/views.py
index 168965db2..c8ac46edf 100644
--- a/docs/tutorials/wiki/src/viewdecorators/tutorial/views.py
+++ b/docs/tutorials/wiki/src/viewdecorators/tutorial/views.py
@@ -2,7 +2,7 @@ from docutils.core import publish_parts
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 @@ wikiwords = re.compile(r"\b([A-Z]\w+[A-Z]+\w+)")
@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 @@ def view_page(context, request):
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 @@ def view_page(context, request):
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 @@ def add_page(context, request):
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 add_page(context, request):
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'))
diff --git a/docs/tutorials/wiki/src/views/tutorial/tests.py b/docs/tutorials/wiki/src/views/tutorial/tests.py
index c5aafcac5..28e424884 100644
--- a/docs/tutorials/wiki/src/views/tutorial/tests.py
+++ b/docs/tutorials/wiki/src/views/tutorial/tests.py
@@ -43,7 +43,7 @@ class AppmakerTests(unittest.TestCase):
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 @@ class ViewPageTests(unittest.TestCase):
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 @@ class AddPageTests(unittest.TestCase):
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 @@ class EditPageTests(unittest.TestCase):
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)
diff --git a/docs/tutorials/wiki/src/views/tutorial/views.py b/docs/tutorials/wiki/src/views/tutorial/views.py
index acc1bbb57..8437fdc51 100644
--- a/docs/tutorials/wiki/src/views/tutorial/views.py
+++ b/docs/tutorials/wiki/src/views/tutorial/views.py
@@ -2,7 +2,7 @@ from docutils.core import publish_parts
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 @@ from tutorial.models import Page
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 @@ def view_page(context, request):
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 @@ def view_page(context, request):
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 @@ def add_page(context, request):
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 add_page(context, request):
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'))
diff --git a/docs/tutorials/wiki2/definingmodels.rst b/docs/tutorials/wiki2/definingmodels.rst
index b710e1396..09e1f26c3 100644
--- a/docs/tutorials/wiki2/definingmodels.rst
+++ b/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/
diff --git a/docs/zcml.rst b/docs/zcml.rst
index 5913f9460..e5bbe5d4b 100644
--- a/docs/zcml.rst
+++ b/docs/zcml.rst
@@ -13,6 +13,7 @@ documentation is organized alphabetically by directive name.
zcml/aclauthorizationpolicy
zcml/adapter
zcml/authtktauthenticationpolicy
+ zcml/asset
zcml/configure
zcml/default_permission
zcml/forbidden
@@ -23,7 +24,6 @@ documentation is organized alphabetically by directive name.
zcml/remoteuserauthenticationpolicy
zcml/renderer
zcml/repozewho1authenticationpolicy
- zcml/resource
zcml/route
zcml/scan
zcml/static
diff --git a/docs/zcml/aclauthorizationpolicy.rst b/docs/zcml/aclauthorizationpolicy.rst
index 2c66da0c8..f09531415 100644
--- a/docs/zcml/aclauthorizationpolicy.rst
+++ b/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
~~~~~~~~~~
diff --git a/docs/zcml/resource.rst b/docs/zcml/asset.rst
index 3f7c58faa..af7a6db94 100644
--- a/docs/zcml/resource.rst
+++ b/docs/zcml/asset.rst
@@ -1,51 +1,51 @@
-.. _resource_directive:
+.. _asset_directive:
-``resource``
-------------
+``asset``
+---------
-The ``resource`` directive adds a resource override for a single
-resource.
+The ``asset`` directive adds an asset override for a single
+static file/directory asset.
Attributes
~~~~~~~~~~
``to_override``
- A :term:`resource specification` specifying the resource to be
+ A :term:`asset specification` specifying the asset to be
overridden.
``override_with``
- A :term:`resource specification` specifying the resource which
+ A :term:`asset specification` specifying the asset which
is used as the override.
Examples
~~~~~~~~
-.. topic:: Overriding a Single Resource File
+.. topic:: Overriding a Single Asset File
.. code-block:: xml
:linenos:
- <resource
+ <asset
to_override="some.package:templates/mytemplate.pt"
override_with="another.package:othertemplates/anothertemplate.pt"
/>
-.. topic:: Overriding all Resources in a Package
+.. topic:: Overriding all Assets in a Package
.. code-block:: xml
:linenos:
- <resource
+ <asset
to_override="some.package"
override_with="another.package"
/>
-.. topic:: Overriding all Resources in a Subdirectory of a Package
+.. topic:: Overriding all Assets in a Subdirectory of a Package
.. code-block:: xml
:linenos:
- <resource
+ <asset
to_override="some.package:templates/"
override_with="another.package:othertemplates/"
/>
@@ -53,10 +53,13 @@ Examples
Alternatives
~~~~~~~~~~~~
-The :meth:`pyramid.config.Configurator.override_resource`
+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:`resource_zcml_directive`.
+See also :ref:`asset_zcml_directive`.
diff --git a/docs/zcml/forbidden.rst b/docs/zcml/forbidden.rst
index 7ea6b85fd..70f65069e 100644
--- a/docs/zcml/forbidden.rst
+++ b/docs/zcml/forbidden.rst
@@ -35,7 +35,7 @@ Attributes
``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
diff --git a/docs/zcml/handler.rst b/docs/zcml/handler.rst
index 301bf7895..01d442ab6 100644
--- a/docs/zcml/handler.rst
+++ b/docs/zcml/handler.rst
@@ -28,7 +28,7 @@ Attributes
``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``
diff --git a/docs/zcml/notfound.rst b/docs/zcml/notfound.rst
index a2ed95bc4..739eccd49 100644
--- a/docs/zcml/notfound.rst
+++ b/docs/zcml/notfound.rst
@@ -34,7 +34,7 @@ Attributes
``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
diff --git a/docs/zcml/route.rst b/docs/zcml/route.rst
index 4f7cdb955..0f94fa11b 100644
--- a/docs/zcml/route.rst
+++ b/docs/zcml/route.rst
@@ -25,7 +25,7 @@ Attributes
``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 @@ Attributes
``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
diff --git a/docs/zcml/view.rst b/docs/zcml/view.rst
index 74d497cb3..b4fabdc2c 100644
--- a/docs/zcml/view.rst
+++ b/docs/zcml/view.rst
@@ -51,7 +51,7 @@ Non-Predicate Attributes
``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 @@ Non-Predicate Attributes
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 @@ Predicate Attributes
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 @@ Examples
:linenos:
<view
- context=".models.MyModel"
+ context=".resources.MyResource"
view=".views.hello_world"
/>
@@ -232,7 +232,7 @@ Examples
:linenos:
<view
- context=".models.MyModel"
+ context=".resources.MyResource"
view=".views.hello_world_post"
request_method="POST"
/>