summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/api.rst1
-rw-r--r--docs/api/config.rst6
-rw-r--r--docs/api/router.rst8
-rw-r--r--docs/authorintro.rst25
-rw-r--r--docs/conf.py2
-rw-r--r--docs/conventions.rst2
-rw-r--r--docs/copyright.rst12
-rw-r--r--docs/designdefense.rst359
-rw-r--r--docs/glossary.rst89
-rw-r--r--docs/index.rst24
-rw-r--r--docs/latexindex.rst33
-rw-r--r--docs/narr/MyProject/myproject/templates/mytemplate.pt172
-rw-r--r--docs/narr/MyProject/myproject/tests.py6
-rw-r--r--docs/narr/advconfig.rst101
-rw-r--r--docs/narr/assets.rst4
-rw-r--r--docs/narr/configuration.rst8
-rw-r--r--docs/narr/declarative.rst1436
-rw-r--r--docs/narr/environment.rst17
-rw-r--r--docs/narr/events.rst65
-rw-r--r--docs/narr/extending.rst16
-rw-r--r--docs/narr/firstapp.rst2
-rw-r--r--docs/narr/hooks.rst39
-rw-r--r--docs/narr/i18n.rst15
-rw-r--r--docs/narr/install.rst2
-rw-r--r--docs/narr/introduction.rst2
-rw-r--r--docs/narr/muchadoabouttraversal.rst87
-rw-r--r--docs/narr/project.rst57
-rw-r--r--docs/narr/renderers.rst55
-rw-r--r--docs/narr/resources.rst2
-rw-r--r--docs/narr/router.rst2
-rw-r--r--docs/narr/security.rst34
-rw-r--r--docs/narr/templates.rst4
-rw-r--r--docs/narr/testing.rst254
-rw-r--r--docs/narr/threadlocals.rst4
-rw-r--r--docs/narr/urldispatch.rst3
-rw-r--r--docs/narr/viewconfig.rst257
-rw-r--r--docs/narr/views.rst6
-rw-r--r--docs/narr/zca.rst47
-rw-r--r--docs/tutorials/bfg/index.rst4
-rw-r--r--docs/tutorials/modwsgi/index.rst12
-rw-r--r--docs/tutorials/wiki/authorization.rst3
-rw-r--r--docs/tutorials/wiki/basiclayout.rst8
-rw-r--r--docs/tutorials/wiki/definingviews.rst2
-rw-r--r--docs/tutorials/wiki/src/authorization/development.ini6
-rw-r--r--docs/tutorials/wiki/src/authorization/setup.py2
-rw-r--r--docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt42
-rw-r--r--docs/tutorials/wiki/src/authorization/tutorial/templates/login.pt38
-rw-r--r--docs/tutorials/wiki/src/authorization/tutorial/templates/mytemplate.pt19
-rw-r--r--docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt35
-rw-r--r--docs/tutorials/wiki/src/authorization/tutorial/views.py2
-rw-r--r--docs/tutorials/wiki/src/basiclayout/development.ini6
-rw-r--r--docs/tutorials/wiki/src/basiclayout/setup.py2
-rw-r--r--docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt19
-rw-r--r--docs/tutorials/wiki/src/basiclayout/tutorial/tests.py6
-rw-r--r--docs/tutorials/wiki/src/basiclayout/tutorial/views.py3
-rw-r--r--docs/tutorials/wiki/src/models/development.ini6
-rw-r--r--docs/tutorials/wiki/src/models/setup.py3
-rw-r--r--docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt19
-rw-r--r--docs/tutorials/wiki/src/models/tutorial/tests.py6
-rw-r--r--docs/tutorials/wiki/src/views/development.ini6
-rw-r--r--docs/tutorials/wiki/src/views/setup.py2
-rw-r--r--docs/tutorials/wiki/src/views/tutorial/templates/edit.pt40
-rw-r--r--docs/tutorials/wiki/src/views/tutorial/templates/mytemplate.pt19
-rw-r--r--docs/tutorials/wiki/src/views/tutorial/templates/view.pt33
-rw-r--r--docs/tutorials/wiki/src/views/tutorial/views.py2
-rw-r--r--docs/tutorials/wiki2/authorization.rst353
-rw-r--r--docs/tutorials/wiki2/definingviews.rst3
-rw-r--r--docs/tutorials/wiki2/src/authorization/development.ini6
-rw-r--r--docs/tutorials/wiki2/src/authorization/setup.py4
-rw-r--r--docs/tutorials/wiki2/src/authorization/tutorial/templates/edit.pt42
-rw-r--r--docs/tutorials/wiki2/src/authorization/tutorial/templates/login.pt38
-rw-r--r--docs/tutorials/wiki2/src/authorization/tutorial/templates/mytemplate.pt19
-rw-r--r--docs/tutorials/wiki2/src/authorization/tutorial/templates/view.pt35
-rw-r--r--docs/tutorials/wiki2/src/authorization/tutorial/tests.py22
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/development.ini6
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/setup.py2
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/models.py3
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt19
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/tests.py6
-rw-r--r--docs/tutorials/wiki2/src/models/development.ini6
-rw-r--r--docs/tutorials/wiki2/src/models/setup.py2
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/models.py3
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/templates/mytemplate.pt19
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/tests.py6
-rw-r--r--docs/tutorials/wiki2/src/views/development.ini6
-rw-r--r--docs/tutorials/wiki2/src/views/setup.py2
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/templates/edit.pt40
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/templates/mytemplate.pt19
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/templates/view.pt33
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/tests.py20
-rw-r--r--docs/whatsnew-1.0.rst721
-rw-r--r--docs/zcml.rst33
-rw-r--r--docs/zcml/aclauthorizationpolicy.rst35
-rw-r--r--docs/zcml/adapter.rst47
-rw-r--r--docs/zcml/asset.rst65
-rw-r--r--docs/zcml/authtktauthenticationpolicy.rst102
-rw-r--r--docs/zcml/configure.rst95
-rw-r--r--docs/zcml/default_permission.rst57
-rw-r--r--docs/zcml/forbidden.rst78
-rw-r--r--docs/zcml/handler.rst158
-rw-r--r--docs/zcml/include.rst71
-rw-r--r--docs/zcml/localenegotiator.rst39
-rw-r--r--docs/zcml/notfound.rst78
-rw-r--r--docs/zcml/remoteuserauthenticationpolicy.rst51
-rw-r--r--docs/zcml/renderer.rst51
-rw-r--r--docs/zcml/repozewho1authenticationpolicy.rst53
-rw-r--r--docs/zcml/route.rst223
-rw-r--r--docs/zcml/scan.rst34
-rw-r--r--docs/zcml/static.rst89
-rw-r--r--docs/zcml/subscriber.rst45
-rw-r--r--docs/zcml/translationdir.rst64
-rw-r--r--docs/zcml/utility.rst46
-rw-r--r--docs/zcml/view.rst266
113 files changed, 2257 insertions, 4561 deletions
diff --git a/docs/api.rst b/docs/api.rst
index b650c8ded..be7942502 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -24,7 +24,6 @@ documentation is organized alphabetically by module name.
api/renderers
api/request
api/response
- api/router
api/scripting
api/security
api/session
diff --git a/docs/api/config.rst b/docs/api/config.rst
index 3f37e739c..4b5f1fa21 100644
--- a/docs/api/config.rst
+++ b/docs/api/config.rst
@@ -28,6 +28,8 @@
.. automethod:: include
+ .. automethod:: add_directive
+
.. automethod:: with_package
.. automethod:: maybe_dotted
@@ -48,14 +50,10 @@
.. automethod:: add_translation_dirs
- .. automethod:: add_handler
-
.. automethod:: add_view
.. automethod:: derive_view
- .. automethod:: load_zcml(spec)
-
.. automethod:: make_wsgi_app()
.. automethod:: override_asset(to_override, override_with)
diff --git a/docs/api/router.rst b/docs/api/router.rst
deleted file mode 100644
index e5ffe97ce..000000000
--- a/docs/api/router.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-.. _router_module:
-
-:mod:`pyramid.router`
----------------------
-
-.. automodule:: pyramid.router
-
-.. autofunction:: pyramid.router.make_app(root_factory, package=None, filename='configure.zcml', settings=None)
diff --git a/docs/authorintro.rst b/docs/authorintro.rst
index f5ac402b0..bbcde68e6 100644
--- a/docs/authorintro.rst
+++ b/docs/authorintro.rst
@@ -54,7 +54,7 @@ technologies.
Book Content
============
-This book is divided into four major parts:
+This book is divided into three major parts:
:ref:`narrative_documentation`
@@ -79,12 +79,6 @@ This book is divided into four major parts:
:app:`Pyramid`. The API documentation is organized
alphabetically by module name.
-:ref:`zcml_reference`
-
- Comprehensive reference material for every :term:`ZCML directive`
- provided by :app:`Pyramid`. The ZCML directive documentation is
- organized alphabetically by directive name.
-
.. index::
single: repoze.zope2
single: Zope 3
@@ -163,6 +157,10 @@ others' technology.
single: Holth, Daniel
single: Hathaway, Shane
single: Akkerman, Wichert
+ single: Laflamme, Blaise
+ single: Bangert, Ben
+ single: Duncan, Casey
+ single: Orr, Mike
Thanks
======
@@ -173,12 +171,13 @@ typewriter (a Royal), and my mother, who bought me my first computer
Thanks to the following people for providing expertise, resources, and
software. Without the help of these folks, neither this book nor the
-software which it details would exist: Paul Everitt, Tres Seaver,
-Andrew Sawyers, Malthe Borch, Carlos de la Guardia, Chris Rossi, Shane
-Hathaway, Daniel Holth, Wichert Akkerman, Georg Brandl, Simon Oram and
-Nat Hardwick of Electrosoup, Ian Bicking of the Open Planning Project,
-Jim Fulton of Zope Corporation, Tom Moroz of the Open Society
-Institute, and Todd Koym of Environmental Health Sciences.
+software which it details would exist: Paul Everitt, Tres Seaver, Andrew
+Sawyers, Malthe Borch, Carlos de la Guardia, Chris Rossi, Shane Hathaway,
+Daniel Holth, Wichert Akkerman, Georg Brandl, Blaise Laflamme, Ben Bangert,
+Casey Duncan, Mike Orr, Simon Oram and Nat Hardwick of Electrosoup, Ian
+Bicking of the Open Planning Project, Jim Fulton of Zope Corporation, Tom
+Moroz of the Open Society Institute, and Todd Koym of Environmental Health
+Sciences.
Thanks to Guido van Rossum and Tim Peters for Python.
diff --git a/docs/conf.py b/docs/conf.py
index aa7cb7d1e..dce4ef879 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -77,7 +77,7 @@ copyright = '%s, Agendaless Consulting' % datetime.datetime.now().year
# other places throughout the built documents.
#
# The short X.Y version.
-version = '1.0a9'
+version = '1.0a10'
# The full version, including alpha/beta/rc tags.
release = version
diff --git a/docs/conventions.rst b/docs/conventions.rst
index 71c40e104..9e8510e4d 100644
--- a/docs/conventions.rst
+++ b/docs/conventions.rst
@@ -35,7 +35,7 @@ References to glossary terms are presented using the following style:
URLs are presented using the following style:
- `Pylons <http://pylonshq.com>`_
+ `Pylons <http://pylonsproject.org>`_
References to sections and chapters are presented using the following
style:
diff --git a/docs/copyright.rst b/docs/copyright.rst
index 9ef093d0c..c8fc01609 100644
--- a/docs/copyright.rst
+++ b/docs/copyright.rst
@@ -54,20 +54,24 @@ Editor:
Contributors:
Ben Bangert, Blaise Laflamme, Rob Miller, Mike Orr, Carlos de la Guardia,
- Paul Everitt, Tres Seaver, Marius Gedminas, Chris Rossi, Joachim Krebs,
- Xavier Spriet, Reed O'Brien, William Chambers, Charlie Choiniere, Jamaludin
- Ahmad.
+ Paul Everitt, Tres Seaver, John Shipman, Marius Gedminas, Chris Rossi,
+ Joachim Krebs, Xavier Spriet, Reed O'Brien, William Chambers, Charlie
+ Choiniere, Jamaludin Ahmad.
.. Cover Designer:
.. Nat Hardwick of `Electrosoup <http://www.electrosoup.co.uk>`_.
Used with permission:
+
The :ref:`webob_chapter` chapter is adapted, with permission, from
documentation originally written by Ian Bicking.
The :ref:`much_ado_about_traversal_chapter` chapter is adapted,
with permission, from an article written by Rob Miller.
+ The :ref:`wiki2_flow_of_authentication` section was contributed by John
+ Shipman.
+
.. Print Production
.. ----------------
@@ -88,7 +92,7 @@ HTML Version and Source Code
----------------------------
An HTML version of this book is freely available via
-http://docs.pylonshq.com
+http://docs.pylonsproject.org
The source code for the examples used in this book are available
within the :app:`Pyramid` software distribution, always available
diff --git a/docs/designdefense.rst b/docs/designdefense.rst
index df14fb440..d741406c9 100644
--- a/docs/designdefense.rst
+++ b/docs/designdefense.rst
@@ -21,19 +21,20 @@ an acronym for "there is more than one way to do it").
it includes more than one way to resolve a URL to a :term:`view callable`:
via :term:`url dispatch` or :term:`traversal`. Multiple methods of
configuration exist: :term:`imperative configuration`, :term:`configuration
-decoration`, and :term:`ZCML`. It works with multiple different kinds of
-persistence and templating systems. And so on. However, the existence of
-most of these overlapping ways to do things are not without reason and
-purpose: we have a number of audiences to serve, and we believe that TIMTOWTI
-at the web framework level actually *prevents* a much more insidious and
-harmful set of duplication at higher levels in the Python web community.
+decoration`, and :term:`ZCML` (optionally via :term:`pyramid_zcml`). It works
+with multiple different kinds of persistence and templating systems. And so
+on. However, the existence of most of these overlapping ways to do things
+are not without reason and purpose: we have a number of audiences to serve,
+and we believe that TIMTOWTI at the web framework level actually *prevents* a
+much more insidious and harmful set of duplication at higher levels in the
+Python web community.
:app:`Pyramid` began its life as :mod:`repoze.bfg`, written by a team of
people with many years of prior :ref:`Zope` experience. The idea of
-:term:`traversal`, the usage of :term:`ZCML` and the way :term:`view lookup`
-works was stolen entirely from Zope. The authorization subsystem provided by
-:app:`Pyramid` is a derivative of Zope's. The idea that an application can
-be *extended* without forking is also a Zope derivative.
+:term:`traversal` and the way :term:`view lookup` works was stolen entirely
+from Zope. The authorization subsystem provided by :app:`Pyramid` is a
+derivative of Zope's. The idea that an application can be *extended* without
+forking is also a Zope derivative.
Implementations of these features were *required* to allow the :app:`Pyramid`
authors to build the bread-and-butter CMS-type systems for customers in the
@@ -164,12 +165,11 @@ variable. Using an API that consults a thread local makes understanding how
it works non-local.
You've now bought in to the fact that there's a registry that is just
-"hanging around". But how does the registry get populated? Why,
-:term:`ZCML` of course. Sometimes. Or via imperative code. In this
-particular case, however, the registration of ``ISettings`` is made by the
-framework itself "under the hood": it's not present in any ZCML nor was it
-performed imperatively. This is extremely hard to comprehend. Problem
-number six.
+"hanging around". But how does the registry get populated? Why, via code
+that calls directives like ``config.add_view``. In this particular case,
+however, the registration of ``ISettings`` is made by the framework itself
+"under the hood": it's not present in any user configuration. This is
+extremely hard to comprehend. Problem number six.
Clearly there's some amount of cognitive load here that needs to be borne by
a reader of code that extends the :app:`Pyramid` framework due to its use of
@@ -323,17 +323,18 @@ the ZCA registry:
- Composability. A ZCA component registry can be populated imperatively, or
there's an existing mechanism to populate a registry via the use of a
- configuration file (ZCML). We didn't need to write a frontend from scratch
- to make use of configuration-file-driven registry population.
+ configuration file (ZCML, via :term:`pyramid_zcml`). We didn't need to
+ write a frontend from scratch to make use of configuration-file-driven
+ registry population.
- Pluggability. Use of the ZCA registry allows for framework extensibility
via a well-defined and widely understood plugin architecture. As long as
framework developers and extenders understand the ZCA registry, it's
possible to extend :app:`Pyramid` almost arbitrarily. For example, it's
- relatively easy to build a ZCML directive that registers several views "all
- at once", allowing app developers to use that ZCML directive as a "macro"
- in code that they write. This is somewhat of a differentiating feature
- from other (non-Zope) frameworks.
+ relatively easy to build a directive that registers several views "all at
+ once", allowing app developers to use that directive as a "macro" in code
+ that they write. This is somewhat of a differentiating feature from other
+ (non-Zope) frameworks.
- Testability. Judicious use of the ZCA registry in framework code makes
testing that code slightly easier. Instead of using monkeypatching or
@@ -346,9 +347,8 @@ the ZCA registry:
for just these purposes. The ZCA registry contains optional C code for
this purpose which demonstrably has no (or very few) bugs.
-- Ecosystem. Many existing Zope packages can be used in
- :app:`Pyramid` with few (or no) changes due to our use of the ZCA
- registry and :term:`ZCML`.
+- Ecosystem. Many existing Zope packages can be used in :app:`Pyramid` with
+ few (or no) changes due to our use of the ZCA registry.
Conclusion
++++++++++
@@ -366,13 +366,12 @@ this is you, it's extremely hard to have a lot of sympathy for you. You'll
either need to get familiar with how we're using the ZCA registry or you'll
need to use only the documented APIs; that's why we document them as APIs.
-If you *extend* or *develop* :app:`Pyramid` (create new ZCML directives, use
-some of the more obscure "ZCML hooks" as described in :ref:`hooks_chapter`,
-or work on the :app:`Pyramid` core code), you will be faced with needing to
-understand at least some ZCA concepts. In some places it's used unabashedly,
-and will be forever. We know it's quirky, but it's also useful and
-fundamentally understandable if you take the time to do some reading about
-it.
+If you *extend* or *develop* :app:`Pyramid` (create new directives, use some
+of the more obscure "hooks" as described in :ref:`hooks_chapter`, or work on
+the :app:`Pyramid` core code), you will be faced with needing to understand
+at least some ZCA concepts. In some places it's used unabashedly, and will
+be forever. We know it's quirky, but it's also useful and fundamentally
+understandable if you take the time to do some reading about it.
Pyramid Uses Interfaces Too Liberally
-------------------------------------
@@ -453,74 +452,11 @@ Pyramid "Encourages Use of ZCML"
:term:`Zope Component Architecture` registry that :app:`Pyramid` uses for
application configuration. Often people claim that Pyramid "needs ZCML".
-Quick answer: it doesn't. At least not anymore. In :mod:`repoze.bfg` (the
-predecessor to Pyramid) versions 1.0 and and 1.1, an application needed to
-possess a ZCML file for it to begin executing successfully. However,
-:mod:`repoze.bfg` 1.2 and greater (including :app:`Pyramid` 1.0) includes a
-completely imperative mode for all configuration. You will be able to make
-"single file" apps in this mode, which should help people who need to see
-everything done completely imperatively. For example, the very most basic
-:app:`Pyramid` "helloworld" program has become something like:
-
-.. code-block:: python
- :linenos:
-
- from webob import Response
- from paste.httpserver import serve
- from pyramid.config import Configurator
-
- def hello_world(request):
- return Response('Hello world!')
-
- if __name__ == '__main__':
- config = Configurator()
- config.add_view(hello_world)
- app = config.make_wsgi_app()
- serve(app)
-
-In this mode, no ZCML is required at all, nor any other sort of frameworky
-frontend to application configuration. Hopefully this mode will allow people
-who are used to doing everything imperatively feel more comfortable.
-
-Pyramid Uses ZCML; ZCML is XML and I Don't Like XML
----------------------------------------------------
-
-:term:`ZCML` is a configuration language in the XML syntax. Due to the
-"imperative configuration" feature (new in :mod:`repoze.bfg` 1.2), you don't
-need to use ZCML at all. But if you really do want to perform declarative
-configuration, perhaps because you want to build an extensible application,
-you may need to use and understand it.
-
-:term:`ZCML` contains elements that are mostly singleton tags that are
-called *declarations*. For an example:
-
-.. code-block:: xml
- :linenos:
-
- <route
- view=".views.my_view"
- path="/"
- name="root"
- />
-
-This declaration associates a :term:`view` with a route pattern.
-
-All :app:`Pyramid` declarations are singleton tags, unlike many other XML
-configuration systems. No XML *values* in ZCML are meaningful; it's always
-just XML tags and attributes. So in the very common case it's not really
-very much different than an otherwise "flat" configuration format like
-``.ini``, except a developer can *create* a directive that requires nesting
-(none of these exist in :app:`Pyramid` itself), and multiple "sections" can
-exist with the same "name" (e.g. two ``<route>`` declarations) must be able
-to exist simultaneously.
-
-You might think some other configuration file format would be better. But
-all configuration formats suck in one way or another. I personally don't
-think any of our lives would be markedly better if the declarative
-configuration format used by :app:`Pyramid` were YAML, JSON, or INI. It's
-all just plumbing that you mostly cut and paste once you've progressed 30
-minutes into your first project. Folks who tend to agitate for another
-configuration file format are folks that haven't yet spent that 30 minutes.
+It doesn't. In :app:`Pyramid` 1.0, ZCML doesn't ship as part of the core;
+instead it ships in the :term:`pyramid_zcml` add-on package, which is
+completely optional. No ZCML is required at all to use :app:`Pyramid`, nor
+any other sort of frameworky declarative frontend to application
+configuration.
.. _model_traversal_confusion:
@@ -541,14 +477,18 @@ 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:`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
+with this notion, and believe it is wrong. Thankfully, 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.
+
+The idea that some folks believe traversal is unilaterally "wrong" 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
+However, 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
@@ -566,28 +506,32 @@ 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.
+Traversal also offers better composability of applications than URL dispatch,
+because it doesn't rely on a fixed ordering of URL matching. You can compose
+a set of disparate functionality (and add to it later) around a mapping of
+view to resource more predictably than trying to get "the right" ordering of
+URL pattern matching.
+
+But the point is ultimately moot. If you don't want to use traversal, you
+needn't. Use URL dispatch instead.
Pyramid Does URL Dispatch, And I Don't Like URL Dispatch
--------------------------------------------------------
-In :app:`Pyramid`, :term:`url dispatch` is the act of resolving a
-URL path to a :term:`view` callable by performing pattern matching
-against some set of ordered route definitions. The route definitions
-are examined in order: the first pattern which matches is used to
-associate the URL with a view callable.
-
-Some people are uncomfortable with this notion, and believe it is
-wrong. These are usually people who are steeped deeply in
-:term:`Zope`. Zope does not provide any mechanism except
-:term:`traversal` to map code to URLs. This is mainly because Zope
-effectively requires use of :term:`ZODB`, which is a hierarchical
-object store. Zope also supports relational databases, but typically
-the code that calls into the database lives somewhere in the ZODB
-object graph (or at least is a :term:`view` related to a node in the
-object graph), and traversal is required to reach this code.
+In :app:`Pyramid`, :term:`url dispatch` is the act of resolving a URL path to
+a :term:`view` callable by performing pattern matching against some set of
+ordered route definitions. The route definitions are examined in order: the
+first pattern which matches is used to associate the URL with a view
+callable.
+
+Some people are uncomfortable with this notion, and believe it is wrong.
+These are usually people who are steeped deeply in :term:`Zope`. Zope does
+not provide any mechanism except :term:`traversal` to map code to URLs. This
+is mainly because Zope effectively requires use of :term:`ZODB`, which is a
+hierarchical object store. Zope also supports relational databases, but
+typically the code that calls into the database lives somewhere in the ZODB
+object graph (or at least is a :term:`view` related to a node in the object
+graph), and traversal is required to reach this code.
I'll argue that URL dispatch is ultimately useful, even if you want to use
traversal as well. You can actually *combine* URL dispatch and traversal in
@@ -604,20 +548,19 @@ present them with the default object view. There are other tricks you can
pull in these hybrid configurations if you're clever (and maybe masochistic)
too.
-Also, if you are a URL dispatch hater, if you should ever be asked to
-write an application that must use some legacy relational database
-structure, you might find that using URL dispatch comes in handy for
-one-off associations between views and URL paths. Sometimes it's just
-pointless to add a node to the object graph that effectively
-represents the entry point for some bit of code. You can just use a
-route and be done with it. If a route matches, a view associated with
-the route will be called; if no route matches, :app:`Pyramid` falls
-back to using traversal.
-
-But the point is ultimately moot. If you use :app:`Pyramid`, and
-you really don't want to use URL dispatch, you needn't use it at all.
-Instead, use :term:`traversal` exclusively to map URL paths to views,
-just like you do in :term:`Zope`.
+Also, if you are a URL dispatch hater, if you should ever be asked to write
+an application that must use some legacy relational database structure, you
+might find that using URL dispatch comes in handy for one-off associations
+between views and URL paths. Sometimes it's just pointless to add a node to
+the object graph that effectively represents the entry point for some bit of
+code. You can just use a route and be done with it. If a route matches, a
+view associated with the route will be called; if no route matches,
+:app:`Pyramid` falls back to using traversal.
+
+But the point is ultimately moot. If you use :app:`Pyramid`, and you really
+don't want to use URL dispatch, you needn't use it at all. Instead, use
+:term:`traversal` exclusively to map URL paths to views, just like you do in
+:term:`Zope`.
Pyramid Views Do Not Accept Arbitrary Keyword Arguments
-------------------------------------------------------
@@ -649,40 +592,24 @@ arguments to any method of a resource object found via traversal:
def aview(self, a, b, c=None):
return '%s %s %c' % (a, b, c)
-When this method is called as the result of being the published
-callable, the Zope request object's GET and POST namespaces are
-searched for keys which match the names of the positional and keyword
-arguments in the request, and the method is called (if possible) with
-its argument list filled with values mentioned therein. TurboGears
-and Pylons 1.X operate similarly.
-
-:app:`Pyramid` has neither of these features. :mod:`pyramid`
-view callables always accept only ``context`` and ``request`` (or just
-``request``), and no other arguments. The rationale: this argument
-specification matching done aggressively can be costly, and
-:app:`Pyramid` has performance as one of its main goals, so we've
-decided to make people obtain information by interrogating the request
-object for it in the view body instead of providing magic to do
-unpacking into the view argument list. The feature itself also just
-seems a bit like a gimmick. Getting the arguments you want explicitly
-from the request via getitem is not really very hard; it's certainly
-never a bottleneck for the author when he writes web apps.
-
-It is possible to replicate the Zope-like behavior in a view callable
-decorator, however, should you badly want something like it back. No
-such decorator currently exists. If you'd like to create one, Google
-for "zope mapply" and adapt the function you'll find to a decorator
-that pulls the argument mapping information out of the
-``request.params`` dictionary.
-
-A similar feature could be implemented to provide the Django-like
-behavior as a decorator by wrapping the view with a decorator that
-looks in ``request.matchdict``.
-
-It's possible at some point that :app:`Pyramid` will grow some form
-of argument matching feature (it would be simple to make it an
-always-on optional feature that has no cost unless you actually use
-it) for, but currently it has none.
+When this method is called as the result of being the published callable, the
+Zope request object's GET and POST namespaces are searched for keys which
+match the names of the positional and keyword arguments in the request, and
+the method is called (if possible) with its argument list filled with values
+mentioned therein. TurboGears and Pylons 1.X operate similarly.
+
+Out of the box, :app:`Pyramid` is configured to have none of these features.
+By default, :mod:`pyramid` view callables always accept only ``reqest`` and
+no other arguments. The rationale: this argument specification matching done
+aggressively can be costly, and :app:`Pyramid` has performance as one of its
+main goals, so we've decided to make people, by default, obtain information
+by interrogating the request object within the view callable body instead of
+providing magic to do unpacking into the view argument list.
+
+However, as of :app:`Pyramid` 1.0a9, user code can influence the way view
+callables are expected to be called, making it possible to compose a system
+out of view callables which are called with arbitrary arguments. See
+:ref:`using_a_view_mapper`.
Pyramid Provides Too Few "Rails"
--------------------------------
@@ -700,32 +627,54 @@ built using :app:`Pyramid` as a base. See also :ref:`apps_are_extensible`.
Pyramid Provides Too Many "Rails"
---------------------------------
-:app:`Pyramid` provides some features that other web frameworks do
-not. Most notably it has machinery which resolves a URL first to a
-:term:`context` before calling a view (which has the capability to
-accept the context in its argument list), and a declarative
-authorization system that makes use of this feature. Most other web
-frameworks besides :term:`Zope`, from which the pattern was stolen,
-have no equivalent core feature.
-
-We consider this an important feature for a particular class of
-applications (CMS-style applications, which the authors are often
-commissioned to write) that usually use :term:`traversal` against a
-persistent object graph. The object graph contains security
-declarations as :term:`ACL` objects.
-
-Having context-sensitive declarative security for individual objects
-in the object graph is simply required for this class of application.
-Other frameworks save for Zope just do not have this feature. This is
-one of the primary reasons that :app:`Pyramid` was actually
-written.
-
-If you don't like this, it doesn't mean you can't use
-:app:`Pyramid`. Just ignore this feature and avoid configuring an
-authorization or authentication policy and using ACLs. You can build
-"Pylons-1.X-style" applications using :app:`Pyramid` that use their own
-security model via decorators or plain-old-imperative logic in view
-code.
+:app:`Pyramid` provides some features that other web frameworks do not.
+These are features meant for use cases that might not make sense to you if
+you're building a simple "bespoke" web application:
+
+- An optional way to map URLs to code using :term:`traversal` which implies a
+ walk of a :term:`resource tree`.
+
+- The ability to aggregate Pyramid application configuration from multiple
+ sources using :meth:`pyramid.config.Configurator.include`.
+
+- View and subscriber registrations made using :term:`interface` objects
+ instead of class objects (e.g. :ref:`using_resource_interfaces`).
+
+- A declarative :term:`authorization` system.
+
+- Multiple separate I18N :term:`translation string` factories, each of which
+ can name its own "domain".
+
+These features are important to the authors of :app:`Pyramid`. The
+:app:`Pyramid` authors are often commissioned to build CMS-style
+applications. Such applications are often "frameworky" because they have
+more than one deployment. Each deployment requires a slightly different
+composition of sub-applications, and the framework and sub-applications often
+need to be *extensible*. Because the application has more than one
+deployment, pluggability and extensibility is important, as maintaining
+multiple forks of the application, one per deployment, is extremely
+undesirable. Because it's easier to extend a system that uses
+:term:`traversal` "from the outside" than it is to do the same in a system
+that uses :term:`URL dispatch`, each deployment uses a :term:`resource tree`
+composed of a persistent tree of domain model objects, and uses
+:term:`traversal` to map :term:`view callable` code to resources in the tree.
+The resource tree contains very granular security declarations, as resources
+are owned and accessible by different sets of users. Interfaces are used to
+make unit testing and implementation substitutability easier.
+
+In a bespoke web application, usually there's a single canonical deployment,
+and therefore no possibility of multiple code forks. Extensibility is not
+required; the code is just changed in-place. Security requirements are often
+less granular. Using the features listed above will often be overkill for
+such an application.
+
+If you don't like these features, it doesn't mean you can't or shouldn't use
+:app:`Pyramid`. They are all optional, and a lot of time has been spent
+making sure you don't need to know about them up-front. You can build
+"Pylons-1.X-style" applications using :app:`Pyramid` that are purely bespoke
+by ignoring the features above. You may find these features handy later
+after building a "bespoke" web application that suddenly becomes popular and
+requires extensibility because it must be deployed in multiple locations.
Pyramid Is Too Big
------------------
@@ -784,7 +733,7 @@ have their own transitive dependencies.
It should be noted that :app:`Pyramid` is positively lithe compared to
:term:`Grok`, a different Zope-based framework. As of this writing, in its
-default configuration, Grok has 126 package distribution dependencies. The
+default configuration, Grok has 109 package distribution dependencies. The
number of dependencies required by :app:`Pyramid` is many times fewer than
Grok (or Zope itself, upon which Grok is based). :app:`Pyramid` has a number
of package distribution dependencies comparable to similarly-targeted
@@ -993,11 +942,11 @@ the :term:`Zope Component Architecture`, you can optionally use it to expose
other more domain-specific configuration plugpoints while developing an
application. The plugpoints you expose needn't be as coarse as the ones
provided automatically by :app:`Pyramid` itself. For example, you might
-compose your own :term:`ZCML` directive that configures a set of views for a
-prebaked purpose (e.g. ``restview`` or somesuch) , allowing other people to
-refer to that directive when they make declarations in the ``configure.zcml``
-of their customization package. There is a cost for this: the developer of
-an application that defines custom plugpoints for its deployers will need to
+compose your own directive that configures a set of views for a prebaked
+purpose (e.g. ``restview`` or somesuch) , allowing other people to refer to
+that directive when they make declarations in the ``includeme`` of their
+customization package. There is a cost for this: the developer of an
+application that defines custom plugpoints for its deployers will need to
understand the ZCA or he will need to develop his own similar extensibility
system.
@@ -1459,7 +1408,7 @@ global*:
# this is executed if the request method was GET or the
# credentials were invalid
-The `Pylons 1.X <http://pylonshq.com>`_ web framework uses a similar
+The `Pylons 1.X <http://pylonsproject.org>`_ web framework uses a similar
strategy. It calls these things "Stacked Object Proxies", so, for purposes
of this discussion, I'll do so as well.
diff --git a/docs/glossary.rst b/docs/glossary.rst
index a7e3a7884..3c6f5cb1a 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -89,9 +89,9 @@ Glossary
dotted Python name
A reference to a Python object by name using a string, in the form
``path.to.modulename:attributename``. Often used in Paste and
- setuptools configurations. A variant is used in dotted names
- within :term:`ZCML` attributes that name objects (such as the ZCML
- "view" directive's "view" attribute): the colon (``:``) is not
+ setuptools configurations. A variant is used in dotted names within
+ configurator method arguments that name objects (such as the "add_view"
+ method's "view" and "context" attributes): the colon (``:``) is not
used; in its place is a dot.
view
@@ -116,8 +116,8 @@ Glossary
with configuration information. This configuration information helps
map a given :term:`request` to a particular view callable and it can
influence the response of a view callable. :app:`Pyramid` views can be
- configured via :term:`imperative configuration`, :term:`ZCML` or by a
- special ``@view_config`` decorator coupled with a :term:`scan`. See
+ configured via :term:`imperative configuration`, or by a special
+ ``@view_config`` decorator coupled with a :term:`scan`. See
:ref:`view_config_chapter` for more information about view
configuration.
@@ -285,7 +285,7 @@ Glossary
WSGI
`Web Server Gateway Interface <http://wsgi.org/>`_. This is a
Python standard for connecting web applications to web servers,
- similar to the concept of Java Servlets. ``pyramid`` requires
+ similar to the concept of Java Servlets. :app:`Pyramid` requires
that your application be served as a WSGI application.
middleware
@@ -377,29 +377,10 @@ Glossary
ultimately a :term:`view`). See also :term:`url dispatch`.
route configuration
- Route configuration is the act of using :term:`imperative
- configuration` or a :term:`ZCML` ``<route>`` statement to
- associate request parameters with a particular :term:`route` using
- pattern matching and :term:`route predicate` statements. See
- :ref:`urldispatch_chapter` for more information about route
- configuration.
-
- ZCML
- `Zope Configuration Markup Language
- <http://www.muthukadan.net/docs/zca.html#zcml>`_, an XML dialect
- used by Zope and :app:`Pyramid` for configuration tasks. ZCML
- is capable of performing different types of :term:`configuration
- declaration`, but its primary purpose in :app:`Pyramid` is to
- perform :term:`view configuration` and :term:`route configuration`
- within the ``configure.zcml`` file in a :app:`Pyramid`
- application. You can use ZCML as an alternative to
- :term:`imperative configuration`.
-
- ZCML directive
- A ZCML "tag" such as ``<view>`` or ``<route>``.
-
- ZCML declaration
- The concrete use of a :term:`ZCML directive` within a ZCML file.
+ Route configuration is the act of associating request parameters with a
+ particular :term:`route` using pattern matching and :term:`route
+ predicate` statements. See :ref:`urldispatch_chapter` for more
+ information about route configuration.
Zope Component Architecture
The `Zope Component Architecture
@@ -457,9 +438,9 @@ Glossary
subscriber
A callable which receives an :term:`event`. A callable becomes a
- subscriber via :term:`imperative configuration` or the
- ``<subscriber>`` ZCML directive. See :ref:`events_chapter` for
- more information.
+ subscriber via :term:`imperative configuration` or via
+ :term:`configuration decoration`. See :ref:`events_chapter` for more
+ information.
request type
An attribute of a :term:`request` that allows for specialization
@@ -577,15 +558,13 @@ Glossary
also `PEP 318 <http://www.python.org/dev/peps/pep-0318/>`_.
configuration declaration
- An individual method call made to an instance of a
- :app:`Pyramid` :term:`Configurator` object which performs an
- arbitrary action, such as registering a :term:`view configuration`
- (via the ``view`` method of the configurator) or :term:`route
- configuration` (via the ``route`` method of the configurator). A
- set of configuration declarations is also usually implied via the
- use of a :term:`ZCML declaration` within an application, or a set
- of configuration declarations might be performed by a :term:`scan`
- of code in a package.
+ An individual method call made to an instance of a :app:`Pyramid`
+ :term:`Configurator` object which performs an arbitrary action, such as
+ registering a :term:`view configuration` (via the ``add_view`` method of
+ the configurator) or :term:`route configuration` (via the ``add_route``
+ method of the configurator). A set of configuration declarations is
+ also implied by the :term:`configuration decoration` detected by a
+ :term:`scan` of code in a package.
configuration decoration
Metadata implying one or more :term:`configuration declaration`
@@ -609,8 +588,8 @@ Glossary
declaration` required by your application.
declarative configuration
- The configuration mode in which you use :term:`ZCML` to make
- a set of :term:`configuration declaration` statements.
+ The configuration mode in which you use :term:`ZCML` to make a set of
+ :term:`configuration declaration` statements. See :term:`pyramid_zcml`.
Not Found view
An :term:`exception view` invoked by :app:`Pyramid` when the
@@ -862,3 +841,27 @@ Glossary
``request.matchdict`` when a :term:`URL dispatch` route has been matched.
Its keys are names as identified within the route pattern; its values are
the values matched by each pattern name.
+
+ pyramid_zcml
+ An add-on package to :app:`Pyramid` which allows applications to be
+ configured via ZCML. It is available on :term:`PyPI`. If you use
+ ``pyramid_zcml``, you can use ZCML as an alternative to
+ :term:`imperative configuration`.
+
+ ZCML
+ `Zope Configuration Markup Language
+ <http://www.muthukadan.net/docs/zca.html#zcml>`_, an XML dialect
+ used by Zope and :term:`pyramid_zcml` for configuration tasks.
+
+ ZCML directive
+ A ZCML "tag" such as ``<view>`` or ``<route>``.
+
+ ZCML declaration
+ The concrete use of a :term:`ZCML directive` within a ZCML file.
+
+ pyramid_handlers
+ An add-on package which allows :app:`Pyramid` users to create classes
+ that are analogues of Pylons 1 "controllers". See
+ `http://docs.pylonsproject.org/projects/pyramid_handlers/dev/
+ <http://docs.pylonsproject.org/projects/pyramid_handlers/dev/>`_.
+
diff --git a/docs/index.rst b/docs/index.rst
index 7b1c46b70..23596e5ce 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -6,14 +6,9 @@ The Pyramid Web Application Development Framework
:app:`Pyramid` is a small, fast, down-to-earth Python web application
development framework. It is developed as part of the `Pylons Project
-<http://docs.pylonshq.com/>`_. It is licensed under a `BSD-like license
+<http://docs.pylonsproject.org/>`_. It is licensed under a `BSD-like license
<http://repoze.org/license.html>`_.
-.. note::
-
- Pyramid is the latest iteration of the web framework previously known as
- :mod:`repoze.bfg`.
-
Front Matter
============
@@ -23,6 +18,14 @@ Front Matter
copyright.rst
conventions.rst
+"What's New" Documents
+======================
+
+.. toctree::
+ :maxdepth: 2
+
+ whatsnew-1.0
+
Narrative documentation
=======================
@@ -58,7 +61,6 @@ Narrative documentation in chapter form explaining how to use
narr/testing
narr/hooks
narr/advconfig
- narr/declarative
narr/extending
narr/router
narr/threadlocals
@@ -86,14 +88,12 @@ applications to various platforms.
Reference Material
==================
-Reference material includes API documentation and documentation of
-every :app:`Pyramid` :term:`ZCML directive`.
+Reference material includes documentation for every :app:`Pyramid` API.
.. toctree::
:maxdepth: 2
api
- zcml
Detailed Change History
=======================
@@ -175,7 +175,7 @@ commenting, and file uploads. See the `KARL site
Support and Development
=======================
-The `Pylons Project web site <http://docs.pylonshq.com/>`_ is the main online
+The `Pylons Project web site <http://pylonsproject.org/>`_ is the main online
source of :app:`Pyramid` support and development information.
To report bugs, use the `issue tracker
@@ -196,7 +196,7 @@ To check out the trunk via ``git``, use this command:
To find out how to become a contributor to :app:`Pyramid`, please see the
`contributor's section of the documentation
-<http://docs.pylonshq.com/index.html#contributing>`_.
+<http://docs.pylonsproject.org/index.html#contributing>`_.
Index and Glossary
==================
diff --git a/docs/latexindex.rst b/docs/latexindex.rst
index 4ff3bbfe7..2426ec4b0 100644
--- a/docs/latexindex.rst
+++ b/docs/latexindex.rst
@@ -51,9 +51,7 @@ Narrative Documentation
narr/testing
narr/hooks
narr/advconfig
- narr/declarative
narr/extending
- narr/router
narr/startup
narr/threadlocals
narr/zca
@@ -99,7 +97,6 @@ API Reference
api/renderers
api/request
api/response
- api/router
api/scripting
api/security
api/settings
@@ -110,36 +107,6 @@ API Reference
api/view
api/wsgi
-.. _zcml_reference:
-
-ZCML Directive Reference
-@@@@@@@@@@@@@@@@@@@@@@@@
-
-.. toctree::
- :maxdepth: 1
-
- zcml/aclauthorizationpolicy
- zcml/adapter
- zcml/authtktauthenticationpolicy
- zcml/asset
- zcml/configure
- zcml/default_permission
- zcml/forbidden
- zcml/handler
- zcml/include
- zcml/localenegotiator
- zcml/notfound
- zcml/remoteuserauthenticationpolicy
- zcml/renderer
- zcml/repozewho1authenticationpolicy
- zcml/route
- zcml/scan
- zcml/static
- zcml/subscriber
- zcml/translationdir
- zcml/utility
- zcml/view
-
.. backmatter::
Glossary and Index
diff --git a/docs/narr/MyProject/myproject/templates/mytemplate.pt b/docs/narr/MyProject/myproject/templates/mytemplate.pt
index 02fc00eeb..0bfea9d53 100644
--- a/docs/narr/MyProject/myproject/templates/mytemplate.pt
+++ b/docs/narr/MyProject/myproject/templates/mytemplate.pt
@@ -1,76 +1,106 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xml:lang="en"
+ xmlns:tal="http://xml.zope.org/namespaces/tal">
<head>
- <title>The Pyramid Web Application Development Framework</title>
- <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
- <meta name="keywords" content="python web application" />
- <meta name="description" content="pyramid web application" />
- <link rel="shortcut icon" href="${request.application_url}/static/favicon.ico" />
- <link rel="stylesheet" href="${request.application_url}/static/pylons.css" type="text/css" media="screen" charset="utf-8" />
- <link href="http://fonts.googleapis.com/css?family=Neuton&amp;subset=latin" rel="stylesheet" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
- <!--[if lte IE 6]>
- <link rel="stylesheet" href="${request.application_url}/static/ie6.css" type="text/css" media="screen" charset="utf-8" />
- <![endif]-->
+ <title>The Pyramid Web Application Development Framework</title>
+ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+ <meta name="keywords" content="python web application" />
+ <meta name="description" content="pyramid web application" />
+ <link rel="shortcut icon"
+ href="${request.static_url('myproject:static/favicon.ico')}" />
+ <link rel="stylesheet"
+ href="${request.static_url('myproject:static/pylons.css')}"
+ type="text/css" media="screen" charset="utf-8" />
+ <link rel="stylesheet"
+ href="http://fonts.googleapis.com/css?family=Neuton|Nobile:regular,i,b,bi&amp;subset=latin"
+ type="text/css" media="screen" charset="utf-8" />
+ <!--[if lte IE 6]>
+ <link rel="stylesheet"
+ href="${request.static_url('myproject:static/ie6.css')}"
+ type="text/css" media="screen" charset="utf-8" />
+ <![endif]-->
</head>
<body>
- <div id="wrap">
- <div id="top">
- <div class="top align-center">
- <div><img src="${request.application_url}/static/pyramid.png" width="750" height="169" alt="pyramid"/></div>
- </div>
- </div>
- <div id="middle">
- <div class="middle align-center">
- <p class="app-welcome">
- Welcome to <span class="app-name">${project}</span>, an application generated by<br/>
- the Pyramid web application development framework.
- </p>
- </div>
- </div>
- <div id="bottom">
- <div class="bottom">
- <div id="left" class="align-right">
- <h2>Search documentation</h2>
- <form method="get" action="http://docs.pylonshq.com/pyramid/dev/search.html">
- <input type="text" id="q" name="q" value="" />
- <input type="submit" id="x" value="Go" />
- </form>
- </div>
- <div id="right" class="align-left">
- <h2>Pyramid links</h2>
- <ul class="links">
- <li>
- <a href="http://pylonshq.com">Pylons Website</a>
- </li>
- <li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#narrative-documentation">Narrative Documentation</a>
- </li>
- <li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#api-documentation">API Documentation</a>
- </li>
- <li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#tutorials">Tutorials</a>
- </li>
- <li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#change-history">Change History</a>
- </li>
- <li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#sample-applications">Sample Applications</a>
- </li>
- <li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#support-and-development">Support and Development</a>
- </li>
- <li>
- <a href="irc://irc.freenode.net#pyramid">IRC Channel</a>
- </li>
- </ul>
- </div>
- </div>
- </div>
- </div>
- <div id="footer">
- <div class="footer">© Copyright 2008-2010, Agendaless Consulting.</div>
- </div>
+ <div id="wrap">
+ <div id="top">
+ <div class="top align-center">
+ <div>
+ <img src="${request.static_url('myproject:static/pyramid.png')}"
+ width="750" height="169" alt="pyramid"/>
+ </div>
+ </div>
+ </div>
+ <div id="middle">
+ <div class="middle align-center">
+ <p class="app-welcome">
+ Welcome to <span class="app-name">${project}</span>,
+ an application generated by<br/>
+ the Pyramid web application development framework.
+ </p>
+ </div>
+ </div>
+ <div id="bottom">
+ <div class="bottom">
+ <div id="left" class="align-right">
+ <h2>Search documentation</h2>
+ <form method="get"
+ action="http://docs.pylonsproject.org/pyramid/dev/search.html">
+ <input type="text" id="q" name="q" value="" />
+ <input type="submit" id="x" value="Go" />
+ </form>
+ </div>
+ <div id="right" class="align-left">
+ <h2>Pyramid links</h2>
+ <ul class="links">
+ <li>
+ <a href="http://pylonsproject.org">
+ Pylons Website
+ </a>
+ </li>
+ <li>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">
+ Narrative Documentation
+ </a>
+ </li>
+ <li>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">
+ API Documentation
+ </a>
+ </li>
+ <li>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">
+ Tutorials
+ </a>
+ </li>
+ <li>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">
+ Change History
+ </a>
+ </li>
+ <li>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">
+ Sample Applications
+ </a>
+ </li>
+ <li>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">
+ Support and Development
+ </a>
+ </li>
+ <li>
+ <a href="irc://irc.freenode.net#pyramid">
+ IRC Channel
+ </a>
+ </li>
+ </ul>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div id="footer">
+ <div class="footer">© Copyright 2008-2010, Agendaless Consulting.</div>
+ </div>
</body>
</html> \ No newline at end of file
diff --git a/docs/narr/MyProject/myproject/tests.py b/docs/narr/MyProject/myproject/tests.py
index b14fb37af..5fa710278 100644
--- a/docs/narr/MyProject/myproject/tests.py
+++ b/docs/narr/MyProject/myproject/tests.py
@@ -1,15 +1,13 @@
import unittest
-from pyramid.config import Configurator
from pyramid import testing
class ViewTests(unittest.TestCase):
def setUp(self):
- self.config = Configurator(autocommit=True)
- self.config.begin()
+ self.config = testing.setUp()
def tearDown(self):
- self.config.end()
+ testing.tearDown()
def test_my_view(self):
from myproject.views import my_view
diff --git a/docs/narr/advconfig.rst b/docs/narr/advconfig.rst
index f8b3ee191..1cdf1e945 100644
--- a/docs/narr/advconfig.rst
+++ b/docs/narr/advconfig.rst
@@ -115,11 +115,8 @@ allowing the circumstance to go unreported, by default Pyramid raises a
running.
Conflict detection happens for any kind of configuration: imperative
-configuration, :term:`ZCML` configuration, or configuration that results from
-the execution of a :term:`scan`.
-
-.. note:: If you use, ZCML, its conflict detection algorithm is described in
- :ref:`zcml_conflict_detection`.
+configuration or configuration that results from the execution of a
+:term:`scan`.
Manually Resolving Conflicts
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -274,7 +271,7 @@ If your code uses the :meth:`pyramid.config.Configurator.include` method to
include external configuration, some conflicts are automatically resolved.
Configuration statements that are made as the result of an "include" will be
overridden by configuration statements that happen within the caller of
-the "include" method. See also
+the "include" method.
Automatic conflict resolution supports this goal: if a user wants to reuse a
Pyramid application, and they want to customize the configuration of this
@@ -301,9 +298,6 @@ These are the methods of the configurator which provide conflict detection:
Some other methods of the configurator also indirectly provide conflict
detection, because they're implemented in terms of conflict-aware methods:
-- :meth:`~pyramid.config.Configurator.add_handler`, a frontend for
- ``add_route`` and ``add_view``.
-
- :meth:`~pyramid.config.Configurator.add_route` does a second type of
conflict detection when a ``view`` parameter is passed (it calls
``add_view``).
@@ -338,6 +332,23 @@ Instead, use :meth:`pyramid.config.Configuration.include`:
Using ``include`` rather than calling the function directly will allow
:ref:`automatic_conflict_resolution` to work.
+:meth:`pyramid.config.Configuration.include` can also accept a :term:`module`
+as an argument:
+
+.. code-block:: python
+ :linenos:
+
+ import myapp
+
+ config.include(myapp)
+
+For this to work properly, the ``myapp`` module must contain a callable with
+the special name ``includeme``, which should perform configuration (like the
+``add_routes`` callable we showed above as an example).
+
+:meth:`pyramid.config.Configuration.include` can also accept a :term:`dotted
+Python name` to a function or a module.
+
.. note: See :ref:`the_include_tag` for a declarative alternative to
:meth:`pyramid.config.Configurator.include`.
@@ -387,9 +398,75 @@ used, two-phase configuration is disabled, and configuration statements must
be ordered in dependency order.
Some configuration methods, such as
-:meth:`pyramid.config.Configurator.add_route` and
-:meth:`pyramid.config.Configurator.add_handler` have internal ordering
-constraints: they routes they imply require relative ordering. Such ordering
+:meth:`pyramid.config.Configurator.add_route` have internal ordering
+constraints: the routes they imply require relative ordering. Such ordering
constraints are not absolved by two-phase configuration. Routes are still
added in configuration execution order.
+Adding Methods to the Configurator via ``add_directive``
+--------------------------------------------------------
+
+Framework extension writers can add arbitrary methods to a
+:term:`Configurator` by using the
+:meth:`pyramid.config.Configurator.add_directive` method of the configurator.
+This makes it possible to extend a Pyramid configurator in arbitrary ways,
+and allows it to perform application-specific tasks more succinctly.
+
+The :meth:`~pyramid.config.Configurator.add_directive` method accepts two
+positional arguments: a method name and a callable object. The callable
+object is usually a function that takes the configurator instance as its
+first argument and accepts other arbitrary positional and keyword arguments.
+For example:
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.events import NewRequest
+ from pyramid.config import Configurator
+
+ def add_newrequest_subscriber(config, subscriber):
+ config.add_subscriber(subscriber, NewRequest).
+
+ if __name__ == '__main__':
+ config = Configurator()
+ config.add_directive('add_newrequest_subscriber',
+ add_newrequest_subscriber)
+
+Once :meth:`~pyramid.config.Configurator.add_directive` is called, a user can
+then call the method by its given name as if it were a built-in method of the
+Configurator:
+
+.. code-block:: python
+ :linenos:
+
+ def mysubscriber(event):
+ print event.request
+
+ config.add_newrequest_subscriber(mysubscriber)
+
+A call to :meth:`~pyramid.config.Configurator.add_directive` is often
+"hidden" within an ``includeme`` function within a "frameworky" package meant
+to be included as per :ref:`including_configuration` via
+:meth:`~pyramid.config.Configurator.include`. For example, if you put this
+code in a package named ``pyramid_subscriberhelpers``:
+
+.. code-block:: python
+ :linenos:
+
+ def includeme(config)
+ config.add_directive('add_newrequest_subscriber',
+ add_newrequest_subscriber)
+
+The user of the add-on package ``pyramid_subscriberhelpers`` would then be
+able to install it and subsequently do:
+
+.. code-block:: python
+ :linenos:
+
+ def mysubscriber(event):
+ print event.request
+
+ from pyramid.config import Configurator
+ config = Configurator()
+ config.include('pyramid_subscriberhelpers')
+ config.add_newrequest_subscriber(mysubscriber)
diff --git a/docs/narr/assets.rst b/docs/narr/assets.rst
index f73ff231a..ee2e0440e 100644
--- a/docs/narr/assets.rst
+++ b/docs/narr/assets.rst
@@ -137,7 +137,7 @@ The value of the ``permission`` argument represents the :term:`permission`
that the user must have relative to the current :term:`context` when the
static view is invoked. A user will be required to possess this permission
to view any of the files represented by ``path`` of the static view. If your
-static resources must be protected by a more complex authorization scheme,
+static assets must be protected by a more complex authorization scheme,
see :ref:`advanced_static`.
Here's another example that uses an :term:`asset specification` instead of an
@@ -345,7 +345,7 @@ application's startup code.
.. code-block:: python
:linenos:
- # .. every other add_route and/or add_handler declaration should come
+ # .. every other add_route declaration should come
# before this one, as it will, by default, catch all requests
config.add_route('catchall_static', '/*subpath', 'myapp.static.static_view')
diff --git a/docs/narr/configuration.rst b/docs/narr/configuration.rst
index 394603946..05bc4d6cc 100644
--- a/docs/narr/configuration.rst
+++ b/docs/narr/configuration.rst
@@ -151,9 +151,7 @@ Declarative Configuration
A third mode of configuration can be employed when you create a
:app:`Pyramid` application named *declarative configuration*. This mode uses
an XML language known as :term:`ZCML` to represent configuration statements
-rather than Python. ZCML is often used when application extensibility is
-important. Most of the examples in the narrative portion of this
-documentation concentrate on imperative configuration rather than ZCML, but
-almost everything that can be configured imperatively can also be configured
-via ZCML. See :ref:`declarative_chapter` for more information about ZCML.
+rather than Python. ZCML is not built-in to Pyramid, but almost everything
+that can be configured imperatively can also be configured via ZCML if you
+install the :term:`pyramid_zcml` package.
diff --git a/docs/narr/declarative.rst b/docs/narr/declarative.rst
deleted file mode 100644
index f36e55b29..000000000
--- a/docs/narr/declarative.rst
+++ /dev/null
@@ -1,1436 +0,0 @@
-.. _declarative_chapter:
-
-Declarative Configuration
-=========================
-
-The mode of configuration detailed in the majority of examples within this
-this book is "imperative" configuration. This is the configuration mode in
-which a developer cedes the least amount of control to the framework; it's
-"imperative" because you express the configuration directly in Python code,
-and you have the full power of Python at your disposal as you issue
-configuration statements. However, another mode of configuration exists
-within :app:`Pyramid` named :term:`ZCML` which often provides better
-opportunity for extensibility.
-
-A complete listing of ZCML directives is available within
-:ref:`zcml_directives`. This chapter provides an overview of how you might
-get started with ZCML and highlights some common tasks performed when you use
-ZCML.
-
-.. index::
- single: declarative configuration
-
-.. _declarative_configuration:
-
-ZCML Configuration
-------------------
-
-A :app:`Pyramid` application can be configured "declaratively", if so
-desired. Declarative configuration relies on *declarations* made external to
-the code in a configuration file format named :term:`ZCML` (Zope
-Configuration Markup Language), an XML dialect.
-
-A :app:`Pyramid` application configured declaratively requires not
-one, but two files: a Python file and a :term:`ZCML` file.
-
-In a file named ``helloworld.py``:
-
-.. code-block:: python
- :linenos:
-
- from paste.httpserver import serve
- from pyramid.response import Response
- from pyramid.config import Configurator
-
- def hello_world(request):
- return Response('Hello world!')
-
- if __name__ == '__main__':
- config = Configurator()
- config.load_zcml('configure.zcml')
- app = config.make_wsgi_app()
- serve(app, host='0.0.0.0')
-
-In a file named ``configure.zcml`` in the same directory as the
-previously created ``helloworld.py``:
-
-.. code-block:: xml
- :linenos:
-
- <configure xmlns="http://pylonshq.com/pyramid">
-
- <include package="pyramid.includes" />
-
- <view
- view="helloworld.hello_world"
- />
-
- </configure>
-
-This pair of files forms an application functionally equivalent to the
-application we created earlier in :ref:`imperative_configuration`.
-Let's examine the differences between that code listing and the code
-above.
-
-In :ref:`imperative_configuration`, we had the following lines within
-the ``if __name__ == '__main__'`` section of ``helloworld.py``:
-
-.. code-block:: python
- :linenos:
-
- if __name__ == '__main__':
- config = Configurator()
- config.add_view(hello_world)
- app = config.make_wsgi_app()
- serve(app, host='0.0.0.0')
-
-In our "declarative" code, we've removed the call to ``add_view`` and
-replaced it with a call to the
-:meth:`pyramid.config.Configurator.load_zcml` method so that
-it now reads as:
-
-.. code-block:: python
- :linenos:
-
- if __name__ == '__main__':
- config = Configurator()
- config.load_zcml('configure.zcml')
- app = config.make_wsgi_app()
- serve(app, host='0.0.0.0')
-
-Everything else is much the same.
-
-The ``config.load_zcml('configure.zcml')`` line tells the configurator
-to load configuration declarations from the file named
-``configure.zcml`` which sits next to ``helloworld.py`` on the
-filesystem. Let's take a look at that ``configure.zcml`` file again:
-
-.. code-block:: xml
- :linenos:
-
- <configure xmlns="http://pylonshq.com/pyramid">
-
- <include package="pyramid.includes" />
-
- <view
- view="helloworld.hello_world"
- />
-
- </configure>
-
-Note that this file contains some XML, and that the XML contains a
-``<view>`` :term:`configuration declaration` tag that references a
-:term:`dotted Python name`. This dotted name refers to the
-``hello_world`` function that lives in our ``helloworld`` Python
-module.
-
-This ``<view>`` declaration tag performs the same function as the
-``add_view`` method that was employed within
-:ref:`imperative_configuration`. In fact, the ``<view>`` tag is
-effectively a "macro" which calls the
-:meth:`pyramid.config.Configurator.add_view` method on your
-behalf.
-
-The ``<view>`` tag is an example of a :app:`Pyramid` declaration
-tag. Other such tags include ``<route>`` and ``<scan>``. Each of
-these tags is effectively a "macro" which calls methods of a
-:class:`pyramid.config.Configurator` object on your behalf.
-
-Essentially, using a :term:`ZCML` file and loading it from the
-filesystem allows us to put our configuration statements within this
-XML file rather as declarations, rather than representing them as
-method calls to a :term:`Configurator` object. Otherwise, declarative
-and imperative configuration are functionally equivalent.
-
-Using declarative configuration has a number of benefits, the primary
-benefit being that applications configured declaratively can be
-*overridden* and *extended* by third parties without requiring the
-third party to change application code. If you want to build a
-framework or an extensible application, using declarative
-configuration is a good idea.
-
-Declarative configuration has an obvious downside: you can't use
-plain-old-Python syntax you probably already know and understand to
-configure your application; instead you need to use :term:`ZCML`.
-
-.. index::
- single: ZCML conflict detection
-
-.. _zcml_conflict_detection:
-
-ZCML Conflict Detection
-~~~~~~~~~~~~~~~~~~~~~~~
-
-A minor additional feature of ZCML is *conflict detection*. If you
-define two declaration tags within the same ZCML file which logically
-"collide", an exception will be raised, and the application will not
-start. For example, the following ZCML file has two conflicting
-``<view>`` tags:
-
-.. code-block:: xml
- :linenos:
-
- <configure xmlns="http://pylonshq.com/pyramid">
-
- <include package="pyramid.includes" />
-
- <view
- view="helloworld.hello_world"
- />
-
- <view
- view="helloworld.hello_world"
- />
-
- </configure>
-
-If you try to use this ZCML file as the source of ZCML for an
-application, an error will be raised when you attempt to start the
-application. This error will contain information about which tags
-might have conflicted.
-
-.. index::
- single: helloworld (declarative)
-
-.. _helloworld_declarative:
-
-Hello World, Goodbye World (Declarative)
-----------------------------------------
-
-Another almost entirely equivalent mode of application configuration
-exists named *declarative* configuration. :app:`Pyramid` can be
-configured for the same "hello world" application "declaratively", if
-so desired.
-
-To do so, first, create a file named ``helloworld.py``:
-
-.. code-block:: python
- :linenos:
-
- from pyramid.config import Configurator
- from pyramid.response import Response
- from paste.httpserver import serve
-
- def hello_world(request):
- return Response('Hello world!')
-
- def goodbye_world(request):
- return Response('Goodbye world!')
-
- if __name__ == '__main__':
- config = Configurator()
- config.load_zcml('configure.zcml')
- app = config.make_wsgi_app()
- serve(app, host='0.0.0.0')
-
-Then create a file named ``configure.zcml`` in the same directory as
-the previously created ``helloworld.py``:
-
-.. code-block:: xml
- :linenos:
-
- <configure xmlns="http://pylonshq.com/pyramid">
-
- <include package="pyramid.includes" />
-
- <view
- view="helloworld.hello_world"
- />
-
- <view
- name="goodbye"
- view="helloworld.goodbye_world"
- />
-
- </configure>
-
-This pair of files forms an application functionally equivalent to the
-application we created earlier in :ref:`helloworld_imperative`. We can run
-it the same way.
-
-.. code-block:: text
-
- $ python helloworld.py
- serving on 0.0.0.0:8080 view at http://127.0.0.1:8080
-
-Let's examine the differences between the code in that section and the code
-above. In :ref:`helloworld_imperative_appconfig`, we had the following lines
-within the ``if __name__ == '__main__'`` section of ``helloworld.py``:
-
-.. code-block:: python
- :linenos:
-
- if __name__ == '__main__':
- config = Configurator()
- config.add_view(hello_world)
- config.add_view(goodbye_world, name='goodbye')
- app = config.make_wsgi_app()
- serve(app, host='0.0.0.0')
-
-In our "declarative" code, we've added a call to the
-:meth:`pyramid.config.Configurator.load_zcml` method with
-the value ``configure.zcml``, and we've removed the lines which read
-``config.add_view(hello_world)`` and ``config.add_view(goodbye_world,
-name='goodbye')``, so that it now reads as:
-
-.. code-block:: python
- :linenos:
-
- if __name__ == '__main__':
- config = Configurator()
- config.load_zcml('configure.zcml')
- app = config.make_wsgi_app()
- serve(app, host='0.0.0.0')
-
-Everything else is much the same.
-
-The ``config.load_zcml('configure.zcml')`` line tells the configurator
-to load configuration declarations from the ``configure.zcml`` file
-which sits next to ``helloworld.py``. Let's take a look at the
-``configure.zcml`` file now:
-
-.. code-block:: xml
- :linenos:
-
- <configure xmlns="http://pylonshq.com/pyramid">
-
- <include package="pyramid.includes" />
-
- <view
- view="helloworld.hello_world"
- />
-
- <view
- name="goodbye"
- view="helloworld.goodbye_world"
- />
-
- </configure>
-
-We already understand what the view code does, because the application
-is functionally equivalent to the application described in
-:ref:`helloworld_imperative`, but use of :term:`ZCML` is new. Let's
-break that down tag-by-tag.
-
-The ``<configure>`` Tag
-~~~~~~~~~~~~~~~~~~~~~~~
-
-The ``configure.zcml`` ZCML file contains this bit of XML:
-
-.. code-block:: xml
- :linenos:
-
- <configure xmlns="http://pylonshq.com/pyramid">
-
- <!-- other directives -->
-
- </configure>
-
-Because :term:`ZCML` is XML, and because XML requires a single root
-tag for each document, every ZCML file used by :app:`Pyramid` must
-contain a ``configure`` container directive, which acts as the root
-XML tag. It is a "container" directive because its only job is to
-contain other directives.
-
-See also :ref:`configure_directive` and :ref:`word_on_xml_namespaces`.
-
-.. _the_include_tag:
-
-The ``<include>`` Tag
-~~~~~~~~~~~~~~~~~~~~~
-
-The ``configure.zcml`` ZCML file contains this bit of XML within the
-``<configure>`` root tag:
-
-.. code-block:: xml
- :linenos:
-
- <include package="pyramid.includes" />
-
-This self-closing tag instructs :app:`Pyramid` to load a ZCML file
-from the Python package with the :term:`dotted Python name`
-``pyramid.includes``, as specified by its ``package`` attribute.
-This particular ``<include>`` declaration is required because it
-actually allows subsequent declaration tags (such as ``<view>``, which
-we'll see shortly) to be recognized. The ``<include>`` tag
-effectively just includes another ZCML file, causing its declarations
-to be executed. In this case, we want to load the declarations from
-the file named ``configure.zcml`` within the
-:mod:`pyramid.includes` Python package. We know we want to load
-the ``configure.zcml`` from this package because ``configure.zcml`` is
-the default value for another attribute of the ``<include>`` tag named
-``file``. We could have spelled the include tag more verbosely, but
-equivalently as:
-
-.. code-block:: xml
- :linenos:
-
- <include package="pyramid.includes"
- file="configure.zcml"/>
-
-The ``<include>`` tag that includes the ZCML statements implied by the
-``configure.zcml`` file from the Python package named
-:mod:`pyramid.includes` is basically required to come before any
-other named declaration in an application's ``configure.zcml``. If it
-is not included, subsequent declaration tags will fail to be
-recognized, and the configuration system will generate an error at
-startup. However, the ``<include package="pyramid.includes"/>``
-tag needs to exist only in a "top-level" ZCML file, it needn't also
-exist in ZCML files *included by* a top-level ZCML file.
-
-See also :ref:`include_directive`.
-
-The ``<view>`` Tag
-~~~~~~~~~~~~~~~~~~
-
-The ``configure.zcml`` ZCML file contains these bits of XML *after* the
-``<include>`` tag, but *within* the ``<configure>`` root tag:
-
-.. code-block:: xml
- :linenos:
-
- <view
- view="helloworld.hello_world"
- />
-
- <view
- name="goodbye"
- view="helloworld.goodbye_world"
- />
-
-These ``<view>`` declaration tags direct :app:`Pyramid` to create
-two :term:`view configuration` registrations. The first ``<view>``
-tag has an attribute (the attribute is also named ``view``), which
-points at a :term:`dotted Python name`, referencing the
-``hello_world`` function defined within the ``helloworld`` package.
-The second ``<view>`` tag has a ``view`` attribute which points at a
-:term:`dotted Python name`, referencing the ``goodbye_world`` function
-defined within the ``helloworld`` package. The second ``<view>`` tag
-also has an attribute called ``name`` with a value of ``goodbye``.
-
-These effect of the ``<view>`` tag declarations we've put into our
-``configure.zcml`` is functionally equivalent to the effect of lines
-we've already seen in an imperatively-configured application. We're
-just spelling things differently, using XML instead of Python.
-
-In our previously defined application, in which we added view
-configurations imperatively, we saw this code:
-
-.. ignore-next-block
-.. code-block:: python
- :linenos:
-
- config.add_view(hello_world)
- config.add_view(goodbye_world, name='goodbye')
-
-Each ``<view>`` declaration tag encountered in a ZCML file effectively
-invokes the :meth:`pyramid.config.Configurator.add_view`
-method on the behalf of the developer. Various attributes can be
-specified on the ``<view>`` tag which influence the :term:`view
-configuration` it creates.
-
-Since the relative ordering of calls to
-:meth:`pyramid.config.Configurator.add_view` doesn't matter
-(see the sidebar entitled *View Dispatch and Ordering* within
-:ref:`adding_configuration`), the relative order of ``<view>`` tags in
-ZCML doesn't matter either. The following ZCML orderings are
-completely equivalent:
-
-.. topic:: Hello Before Goodbye
-
- .. code-block:: xml
- :linenos:
-
- <view
- view="helloworld.hello_world"
- />
-
- <view
- name="goodbye"
- view="helloworld.goodbye_world"
- />
-
-.. topic:: Goodbye Before Hello
-
- .. code-block:: xml
- :linenos:
-
- <view
- name="goodbye"
- view="helloworld.goodbye_world"
- />
-
- <view
- view="helloworld.hello_world"
- />
-
-We've now configured a :app:`Pyramid` helloworld application
-declaratively. More information about this mode of configuration is
-available in :ref:`declarative_configuration` and within
-:ref:`zcml_reference`.
-
-.. index::
- single: ZCML granularity
-
-ZCML Granularity
-~~~~~~~~~~~~~~~~
-
-It's extremely helpful to third party application "extenders" (aka
-"integrators") if the :term:`ZCML` that composes the configuration for an
-application is broken up into separate files which do very specific things.
-These more specific ZCML files can be reintegrated within the application's
-main ``configure.zcml`` via ``<include file="otherfile.zcml"/>``
-declarations. When ZCML files contain sets of specific declarations, an
-integrator can avoid including any ZCML he does not want by including only
-ZCML files which contain the declarations he needs. He is not forced to
-"accept everything" or "use nothing".
-
-For example, it's often useful to put all ``<route>`` declarations in a
-separate ZCML file, as ``<route>`` statements have a relative ordering that
-is extremely important to the application: if an extender wants to add a
-route to the "middle" of the routing table, he will always need to disuse all
-the routes and cut and paste the routing configuration into his own
-application. It's useful for the extender to be able to disuse just a
-*single* ZCML file in this case, accepting the remainder of the configuration
-from other :term:`ZCML` files in the original application.
-
-Granularizing ZCML is not strictly required. An extender can always disuse
-*all* your ZCML, choosing instead to copy and paste it into his own package,
-if necessary. However, doing so is considerate, and allows for the best
-reusability. Sometimes it's possible to include only certain ZCML files from
-an application that contain only the registrations you really need, omitting
-others. But sometimes it's not. For brute force purposes, when you're
-getting ``view`` or ``route`` registrations that you don't actually want in
-your overridden application, it's always appropriate to just *not include*
-any ZCML file from the overridden application. Instead, just cut and paste
-the entire contents of the ``configure.zcml`` (and any ZCML file included by
-the overridden application's ``configure.zcml``) into your own package and
-omit the ``<include package=""/>`` ZCML declaration in the overriding
-package's ``configure.zcml``.
-
-.. _zcml_scanning:
-
-Scanning via ZCML
------------------
-
-:term:`ZCML` can invoke a :term:`scan` via its ``<scan>`` directive. If a
-ZCML file is processed that contains a scan directive, the package the ZCML
-file points to is scanned.
-
-.. code-block:: python
- :linenos:
-
- # helloworld.py
-
- from paste.httpserver import serve
- from pyramid.response import Response
- from pyramid.view import view_config
-
- @view_config()
- def hello(request):
- return Response('Hello')
-
- if __name__ == '__main__':
- from pyramid.config import Configurator
- config = Configurator()
- config.load_zcml('configure.zcml')
- app = config.make_wsgi_app()
- serve(app, host='0.0.0.0')
-
-.. code-block:: xml
- :linenos:
-
- <configure xmlns="http://namespaces.repoze.org">
-
- <!-- configure.zcml -->
-
- <include package="pyramid.includes"/>
- <scan package="."/>
-
- </configure>
-
-See also :ref:`scan_directive`.
-
-Which Mode Should I Use?
-------------------------
-
-A combination of imperative configuration, declarative configuration
-via ZCML and scanning can be used to configure any application. They
-are not mutually exclusive.
-
-The :app:`Pyramid` authors often recommend using mostly declarative
-configuration, because it's the more traditional form of configuration
-used in :app:`Pyramid` applications, it can be overridden and
-extended by third party deployers, and there are more examples for it
-"in the wild".
-
-However, imperative mode configuration can be simpler to understand,
-and the framework is not "opinionated" about the choice. This book
-presents examples in both styles, mostly interchangeably. You can
-choose the mode that best fits your brain as necessary.
-
-.. index::
- single: ZCML view configuration
-
-.. _mapping_views_using_zcml_section:
-
-View Configuration Via ZCML
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-You may associate a view with a URL by adding :ref:`view_directive`
-declarations via :term:`ZCML` in a ``configure.zcml`` file. An
-example of a view declaration in ZCML is as follows:
-
-.. code-block:: xml
- :linenos:
-
- <view
- context=".resources.Hello"
- view=".views.hello_world"
- name="hello.html"
- />
-
-The above maps the ``.views.hello_world`` view callable function to
-the following set of :term:`resource location` results:
-
-- A :term:`context` object which is an instance (or subclass) of the
- Python class represented by ``.resources.Hello``
-
-- A :term:`view name` equalling ``hello.html``.
-
-.. note:: Values prefixed with a period (``.``) for the ``context``
- and ``view`` attributes of a ``view`` declaration (such as those
- 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 ``.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:`resource` type:
-
-.. code-block:: xml
- :linenos:
-
- <view
- 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
-``.resources.Hello`` and there is no :term:`view name` associated with the
-result of :term:`resource location`, the *default view callable* will be
-used. In this case, it's the view at ``.views.hello_world``.
-
-A default view callable can alternately be defined by using the empty
-string as its ``name`` attribute:
-
-.. code-block:: xml
- :linenos:
-
- <view
- context=".resources.Hello"
- view=".views.hello_world"
- name=""
- />
-
-You may also declare that a view callable is good for any context type
-by using the special ``*`` character as the value of the ``context``
-attribute:
-
-.. code-block:: xml
- :linenos:
-
- <view
- context="*"
- view=".views.hello_world"
- name="hello.html"
- />
-
-This indicates that when :app:`Pyramid` identifies that the
-:term:`view name` is ``hello.html`` and the context is of any type,
-the ``.views.hello_world`` view callable will be invoked.
-
-A ZCML ``view`` declaration's ``view`` attribute can also name a
-class. In this case, the rules described in :ref:`class_as_view`
-apply for the class which is named.
-
-See :ref:`view_directive` for complete ZCML directive documentation.
-
-.. index::
- single: ZCML directive; route
-
-.. _zcml_route_configuration:
-
-Configuring a Route via ZCML
-----------------------------
-
-Instead of using the imperative :meth:`pyramid.config.Configurator.add_route`
-method to add a new route, you can alternately use :term:`ZCML`.
-:ref:`route_directive` statements in a :term:`ZCML` file. For example, the
-following :term:`ZCML declaration` causes a route to be added to the
-application.
-
-.. code-block:: xml
- :linenos:
-
- <route
- name="myroute"
- pattern="/prefix/{one}/{two}"
- view=".views.myview"
- />
-
-.. note::
-
- Values prefixed with a period (``.``) within the values of ZCML
- attributes such as the ``view`` attribute of a ``route`` mean
- "relative to the Python package directory in which this
- :term:`ZCML` file is stored". So if the above ``route``
- declaration was made inside a ``configure.zcml`` file that lived in
- the ``hello`` package, you could replace the relative
- ``.views.myview`` with the absolute ``hello.views.myview`` 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.
-
-The order that routes are evaluated when declarative configuration is used
-is the order that they appear relative to each other in the ZCML file.
-
-See :ref:`route_directive` for full ``route`` ZCML directive
-documentation.
-
-.. _zcml_handler_configuration:
-
-Configuring a Handler via ZCML
-------------------------------
-
-Instead of using the imperative
-:meth:`pyramid.config.Configurator.add_handler` method to add a new
-route, you can alternately use :term:`ZCML`. :ref:`handler_directive`
-statements in a :term:`ZCML` file used by your application is a sign that
-you're using :term:`URL dispatch`. For example, the following :term:`ZCML
-declaration` causes a route to be added to the application.
-
-.. code-block:: xml
- :linenos:
-
- <handler
- route_name="myroute"
- pattern="/prefix/{action}"
- handler=".handlers.MyHandler"
- />
-
-.. note::
-
- Values prefixed with a period (``.``) within the values of ZCML attributes
- such as the ``handler`` attribute of a ``handler`` directive mean
- "relative to the Python package directory in which this :term:`ZCML` file
- is stored". So if the above ``handler`` declaration was made inside a
- ``configure.zcml`` file that lived in the ``hello`` package, you could
- replace the relative ``.views.MyHandler`` with the absolute
- ``hello.views.MyHandler`` 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.
-
-The order that the routes attached to handlers are evaluated when declarative
-configuration is used is the order that they appear relative to each other in
-the ZCML file.
-
-See :ref:`handler_directive` for full ``handler`` ZCML directive
-documentation.
-
-.. index::
- triple: view; zcml; static resource
-
-.. _zcml_static_assets_section:
-
-Serving Static Assets Using ZCML
---------------------------------
-
-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:`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 assets such as
-``some_package:a/b/c/static``.
-
-Here's an example of a ``static`` ZCML directive that will serve files
-up under the ``/static`` URL from the ``/var/www/static`` directory of
-the computer which runs the :app:`Pyramid` application using an
-absolute path.
-
-.. code-block:: xml
- :linenos:
-
- <static
- name="static"
- path="/var/www/static"
- />
-
-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:`asset specification`.
-
-.. code-block:: xml
- :linenos:
-
- <static
- name="static"
- path="some_package:a/b/c/static"
- />
-
-Here's an example of a ``static`` directive that will serve files up
-under the ``/static`` URL from the ``static`` directory of the Python
-package in which the ``configure.zcml`` file lives using a
-package-relative path.
-
-.. code-block:: xml
- :linenos:
-
- <static
- name="static"
- path="static"
- />
-
-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
-files in this directory via a browser at URLs prefixed with the
-directive's ``name``. For instance if the ``static`` directive's
-``name`` is ``static`` and the static directive's ``path`` is
-``/path/to/static``, ``http://localhost:6543/static/foo.js`` will
-return the file ``/path/to/static/dir/foo.js``. The static directory
-may contain 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 ``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 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`.
-
-For example, the ``static`` ZCML directive may be fed a ``name``
-argument which is ``http://example.com/images``:
-
-.. code-block:: xml
- :linenos:
-
- <static
- name="http://example.com/images"
- path="mypackage:images"
- />
-
-Because the ``static`` ZCML directive is provided with a ``name`` argument
-that is the URL prefix ``http://example.com/images``, subsequent calls to
-:func:`pyramid.url.static_url` with paths that start with the ``path``
-argument passed to :meth:`pyramid.url.static_url` will generate a URL
-something like ``http://example.com/logo.png``. The external webserver
-listening on ``example.com`` must be itself configured to respond properly to
-such a request. The :func:`pyramid.url.static_url` API is discussed in more
-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_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
------------------------------------------
-
-If you'd rather use :term:`ZCML` to specify an authorization policy
-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 the resource tree when attempting to call some :term:`view`, modify
-your ``configure.zcml`` to look something like this:
-
-.. code-block:: xml
- :linenos:
-
- <configure xmlns="http://pylonshq.com/pyramid">
-
- <!-- views and other directives before this... -->
-
- <authtktauthenticationpolicy
- secret="iamsosecret"/>
-
- <aclauthorizationpolicy/>
-
- </configure>
-
-"Under the hood", these statements cause an instance of the class
-:class:`pyramid.authentication.AuthTktAuthenticationPolicy` to be
-injected as the :term:`authentication policy` used by this application
-and an instance of the class
-:class:`pyramid.authorization.ACLAuthorizationPolicy` to be
-injected as the :term:`authorization policy` used by this application.
-
-:app:`Pyramid` ships with a number of authorization and
-authentication policy ZCML directives that should prove useful. See
-:ref:`authentication_policies_directives_section` and
-:ref:`authorization_policies_directives_section` for more information.
-
-.. index::
- pair: ZCML directive; authentication policy
-
-.. _authentication_policies_directives_section:
-
-Built-In Authentication Policy ZCML Directives
-----------------------------------------------
-
-Instead of configuring an authentication policy and authorization
-policy imperatively, :app:`Pyramid` ships with a few "pre-chewed"
-authentication policy ZCML directives that you can make use of within
-your application.
-
-``authtktauthenticationpolicy``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When this directive is used, authentication information is obtained
-from an "auth ticket" cookie value, assumed to be set by a custom
-login form.
-
-An example of its usage, with all attributes fully expanded:
-
-.. code-block:: xml
- :linenos:
-
- <authtktauthenticationpolicy
- secret="goshiamsosecret"
- callback=".somemodule.somefunc"
- cookie_name="mycookiename"
- secure="false"
- include_ip="false"
- timeout="86400"
- reissue_time="600"
- max_age="31536000"
- path="/"
- http_only="false"
- />
-
-See :ref:`authtktauthenticationpolicy_directive` for details about
-this directive.
-
-``remoteuserauthenticationpolicy``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When this directive is used, authentication information is obtained
-from a ``REMOTE_USER`` key in the WSGI environment, assumed to
-be set by a WSGI server or an upstream middleware component.
-
-An example of its usage, with all attributes fully expanded:
-
-.. code-block:: xml
- :linenos:
-
- <remoteuserauthenticationpolicy
- environ_key="REMOTE_USER"
- callback=".somemodule.somefunc"
- />
-
-See :ref:`remoteuserauthenticationpolicy_directive` for detailed
-information.
-
-``repozewho1authenticationpolicy``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When this directive is used, authentication information is obtained
-from a ``repoze.who.identity`` key in the WSGI environment, assumed to
-be set by :term:`repoze.who` middleware.
-
-An example of its usage, with all attributes fully expanded:
-
-.. code-block:: xml
- :linenos:
-
- <repozewho1authenticationpolicy
- identifier_name="auth_tkt"
- callback=".somemodule.somefunc"
- />
-
-See :ref:`repozewho1authenticationpolicy_directive` for detailed
-information.
-
-.. index::
- pair: ZCML directive; authorization policy
-
-.. _authorization_policies_directives_section:
-
-Built-In Authorization Policy ZCML Directives
----------------------------------------------
-
-``aclauthorizationpolicy``
-
-When this directive is used, authorization information is obtained
-from :term:`ACL` objects attached to resources.
-
-An example of its usage, with all attributes fully expanded:
-
-.. code-block:: xml
- :linenos:
-
- <aclauthorizationpolicy/>
-
-In other words, it has no configuration attributes; its existence in a
-``configure.zcml`` file enables it.
-
-See :ref:`aclauthorizationpolicy_directive` for detailed information.
-
-.. _zcml_adding_and_overriding_renderers:
-
-Adding and Overriding Renderers via ZCML
-----------------------------------------
-
-New templating systems and serializers can be associated with :app:`Pyramid`
-renderer names. To this end, configuration declarations can be made which
-override an existing :term:`renderer factory` and which add a new renderer
-factory.
-
-Adding or overriding a renderer via ZCML is accomplished via the
-:ref:`renderer_directive` ZCML directive.
-
-For example, to add a renderer which renders views which have a
-``renderer`` attribute that is a path that ends in ``.jinja2``:
-
-.. code-block:: xml
- :linenos:
-
- <renderer
- name=".jinja2"
- factory="my.package.MyJinja2Renderer"
- />
-
-The ``factory`` attribute is a :term:`dotted Python name` that must
-point to an implementation of a :term:`renderer factory`.
-
-The ``name`` attribute is the renderer name.
-
-Registering a Renderer Factory
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-See :ref:`adding_a_renderer` for more information for the definition of a
-:term:`renderer factory`. Here's an example of the registration of a simple
-:term:`renderer factory` via ZCML:
-
-.. code-block:: xml
- :linenos:
-
- <renderer
- name="amf"
- factory="my.package.MyAMFRenderer"
- />
-
-Adding the above ZCML to your application will allow you to use the
-``my.package.MyAMFRenderer`` renderer factory implementation in view
-configurations by subseqently referring to it as ``amf`` in the ``renderer``
-attribute of a :term:`view configuration`:
-
-.. code-block:: xml
- :linenos:
-
- <view
- view="mypackage.views.my_view"
- renderer="amf"
- />
-
-Here's an example of the registration of a more complicated renderer
-factory, which expects to be passed a filesystem path:
-
-.. code-block:: xml
- :linenos:
-
- <renderer
- name=".jinja2"
- factory="my.package.MyJinja2Renderer"
- />
-
-Adding the above ZCML to your application will allow you to use the
-``my.package.MyJinja2Renderer`` renderer factory implementation in
-view configurations by referring to any ``renderer`` which *ends in*
-``.jinja`` in the ``renderer`` attribute of a :term:`view
-configuration`:
-
-.. code-block:: xml
- :linenos:
-
- <view
- view="mypackage.views.my_view"
- renderer="templates/mytemplate.jinja2"
- />
-
-When a :term:`view configuration` which has a ``name`` attribute that does
-contain a dot, such as ``templates/mytemplate.jinja2`` above is encountered at
-startup time, the value of the name attribute is split on its final dot. The
-second element of the split is typically the filename extension. This
-extension is used to look up a renderer factory for the configured view. Then
-the value of ``renderer`` is passed to the factory to create a renderer for the
-view. In this case, the view configuration will create an instance of a
-``Jinja2Renderer`` for each view configuration which includes anything ending
-with ``.jinja2`` as its ``renderer`` value. The ``name`` passed to the
-``Jinja2Renderer`` constructor will be whatever the user passed as
-``renderer=`` to the view configuration.
-
-See also :ref:`renderer_directive` and
-:meth:`pyramid.config.Configurator.add_renderer`.
-
-Overriding an Existing Renderer
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-You can associate more than one filename extension with the same
-existing renderer implementation as necessary if you need to use a
-different file extension for the same kinds of templates. For
-example, to associate the ``.zpt`` extension with the Chameleon ZPT
-renderer factory, use:
-
-.. code-block:: xml
- :linenos:
-
- <renderer
- name=".zpt"
- factory="pyramid.chameleon_zpt.renderer_factory"
- />
-
-After you do this, :app:`Pyramid` will treat templates ending in
-both the ``.pt`` and ``.zpt`` filename extensions as Chameleon ZPT
-templates.
-
-To override the default mapping in which files with a ``.pt``
-extension are rendered via a Chameleon ZPT page template renderer, use
-a variation on the following in your application's ZCML:
-
-.. code-block:: xml
- :linenos:
-
- <renderer
- name=".pt"
- factory="my.package.pt_renderer"
- />
-
-After you do this, the :term:`renderer factory` in
-``my.package.pt_renderer`` will be used to render templates which end
-in ``.pt``, replacing the default Chameleon ZPT renderer.
-
-To override the default mapping in which files with a ``.txt``
-extension are rendered via a Chameleon text template renderer, use a
-variation on the following in your application's ZCML:
-
-.. code-block:: xml
- :linenos:
-
- <renderer
- name=".txt"
- factory="my.package.text_renderer"
- />
-
-After you do this, the :term:`renderer factory` in
-``my.package.text_renderer`` will be used to render templates which
-end in ``.txt``, replacing the default Chameleon text renderer.
-
-To associate a *default* renderer with *all* view configurations (even
-ones which do not possess a ``renderer`` attribute), use a variation
-on the following (ie. omit the ``name`` attribute to the renderer
-tag):
-
-.. code-block:: xml
- :linenos:
-
- <renderer
- factory="pyramid.renderers.json_renderer_factory"
- />
-
-See also :ref:`renderer_directive` and
-:meth:`pyramid.config.Configurator.add_renderer`.
-
-.. _zcml_adding_a_translation_directory:
-
-Adding a Translation Directory via ZCML
----------------------------------------
-
-You can add a translation directory via ZCML by using the
-:ref:`translationdir_directive` ZCML directive:
-
-.. code-block:: xml
- :linenos:
-
- <translationdir dir="my.application:locale/"/>
-
-A message catalog in a translation directory added via
-:ref:`translationdir_directive` will be merged into translations from
-a message catalog added earlier if both translation directories
-contain translations for the same locale and :term:`translation
-domain`.
-
-See also :ref:`translationdir_directive` and
-:ref:`adding_a_translation_directory`.
-
-.. _zcml_adding_a_locale_negotiator:
-
-Adding a Custom Locale Negotiator via ZCML
-------------------------------------------
-
-You can add a custom locale negotiator via ZCML by using the
-:ref:`localenegotiator_directive` ZCML directive:
-
-.. code-block:: xml
- :linenos:
-
- <localenegotiator
- negotiator="my_application.my_module.my_locale_negotiator"
- />
-
-See also :ref:`custom_locale_negotiator` and
-:ref:`localenegotiator_directive`.
-
-.. index::
- pair: subscriber; ZCML directive
-
-.. _zcml_event_listener:
-
-Configuring an Event Listener via ZCML
---------------------------------------
-
-You can configure an :term:`subscriber` by modifying your application's
-``configure.zcml``. Here's an example of a bit of XML you can add to the
-``configure.zcml`` file which registers the above ``mysubscriber`` function,
-which we assume lives in a ``subscribers.py`` module within your application:
-
-.. code-block:: xml
- :linenos:
-
- <subscriber
- for="pyramid.events.NewRequest"
- handler=".subscribers.mysubscriber"
- />
-
-See also :ref:`subscriber_directive` and :ref:`events_chapter`.
-
-.. index::
- single: not found view
-
-.. _notfound_zcml:
-
-Configuring a Not Found View via ZCML
--------------------------------------
-
-If your application uses :term:`ZCML`, you can replace the Not Found view by
-placing something like the following ZCML in your ``configure.zcml`` file.
-
-.. code-block:: xml
- :linenos:
-
- <view
- view="helloworld.views.notfound_view"
- context="pyramid.exceptions.NotFound"
- />
-
-Replace ``helloworld.views.notfound_view`` with the Python dotted name to the
-notfound view you want to use.
-
-See :ref:`changing_the_notfound_view` for more information.
-
-.. index::
- single: forbidden view
-
-.. _forbidden_zcml:
-
-Configuring a Forbidden View via ZCML
--------------------------------------
-
-If your application uses :term:`ZCML`, you can replace the Forbidden view by
-placing something like the following ZCML in your ``configure.zcml`` file.
-
-.. code-block:: xml
- :linenos:
-
- <view
- view="helloworld.views.notfound_view"
- context="pyramid.exceptions.Forbidden"
- />
-
-Replace ``helloworld.views.forbidden_view`` with the Python dotted name to
-the forbidden view you want to use.
-
-See :ref:`changing_the_forbidden_view` for more information.
-
-.. _changing_traverser_zcml:
-
-Configuring an Alternate Traverser via ZCML
--------------------------------------------
-
-Use an ``adapter`` stanza in your application's ``configure.zcml`` to
-change the default traverser:
-
-.. code-block:: xml
- :linenos:
-
- <adapter
- factory="myapp.traversal.Traverser"
- provides="pyramid.interfaces.ITraverser"
- for="*"
- />
-
-Or to register a traverser for a specific resource type:
-
-.. code-block:: xml
- :linenos:
-
- <adapter
- factory="myapp.traversal.Traverser"
- provides="pyramid.interfaces.ITraverser"
- for="myapp.resources.MyRoot"
- />
-
-See :ref:`changing_the_traverser` for more information.
-
-.. index::
- single: url generator
-
-.. _changing_resource_url_zcml:
-
-Changing ``resource_url`` URL Generation via ZCML
--------------------------------------------------
-
-You can change how :func:`pyramid.url.resource_url` generates a URL for a
-specific type of resource by adding an adapter statement to your
-``configure.zcml``.
-
-.. code-block:: xml
- :linenos:
-
- <adapter
- factory="myapp.traversal.URLGenerator"
- provides="pyramid.interfaces.IContextURL"
- for="myapp.resources.MyRoot *"
- />
-
-See :ref:`changing_resource_url` for more information.
-
-.. _changing_request_factory_zcml:
-
-Changing the Request Factory via ZCML
--------------------------------------
-
-A ``MyRequest`` class can be registered via ZCML as a request factory through
-the use of the ZCML ``utility`` directive. In the below, we assume it lives
-in a package named ``mypackage.mymodule``.
-
-.. code-block:: xml
- :linenos:
-
- <utility
- component="mypackage.mymodule.MyRequest"
- provides="pyramid.interfaces.IRequestFactory"
- />
-
-See :ref:`changing_request_factory` for more information.
-
-.. _adding_renderer_globals_zcml:
-
-Changing the Renderer Globals Factory via ZCML
-----------------------------------------------
-
-A renderer globals factory can be registered via ZCML as a through the use of
-the ZCML ``utility`` directive. In the below, we assume a
-``renderers_globals_factory`` function lives in a package named
-``mypackage.mymodule``.
-
-.. code-block:: xml
- :linenos:
-
- <utility
- component="mypackage.mymodule.renderer_globals_factory"
- provides="pyramid.interfaces.IRendererGlobalsFactory"
- />
-
-See :ref:`adding_renderer_globals` for more information.
-
diff --git a/docs/narr/environment.rst b/docs/narr/environment.rst
index 7caa1dcc6..7b7946aae 100644
--- a/docs/narr/environment.rst
+++ b/docs/narr/environment.rst
@@ -38,10 +38,11 @@ application-specific configuration settings.
Reloading Templates
-------------------
-When this value is true, reload templates without a restart, so you can see
-changes to templates take effect immediately during development. This flag
-is meaningful to Chameleon and Mako templates, as well as most third-party
-template rendering extensions.
+When this value is true, templates are automatically reloaded whenever
+they are modified without restarting the application, so you can see
+changes to templates take effect immediately during development. This
+flag is meaningful to Chameleon and Mako templates, as well as most
+third-party template rendering extensions.
+---------------------------------+-----------------------------+
| Environment Variable Name | Config File Setting Name |
@@ -335,6 +336,14 @@ with ``reload_``). on in one fell swoop, you can use
affect settings that do not start with ``reload_*`` such as
``debug_notfound``.
+.. note::
+ Specifying configuration settings via environment variables is generally
+ most useful during development, where you may wish to augment or
+ override the more permanent settings in the configuration file.
+ This is useful because many of the reload and debug settings may
+ have performance or security (i.e., disclosure) implications
+ that make them undesirable in a production environment.
+
.. index::
single: reload_templates
single: reload_assets
diff --git a/docs/narr/events.rst b/docs/narr/events.rst
index 06b30883f..224eeca16 100644
--- a/docs/narr/events.rst
+++ b/docs/narr/events.rst
@@ -38,52 +38,51 @@ you'll need to use the
need to use the :func:`pyramid.events.subscriber` decorator to decorate a
function found via a :term:`scan`.
-.. topic:: Configuring an Event Listener Imperatively
+Configuring an Event Listener Imperatively
+------------------------------------------
- You can imperatively configure a subscriber function to be called
- for some event type via the
- :meth:`pyramid.config.Configurator.add_subscriber`
- method (see also :term:`Configurator`):
+You can imperatively configure a subscriber function to be called
+for some event type via the
+:meth:`pyramid.config.Configurator.add_subscriber`
+method (see also :term:`Configurator`):
- .. code-block:: python
- :linenos:
-
- from pyramid.events import NewRequest
+.. code-block:: python
+ :linenos:
- from subscribers import mysubscriber
+ from pyramid.events import NewRequest
- # "config" below is assumed to be an instance of a
- # pyramid.config.Configurator object
+ from subscribers import mysubscriber
- config.add_subscriber(mysubscriber, NewRequest)
+ # "config" below is assumed to be an instance of a
+ # pyramid.config.Configurator object
- The first argument to
- :meth:`pyramid.config.Configurator.add_subscriber` is the
- subscriber function (or a :term:`dotted Python name` which refers
- to a subscriber callable); the second argument is the event type.
+ config.add_subscriber(mysubscriber, NewRequest)
-.. topic:: Configuring an Event Listener Using a Decorator
+The first argument to
+:meth:`pyramid.config.Configurator.add_subscriber` is the
+subscriber function (or a :term:`dotted Python name` which refers
+to a subscriber callable); the second argument is the event type.
- You can configure a subscriber function to be called for some event
- type via the :func:`pyramid.events.subscriber` function.
+Configuring an Event Listener Using a Decorator
+-----------------------------------------------
- .. code-block:: python
- :linenos:
+You can configure a subscriber function to be called for some event
+type via the :func:`pyramid.events.subscriber` function.
- from pyramid.events import NewRequest
- from pyramid.events import subscriber
+.. code-block:: python
+ :linenos:
- @subscriber(NewRequest)
- def mysubscriber(event):
- event.request.foo = 1
+ from pyramid.events import NewRequest
+ from pyramid.events import subscriber
- When the :func:`pyramid.subscriber` decorator is used a
- :term:`scan` must be performed against the package containing the
- decorated function for the decorator to have any effect. See
- :func:`pyramid.subscriber` for more information.
+ @subscriber(NewRequest)
+ def mysubscriber(event):
+ event.request.foo = 1
-.. note:: You can also configure an event listener via ZCML. See
- :ref:`zcml_event_listener`.
+When the :func:`pyramid.subscriber` decorator is used a
+:term:`scan` must be performed against the package containing the
+decorated function for the decorator to have any effect. See
+:func:`pyramid.subscriber` for more information.
Either of the above registration examples implies that every time the
:app:`Pyramid` framework emits an event object that supplies an
diff --git a/docs/narr/extending.rst b/docs/narr/extending.rst
index 524dcb2ac..c709e1f8f 100644
--- a/docs/narr/extending.rst
+++ b/docs/narr/extending.rst
@@ -108,7 +108,7 @@ extensible and overrideable. :term:`ZCML` declarations that belong to an
application can be overridden and extended by integrators as necessary in a
similar fashion. If you use only :term:`ZCML` to configure your application,
it will automatically be maximally extensible without any manual effort. See
-:ref:`declarative_chapter` for information about using ZCML.
+:term:`pyramid_zcml` for information about using ZCML.
Fundamental Plugpoints
~~~~~~~~~~~~~~~~~~~~~~
@@ -121,9 +121,9 @@ ZCML ``<route>`` directive). Views are declarations made using the
directive). Assets are files that are accessed by :app:`Pyramid` using the
:term:`pkg_resources` API such as static files and templates via a
:term:`asset specification`. Other directives and configurator methods also
-deal in routes, views, and assets. For example,
-:meth:`pyramid.config.Configurator.add_handler` adds a single route, and some
-number of views.
+deal in routes, views, and assets. For example, ``add_handler`` directive of
+the ``pyramid_handlers`` package adds a single route, and some number of
+views.
.. index::
single: extending an existing application
@@ -196,7 +196,7 @@ like this:
:ref:`creating_a_project` for more information.
- In the new package, create Python files containing views and other
- overridden elements, such as templates and static resources as necessary.
+ overridden elements, such as templates and static assets as necessary.
- Install the new package into the same Python environment as the original
application (e.g. ``python setup.py develop`` or ``python setup.py
@@ -278,7 +278,7 @@ into the override package's file and changing them as necessary. Then
disinclude any ``add_route`` statements from the original application.
.. index::
- pair: overriding; resources
+ pair: overriding; assets
.. _overriding_resources:
@@ -286,10 +286,10 @@ Overriding Assets
~~~~~~~~~~~~~~~~~
Assets are files on the filesystem that are accessible within a Python
-*package*. An entire chapter is devoted to resources: :ref:`assets_chapter`.
+*package*. An entire chapter is devoted to assets: :ref:`assets_chapter`.
Within this chapter is a section named :ref:`overriding_assets_section`.
This section of that chapter describes in detail how to override package
-resources with other resources by using the
+assets with other assets by using the
:meth:`pyramid.config.Configurator.override_asset` method. Add such
``override_asset`` calls to your override package's ``__init__.py`` to
perform overrides.
diff --git a/docs/narr/firstapp.rst b/docs/narr/firstapp.rst
index 3f1098da4..34e6981a4 100644
--- a/docs/narr/firstapp.rst
+++ b/docs/narr/firstapp.rst
@@ -327,4 +327,4 @@ For more information about :term:`view configuration`, see
An example of using *declarative* configuration (:term:`ZCML`) instead of
imperative configuration to create a similar "hello world" is available
-within :ref:`declarative_configuration`.
+within the documentation for :term:`pyramid_zcml`.
diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst
index cf3f56e87..b3b41046f 100644
--- a/docs/narr/hooks.rst
+++ b/docs/narr/hooks.rst
@@ -70,9 +70,6 @@ Here's some sample code that implements a minimal NotFound view callable:
:exc:`pyramid.exceptions.NotFound` exception instance. If available, the
resource context will still be available as ``request.context``.
-For information about how to configure a not found view via :term:`ZCML`, see
-:ref:`notfound_zcml`.
-
.. index::
single: forbidden view
@@ -83,7 +80,7 @@ Changing the Forbidden View
When :app:`Pyramid` can't authorize execution of a view based on the
:term:`authorization policy` in use, it invokes a :term:`forbidden view`.
-The default forbidden response has a 401 status code and is very plain, but
+The default forbidden response has a 403 status code and is very plain, but
the view which generates it can be overridden as necessary.
The :term:`forbidden view` callable is a view callable like any other. The
@@ -132,15 +129,6 @@ Here's some sample code that implements a minimal forbidden view:
``debug_authorization`` environment setting is true than it is when
it is false.
-.. warning:: the default forbidden view sends a response with a ``401
- Unauthorized`` status code for backwards compatibility reasons.
- You can influence the status code of Forbidden responses by using
- an alternate forbidden view. For example, it would make sense to
- return a response with a ``403 Forbidden`` status code.
-
-For information about how to configure a forbidden view via :term:`ZCML`, see
-:ref:`forbidden_zcml`.
-
.. index::
single: request factory
@@ -185,8 +173,6 @@ already constructed a :term:`configurator` it can also be registered via the
config = Configurator()
config.set_request_factory(MyRequest)
-To use ZCML for the same purpose, see :ref:`changing_request_factory_zcml`.
-
.. index::
single: renderer globals
@@ -242,9 +228,6 @@ already constructed a :term:`configurator` it can also be registered via the
Another mechanism which allows event subscribers to add renderer global values
exists in :ref:`beforerender_event`.
-If you'd rather ZCML to register a renderer globals factory, see
-:ref:`adding_renderer_globals_zcml`.
-
.. index::
single: before render event
@@ -365,10 +348,11 @@ parameter: ``request``. For example:
transaction.commit()
request.add_finished_callback(commit_callback)
-Finished callbacks are called in the order they're added ( first- to
-most-recently- added). Finished callbacks (unlike a :term:`response
-callback`) are *always* called, even if an exception happens in application
-code that prevents a response from being generated.
+Finished callbacks are called in the order they're added
+(first-to-most-recently-added). Finished callbacks (unlike a
+:term:`response callback`) are *always* called, even if an exception
+happens in application code that prevents a response from being
+generated.
The set of finished callbacks associated with a request are called *very
late* in the processing of that request; they are essentially the very last
@@ -474,9 +458,6 @@ when the application :term:`root factory` returned an instance of the
``myapp.resources.MyRoot`` object. Otherwise it would use the default
:app:`Pyramid` traverser to do traversal.
-For information about how to configure an alternate traverser via
-:term:`ZCML`, see :ref:`changing_traverser_zcml`.
-
.. index::
single: url generator
@@ -543,12 +524,14 @@ The default context URL generator is available for perusal as the class
.. index::
single: view mapper
+.. _using_a_view_mapper:
+
Using a View Mapper
-------------------
The default calling conventions for view callables are documented in the
-:ref:`views_chapter`. You can change the way users define view callbles by
-employing a :term:`view mapper`.
+:ref:`views_chapter` chapter. You can change the way users define view
+callbles by employing a :term:`view mapper`.
A view mapper is an object that accepts a set of keyword arguments and which
returns a callable. The returned callable is called with the :term:`view
@@ -609,6 +592,7 @@ A user might make use of these framework components like so:
from webob import Response
from pyramid.config import Configurator
+ import pyramid_handlers
from paste.httpserver import serve
class MyController(BaseController):
@@ -617,6 +601,7 @@ A user might make use of these framework components like so:
if __name__ == '__main__':
config = Configurator()
+ config.include(pyramid_handlers)
config.add_handler('one', '/{id}', MyController, action='index')
config.add_handler('two', '/{action}/{id}', MyController)
serve(config.make_wsgi_app())
diff --git a/docs/narr/i18n.rst b/docs/narr/i18n.rst
index c2a5b8ce7..83973a17e 100644
--- a/docs/narr/i18n.rst
+++ b/docs/narr/i18n.rst
@@ -867,11 +867,11 @@ which itself includes an ``LC_MESSAGES`` directory. Each
Each ``.mo`` file represents a :term:`message catalog`, which is used
to provide translations to your application.
-Adding a :term:`translation directory` registers all of its
-constituent :term:`message catalog` files (all of the ``.mo`` files
-found within all ``LC_MESSAGES`` directories within each locale
-directory in the translation directory) within your :app:`Pyramid`
-application to be available to use for translation services.
+Adding a :term:`translation directory` registers all of its constituent
+:term:`message catalog` files within your :app:`Pyramid` application to
+be available to use for translation services. This includes all of the
+``.mo`` files found within all ``LC_MESSAGES`` directories within each
+locale directory in the translation directory.
You can add a translation directory imperatively by using the
:meth:`pyramid.config.Configurator.add_translation_dirs` during
@@ -890,9 +890,6 @@ will be merged into translations from a message catalog added earlier
if both translation directories contain translations for the same
locale and :term:`translation domain`.
-.. note:: You can also add a translation directory via ZCML. See
- :ref:`zcml_adding_a_translation_directory`
-
Setting the Locale
~~~~~~~~~~~~~~~~~~
@@ -1019,5 +1016,3 @@ For example:
config = Configurator()
config.set_locale_negotiator(my_locale_negotiator)
-.. note:: You can also add a custom locale negotiator via ZCML. See
- :ref:`zcml_adding_a_locale_negotiator`
diff --git a/docs/narr/install.rst b/docs/narr/install.rst
index e32d0c6c3..c5ec14aa1 100644
--- a/docs/narr/install.rst
+++ b/docs/narr/install.rst
@@ -295,7 +295,7 @@ Installing :app:`Pyramid` on a Windows System
c:\> cd env
-#. (Optional) Consider using ``bin\activate.bat`` to make your shell
+#. (Optional) Consider using ``Scripts\activate.bat`` to make your shell
environment wired to use the virtualenv.
#. Use ``easy_install`` pointed at the "current" index to get
diff --git a/docs/narr/introduction.rst b/docs/narr/introduction.rst
index c61ef21d4..2da75df39 100644
--- a/docs/narr/introduction.rst
+++ b/docs/narr/introduction.rst
@@ -104,7 +104,7 @@ What Is The Pylons Project?
:app:`Pyramid` is a member of the collection of software published under the
Pylons Project. Pylons software is written by a loose-knit community of
-contributors. The `Pylons Project website <http://docs.pylonshq.com>`_
+contributors. The `Pylons Project website <http://docs.pylonsproject.org>`_
includes details about how :app:`Pyramid` relates to the Pylons Project.
.. index::
diff --git a/docs/narr/muchadoabouttraversal.rst b/docs/narr/muchadoabouttraversal.rst
index bc1b48462..c57e58cd0 100644
--- a/docs/narr/muchadoabouttraversal.rst
+++ b/docs/narr/muchadoabouttraversal.rst
@@ -43,12 +43,12 @@ ever used a run-of-the-mill file system with folders and files.
URL Dispatch
------------
-Let's step back and consider the problem we're trying to solve, which is
-simple. An HTTP request for a particular path has been routed to our web
-application. The requested path will possibly invoke a specific :term:`view
-callable` function defined somewhere in our app. We're trying to determine
-*which* callable function, if any, should be invoked for a given requested
-URL.
+Let's step back and consider the problem we're trying to solve. An
+HTTP request for a particular path has been routed to our web
+application. The requested path will possibly invoke a specific
+:term:`view callable` function defined somewhere in our app. We're
+trying to determine *which* callable function, if any, should be
+invoked for a given requested URL.
Many systems, including Pyramid, offer a simple solution. They offer the
concept of "URL matching". URL matching approaches this problem by parsing
@@ -59,10 +59,9 @@ request path matches a specific pattern, the associated function is called.
If the request path matches more than one pattern, some conflict resolution
scheme is used, usually a simple order precedence so that the first match
will take priority over any subsequent matches. If a request path doesn't
-match any of the defined patterns, :app:`Pyramid` a "404 Not Found" response
-is returned.
+match any of the defined patterns, a "404 Not Found" response is returned.
-In Pyramid, we offer an implementation of URL mapping which we call
+In Pyramid, we offer an implementation of URL matching which we call
:term:`URL dispatch`. Using :app:`Pyramid` syntax, we might have a match
pattern such as ``/{userid}/photos/{photoid}``, mapped to a ``photo_view()``
function defined somewhere in our code. Then a request for a path such as
@@ -115,7 +114,7 @@ then you understand view lookup.
The major difference between file system lookup and traversal is that a file
system lookup steps through nested directories and files in a file system
-tree, while traversal steps through nested dictionary-type objects in an
+tree, while traversal steps through nested dictionary-type objects in a
:term:`resource tree`. Let's take a detailed look at one of our example
paths, so we can see what I mean:
@@ -123,7 +122,7 @@ The path ``/joeschmoe/photos/photo1``, has four segments: ``/``,
``joeschmoe``, ``photos`` and ``photo1``. With file system lookup we might
have a root folder (``/``) containing a nested folder (``joeschmoe``), which
contains another nested folder (``photos``), which finally contains a JPG
-file ("photo1"). With traversal, we instead have a dictionary-like root
+file (``photo1``). With traversal, we instead have a dictionary-like root
object. Asking for the ``joeschmoe`` key gives us another dictionary-like
object. Asking this in turn for the ``photos`` key gives us yet another
mapping object, which finally (hopefully) contains the resource that we're
@@ -154,9 +153,9 @@ Since :app:`Pyramid` is not a highly opinionated framework, it makes no
restriction on how a :term:`resource` is implemented; a developer can
implement them as he wishes. One common pattern used is to persist all of
the resources, including the root, in a database as a graph. The root object
-is a dictionarylike object. Dictionarylike objects in Python supply a
+is a dictionary-like object. Dictionary-like objects in Python supply a
``__getitem__`` method which is called when key lookup is done. Under the
-hood, when ``adict`` is a dictionarylike object, Python translates
+hood, when ``adict`` is a dictionary-like object, Python translates
``adict['a']`` to ``adict.__getitem__('a')``. Try doing this in a Python
interpreter prompt if you don't believe us:
@@ -174,7 +173,7 @@ interpreter prompt if you don't believe us:
1
-The dictionarylike root object stores the ids of all of its subresources as
+The dictionary-like root object stores the ids of all of its subresources as
keys, and provides a ``__getitem__`` implementation that fetches them. So
``get_root()`` fetches the unique root object, while
``get_root()['joeschmoe']`` returns a different object, also stored in the
@@ -185,12 +184,13 @@ days, or anywhere else, it doesn't matter. As long as the returned objects
provide the dictionary-like API (i.e. as long as they have an appropriately
implemented ``__getitem__`` method) then traversal will work.
-In fact, you don't need a "database" at all. You could trivially implement a
-set of objects with ``__getitem__`` methods that search for files in specific
-directories, and thus precisely recreate the older mechanism of having the
-URL path mapped directly to a folder structure on the file system. Or you
-could use plain dictionaries too. Traversal is in fact a superset of file
-system lookup.
+In fact, you don't need a "database" at all. You could use plain
+dictionaries, with your site's URL structure hard-coded directly in
+the Python source. Or you could trivially implement a set of objects
+with ``__getitem__`` methods that search for files in specific
+directories, and thus precisely recreate the traditional mechanism of
+having the URL path mapped directly to a folder structure on the file
+system. Traversal is in fact a superset of file system lookup.
.. note:: See the chapter entitled :ref:`resources_chapter` for a more
technical overview of resources.
@@ -207,13 +207,14 @@ that you might want to take after finding a :term:`resource`. With our photo
example, for instance, you might want to view the photo in a page, but you
might also want to provide a way for the user to edit the photo and any
associated metadata. We'll call the former the ``view`` view, and the latter
-will be the ``edit`` view (Original, I know.) :app:`Pyramid` has a
-centralized view registry where named views can be associated with specific
-resource types. So in our example, we'll assume that we've registered
-``view`` and ``edit`` views for photo objects, and that we've specified the
-``view`` view as the default, so that ``/joeschmoe/photos/photo1/view`` and
-``/joeschmoe/photos/photo1`` are equivalent. The edit view would sensibly be
-provided by a request for ``/joeschmoe/photos/photo1/edit``.
+will be the ``edit`` view. (Original, I know.) :app:`Pyramid` has a
+centralized view :term:`application registry` where named views can be
+associated with specific resource types. So in our example, we'll assume
+that we've registered ``view`` and ``edit`` views for photo objects, and that
+we've specified the ``view`` view as the default, so that
+``/joeschmoe/photos/photo1/view`` and ``/joeschmoe/photos/photo1`` are
+equivalent. The edit view would sensibly be provided by a request for
+``/joeschmoe/photos/photo1/edit``.
Hopefully it's clear that the first portion of the edit view's URL path is
going to resolve to the same resource as the non-edit version, specifically
@@ -232,15 +233,15 @@ response.
You might conceptualize a request for ``/joeschmoe/photos/photo1/edit`` as
ultimately converted into the following piece of Pythonic pseudocode::
-
+
context = get_root()['joeschmoe']['photos']['photo1']
view_callable = get_view(context, 'edit')
request.context = context
view_callable(request)
The ``get_root`` and ``get_view`` functions don't really exist. Internally,
-:app:`Pyramid` does something more complicated. But the example above is a
-reasonable approximation of the view lookup algorithm in pseudocode.
+:app:`Pyramid` does something more complicated. But the example above
+is a reasonable approximation of the view lookup algorithm in pseudocode.
Use Cases
---------
@@ -264,20 +265,18 @@ folder. He might decide to nest folders dozens of layers deep. How will you
construct matching patterns that could account for every possible combination
of paths that might develop?
-It's possible, but it will make for some somewhat ugly URLs. And the
-matching patterns are going to become complex quickly as you try to handle
-all of the edge cases.
-
-With traversal, however, it's straightforward. If you want 20 layers of
-nesting, it's no problem. :app:`Pyramid` will happily call ``__getitem__``
-as many times as it needs to, until it runs out of path segments or until a
-resource raises a :exc:`KeyError`. Each resource only needs to know how to
-fetch its immediate children, the traversal algorithm takes care of the rest.
-
-One of the key advantages of traversal is that the structure of the resource
-tree can live in the database, and not in the code. It's simple to let users
-modify the tree at runtime to set up their own personalized directory
-structures.
+It might be possible, but it certainly won't be easy. The matching
+patterns are going to become complex quickly as you try to handle all
+of the edge cases.
+
+With traversal, however, it's straightforward. 20 layers of nesting would be
+no problem. :app:`Pyramid` will happily call ``__getitem__`` as many times
+as it needs to, until it runs out of path segments or until a resource raises
+a :exc:`KeyError`. Each resource only needs to know how to fetch its
+immediate children, the traversal algorithm takes care of the rest. Also,
+since the structure of the resource tree can live in the database and not in
+the code, it's simple to let users modify the tree at runtime to set up their
+own personalized "directory" structures.
Another use case in which traversal shines is when there is a need to support
a context-dependent security policy. One example might be a document
diff --git a/docs/narr/project.rst b/docs/narr/project.rst
index c1017b5c1..f0ee91164 100644
--- a/docs/narr/project.rst
+++ b/docs/narr/project.rst
@@ -8,13 +8,13 @@ As we saw in :ref:`firstapp_chapter`, it's possible to create a
convenient to use a *template* to generate a basic :app:`Pyramid`
:term:`project`.
-A project is a directory that contains at least one :term:`package`. You'll
-use a template to create a project, and you'll create your application logic
-within a package that lives inside the project. Even if your application is
-extremely simple, it is useful to place code that drives the application
-within a package, because a package is more easily extended with new code.
-An application that lives inside a package can also be distributed more
-easily than one which does not live within a package.
+A project is a directory that contains at least one Python :term:`package`.
+You'll use a template to create a project, and you'll create your application
+logic within a package that lives inside the project. Even if your
+application is extremely simple, it is useful to place code that drives the
+application within a package, because a package is more easily extended with
+new code. An application that lives inside a package can also be distributed
+more easily than one which does not live within a package.
:app:`Pyramid` comes with a variety of templates that you can use to generate
a project. Each template makes different configuration assumptions about
@@ -26,13 +26,9 @@ and so therefore they are often referred to as "paster templates".
.. index::
single: paster templates
single: pyramid_starter paster template
- single: pyramid_starter_zcml paster template
single: pyramid_zodb paster template
single: pyramid_alchemy paster template
single: pyramid_routesalchemy paster template
- single: pylons_minimal paster template
- single: pylons_basic paster template
- single: pylons_sqla paster template
.. _additional_paster_templates:
@@ -48,8 +44,6 @@ each other on a number of axes:
- the mechanism they use to map URLs to code (:term:`traversal` or :term:`URL
dispatch`).
-- the type of configuration used (:term:`ZCML` vs. imperative configuration).
-
- whether or not the ``pyramid_beaker`` library is relied upon as the
sessioning implementation (as opposed to no sessioning or default
sessioning).
@@ -59,10 +53,6 @@ The included templates are these:
``pyramid_starter``
URL mapping via :term:`traversal` and no persistence mechanism.
-``pyramid_starter_zcml``
- URL mapping via :term:`traversal` and no persistence mechanism, using
- :term:`ZCML` (declarative configuration).
-
``pyramid_zodb``
URL mapping via :term:`traversal` and persistence via :term:`ZODB`.
@@ -74,20 +64,6 @@ The included templates are these:
URL mapping via :term:`traversal` and persistence via
:term:`SQLAlchemy`
-``pylons_minimal``
- URL mapping via :term:`URL dispatch` and Pylons-style view handlers,
- minimal setup, uses ``pyramid_beaker`` as a sessioning implementation.
-
-``pylons_basic``
- URL mapping via :term:`URL dispatch` and Pylons-style view handlers, and
- some extra functionality, uses ``pyramid_beaker`` as a sessioning
- implementation.
-
-``pylons_sqla``
- URL mapping via :term:`URL dispatch` and Pylons-style view handlers, some
- extra functionality, and SQLAlchemy set up, uses ``pyramid_beaker`` as a
- sessioning implementation.
-
.. index::
single: creating a project
single: project
@@ -601,7 +577,7 @@ or influencing runtime behavior of a :app:`Pyramid` application. See
default 'application' (although it's actually a pipeline of middleware and an
application) run by ``paster serve`` when it is invoked against this
configuration file. The name ``main`` is a convention used by PasteDeploy
-signifying that it the default application.
+signifying that it is the default application.
The ``[server:main]`` section of the configuration file configures a WSGI
server which listens on TCP port 6543. It is configured to listen on all
@@ -705,7 +681,8 @@ who want to use your application.
be included in the tarball. If you don't use Subversion, and instead use
a different version control system, you may need to install a setuptools
add-on such as ``setuptools-git`` or ``setuptools-hg`` for this behavior
- to work properly.
+ to work properly. Alternatively, you can specify the non-Python-source
+ files by hand in a ``manifest template``, called ``MANIFEST.in`` by default.
``setup.cfg``
~~~~~~~~~~~~~
@@ -876,9 +853,6 @@ represent the root.
This directory contains static assets which support the ``mytemplate.pt``
template. It includes CSS and images.
-.. index::
- single: tests.py
-
``templates/mytemplate.pt``
~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -892,6 +866,9 @@ Templates are accessed and used by view configurations and sometimes by view
functions themselves. See :ref:`templates_used_directly` and
:ref:`templates_used_as_renderers`.
+.. index::
+ single: tests.py
+
``tests.py``
~~~~~~~~~~~~
@@ -964,10 +941,10 @@ To this:
renderer='myproject:templates/mytemplate.pt')
You can then continue to add files to the ``views`` directory, and refer to
-views or handler classes/functions within those files via the dotted name
-passed as the first argument to ``add_view``. For example, if you added a
-file named ``anothermodule.py`` to the ``views`` subdirectory, and added a
-view callable named ``my_view`` to it:
+view classes or functions within those files via the dotted name passed as
+the first argument to ``add_view``. For example, if you added a file named
+``anothermodule.py`` to the ``views`` subdirectory, and added a view callable
+named ``my_view`` to it:
.. code-block:: python
:linenos:
diff --git a/docs/narr/renderers.rst b/docs/narr/renderers.rst
index d888e3376..a80c5a9c2 100644
--- a/docs/narr/renderers.rst
+++ b/docs/narr/renderers.rst
@@ -389,21 +389,17 @@ documentation in :ref:`request_module`.
.. _adding_and_overriding_renderers:
-Adding and Overriding Renderers
--------------------------------
+Adding and Changing Renderers
+-----------------------------
New templating systems and serializers can be associated with :app:`Pyramid`
renderer names. To this end, configuration declarations can be made which
-override an existing :term:`renderer factory`, and which add a new renderer
+change an existing :term:`renderer factory`, and which add a new renderer
factory.
Renderers can be registered imperatively using the
:meth:`pyramid.config.Configurator.add_renderer` API.
-.. note:: The tasks described in this section can also be performed via
- :term:`declarative configuration`. See
- :ref:`zcml_adding_and_overriding_renderers`.
-
For example, to add a renderer which renders views which have a
``renderer`` attribute that is a path that ends in ``.jinja2``:
@@ -546,7 +542,7 @@ set as ``renderer=`` in the view configuration.
See also :ref:`renderer_directive` and
:meth:`pyramid.config.Configurator.add_renderer`.
-Overriding an Existing Renderer
+Changing an Existing Renderer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can associate more than one filename extension with the same existing
@@ -563,7 +559,7 @@ extension for the same kinds of templates. For example, to associate the
After you do this, :app:`Pyramid` will treat templates ending in both the
``.pt`` and ``.zpt`` filename extensions as Chameleon ZPT templates.
-To override the default mapping in which files with a ``.pt`` extension are
+To change the default mapping in which files with a ``.pt`` extension are
rendered via a Chameleon ZPT page template renderer, use a variation on the
following in your application's startup code:
@@ -585,3 +581,44 @@ the ``name`` attribute to the renderer tag:
config.add_renderer(None, 'mypackage.json_renderer_factory')
+Overriding A Renderer At Runtime
+--------------------------------
+
+.. warning:: This is an advanced feature, not typically used by "civilians".
+
+In some circumstances, it is necessary to instruct the system to ignore the
+static renderer declaration provided by the developer in view configuration,
+replacing the renderer with another *after a request starts*. For example,
+an "omnipresent" XML-RPC implementation that detects that the request is from
+an XML-RPC client might override a view configuration statement made by the
+user instructing the view to use a template renderer with one that uses an
+XML-RPC renderer. This renderer would produce an XML-RPC representation of
+the data returned by an arbitrary view callable.
+
+To use this feature, create a :class:`pyramid.events.NewRequest`
+:term:`subscriber` which sniffs at the request data and which conditionally
+sets an ``override_renderer`` attribute on the request itself, which is the
+*name* of a registered renderer. For example:
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.event import subscriber
+ from pyramid.event import NewRequest
+
+ @subscriber(NewRequest)
+ def set_xmlrpc_params(event):
+ request = event.request
+ if (request.content_type == 'text/xml'
+ and request.method == 'POST'
+ and not 'soapaction' in request.headers
+ and not 'x-pyramid-avoid-xmlrpc' in request.headers):
+ params, method = parse_xmlrpc_request(request)
+ request.xmlrpc_params, request.xmlrpc_method = params, method
+ request.is_xmlrpc = True
+ request.override_renderer = 'xmlrpc'
+ return True
+
+The result of such a subscriber will be to replace any existing static
+renderer configured by the developer with a (notional, nonexistent) XML-RPC
+renderer if the request appears to come from an XML-RPC client.
diff --git a/docs/narr/resources.rst b/docs/narr/resources.rst
index cf13f8c8d..c97b4c676 100644
--- a/docs/narr/resources.rst
+++ b/docs/narr/resources.rst
@@ -186,7 +186,7 @@ you will reach the filesystem root directory.
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
+ traversed resource (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``.
diff --git a/docs/narr/router.rst b/docs/narr/router.rst
index f9e98373c..782098bac 100644
--- a/docs/narr/router.rst
+++ b/docs/narr/router.rst
@@ -44,7 +44,7 @@ processing?
#. If any route matches, the request is mutated; a ``matchdict`` and
``matched_route`` attributes are added to the request object; the
- former contains a dictionary representign the matched dynamic
+ former contains a dictionary representing the matched dynamic
elements of the request's ``PATH_INFO`` value, the latter contains
the :class:`pyramid.interfaces.IRoute` object representing the
route which matched. The root object associated with the route
diff --git a/docs/narr/security.rst b/docs/narr/security.rst
index 62a4727bc..e395b15f1 100644
--- a/docs/narr/security.rst
+++ b/docs/narr/security.rst
@@ -6,13 +6,14 @@
Security
========
-:app:`Pyramid` provides an optional declarative authorization system that
-prevents a :term:`view` from being invoked when the user represented by
-credentials in the :term:`request` does not have an appropriate level of
-access when a particular resource is the :term:`context`. Here's how it
-works at a high level:
+:app:`Pyramid` provides an optional declarative authorization system
+that can prevent a :term:`view` from being invoked based on an
+:term:`authorization policy`. Before a view is invoked, the
+authorization system can use the credentials in the :term:`request`
+along with the :term:`context` resource to determine if access will be
+allowed. Here's how it works at a high level:
-- A :term:`request` is generated when a user visits our application.
+- A :term:`request` is generated when a user visits the application.
- Based on the request, a :term:`context` resource is located through
:term:`resource location`. A context is located differently depending on
@@ -40,6 +41,15 @@ works at a high level:
- If the authorization policy denies access, the view callable is not
invoked; instead the :term:`forbidden view` is invoked.
+Security in :app:`Pyramid`, unlike many systems, cleanly and explicitly
+separates authentication and authorization. Authentication is merely the
+mechanism by which credentials provided in the :term:`request` are
+resolved to one or more :term:`principal` identifiers. These identifiers
+represent the users and groups in effect during the request.
+Authorization then determines access based on the :term:`principal`
+identifiers, the :term:`view callable` being invoked, and the
+:term:`context` resource.
+
Authorization is enabled by modifying your application to include an
:term:`authentication policy` and :term:`authorization policy`.
:app:`Pyramid` comes with a variety of implementations of these
@@ -106,9 +116,6 @@ See also the :mod:`pyramid.authorization` and
:mod:`pyramid.authentication` modules for alternate implementations
of authorization and authentication policies.
-You can also enable a security policy declaratively via ZCML. See
-:ref:`zcml_authorization_policy`.
-
.. index::
single: permissions
single: protecting views
@@ -154,9 +161,6 @@ may be performed via the ``@view_config`` decorator:
""" Add blog entry code goes here """
pass
-Or the same thing can be done using the ``permission`` attribute of the ZCML
-:ref:`view_directive` directive.
-
As a result of any of these various view configuration statements, if an
authorization policy is in place when the view callable is found during
normal application operations, the requesting user will need to possess the
@@ -169,8 +173,8 @@ to invoke the ``blog_entry_add_view`` view. If he does not, the
Setting a Default Permission
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-If a permission is not supplied to a view configuration, the
-registered view always be executable by entirely anonymous users: any
+If a permission is not supplied to a view configuration, the registered
+view will always be executable by entirely anonymous users: any
authorization policy in effect is ignored.
In support of making it easier to configure applications which are
@@ -189,8 +193,6 @@ application:
:meth:`pyramid.config.Configurator.set_default_permission`
method.
-- The :ref:`default_permission_directive` ZCML directive.
-
When a default permission is registered:
- if a view configuration names an explicit ``permission``, the default
diff --git a/docs/narr/templates.rst b/docs/narr/templates.rst
index 7ef8e1923..b97cc7be6 100644
--- a/docs/narr/templates.rst
+++ b/docs/narr/templates.rst
@@ -448,7 +448,7 @@ Here's what a simple :term:`Chameleon` ZPT template used under
<body>
<h1 class="title">Welcome to <code>${project}</code>, an
application generated by the <a
- href="http://pylonshq.com/pyramid">pyramid</a> web
+ href="http://docs.pylonsproject.org/projects/pyramid/dev/">pyramid</a> web
application framework.</h1>
</body>
</html>
@@ -744,7 +744,7 @@ look like:
<body>
<h1 class="title">Welcome to <code>${project}</code>, an
application generated by the <a
- href="http://pylonshq.com/pyramid">pyramid</a> web
+ href="http://docs.pylonsproject.org/projects/pyramid/dev/">pyramid</a> web
application framework.</h1>
</body>
</html>
diff --git a/docs/narr/testing.rst b/docs/narr/testing.rst
index 007b96c2a..e166962f2 100644
--- a/docs/narr/testing.rst
+++ b/docs/narr/testing.rst
@@ -78,81 +78,84 @@ See :ref:`threadlocals_chapter` for information about these functions and the
data structures they return.
If your code uses these ``get_current_*`` functions or calls :app:`Pyramid`
-code which uses ``get_current_*`` functions, you will need to construct a
-:term:`Configurator` and call its ``begin`` method within the ``setUp``
-method of your unit test and call the same Configurator's ``end`` method
-within the ``tearDown`` method of your unit test.
-
-We'll also instruct the Configurator we use during testing to *autocommit*.
-Normally when a Configurator is used by an application, it defers performing
-any "real work" until its ``.commit`` method is called (often implicitly by
-the :meth:`pyramid.config.Configurator.make_wsgi_app` method). Passing
-``autocommit=True`` to the Configurator constructor causes the Configurator
-to perform all actions implied by methods called on it immediately, which is
-more convenient for unit-testing purposes than needing to call
-:meth:`pyramid.config.Configurator.commit` in each test.
-
-The use of a Configurator and its ``begin`` and ``end`` methods allows you to
-supply each unit test method in a test case with an environment that has an
-isolated registry and an isolated request for the duration of a single test.
-Here's an example of using this feature:
+code which uses ``get_current_*`` functions, you will need to call
+:func:`pyramid.testing.setUp` in your test setup and you will need to call
+:func:`pyramid.testing.tearDown` in your test teardown.
+:func:`~pyramid.testing.setUp` pushes a registry onto the :term:`thread
+local` stack, which makes the ``get_current_*`` functions work. It returns a
+:term:`Configurator` object which can be used to perform extra configuration
+required by the code under test. :func:`~pyramid.testing.tearDown` pops the
+thread local stack.
+
+Normally when a Configurator is used directly with the ``main`` block of
+a Pyramid application, it defers performing any "real work" until its
+``.commit`` method is called (often implicitly by the
+:meth:`pyramid.config.Configurator.make_wsgi_app` method). The
+Configurator returned by :func:`~pyramid.testing.setUp` is an
+*autocommitting* Configurator, however, which performs all actions
+implied by methods called on it immediately. This is more convenient
+for unit-testing purposes than needing to call
+:meth:`pyramid.config.Configurator.commit` in each test after adding
+extra configuration statements.
+
+The use of the :func:`~pyramid.testing.setUp` and
+:func:`~pyramid.testing.tearDown` functions allows you to supply each unit
+test method in a test case with an environment that has an isolated registry
+and an isolated request for the duration of a single test. Here's an example
+of using this feature:
.. code-block:: python
:linenos:
import unittest
- from pyramid.config import Configurator
+ from pyramid import testing
class MyTest(unittest.TestCase):
def setUp(self):
- self.config = Configurator(autocommit=True)
- self.config.begin()
+ self.config = testing.setUp()
def tearDown(self):
- self.config.end()
+ testing.tearDown()
The above will make sure that
-:func:`pyramid.threadlocal.get_current_registry` will return the
-:term:`application registry` associated with the ``config`` Configurator
-instance when :func:`pyramid.threadlocal.get_current_registry` is called in a
-test case method attached to ``MyTest``. Each test case method attached to
-``MyTest`` will use an isolated registry.
+:func:`pyramid.threadlocal.get_current_registry` called within a test
+case method of ``MyTest`` will return the :term:`application registry`
+associated with the ``config`` Configurator instance. Each test case
+method attached to ``MyTest`` will use an isolated registry.
-The :meth:`pyramid.config.Configurator.begin` method accepts various
-arguments that influence the code run during the test. See the
-:ref:`configuration_module` chapter for information about the API of a
-:term:`Configurator`, including its ``begin`` and ``end`` methods.
+The :func:`~pyramid.testing.setUp` and :func:`~pyramid.testing.tearDown`
+functions accepts various arguments that influence the environment of the
+test. See the :ref:`testing_module` chapter for information about the extra
+arguments supported by these functions.
If you also want to make :func:`pyramid.get_current_request` return something
other than ``None`` during the course of a single test, you can pass a
-:term:`request` object into the :meth:`pyramid.config.Configurator.begin`
-method of the Configurator within the ``setUp`` method of your test:
+:term:`request` object into the :func:`pyramid.testing.setUp` within the
+``setUp`` method of your test:
.. code-block:: python
:linenos:
import unittest
- from pyramid.config import Configurator
from pyramid import testing
class MyTest(unittest.TestCase):
def setUp(self):
- self.config = Configurator(autocommit=True)
request = testing.DummyRequest()
- self.config.begin(request=request)
+ self.config = testing.setUp(request=request)
def tearDown(self):
- self.config.end()
-
-If you pass a :term:`request` object into the ``begin`` method of the
-configurator within your test case's ``setUp``, any test method attached to
-the ``MyTest`` test case that directly or indirectly calls
-:func:`pyramid.threadlocal.get_current_request` will receive the request you
-passed into the ``begin`` method. Otherwise, during testing,
-:func:`pyramid.threadlocal.get_current_request` will return ``None``. We use
-a "dummy" request implementation supplied by
-:class:`pyramid.testing.DummyRequest` because it's easier to construct than a
-"real" :app:`Pyramid` request object.
+ testing.tearDown()
+
+If you pass a :term:`request` object into :func:`pyramid.testing.setUp`
+within your test case's ``setUp``, any test method attached to the
+``MyTest`` test case that directly or indirectly calls
+:func:`pyramid.threadlocal.get_current_request` will receive the request
+object. Otherwise, during testing,
+:func:`pyramid.threadlocal.get_current_request` will return ``None``.
+We use a "dummy" request implementation supplied by
+:class:`pyramid.testing.DummyRequest` because it's easier to construct
+than a "real" :app:`Pyramid` request object.
What?
~~~~~
@@ -162,18 +165,18 @@ they're used by frameworks. Sorry. So here's a rule of thumb: if you don't
*know* whether you're calling code that uses the
:func:`pyramid.threadlocal.get_current_registry` or
:func:`pyramid.threadlocal.get_current_request` functions, or you don't care
-about any of this, but you still want to write test code, just always create
-an autocommitting Configurator instance and call its ``begin`` method within
-the ``setUp`` of a unit test, then subsequently call its ``end`` method in
-the test's ``tearDown``. This won't really hurt anything if the application
-you're testing does not call any ``get_current*`` function.
+about any of this, but you still want to write test code, just always call
+:func:`pyramid.testing.setUp` in your test's ``setUp`` method and
+:func:`pyramid.testing.tearDown` in your tests' ``tearDown`` method. This
+won't really hurt anything if the application you're testing does not call
+any ``get_current*`` function.
.. index::
single: pyramid.testing
single: Configurator testing API
Using the ``Configurator`` and ``pyramid.testing`` APIs in Unit Tests
-------------------------------------------------------------------------
+---------------------------------------------------------------------
The ``Configurator`` API and the ``pyramid.testing`` module provide a number
of functions which can be used during unit testing. These functions make
@@ -187,29 +190,29 @@ function.
.. code-block:: python
:linenos:
+ from pyramid.security import has_permission
+ from pyramid.exceptions import Forbidden
+
def view_fn(request):
- from pyramid.chameleon_zpt import render_template_to_response
- if 'say' in request.params:
- return render_template_to_response('templates/submitted.pt',
- say=request.params['say'])
- return render_template_to_response('templates/show.pt', say='Hello')
-
-Without invoking any startup code or using the testing API, an attempt to run
-this view function in a unit test will result in an error. When a
-:app:`Pyramid` application starts normally, it will populate a
-:term:`application registry` using :term:`configuration declaration` calls
-made against a :term:`Configurator` (sometimes deferring to the application's
-``configure.zcml`` :term:`ZCML` file via ``load_zcml``). But if this
-application registry is not created and populated (e.g. with an
-:meth:`pyramid.config.Configurator.add_view` :term:`configuration
-declaration` or ``view`` declarations in :term:`ZCML`), like when you invoke
-application code via a unit test, :app:`Pyramid` API functions will tend to
-fail.
+ if not has_permission('edit', request.context, request):
+ raise Forbidden
+ return {'greeting':'hello'}
+
+Without doing anything special during a unit test, the call to
+:func:`pyramid.security.has_permission` in this view function will always
+return a ``True`` value. When a :app:`Pyramid` application starts normally,
+it will populate a :term:`application registry` using :term:`configuration
+declaration` calls made against a :term:`Configurator`. But if this
+application registry is not created and populated (e.g. by initializing the
+configurator with an authorization policy), like when you invoke application
+code via a unit test, :app:`Pyramid` API functions will tend to either fail
+or return default results. So how do you test the branch of the code in this
+view function that raises :exc:`Forbidden`?
The testing API provided by :app:`Pyramid` allows you to simulate various
application registry registrations for use under a unit testing framework
without needing to invoke the actual application configuration implied by its
-``run.py``. For example, if you wanted to test the above ``view_fn``
+``main`` function. For example, if you wanted to test the above ``view_fn``
(assuming it lived in the package named ``my.package``), you could write a
:class:`unittest.TestCase` that used the testing API.
@@ -217,72 +220,68 @@ without needing to invoke the actual application configuration implied by its
:linenos:
import unittest
- from pyramid.config import Configurator
from pyramid import testing
class MyTest(unittest.TestCase):
def setUp(self):
- self.config = Configurator(autocommit=True)
- self.config.begin()
+ self.config = testing.setUp()
def tearDown(self):
- self.config.end()
+ testing.tearDown()
- def test_view_fn_not_submitted(self):
+ def test_view_fn_forbidden(self):
+ from pyramid.exceptions import Forbidden
from my.package import view_fn
- renderer = self.config.testing_add_renderer('templates/show.pt')
+ self.config.testing_securitypolicy(userid='hank',
+ permissive=False)
request = testing.DummyRequest()
- response = view_fn(request)
- renderer.assert_(say='Hello')
+ request.context = testing.DummyResource()
+ self.assertRaises(Forbidden, view_fn, request)
- def test_view_fn_submitted(self):
+ def test_view_fn_allowed(self):
+ from pyramid.exceptions import Forbidden
from my.package import view_fn
- renderer = self.config.testing_add_renderer(
- 'templates/submitted.pt')
+ self.config.testing_securitypolicy(userid='hank',
+ permissive=True)
request = testing.DummyRequest()
- request.params['say'] = 'Yo'
+ request.context = testing.DummyResource()
response = view_fn(request)
- renderer.assert_(say='Yo')
-
+ self.assertEqual(response, {'greeting':'hello'})
+
In the above example, we create a ``MyTest`` test case that inherits from
:mod:`unittest.TestCase`. If it's in our :app:`Pyramid` application, it will
be found when ``setup.py test`` is run. It has two test methods.
-The first test method, ``test_view_fn_not_submitted`` tests the ``view_fn``
-function in the case that no "form" values (represented by request.params)
-have been submitted. Its first line registers a "dummy template renderer"
-named ``templates/show.pt`` via the
-:meth:`pyramid.config.Configurator.testing_add_renderer` method; this method
-returns a :class:`pyramid.testing.DummyTemplateRenderer` instance which we
-hang on to for later.
+The first test method, ``test_view_fn_forbidden`` tests the ``view_fn`` when
+the authentication policy forbids the current user the ``edit`` permission.
+Its third line registers a "dummy" "non-permissive" authorization policy
+using the :meth:`pyramid.config.Configurator.testing_securitypolicy` method,
+which is a special helper method for unit testing.
We then create a :class:`pyramid.testing.DummyRequest` object which simulates
a WebOb request object API. A :class:`pyramid.testing.DummyRequest` is a
request object that requires less setup than a "real" :app:`Pyramid` request.
We call the function being tested with the manufactured request. When the
-function is called, :func:`pyramid.chameleon_zpt.render_template_to_response`
-will call the "dummy" template renderer object instead of the real template
-renderer object. When the dummy renderer is called, it will set attributes
-on itself corresponding to the non-path keyword arguments provided to the
-:func:`pyramid.chameleon_zpt.render_template_to_response` function. We check
-that the ``say`` parameter sent into the template rendering function was
-``Hello`` in this specific example. The ``assert_`` method of the renderer
-we've created will raise an :exc:`AssertionError` if the value passed to the
-renderer as ``say`` does not equal ``Hello`` (any number of keyword arguments
-are supported).
-
-The second test method, named ``test_view_fn_submitted`` tests the alternate
-case, where the ``say`` form value has already been set in the request and
-performs a similar template registration and assertion. We assert at the end
-of this that the renderer's ``say`` attribute is ``Yo``, as this is what is
-expected of the view function in the branch it's testing.
-
-Note that the test calls the :meth:`pyramid.config.Configurator.begin` method
-in its ``setUp`` method and the ``end`` method of the same in its
-``tearDown`` method. If you use any of the
-:class:`pyramid.config.Configurator` APIs during testing, be sure to use this
-pattern in your test case's ``setUp`` and ``tearDown``; these methods make
-sure you're using a "fresh" :term:`application registry` per test run.
+function is called, :func:`pyramid.security.has_permission` will call the
+"dummy" authentication policy we've registered through
+:meth:`pyramid.config.Configuration.testing_securitypolicy`, which denies
+access. We check that the view function raises a :exc:`Forbidden` error.
+
+The second test method, named ``test_view_fn_allowed`` tests the alternate
+case, where the authentication policy allows access. Notice that we pass
+different values to
+:meth:`pyramid.config.Configurator.testing_securitypolicy` to obtain this
+result. We assert at the end of this that the view function returns a value.
+
+Note that the test calls the :func:`pyramid.testing.setUp` function in its
+``setUp`` method and the :func:`pyramid.testing.tearDown` function in its
+``tearDown`` method. We assign the result of :func:`pyramid.testing.setUp`
+as ``config`` on the unittest class. This is a :term:`Configurator` object
+and all methods of the configurator can be called as necessary within
+tests. If you use any of the :class:`pyramid.config.Configurator` APIs during
+testing, be sure to use this pattern in your test case's ``setUp`` and
+``tearDown``; these methods make sure you're using a "fresh"
+:term:`application registry` per test run.
See the :ref:`testing_module` chapter for the entire :app:`Pyramid` -specific
testing API. This chapter describes APIs for registering a security policy,
@@ -309,12 +308,13 @@ implementations to give the code under test only enough context to run.
some code *and* its integration with the rest of the :app:`Pyramid`
framework.
-In :app:`Pyramid` applications that use :term:`ZCML`, you can create an
-integration test by *loading its ZCML* in the test's setup code. This causes
-the entire :app:`Pyramid` environment to be set up and torn down as if your
-application was running "for real". This is a heavy-hammer way of making
-sure that your tests have enough context to run properly, and it tests your
-code's integration with the rest of :app:`Pyramid`.
+In :app:`Pyramid` applications that are plugins to Pyramid, you can create an
+integration test by including it's ``includeme`` function via
+:meth:`pyramid.config.Configurator.include` in the test's setup code. This
+causes the entire :app:`Pyramid` environment to be set up and torn down as if
+your application was running "for real". This is a heavy-hammer way of
+making sure that your tests have enough context to run properly, and it tests
+your code's integration with the rest of :app:`Pyramid`.
Let's demonstrate this by showing an integration test for a view. The below
test assumes that your application's package name is ``myapp``, and that
@@ -327,23 +327,21 @@ after accessing some values that require a fully set up environment.
import unittest
- from pyramid.config import Configurator
from pyramid import testing
class ViewIntegrationTests(unittest.TestCase):
def setUp(self):
""" This sets up the application registry with the
- registrations your application declares in its configure.zcml
- (including dependent registrations for pyramid itself).
+ registrations your application declares in its ``includeme``
+ function.
"""
import myapp
- self.config = Configurator(package=myapp, autocommit=True)
- self.config.begin()
- self.config.load_zcml('myapp:configure.zcml')
+ self.config = testing.setUp()
+ self.config.include('myapp')
def tearDown(self):
""" Clear out the application registry """
- self.config.end()
+ testing.tearDown()
def test_my_view(self):
from myapp.views import my_view
diff --git a/docs/narr/threadlocals.rst b/docs/narr/threadlocals.rst
index 171eaa1c7..13bfe41cb 100644
--- a/docs/narr/threadlocals.rst
+++ b/docs/narr/threadlocals.rst
@@ -111,8 +111,8 @@ follows:
each as ``request``).
- ``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`.
+ 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/urldispatch.rst b/docs/narr/urldispatch.rst
index e64513a96..a9057003f 100644
--- a/docs/narr/urldispatch.rst
+++ b/docs/narr/urldispatch.rst
@@ -1287,6 +1287,3 @@ References
A tutorial showing how :term:`URL dispatch` can be used to create a
:app:`Pyramid` application exists in :ref:`bfg_sql_wiki_tutorial`.
-Route configuration may also be added to the system via :term:`ZCML` (see
-:ref:`zcml_route_configuration`).
-
diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst
index f8b3fdb24..3f2b1b179 100644
--- a/docs/narr/viewconfig.rst
+++ b/docs/narr/viewconfig.rst
@@ -63,14 +63,10 @@ View configuration is performed in one of these ways:
:meth:`pyramid.config.Configurator.add_route` method, passing a ``view``
argument specifying a view callable.
-- by using the :meth:`pyramid.config.Configurator.add_handler` against a
- :term:`view handler` class (useful only for :term:`URL dispatch`
- applications).
-
-.. note:: You can also add view configuration by adding a ``<view>``,
- ``<route>`` or ``<handler>`` declaration to :term:`ZCML` used by your
- application as per :ref:`mapping_views_using_zcml_section`,
- :ref:`view_directive`, :ref:`route_directive` or :ref:`handler_directive`.
+.. note:: A package named ``pyramid_handlers`` (available from PyPI) provides
+ an analogue of :term:`Pylons` -style "controllers", which are a special
+ kind of view class which provides more automation when your application
+ uses :term:`URL dispatch` solely.
.. _view_configuration_parameters:
@@ -442,9 +438,6 @@ you *must* do use the ``scan`` method of a
# pyramid.config.Configurator class
config.scan()
-.. note:: See :ref:`zcml_scanning` for information about how to invoke a scan
- via ZCML (if you're not using imperative configuration).
-
Please see :ref:`decorations_and_code_scanning` for detailed information
about what happens when code is scanned for configuration declarations
resulting from use of decorators like :class:`pyramid.view.view_config`.
@@ -599,248 +592,6 @@ which is the view itself or a :term:`dotted Python name` to such an object.
All other arguments are optional. See
:meth:`pyramid.config.Configurator.add_view` for more information.
-.. _using_add_handler:
-
-Handler Registration Using :meth:`~pyramid.config.Configurator.add_handler`
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-:app:`Pyramid` provides the special concept of a :term:`view handler`. View
-handlers are view classes that implement a number of methods, each of which
-is a :term:`view callable` as a convenience for :term:`URL dispatch` users.
-
-.. note::
-
- View handlers are *not* useful when using :term:`traversal`, only when using
- :term:`url dispatch`.
-
-Using a view handler instead of a plain function or class :term:`view
-callable` makes it unnecessary to call
-:meth:`pyramid.config.Configurator.add_route` (and/or
-:meth:`pyramid.config.Configurator.add_view`) "by hand" multiple times,
-making it more pleasant to register a collection of views as a single class
-when using :term:`url dispatch`. The view handler machinery also introduces
-the concept of an ``action``, which is used as a :term:`view predicate` to
-control which method of the handler is called. The method name is the
-default *action name* of a handler view callable.
-
-The concept of a view handler is analogous to a "controller" in Pylons 1.0.
-
-The view handler class is initialized by :app:`Pyramid` in the same manner as
-a "plain" view class. Its ``__init__`` is called with a request object (see
-:ref:`class_as_view`). It implements methods, each of which is a :term:`view
-callable`. When a request enters the system which corresponds with an
-*action* related to one of its view callable methods, this method is called,
-and it is expected to return a response.
-
-Here's an example view handler class:
-
-.. code-block:: python
- :linenos:
-
- from pyramid.response import Response
-
- from pyramid.view import action
-
- class Hello(object):
- def __init__(self, request):
- self.request = request
-
- def index(self):
- return Response('Hello world!')
-
- @action(renderer="mytemplate.mak")
- def bye(self):
- return {}
-
-The :class:`pyramid.view.action` decorator is used to fine-tune the view
-parameters for each potential view callable which is a method of the handler.
-
-Handlers are added to application configuration via the
-:meth:`pyramid.config.Configurator.add_handler` API. The
-:meth:`~pyramid.config.Configurator.add_handler` method will scan a
-:term:`view handler` class and automatically set up view configurations for
-its methods that represent "auto-exposed" view callable, or those that were
-decorated explicitly with the :class:`~pyramid.view.action` decorator. This
-decorator is used to setup additional view configuration information for
-individual methods of the class, and can be used repeatedly for a single view
-method to register multiple view configurations for it.
-
-.. code-block:: python
- :linenos:
-
- from myapp.handlers import Hello
- config.add_handler('hello', '/hello/{action}', handler=Hello)
-
-This example will result in a route being added for the pattern
-``/hello/{action}``, and each method of the ``Hello`` class will then be
-examined to see if it should be registered as a potential view callable when
-the ``/hello/{action}`` pattern matches. The value of ``{action}`` in the
-route pattern will be used to determine which view should be called, and each
-view in the class will be setup with a view predicate that requires a
-specific ``action`` name. By default, the action name for a method of a
-handler is the method name.
-
-If the URL was ``/hello/index``, the above example pattern would match, and,
-by default, the ``index`` method of the ``Hello`` class would be called.
-
-Alternatively, the action can be declared specifically for a URL to be
-registered for a *specific* ``action`` name:
-
-.. code-block:: python
- :linenos:
-
- from myapp.handlers import Hello
- config.add_handler('hello_index', '/hello/index',
- handler=Hello, action='index')
-
-This will result one of the methods that are configured for the ``action`` of
-'index' in the ``Hello`` handler class to be called. In this case the name of
-the method is the same as the action name: ``index``. However, this need not
-be the case, as we will see below.
-
-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:`asset specification` or a Python
-reference to the handler class. Additional keyword arguments are passed
-directly through to :meth:`pyramid.config.Configurator.add_route`.
-
-For example:
-
-.. code-block:: python
- :linenos:
-
- config.add_handler('hello', '/hello/{action}',
- handler='mypackage.handlers.MyHandler')
-
-Multiple :meth:`~pyramid.config.Configurator.add_handler` calls can specify
-the same handler, to register specific route names for different
-handler/action combinations. For example:
-
-.. code-block:: python
- :linenos:
-
- config.add_handler('hello_index', '/hello/index',
- handler=Hello, action='index')
- config.add_handler('bye_index', '/hello/bye',
- handler=Hello, action='bye')
-
-.. note::
-
- Handler configuration may also be added to the system via :term:`ZCML` (see
- :ref:`zcml_handler_configuration`).
-
-View Setup in the Handler Class
-+++++++++++++++++++++++++++++++
-
-A handler class can have a single class level attribute called
-``__autoexpose__`` which should be a regular expression or the value
-``None``. It's used to determine which method names will result in additional
-view configurations being registered.
-
-When :meth:`~pyramid.config.Configurator.add_handler` runs, every method in
-the handler class will be searched and a view registered if the method name
-matches the ``__autoexpose__`` regular expression, or if the method was
-decorated with :class:`~pyramid.view.action`.
-
-Every method in the handler class that has a name meeting the
-``__autoexpose__`` regular expression will have a view registered for an
-``action`` name corresponding to the method name. This functionality can be
-disabled by setting the ``__autoexpose__`` attribute to ``None``:
-
-.. code-block:: python
- :linenos:
-
- from pyramid.view import action
-
- class Hello(object):
- __autoexpose__ = None
-
- def __init__(self, request):
- self.request = request
-
- @action()
- def index(self):
- return Response('Hello world!')
-
- @action(renderer="mytemplate.mak")
- def bye(self):
- return {}
-
-With auto-expose effectively disabled, no views will be registered for a
-method unless it is specifically decorated with
-:class:`~pyramid.view.action`.
-
-Action Decorators in a Handler
-++++++++++++++++++++++++++++++
-
-The :class:`~pyramid.view.action` decorator registers view configuration
-information on the handler method, which is used by
-:meth:`~pyramid.config.Configurator.add_handler` to setup the view
-configuration.
-
-All keyword arguments are recorded, and passed to
-:meth:`~pyramid.config.Configurator.add_view`. Any valid keyword arguments
-for :meth:`~pyramid.config.Configurator.add_view` can thus be used with the
-:class:`~pyramid.view.action` decorator to further restrict when the view
-will be called.
-
-One important difference is that a handler method can respond to an
-``action`` name that is different from the method name by passing in a
-``name`` argument.
-
-Example:
-
-.. code-block:: python
- :linenos:
-
- from pyramid.view import action
-
- class Hello(object):
- def __init__(self, request):
- self.request = request
-
- @action(name='index', renderer='created.mak', request_method='POST')
- def create(self):
- return {}
-
- @action(renderer="view_all.mak", request_method='GET')
- def index(self):
- return {}
-
-This will register two views that require the ``action`` to be ``index``,
-with the additional view predicate requiring a specific request method.
-
-It can be useful to decorate a single method multiple times with
-:class:`~pyramid.view.action`. Each action decorator will register a new view
-for the method. By specifying different names and renderers for each action,
-the same view logic can be exposed and rendered differently on multiple URLs.
-
-Example:
-
-.. code-block:: python
- :linenos:
-
- from pyramid.view import action
-
- class Hello(object):
- def __init__(self, request):
- self.request = request
-
- @action(name='home', renderer='home.mak')
- @action(name='about', renderer='about.mak')
- def show_template(self):
- # prep some template vars
- return {}
-
- # in the config
- config.add_handler('hello', '/hello/{action}', handler=Hello)
-
-With this configuration, the url ``/hello/home`` will find a view
-configuration that results in calling the ``show_template`` method, then
-rendering the template with ``home.mak``, and the url ``/hello/about`` will
-call the same method and render the ``about.mak`` template.
-
.. index::
single: resource interfaces
diff --git a/docs/narr/views.rst b/docs/narr/views.rst
index e8cf2f83c..e1eacfeae 100644
--- a/docs/narr/views.rst
+++ b/docs/narr/views.rst
@@ -130,8 +130,10 @@ method expected to return a response, you can either:
values, each pointing at a different method of the class if you'd like the
class to represent a collection of related view callables.
-- treat the class as a :term:`view handler` by using it as the ``handler=``
- argument of a call to :meth:`pyramid.config.Configurator.add_handler`.
+.. note:: A package named :term:`pyramid_handlers` (available from PyPI)
+ provides an analogue of :term:`Pylons` -style "controllers", which are a
+ special kind of view class which provides more automation when your
+ application uses :term:`URL dispatch` solely.
.. index::
single: view calling convention
diff --git a/docs/narr/zca.rst b/docs/narr/zca.rst
index f330fd551..78a7b0b75 100644
--- a/docs/narr/zca.rst
+++ b/docs/narr/zca.rst
@@ -57,7 +57,7 @@ Using the ZCA Global API in a :app:`Pyramid` Application
-----------------------------------------------------------
:term:`Zope` uses a single ZCA registry -- the "global" ZCA registry
--- for all Zope applications run in the same Python process,
+-- for all Zope applications that run in the same Python process,
effectively making it impossible to run more than one Zope application
in a single process.
@@ -158,9 +158,7 @@ Consider the following bit of idiomatic :app:`Pyramid` startup code:
def app(global_settings, **settings):
config = Configurator(settings=settings)
- config.begin()
- config.load_zcml('configure.zcml')
- config.end()
+ config.include('some.other.package')
return config.make_wsgi_app()
When the ``app`` function above is run, a :term:`Configurator` is
@@ -198,9 +196,7 @@ setup code. For example:
def app(global_settings, **settings):
config = Configurator(settings=settings)
config.hook_zca()
- config.begin()
- config.load_zcml('configure.zcml')
- config.end()
+ config.include('some.other.application')
return config.make_wsgi_app()
We've added a line to our original startup code, line number 6, which
@@ -250,9 +246,7 @@ registry at startup time instead of constructing a new one:
config = Configurator(registry=globalreg)
config.setup_registry(settings=settings)
config.hook_zca()
- config.begin()
- config.load_zcml('configure.zcml')
- config.end()
+ config.include('some.other.application')
return config.make_wsgi_app()
Lines 5, 6, and 7 above are the interesting ones. Line 5 retrieves
@@ -268,36 +262,3 @@ rather than creating a new application-specific registry; since by
default the ZCA global API will use this registry, things will work as
you might expect a Zope app to when you use the global ZCA API.
-.. index::
- single: Zope ZCML directives
- single: getGlobalSiteManager
- single: getSiteManager
-
-Using Broken ZCML Directives
-----------------------------
-
-Some :term:`Zope` and third-party :term:`ZCML` directives use the
-``zope.component.getGlobalSiteManager`` API to get "the registry" when
-they should actually be calling ``zope.component.getSiteManager``.
-
-``zope.component.getSiteManager`` can be overridden by
-:app:`Pyramid` via
-:meth:`pyramid.config.Configurator.hook_zca`, while
-``zope.component.getGlobalSiteManager`` cannot. Directives that use
-``zope.component.getGlobalSiteManager`` are effectively broken; no
-ZCML directive should be using this function to find a registry to
-populate.
-
-You cannot use ZCML directives which use
-``zope.component.getGlobalSiteManager`` within a :app:`Pyramid`
-application without passing the ZCA global registry to the
-:term:`Configurator` constructor at application startup, as per
-:ref:`using_the_zca_global_registry`.
-
-One alternative exists: fix the ZCML directive to use
-``getSiteManager`` rather than ``getGlobalSiteManager``. If a
-directive disuses ``getGlobalSiteManager``, the ``hook_zca`` method of
-using a component registry as documented in :ref:`hook_zca` will begin
-to work, allowing you to make use of the ZCML directive without
-also using the ZCA global registry.
-
diff --git a/docs/tutorials/bfg/index.rst b/docs/tutorials/bfg/index.rst
index 3c0b3bf01..9f9a5238c 100644
--- a/docs/tutorials/bfg/index.rst
+++ b/docs/tutorials/bfg/index.rst
@@ -176,6 +176,10 @@ Here's how to convert a :mod:`repoze.bfg` application to a
<bfg:failingtag attr="foo"/>
</configure>
+ You will also need to add the ``pyramid_zcml`` package to your
+ ``setup.py`` ``install_requires`` list. In Pyramid, ZCML configuration
+ became an optional add-on supported by the ``pyramid_zcml`` package.
+
#. Retest your application using :app:`Pyramid`. This might be as
easy as:
diff --git a/docs/tutorials/modwsgi/index.rst b/docs/tutorials/modwsgi/index.rst
index 766f05b56..4257f40b3 100644
--- a/docs/tutorials/modwsgi/index.rst
+++ b/docs/tutorials/modwsgi/index.rst
@@ -14,12 +14,12 @@ This particular tutorial was developed under Apple's Mac OS X platform
largely the same for all systems, delta specific path information for
commands and files.
-.. note:: Unfortunately these instructions almost certainly won't work
- for deploying a :app:`Pyramid` application on a Windows system
- using ``mod_wsgi``. If you have experience with :app:`Pyramid`
- and ``mod_wsgi`` on Windows systems, please help us document
- this experience by submitting documentation to the `mailing list
- <http://lists.repoze.org/listinfo/repoze-dev>`_.
+.. note:: Unfortunately these instructions almost certainly won't work for
+ deploying a :app:`Pyramid` application on a Windows system using
+ ``mod_wsgi``. If you have experience with :app:`Pyramid` and ``mod_wsgi``
+ on Windows systems, please help us document this experience by submitting
+ documentation to the `Pylons-devel maillist
+ <http://groups.google.com/group/pylons-devel>`_.
#. The tutorial assumes you have Apache already installed on your
system. If you do not, install Apache 2.X for your platform in
diff --git a/docs/tutorials/wiki/authorization.rst b/docs/tutorials/wiki/authorization.rst
index ee86eb543..5e45c070e 100644
--- a/docs/tutorials/wiki/authorization.rst
+++ b/docs/tutorials/wiki/authorization.rst
@@ -137,6 +137,7 @@ referred to within the login view we just added to ``login.py``.
.. literalinclude:: src/authorization/tutorial/templates/login.pt
:language: xml
+ :tab-width: 2
Change ``view.pt`` and ``edit.pt``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -281,12 +282,14 @@ Our ``edit.pt`` template will look something like this when we're done:
.. literalinclude:: src/authorization/tutorial/templates/edit.pt
:linenos:
:language: xml
+ :tab-width: 2
Our ``view.pt`` template will look something like this when we're done:
.. literalinclude:: src/authorization/tutorial/templates/view.pt
:linenos:
:language: xml
+ :tab-width: 2
Revisiting the Application
---------------------------
diff --git a/docs/tutorials/wiki/basiclayout.rst b/docs/tutorials/wiki/basiclayout.rst
index 4017d7af8..884f17840 100644
--- a/docs/tutorials/wiki/basiclayout.rst
+++ b/docs/tutorials/wiki/basiclayout.rst
@@ -187,9 +187,11 @@ The ``egg:repoze.zodbconn#closer`` middleware is in the middle of the
pipeline. This is a piece of middleware which closes the ZODB connection
opened by the ``PersistentApplicationFinder`` at the end of the request.
-The ``egg:repoze.tm#tm`` middleware is the last piece of middleware in the
-pipeline. This commits a transaction near the end of the request unless
-there's an exception raised.
+The ``tm`` middleware is the last piece of middleware in the pipeline. This
+commits a transaction near the end of the request unless there's an exception
+raised or the HTTP response code is an error code. The ``tm`` refers to the
+``[filter:tm]`` section beneath the pipeline declaration, which configures
+the transaction manager.
The final line in the ``[pipeline:main]`` section is ``tutorial``, which
refers to the ``[app:tutorial]`` section above it. The ``[app:tutorial]``
diff --git a/docs/tutorials/wiki/definingviews.rst b/docs/tutorials/wiki/definingviews.rst
index 90768f320..7ad5e57cb 100644
--- a/docs/tutorials/wiki/definingviews.rst
+++ b/docs/tutorials/wiki/definingviews.rst
@@ -231,6 +231,7 @@ the below:
.. literalinclude:: src/views/tutorial/templates/view.pt
:language: xml
+ :tab-width: 2
.. note:: The names available for our use in a template are always those that
are present in the dictionary returned by the view callable. But our
@@ -257,6 +258,7 @@ below:
.. literalinclude:: src/views/tutorial/templates/edit.pt
:language: xml
+ :tab-width: 2
Static Assets
-------------
diff --git a/docs/tutorials/wiki/src/authorization/development.ini b/docs/tutorials/wiki/src/authorization/development.ini
index 6f4c33d93..054720aa2 100644
--- a/docs/tutorials/wiki/src/authorization/development.ini
+++ b/docs/tutorials/wiki/src/authorization/development.ini
@@ -12,9 +12,13 @@ zodb_uri = file://%(here)s/Data.fs?connection_cache_size=20000
pipeline =
egg:WebError#evalerror
egg:repoze.zodbconn#closer
- egg:repoze.tm#tm
+ tm
tutorial
+[filter:tm]
+use = egg:repoze.tm2#tm
+commit_veto = repoze.tm:default_commit_veto
+
[server:main]
use = egg:Paste#http
host = 0.0.0.0
diff --git a/docs/tutorials/wiki/src/authorization/setup.py b/docs/tutorials/wiki/src/authorization/setup.py
index c1b8e9f33..38f913961 100644
--- a/docs/tutorials/wiki/src/authorization/setup.py
+++ b/docs/tutorials/wiki/src/authorization/setup.py
@@ -9,7 +9,7 @@ CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
requires = [
'pyramid',
'repoze.zodbconn',
- 'repoze.tm',
+ 'repoze.tm2>=1.0b1', # default_commit_veto
'ZODB3',
'WebError',
'docutils',
diff --git a/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt b/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt
index 0e5858d3b..b5fa54dec 100644
--- a/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt
+++ b/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt
@@ -1,16 +1,22 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
+ xmlns:tal="http://xml.zope.org/namespaces/tal">
<head>
- <title>${page.__name__} - Pyramid tutorial wiki (based on TurboGears 20-Minute Wiki)</title>
+ <title>${page.__name__} - Pyramid tutorial wiki (based on
+ TurboGears 20-Minute Wiki)</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<meta name="keywords" content="python web application" />
<meta name="description" content="pyramid web application" />
- <link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" />
- <link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
+ <link rel="shortcut icon"
+ href="${request.static_url('tutorial:static/favicon.ico')}" />
+ <link rel="stylesheet"
+ href="${request.static_url('tutorial:static/pylons.css')}"
+ type="text/css" media="screen" charset="utf-8" />
<!--[if lte IE 6]>
- <link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" />
+ <link rel="stylesheet"
+ href="${request.static_url('tutorial:static/ie6.css')}"
+ type="text/css" media="screen" charset="utf-8" />
<![endif]-->
</head>
<body>
@@ -18,19 +24,22 @@
<div id="top-small">
<div class="top-small align-center">
<div>
- <img src="${request.static_url('tutorial:static/pyramid-small.png')}" width="220" height="50" alt="pyramid" />
+ <img width="220" height="50" alt="pyramid"
+ src="${request.static_url('tutorial:static/pyramid-small.png')}" />
</div>
</div>
</div>
<div id="middle">
<div class="middle align-right">
<div id="left" class="app-welcome align-left">
- Editing <b><span tal:replace="page.__name__">Page Name Goes Here</span></b><br/>
- You can return to the <a href="${request.application_url}">FrontPage</a>.<br/>
+ Editing <b><span tal:replace="page.__name__">Page Name
+ Goes Here</span></b><br/>
+ You can return to the
+ <a href="${request.application_url}">FrontPage</a>.<br/>
</div>
<div id="right" class="app-welcome align-right">
<span tal:condition="logged_in">
- <a href="${request.application_url}/logout">Logout</a>
+ <a href="${request.application_url}/logout">Logout</a>
</span>
</div>
</div>
@@ -38,9 +47,10 @@
<div id="bottom">
<div class="bottom">
<form action="${save_url}" method="post">
- <textarea name="body" tal:content="page.data" rows="10" cols="60"/><br/>
- <input type="submit" name="form.submitted" value="Save"/>
- </form>
+ <textarea name="body" tal:content="page.data" rows="10"
+ cols="60"/><br/>
+ <input type="submit" name="form.submitted" value="Save"/>
+ </form>
</div>
</div>
</div>
@@ -48,4 +58,4 @@
<div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div>
</div>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/docs/tutorials/wiki/src/authorization/tutorial/templates/login.pt b/docs/tutorials/wiki/src/authorization/tutorial/templates/login.pt
index 974e22f37..554b4ea87 100644
--- a/docs/tutorials/wiki/src/authorization/tutorial/templates/login.pt
+++ b/docs/tutorials/wiki/src/authorization/tutorial/templates/login.pt
@@ -1,16 +1,22 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
+ xmlns:tal="http://xml.zope.org/namespaces/tal">
<head>
- <title>Login - Pyramid tutorial wiki (based on TurboGears 20-Minute Wiki)</title>
+ <title>Login - Pyramid tutorial wiki (based on TurboGears
+ 20-Minute Wiki)</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<meta name="keywords" content="python web application" />
<meta name="description" content="pyramid web application" />
- <link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" />
- <link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
+ <link rel="shortcut icon"
+ href="${request.static_url('tutorial:static/favicon.ico')}" />
+ <link rel="stylesheet"
+ href="${request.static_url('tutorial:static/pylons.css')}"
+ type="text/css" media="screen" charset="utf-8" />
<!--[if lte IE 6]>
- <link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" />
+ <link rel="stylesheet"
+ href="${request.static_url('tutorial:static/ie6.css')}"
+ type="text/css" media="screen" charset="utf-8" />
<![endif]-->
</head>
<body>
@@ -18,7 +24,8 @@
<div id="top-small">
<div class="top-small align-center">
<div>
- <img src="${request.static_url('tutorial:static/pyramid-small.png')}" width="220" height="50" alt="pyramid" />
+ <img width="220" height="50" alt="pyramid"
+ src="${request.static_url('tutorial:static/pyramid-small.png')}" />
</div>
</div>
</div>
@@ -34,11 +41,12 @@
<div id="bottom">
<div class="bottom">
<form action="${url}" method="post">
- <input type="hidden" name="came_from" value="${came_from}"/>
- <input type="text" name="login" value="${login}"/><br/>
- <input type="password" name="password" value="${password}"/><br/>
- <input type="submit" name="form.submitted" value="Log In"/>
- </form>
+ <input type="hidden" name="came_from" value="${came_from}"/>
+ <input type="text" name="login" value="${login}"/><br/>
+ <input type="password" name="password"
+ value="${password}"/><br/>
+ <input type="submit" name="form.submitted" value="Log In"/>
+ </form>
</div>
</div>
</div>
@@ -46,4 +54,4 @@
<div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div>
</div>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/docs/tutorials/wiki/src/authorization/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/authorization/tutorial/templates/mytemplate.pt
index cac9ccaa7..e31a342b2 100644
--- a/docs/tutorials/wiki/src/authorization/tutorial/templates/mytemplate.pt
+++ b/docs/tutorials/wiki/src/authorization/tutorial/templates/mytemplate.pt
@@ -7,8 +7,7 @@
<meta name="description" content="pyramid web application" />
<link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" />
<link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
+ <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton|Nobile:regular,i,b,bi&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
<!--[if lte IE 6]>
<link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" />
<![endif]-->
@@ -32,7 +31,7 @@
<div class="bottom">
<div id="left" class="align-right">
<h2>Search documentation</h2>
- <form method="get" action="http://docs.pylonshq.com/pyramid/dev/search.html">
+ <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/dev/search.html">
<input type="text" id="q" name="q" value="" />
<input type="submit" id="x" value="Go" />
</form>
@@ -41,25 +40,25 @@
<h2>Pyramid links</h2>
<ul class="links">
<li>
- <a href="http://pylonshq.com">Pylons Website</a>
+ <a href="http://pylonsproject.org">Pylons Website</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#narrative-documentation">Narrative Documentation</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#api-documentation">API Documentation</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#tutorials">Tutorials</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#change-history">Change History</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#sample-applications">Sample Applications</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#support-and-development">Support and Development</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a>
</li>
<li>
<a href="irc://irc.freenode.net#pyramid">IRC Channel</a>
diff --git a/docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt b/docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt
index 3fd709338..d77d174c1 100644
--- a/docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt
+++ b/docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt
@@ -1,16 +1,22 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
+ xmlns:tal="http://xml.zope.org/namespaces/tal">
<head>
- <title>${page.__name__} - Pyramid tutorial wiki (based on TurboGears 20-Minute Wiki)</title>
+ <title>${page.__name__} - Pyramid tutorial wiki (based on
+ TurboGears 20-Minute Wiki)</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<meta name="keywords" content="python web application" />
<meta name="description" content="pyramid web application" />
- <link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" />
- <link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
+ <link rel="shortcut icon"
+ href="${request.static_url('tutorial:static/favicon.ico')}" />
+ <link rel="stylesheet"
+ href="${request.static_url('tutorial:static/pylons.css')}"
+ type="text/css" media="screen" charset="utf-8" />
<!--[if lte IE 6]>
- <link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" />
+ <link rel="stylesheet"
+ href="${request.static_url('tutorial:static/ie6.css')}"
+ type="text/css" media="screen" charset="utf-8" />
<![endif]-->
</head>
<body>
@@ -18,19 +24,22 @@
<div id="top-small">
<div class="top-small align-center">
<div>
- <img src="${request.static_url('tutorial:static/pyramid-small.png')}" width="220" height="50" alt="pyramid" />
+ <img width="220" height="50" alt="pyramid"
+ src="${request.static_url('tutorial:static/pyramid-small.png')}" />
</div>
</div>
</div>
<div id="middle">
<div class="middle align-right">
<div id="left" class="app-welcome align-left">
- Viewing <b><span tal:replace="page.__name__">Page Name Goes Here</span></b><br/>
- You can return to the <a href="${request.application_url}">FrontPage</a>.<br/>
+ Viewing <b><span tal:replace="page.__name__">Page Name
+ Goes Here</span></b><br/>
+ You can return to the
+ <a href="${request.application_url}">FrontPage</a>.<br/>
</div>
<div id="right" class="app-welcome align-right">
<span tal:condition="logged_in">
- <a href="${request.application_url}/logout">Logout</a>
+ <a href="${request.application_url}/logout">Logout</a>
</span>
</div>
</div>
@@ -52,4 +61,4 @@
<div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div>
</div>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/docs/tutorials/wiki/src/authorization/tutorial/views.py b/docs/tutorials/wiki/src/authorization/tutorial/views.py
index 183cb2a8d..a83e17de4 100644
--- a/docs/tutorials/wiki/src/authorization/tutorial/views.py
+++ b/docs/tutorials/wiki/src/authorization/tutorial/views.py
@@ -13,7 +13,7 @@ wikiwords = re.compile(r"\b([A-Z]\w+[A-Z]+\w+)")
@view_config(context='tutorial.models.Wiki', permission='view')
def view_wiki(context, request):
- return HTTPFound(location = resource_url(context, request, 'FrontPage'))
+ return HTTPFound(location=resource_url(context, request, 'FrontPage'))
@view_config(context='tutorial.models.Page',
renderer='templates/view.pt', permission='view')
diff --git a/docs/tutorials/wiki/src/basiclayout/development.ini b/docs/tutorials/wiki/src/basiclayout/development.ini
index 6f4c33d93..054720aa2 100644
--- a/docs/tutorials/wiki/src/basiclayout/development.ini
+++ b/docs/tutorials/wiki/src/basiclayout/development.ini
@@ -12,9 +12,13 @@ zodb_uri = file://%(here)s/Data.fs?connection_cache_size=20000
pipeline =
egg:WebError#evalerror
egg:repoze.zodbconn#closer
- egg:repoze.tm#tm
+ tm
tutorial
+[filter:tm]
+use = egg:repoze.tm2#tm
+commit_veto = repoze.tm:default_commit_veto
+
[server:main]
use = egg:Paste#http
host = 0.0.0.0
diff --git a/docs/tutorials/wiki/src/basiclayout/setup.py b/docs/tutorials/wiki/src/basiclayout/setup.py
index 7fb15b782..cb3b92347 100644
--- a/docs/tutorials/wiki/src/basiclayout/setup.py
+++ b/docs/tutorials/wiki/src/basiclayout/setup.py
@@ -9,7 +9,7 @@ CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
requires = [
'pyramid',
'repoze.zodbconn',
- 'repoze.tm',
+ 'repoze.tm2>=1.0b1', # default_commit_veto
'ZODB3',
'WebError',
]
diff --git a/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt
index cac9ccaa7..2a2340683 100644
--- a/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt
+++ b/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt
@@ -7,8 +7,7 @@
<meta name="description" content="pyramid web application" />
<link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" />
<link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
+ <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton|Nobile:regular,i,b,bi&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
<!--[if lte IE 6]>
<link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" />
<![endif]-->
@@ -32,7 +31,7 @@
<div class="bottom">
<div id="left" class="align-right">
<h2>Search documentation</h2>
- <form method="get" action="http://docs.pylonshq.com/pyramid/dev/search.html">
+ <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/dev/search.html">
<input type="text" id="q" name="q" value="" />
<input type="submit" id="x" value="Go" />
</form>
@@ -41,25 +40,25 @@
<h2>Pyramid links</h2>
<ul class="links">
<li>
- <a href="http://pylonshq.com">Pylons Website</a>
+ <a href="http://pylonsproject.org/">Pylons Website</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#narrative-documentation">Narrative Documentation</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#api-documentation">API Documentation</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#tutorials">Tutorials</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#change-history">Change History</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#sample-applications">Sample Applications</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#support-and-development">Support and Development</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a>
</li>
<li>
<a href="irc://irc.freenode.net#pyramid">IRC Channel</a>
diff --git a/docs/tutorials/wiki/src/basiclayout/tutorial/tests.py b/docs/tutorials/wiki/src/basiclayout/tutorial/tests.py
index 0a3d507a0..1f3c3bb4d 100644
--- a/docs/tutorials/wiki/src/basiclayout/tutorial/tests.py
+++ b/docs/tutorials/wiki/src/basiclayout/tutorial/tests.py
@@ -1,15 +1,13 @@
import unittest
-from pyramid.config import Configurator
from pyramid import testing
class ViewTests(unittest.TestCase):
def setUp(self):
- self.config = Configurator(autocommit=True)
- self.config.begin()
+ self.config = testing.setUp()
def tearDown(self):
- self.config.end()
+ testing.tearDown()
def test_my_view(self):
from tutorial.views import my_view
diff --git a/docs/tutorials/wiki/src/basiclayout/tutorial/views.py b/docs/tutorials/wiki/src/basiclayout/tutorial/views.py
index 555f49e6d..157b9ac8f 100644
--- a/docs/tutorials/wiki/src/basiclayout/tutorial/views.py
+++ b/docs/tutorials/wiki/src/basiclayout/tutorial/views.py
@@ -1,6 +1,7 @@
from pyramid.view import view_config
from tutorial.models import MyModel
-@view_config(context=MyModel, renderer='tutorial:templates/mytemplate.pt')
+@view_config(context=MyModel,
+ renderer='tutorial:templates/mytemplate.pt')
def my_view(request):
return {'project':'tutorial'}
diff --git a/docs/tutorials/wiki/src/models/development.ini b/docs/tutorials/wiki/src/models/development.ini
index 6f4c33d93..054720aa2 100644
--- a/docs/tutorials/wiki/src/models/development.ini
+++ b/docs/tutorials/wiki/src/models/development.ini
@@ -12,9 +12,13 @@ zodb_uri = file://%(here)s/Data.fs?connection_cache_size=20000
pipeline =
egg:WebError#evalerror
egg:repoze.zodbconn#closer
- egg:repoze.tm#tm
+ tm
tutorial
+[filter:tm]
+use = egg:repoze.tm2#tm
+commit_veto = repoze.tm:default_commit_veto
+
[server:main]
use = egg:Paste#http
host = 0.0.0.0
diff --git a/docs/tutorials/wiki/src/models/setup.py b/docs/tutorials/wiki/src/models/setup.py
index 5034a3989..3cd43d5d8 100644
--- a/docs/tutorials/wiki/src/models/setup.py
+++ b/docs/tutorials/wiki/src/models/setup.py
@@ -9,10 +9,9 @@ CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
requires = [
'pyramid',
'repoze.zodbconn',
- 'repoze.tm',
+ 'repoze.tm2>=1.0b1', # default_commit_veto
'ZODB3',
'WebError',
- 'docutils',
]
setup(name='tutorial',
diff --git a/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt
index cac9ccaa7..e31a342b2 100644
--- a/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt
+++ b/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt
@@ -7,8 +7,7 @@
<meta name="description" content="pyramid web application" />
<link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" />
<link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
+ <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton|Nobile:regular,i,b,bi&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
<!--[if lte IE 6]>
<link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" />
<![endif]-->
@@ -32,7 +31,7 @@
<div class="bottom">
<div id="left" class="align-right">
<h2>Search documentation</h2>
- <form method="get" action="http://docs.pylonshq.com/pyramid/dev/search.html">
+ <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/dev/search.html">
<input type="text" id="q" name="q" value="" />
<input type="submit" id="x" value="Go" />
</form>
@@ -41,25 +40,25 @@
<h2>Pyramid links</h2>
<ul class="links">
<li>
- <a href="http://pylonshq.com">Pylons Website</a>
+ <a href="http://pylonsproject.org">Pylons Website</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#narrative-documentation">Narrative Documentation</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#api-documentation">API Documentation</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#tutorials">Tutorials</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#change-history">Change History</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#sample-applications">Sample Applications</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#support-and-development">Support and Development</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a>
</li>
<li>
<a href="irc://irc.freenode.net#pyramid">IRC Channel</a>
diff --git a/docs/tutorials/wiki/src/models/tutorial/tests.py b/docs/tutorials/wiki/src/models/tutorial/tests.py
index 839964538..51c97a95d 100644
--- a/docs/tutorials/wiki/src/models/tutorial/tests.py
+++ b/docs/tutorials/wiki/src/models/tutorial/tests.py
@@ -1,6 +1,5 @@
import unittest
-from pyramid.config import Configurator
from pyramid import testing
class PageModelTests(unittest.TestCase):
@@ -50,11 +49,10 @@ class AppmakerTests(unittest.TestCase):
class ViewTests(unittest.TestCase):
def setUp(self):
- self.config = Configurator(autocommit=True)
- self.config.begin()
+ self.config = testing.setUp()
def tearDown(self):
- self.config.end()
+ testing.tearDown()
def test_my_view(self):
from tutorial.views import my_view
diff --git a/docs/tutorials/wiki/src/views/development.ini b/docs/tutorials/wiki/src/views/development.ini
index 6f4c33d93..054720aa2 100644
--- a/docs/tutorials/wiki/src/views/development.ini
+++ b/docs/tutorials/wiki/src/views/development.ini
@@ -12,9 +12,13 @@ zodb_uri = file://%(here)s/Data.fs?connection_cache_size=20000
pipeline =
egg:WebError#evalerror
egg:repoze.zodbconn#closer
- egg:repoze.tm#tm
+ tm
tutorial
+[filter:tm]
+use = egg:repoze.tm2#tm
+commit_veto = repoze.tm:default_commit_veto
+
[server:main]
use = egg:Paste#http
host = 0.0.0.0
diff --git a/docs/tutorials/wiki/src/views/setup.py b/docs/tutorials/wiki/src/views/setup.py
index 5034a3989..9538cbbff 100644
--- a/docs/tutorials/wiki/src/views/setup.py
+++ b/docs/tutorials/wiki/src/views/setup.py
@@ -9,7 +9,7 @@ CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
requires = [
'pyramid',
'repoze.zodbconn',
- 'repoze.tm',
+ 'repoze.tm2>=1.0b1', # default_commit_veto
'ZODB3',
'WebError',
'docutils',
diff --git a/docs/tutorials/wiki/src/views/tutorial/templates/edit.pt b/docs/tutorials/wiki/src/views/tutorial/templates/edit.pt
index 077a0dcb7..c6c589c1a 100644
--- a/docs/tutorials/wiki/src/views/tutorial/templates/edit.pt
+++ b/docs/tutorials/wiki/src/views/tutorial/templates/edit.pt
@@ -1,16 +1,22 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
+ xmlns:tal="http://xml.zope.org/namespaces/tal">
<head>
- <title>${page.__name__} - Pyramid tutorial wiki (based on TurboGears 20-Minute Wiki)</title>
+ <title>${page.__name__} - Pyramid tutorial wiki (based on
+ TurboGears 20-Minute Wiki)</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<meta name="keywords" content="python web application" />
<meta name="description" content="pyramid web application" />
- <link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" />
- <link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
+ <link rel="shortcut icon"
+ href="${request.static_url('tutorial:static/favicon.ico')}" />
+ <link rel="stylesheet"
+ href="${request.static_url('tutorial:static/pylons.css')}"
+ type="text/css" media="screen" charset="utf-8" />
<!--[if lte IE 6]>
- <link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" />
+ <link rel="stylesheet"
+ href="${request.static_url('tutorial:static/ie6.css')}"
+ type="text/css" media="screen" charset="utf-8" />
<![endif]-->
</head>
<body>
@@ -18,15 +24,18 @@
<div id="top-small">
<div class="top-small align-center">
<div>
- <img src="${request.static_url('tutorial:static/pyramid-small.png')}" width="220" height="50" alt="pyramid" />
+ <img width="220" height="50" alt="pyramid"
+ src="${request.static_url('tutorial:static/pyramid-small.png')}" />
</div>
</div>
</div>
<div id="middle">
<div class="middle align-right">
<div id="left" class="app-welcome align-left">
- Editing <b><span tal:replace="page.__name__">Page Name Goes Here</span></b><br/>
- You can return to the <a href="${request.application_url}">FrontPage</a>.<br/>
+ Editing <b><span tal:replace="page.__name__">Page Name Goes
+ Here</span></b><br/>
+ You can return to the
+ <a href="${request.application_url}">FrontPage</a>.<br/>
</div>
<div id="right" class="app-welcome align-right"></div>
</div>
@@ -34,9 +43,10 @@
<div id="bottom">
<div class="bottom">
<form action="${save_url}" method="post">
- <textarea name="body" tal:content="page.data" rows="10" cols="60"/><br/>
- <input type="submit" name="form.submitted" value="Save"/>
- </form>
+ <textarea name="body" tal:content="page.data" rows="10"
+ cols="60"/><br/>
+ <input type="submit" name="form.submitted" value="Save"/>
+ </form>
</div>
</div>
</div>
@@ -44,4 +54,4 @@
<div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div>
</div>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/docs/tutorials/wiki/src/views/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/views/tutorial/templates/mytemplate.pt
index cac9ccaa7..e31a342b2 100644
--- a/docs/tutorials/wiki/src/views/tutorial/templates/mytemplate.pt
+++ b/docs/tutorials/wiki/src/views/tutorial/templates/mytemplate.pt
@@ -7,8 +7,7 @@
<meta name="description" content="pyramid web application" />
<link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" />
<link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
+ <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton|Nobile:regular,i,b,bi&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
<!--[if lte IE 6]>
<link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" />
<![endif]-->
@@ -32,7 +31,7 @@
<div class="bottom">
<div id="left" class="align-right">
<h2>Search documentation</h2>
- <form method="get" action="http://docs.pylonshq.com/pyramid/dev/search.html">
+ <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/dev/search.html">
<input type="text" id="q" name="q" value="" />
<input type="submit" id="x" value="Go" />
</form>
@@ -41,25 +40,25 @@
<h2>Pyramid links</h2>
<ul class="links">
<li>
- <a href="http://pylonshq.com">Pylons Website</a>
+ <a href="http://pylonsproject.org">Pylons Website</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#narrative-documentation">Narrative Documentation</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#api-documentation">API Documentation</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#tutorials">Tutorials</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#change-history">Change History</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#sample-applications">Sample Applications</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#support-and-development">Support and Development</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a>
</li>
<li>
<a href="irc://irc.freenode.net#pyramid">IRC Channel</a>
diff --git a/docs/tutorials/wiki/src/views/tutorial/templates/view.pt b/docs/tutorials/wiki/src/views/tutorial/templates/view.pt
index f676c1d25..97b87c44f 100644
--- a/docs/tutorials/wiki/src/views/tutorial/templates/view.pt
+++ b/docs/tutorials/wiki/src/views/tutorial/templates/view.pt
@@ -1,16 +1,22 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
+ xmlns:tal="http://xml.zope.org/namespaces/tal">
<head>
- <title>${page.__name__} - Pyramid tutorial wiki (based on TurboGears 20-Minute Wiki)</title>
+ <title>${page.__name__} - Pyramid tutorial wiki (based on
+ TurboGears 20-Minute Wiki)</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<meta name="keywords" content="python web application" />
<meta name="description" content="pyramid web application" />
- <link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" />
- <link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
+ <link rel="shortcut icon"
+ href="${request.static_url('tutorial:static/favicon.ico')}" />
+ <link rel="stylesheet"
+ href="${request.static_url('tutorial:static/pylons.css')}"
+ type="text/css" media="screen" charset="utf-8" />
<!--[if lte IE 6]>
- <link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" />
+ <link rel="stylesheet"
+ href="${request.static_url('tutorial:static/ie6.css')}"
+ type="text/css" media="screen" charset="utf-8" />
<![endif]-->
</head>
<body>
@@ -18,15 +24,18 @@
<div id="top-small">
<div class="top-small align-center">
<div>
- <img src="${request.static_url('tutorial:static/pyramid-small.png')}" width="220" height="50" alt="pyramid" />
+ <img width="220" height="50" alt="pyramid"
+ src="${request.static_url('tutorial:static/pyramid-small.png')}" />
</div>
</div>
</div>
<div id="middle">
<div class="middle align-right">
<div id="left" class="app-welcome align-left">
- Viewing <b><span tal:replace="page.__name__">Page Name Goes Here</span></b><br/>
- You can return to the <a href="${request.application_url}">FrontPage</a>.<br/>
+ Viewing <b><span tal:replace="page.__name__">Page Name Goes
+ Here</span></b><br/>
+ You can return to the
+ <a href="${request.application_url}">FrontPage</a>.<br/>
</div>
<div id="right" class="app-welcome align-right"></div>
</div>
@@ -48,4 +57,4 @@
<div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div>
</div>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/docs/tutorials/wiki/src/views/tutorial/views.py b/docs/tutorials/wiki/src/views/tutorial/views.py
index c96bc2e9c..42420f2fe 100644
--- a/docs/tutorials/wiki/src/views/tutorial/views.py
+++ b/docs/tutorials/wiki/src/views/tutorial/views.py
@@ -12,7 +12,7 @@ wikiwords = re.compile(r"\b([A-Z]\w+[A-Z]+\w+)")
@view_config(context='tutorial.models.Wiki')
def view_wiki(context, request):
- return HTTPFound(location = resource_url(context, request, 'FrontPage'))
+ return HTTPFound(location=resource_url(context, request, 'FrontPage'))
@view_config(context='tutorial.models.Page',
renderer='tutorial:templates/view.pt')
diff --git a/docs/tutorials/wiki2/authorization.rst b/docs/tutorials/wiki2/authorization.rst
index 5b07fe788..3f1d2669a 100644
--- a/docs/tutorials/wiki2/authorization.rst
+++ b/docs/tutorials/wiki2/authorization.rst
@@ -125,7 +125,7 @@ Adding ``security.py``
~~~~~~~~~~~~~~~~~~~~~~
Add a ``security.py`` module within your package (in the same directory as
-"__init__.py", "views.py", etc) with the following content:
+:file:`__init__.py`, :file:`views.py`, etc) with the following content:
.. literalinclude:: src/authorization/tutorial/security.py
:linenos:
@@ -203,6 +203,7 @@ referred to within the login view we just added to ``login.py``.
.. literalinclude:: src/authorization/tutorial/templates/login.pt
:language: xml
+ :tab-width: 2
Change ``view.pt`` and ``edit.pt``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -260,11 +261,13 @@ Our ``edit.pt`` template will look something like this when we're done:
.. literalinclude:: src/authorization/tutorial/templates/edit.pt
:language: xml
+ :tab-width: 2
Our ``view.pt`` template will look something like this when we're done:
.. literalinclude:: src/authorization/tutorial/templates/view.pt
:language: xml
+ :tab-width: 2
Revisiting the Application
---------------------------
@@ -275,5 +278,353 @@ of hitting an edit or add page and submitting the login form with the
hand corner. When we click it, we're logged out, and redirected back
to the front page.
+.. _wiki2_flow_of_authentication:
+
+Overall flow of an authentication
+---------------------------------
+
+Now that you have seen all the pieces of the authentication
+mechanism, here are some examples that show how they all work
+together.
+
+#. Failed login: The user requests ``/FrontPage/edit_page``. The
+ site presents the login form. The user enters ``editor`` as
+ the login, but enters an invalid password ``bad``.
+ The site redisplays the login form with the message "Failed
+ login". See :ref:`failed_login`.
+
+#. The user again requests ``/FrontPage/edit_page``. The site
+ presents the login form, and this time the user enters
+ login ``editor`` and password ``editor``. The site presents
+ the edit form with the content of ``/FrontPage``. The user
+ makes some changes and saves them. See :ref:`good_login`.
+
+#. The user again revisits ``/FrontPage/edit_page``. The site
+ goes immediately to the edit form without requesting
+ credentials. See :ref:`revisit`.
+
+#. The user clicks the ``Logout`` link. See :ref:`logging_out`.
+
+.. _failed_login:
+
+Failed login
+~~~~~~~~~~~~
+
+The process starts when the user enters URL
+``http://localhost:6543/FrontPage/edit_page``. Let's assume that
+this is the first request ever made to the application and the
+page database is empty except for the ``Page`` instance created
+for the front page by the ``initialize_sql`` function in
+:file:`models.py`.
+
+This process involves two complete request/response cycles.
+
+1. From the front page, the user clicks :guilabel:`Edit page`.
+ The request is to ``/FrontPage/edit_page``. The view callable
+ is ``login.login``. The response is the ``login.pt`` template
+ with blank fields.
+
+2. The user enters invalid credentials and clicks :guilabel:`Log
+ in`. A ``POST`` request is sent to ``/FrontPage/edit_page``.
+ The view callable is again ``login.login``. The response is
+ the ``login.pt`` template showing the message "Failed login",
+ with the entry fields displaying their former values.
+
+Cycle 1:
+
+#. During URL dispatch, the route ``'/{pagename}/edit_page'`` is
+ considered for matching. The associated view has a
+ ``view_permission='edit'`` permission attached, so the
+ dispatch logic has to verify that the user has that permission
+ or the route is not considered to match.
+
+ The context for all route matching comes from the configured
+ root factory, :meth:`RootFactory` in :file:`models.py`.
+ This class has an ``__acl__`` attribute that defines the
+ access control list for all routes::
+ __acl__ = [ (Allow, Everyone, 'view'),
+ (Allow, 'group:editors', 'edit') ]
+
+ In practice, this means that for any route that requires the
+ ``edit`` permission, the user must be authenticated and
+ have the ``group:editors`` principal or the route is not
+ considered to match.
+#. To find the list of the user's principals, the authorization
+ first policy checks to see if the user has a
+ ``paste.auth.auth_tkt`` cookie. Since the user has never been
+ to the site, there is no such cookie, and the user is
+ considered to be unauthenticated.
+
+#. Since the user is unauthenticated, the ``groupfinder``
+ function in :file:`security.py` is called with ``None`` as its
+ ``userid`` argument. The function returns an empty list of
+ principals.
+
+#. Because that list does not contain the ``group:editors``
+ principal, the ``'/{pagename}/edit_page'`` route's ``edit``
+ permission fails, and the route does not match.
+
+#. Because no routes match, the `forbidden view` callable is
+ invoked: the ``login`` function in module ``login.py``.
+
+#. Inside the ``login`` function, the value of ``login_url`` is
+ ``http://localhost:6543/login``, and the value of
+ ``referrer`` is ``http://localhost:6543/FrontPage/edit_page``.
+
+ Because ``request.params`` has no key for ``'came_from'``, the
+ variable ``came_from`` is also set to
+ ``http://localhost:6543/FrontPage/edit_page``. Variables
+ ``message``, ``login``, and ``password`` are set to the empty
+ string.
+
+ Because ``request.params`` has no key for
+ ``'form.submitted'``, the ``login`` function returns this
+ dictionary::
+
+ {'message': '', 'url':'http://localhost:6543/login',
+ 'came_from':'http://localhost:6543/FrontPage/edit_page',
+ 'login':'', 'password':''}
+
+#. This dictionary is used to render the ``login.pt`` template.
+ In the form, the ``action`` attribute is
+ ``http://localhost:6543/login``, and the value of
+ ``came_from`` is included in that form as a hidden field
+ by this line in the template::
+
+ <input type="hidden" name="came_from" value="${came_from}"/>
+
+Cycle 2:
+
+#. The user enters incorrect credentials and clicks the
+ :guilabel:`Log in` button, which does a ``POST`` request to
+ URL ``http://localhost:6543/login``. The name of the
+ :guilabel:`Log in` button in this form is ``form.submitted``.
+
+#. The route with pattern ``'/login'`` matches this URL, so
+ control is passed again to the ``login`` view callable.
+
+#. The ``login_url`` and ``referrer`` have the same value
+ this time (``http://localhost:6543/login``), so variable
+ ``referrer`` is set to ``'/'``.
+
+ Since ``request.params`` does have a key ``'form.submitted'``,
+ the values of ``login`` and ``password`` are retrieved from
+ ``request.params``.
+
+ Because the login and password do not match any of the entries
+ in the ``USERS`` dictionary in ``security.py``, variable
+ ``message`` is set to ``'Failed login'``.
+
+ The view callable returns this dictionary::
+
+ {'message':'Failed login',
+ 'url':'http://localhost:6543/login', 'came_from':'/',
+ 'login':'editor', 'password':'bad'}
+
+#. The ``login.pt`` template is rendered using those values.
+
+.. _good_login:
+
+Successful login
+~~~~~~~~~~~~~~~~
+
+In this scenario, the user again requests URL
+``/FrontPage/edit_page``.
+
+This process involves four complete request/response cycles.
+
+1. The user clicks :guilabel:`Edit page`. The view callable is
+ ``login.login``. The response is template ``login.pt``,
+ with all the fields blank.
+
+2. The user enters valid credentials and clicks :guilabel:`Log in`.
+ The view callable is ``login.login``. The response is a
+ redirect to ``/FrontPage/edit_page``.
+
+3. The view callable is ``views.edit_page``. The response
+ renders template ``edit.pt``, displaying the current page
+ content.
+
+4. The user edits the content and clicks :guilabel:`Save`.
+ The view callable is ``views.edit_page``. The response
+ is a redirect to ``/FrontPage``.
+
+Execution proceeds as in :ref:`failed_login`, up to the point
+where the password ``editor`` is successfully matched against the
+value from the ``USERS`` dictionary.
+
+Cycle 2:
+
+#. Within the ``login.login`` view callable, the value of
+ ``login_url`` is ``http://localhost:6543/login``, and the
+ value of ``referrer`` is ``'/'``, and ``came_from`` is
+ ``http://localhost:6543/FrontPage/edit_page`` when this block
+ is executed:
+
+ .. code-block:: python
+
+ if USERS.get(login) == password:
+ headers = remember(request, login)
+ return HTTPFound(location=came_from, headers=headers)
+
+#. Because the password matches this time,
+ :mod:`pyramid.security.remember` returns a sequence of header
+ tuples that will set a ``paste.auth.auth_tkt`` authentication
+ cookie in the user's browser for the login ``'editor'``.
+
+#. The ``HTTPFound`` exception returns a response that redirects
+ the browser to ``http://localhost:6543/FrontPage/edit_page``,
+ including the headers that set the authentication cookie.
+
+Cycle 3:
+
+#. Route pattern ``'/{pagename}/edit_page'`` matches this URL,
+ but the corresponding view is restricted by an ``'edit'``
+ permission.
+
+#. Because the user now has an authentication cookie defining
+ their login name as ``'editor'``, the ``groupfinder`` function
+ is called with that value as its ``userid`` argument.
+
+#. The ``groupfinder`` function returns the list
+ ``['group:editors']``. This satisfies the access control
+ entry ``(Allow, 'group:editors', 'edit')``, which grants the
+ ``edit`` permission. Thus, this route matches, and control
+ passes to view callable ``edit_page``.
+
+#. Within ``edit_page``, ``name`` is set to ``'FrontPage'``, the
+ page name from ``request.matchdict['pagename']``, and
+ ``page`` is set to an instance of :class:`models.Page`
+ that holds the current content of ``FrontPage``.
+
+#. Since this request did not come from a form,
+ ``request.params`` does not have a key for
+ ``'form.submitted'``.
+
+#. The ``edit_page`` function calls
+ :meth:`pyramid.security.authenticated_userid` to find out
+ whether the user is authenticated. Because of the cookies
+ set previously, the variable ``logged_in`` is set to
+ the userid ``'editor'``.
+
+#. The ``edit_page`` function returns this dictionary::
+
+ {'page':page, 'logged_in':'editor',
+ 'save_url':'http://localhost:6543/FrontPage/edit_page'}
+
+#. Template :file:`edit.pt` is rendered with those values.
+ Among other features of this template, these lines
+ cause the inclusion of a :guilabel:`Logout` link::
+
+ <span tal:condition="logged_in">
+ <a href="${request.application_url}/logout">Logout</a>
+ </span>
+
+ For the example case, this link will refer to
+ ``http://localhost:6543/logout``.
+
+ These lines of the template display the current page's
+ content in a form whose ``action`` attribute is
+ ``http://localhost:6543/FrontPage/edit_page``::
+
+ <form action="${save_url}" method="post">
+ <textarea name="body" tal:content="page.data" rows="10" cols="60"/>
+ <input type="submit" name="form.submitted" value="Save"/>
+ </form>
+
+Cycle 4:
+
+#. The user edits the page content and clicks
+ :guilabel:`Save`.
+
+#. URL ``http://localhost:6543/FrontPage/edit_page`` goes through
+ the same routing as before, up until the line that checks
+ whether ``request.params`` has a key ``'form.submitted'``.
+ This time, within the ``edit_page`` view callable, these
+ lines are executed::
+
+ page.data = request.params['body']
+ session.add(page)
+ return HTTPFound(location = route_url('view_page', request,
+ pagename=name))
+
+ The first two lines replace the old page content with the
+ contents of the ``body`` text area from the form, and then
+ update the page stored in the database. The third line
+ causes a response that redirects the browser to
+ ``http://localhost:6543/FrontPage``.
+
+.. _revisit:
+
+Revisiting after authentication
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In this case, the user has an authentication cookie set in their
+browser that specifies their login as ``'editor'``. The
+requested URL is ``http://localhost:6543/FrontPage/edit_page``.
+
+This process requires two request/response cycles.
+
+1. The user clicks :guilabel:`Edit page`. The view callable is
+ ``views.edit_page``. The response is ``edit.pt``, showing
+ the current page content.
+
+2. The user edits the content and clicks :guilabel:`Save`.
+ The view callable is ``views.edit_page``. The response is
+ a redirect to ``/Frontpage``.
+
+Cycle 1:
+
+#. The route with pattern ``/{pagename}/edit_page`` matches the
+ URL, and because of the authentication cookie, ``groupfinder``
+ returns a list containing the ``group:editors`` principal,
+ which ``models.RootFactory.__acl__`` uses to grant the
+ ``edit`` permission, so this route matches and dispatches
+ to the view callable :meth:`views.edit_page`.
+
+#. In ``edit_page``, because the request did not come from a form
+ submission, ``request.params`` has no key for
+ ``'form.submitted'``.
+
+#. The variable ``logged_in`` is set to the login name
+ ``'editor'`` by calling ``authenticated_userid``, which
+ extracts it from the authentication cookie.
+
+#. The function returns this dictionary::
+
+ {'page':page,
+ 'save_url':'http://localhost:6543/FrontPage/edit_page',
+ 'logged_in':'editor'}
+
+#. Template :file:`edit.pt` is rendered with the values from
+ that dictionary. Because of the presence of the
+ ``'logged_in'`` entry, a :guilabel:`Logout` link appears.
+
+Cycle 2:
+
+#. The user edits the page content and clicks :guilabel:`Save`.
+
+#. The ``POST`` operation works as in :ref:`good_login`.
+
+.. _logging_out:
+
+Logging out
+~~~~~~~~~~~
+
+This process starts with a request URL
+``http://localhost:6543/logout``.
+
+#. The route with pattern ``'/logout'`` matches and dispatches
+ to the view callable ``logout`` in :file:`login.py`.
+
+#. The call to :meth:`pyramid.security.forget` returns a list of
+ header tuples that will, when returned with the response,
+ cause the browser to delete the user's authentication cookie.
+
+#. The view callable returns an ``HTTPFound`` exception that
+ redirects the browser to named route ``view_wiki``, which
+ will translate to URL ``http://localhost:6543``. It
+ also passes along the headers that delete the
+ authentication cookie.
diff --git a/docs/tutorials/wiki2/definingviews.rst b/docs/tutorials/wiki2/definingviews.rst
index d4417ed0b..acf539e1a 100644
--- a/docs/tutorials/wiki2/definingviews.rst
+++ b/docs/tutorials/wiki2/definingviews.rst
@@ -213,6 +213,7 @@ the below:
.. literalinclude:: src/views/tutorial/templates/view.pt
:language: xml
+ :tab-width: 2
.. note:: The names available for our use in a template are always
those that are present in the dictionary returned by the view
@@ -240,6 +241,8 @@ the below:
.. literalinclude:: src/views/tutorial/templates/edit.pt
:language: xml
+ :tab-width: 2
+
Static Assets
-------------
diff --git a/docs/tutorials/wiki2/src/authorization/development.ini b/docs/tutorials/wiki2/src/authorization/development.ini
index b0cfd12a7..3b615f635 100644
--- a/docs/tutorials/wiki2/src/authorization/development.ini
+++ b/docs/tutorials/wiki2/src/authorization/development.ini
@@ -11,9 +11,13 @@ sqlalchemy.url = sqlite:///%(here)s/tutorial.db
[pipeline:main]
pipeline =
egg:WebError#evalerror
- egg:repoze.tm2#tm
+ tm
tutorial
+[filter:tm]
+use = egg:repoze.tm2#tm
+commit_veto = repoze.tm:default_commit_veto
+
[server:main]
use = egg:Paste#http
host = 0.0.0.0
diff --git a/docs/tutorials/wiki2/src/authorization/setup.py b/docs/tutorials/wiki2/src/authorization/setup.py
index 3be3146b7..ae9869d50 100644
--- a/docs/tutorials/wiki2/src/authorization/setup.py
+++ b/docs/tutorials/wiki2/src/authorization/setup.py
@@ -11,10 +11,10 @@ requires = [
'pyramid',
'SQLAlchemy',
'transaction',
- 'repoze.tm2',
+ 'repoze.tm2>=1.0b1', # default_commit_veto
'zope.sqlalchemy',
'WebError',
- 'docutils'
+ 'docutils',
]
if sys.version_info[:3] < (2,5,0):
diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/templates/edit.pt b/docs/tutorials/wiki2/src/authorization/tutorial/templates/edit.pt
index e8c59eb10..cea9b4932 100644
--- a/docs/tutorials/wiki2/src/authorization/tutorial/templates/edit.pt
+++ b/docs/tutorials/wiki2/src/authorization/tutorial/templates/edit.pt
@@ -1,16 +1,22 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
+ xmlns:tal="http://xml.zope.org/namespaces/tal">
<head>
- <title>${page.name} - Pyramid tutorial wiki (based on TurboGears 20-Minute Wiki)</title>
+ <title>${page.name} - Pyramid tutorial wiki (based on
+ TurboGears 20-Minute Wiki)</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<meta name="keywords" content="python web application" />
<meta name="description" content="pyramid web application" />
- <link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" />
- <link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
+ <link rel="shortcut icon"
+ href="${request.static_url('tutorial:static/favicon.ico')}" />
+ <link rel="stylesheet"
+ href="${request.static_url('tutorial:static/pylons.css')}"
+ type="text/css" media="screen" charset="utf-8" />
<!--[if lte IE 6]>
- <link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" />
+ <link rel="stylesheet"
+ href="${request.static_url('tutorial:static/ie6.css')}"
+ type="text/css" media="screen" charset="utf-8" />
<![endif]-->
</head>
<body>
@@ -18,19 +24,22 @@
<div id="top-small">
<div class="top-small align-center">
<div>
- <img src="${request.static_url('tutorial:static/pyramid-small.png')}" width="220" height="50" alt="pyramid" />
+ <img width="220" height="50" alt="pyramid"
+ src="${request.static_url('tutorial:static/pyramid-small.png')}" />
</div>
</div>
</div>
<div id="middle">
<div class="middle align-right">
<div id="left" class="app-welcome align-left">
- Editing <b><span tal:replace="page.name">Page Name Goes Here</span></b><br/>
- You can return to the <a href="${request.application_url}">FrontPage</a>.<br/>
+ Editing <b><span tal:replace="page.name">Page Name
+ Goes Here</span></b><br/>
+ You can return to the
+ <a href="${request.application_url}">FrontPage</a>.<br/>
</div>
<div id="right" class="app-welcome align-right">
<span tal:condition="logged_in">
- <a href="${request.application_url}/logout">Logout</a>
+ <a href="${request.application_url}/logout">Logout</a>
</span>
</div>
</div>
@@ -38,9 +47,10 @@
<div id="bottom">
<div class="bottom">
<form action="${save_url}" method="post">
- <textarea name="body" tal:content="page.data" rows="10" cols="60"/><br/>
- <input type="submit" name="form.submitted" value="Save"/>
- </form>
+ <textarea name="body" tal:content="page.data" rows="10"
+ cols="60"/><br/>
+ <input type="submit" name="form.submitted" value="Save"/>
+ </form>
</div>
</div>
</div>
@@ -48,4 +58,4 @@
<div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div>
</div>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/templates/login.pt b/docs/tutorials/wiki2/src/authorization/tutorial/templates/login.pt
index 974e22f37..554b4ea87 100644
--- a/docs/tutorials/wiki2/src/authorization/tutorial/templates/login.pt
+++ b/docs/tutorials/wiki2/src/authorization/tutorial/templates/login.pt
@@ -1,16 +1,22 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
+ xmlns:tal="http://xml.zope.org/namespaces/tal">
<head>
- <title>Login - Pyramid tutorial wiki (based on TurboGears 20-Minute Wiki)</title>
+ <title>Login - Pyramid tutorial wiki (based on TurboGears
+ 20-Minute Wiki)</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<meta name="keywords" content="python web application" />
<meta name="description" content="pyramid web application" />
- <link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" />
- <link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
+ <link rel="shortcut icon"
+ href="${request.static_url('tutorial:static/favicon.ico')}" />
+ <link rel="stylesheet"
+ href="${request.static_url('tutorial:static/pylons.css')}"
+ type="text/css" media="screen" charset="utf-8" />
<!--[if lte IE 6]>
- <link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" />
+ <link rel="stylesheet"
+ href="${request.static_url('tutorial:static/ie6.css')}"
+ type="text/css" media="screen" charset="utf-8" />
<![endif]-->
</head>
<body>
@@ -18,7 +24,8 @@
<div id="top-small">
<div class="top-small align-center">
<div>
- <img src="${request.static_url('tutorial:static/pyramid-small.png')}" width="220" height="50" alt="pyramid" />
+ <img width="220" height="50" alt="pyramid"
+ src="${request.static_url('tutorial:static/pyramid-small.png')}" />
</div>
</div>
</div>
@@ -34,11 +41,12 @@
<div id="bottom">
<div class="bottom">
<form action="${url}" method="post">
- <input type="hidden" name="came_from" value="${came_from}"/>
- <input type="text" name="login" value="${login}"/><br/>
- <input type="password" name="password" value="${password}"/><br/>
- <input type="submit" name="form.submitted" value="Log In"/>
- </form>
+ <input type="hidden" name="came_from" value="${came_from}"/>
+ <input type="text" name="login" value="${login}"/><br/>
+ <input type="password" name="password"
+ value="${password}"/><br/>
+ <input type="submit" name="form.submitted" value="Log In"/>
+ </form>
</div>
</div>
</div>
@@ -46,4 +54,4 @@
<div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div>
</div>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki2/src/authorization/tutorial/templates/mytemplate.pt
index cac9ccaa7..e31a342b2 100644
--- a/docs/tutorials/wiki2/src/authorization/tutorial/templates/mytemplate.pt
+++ b/docs/tutorials/wiki2/src/authorization/tutorial/templates/mytemplate.pt
@@ -7,8 +7,7 @@
<meta name="description" content="pyramid web application" />
<link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" />
<link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
+ <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton|Nobile:regular,i,b,bi&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
<!--[if lte IE 6]>
<link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" />
<![endif]-->
@@ -32,7 +31,7 @@
<div class="bottom">
<div id="left" class="align-right">
<h2>Search documentation</h2>
- <form method="get" action="http://docs.pylonshq.com/pyramid/dev/search.html">
+ <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/dev/search.html">
<input type="text" id="q" name="q" value="" />
<input type="submit" id="x" value="Go" />
</form>
@@ -41,25 +40,25 @@
<h2>Pyramid links</h2>
<ul class="links">
<li>
- <a href="http://pylonshq.com">Pylons Website</a>
+ <a href="http://pylonsproject.org">Pylons Website</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#narrative-documentation">Narrative Documentation</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#api-documentation">API Documentation</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#tutorials">Tutorials</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#change-history">Change History</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#sample-applications">Sample Applications</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#support-and-development">Support and Development</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a>
</li>
<li>
<a href="irc://irc.freenode.net#pyramid">IRC Channel</a>
diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/templates/view.pt b/docs/tutorials/wiki2/src/authorization/tutorial/templates/view.pt
index d0360429c..7d01aefb9 100644
--- a/docs/tutorials/wiki2/src/authorization/tutorial/templates/view.pt
+++ b/docs/tutorials/wiki2/src/authorization/tutorial/templates/view.pt
@@ -1,16 +1,22 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
+ xmlns:tal="http://xml.zope.org/namespaces/tal">
<head>
- <title>${page.name} - Pyramid tutorial wiki (based on TurboGears 20-Minute Wiki)</title>
+ <title>${page.name} - Pyramid tutorial wiki (based on
+ TurboGears 20-Minute Wiki)</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<meta name="keywords" content="python web application" />
<meta name="description" content="pyramid web application" />
- <link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" />
- <link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
+ <link rel="shortcut icon"
+ href="${request.static_url('tutorial:static/favicon.ico')}" />
+ <link rel="stylesheet"
+ href="${request.static_url('tutorial:static/pylons.css')}"
+ type="text/css" media="screen" charset="utf-8" />
<!--[if lte IE 6]>
- <link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" />
+ <link rel="stylesheet"
+ href="${request.static_url('tutorial:static/ie6.css')}"
+ type="text/css" media="screen" charset="utf-8" />
<![endif]-->
</head>
<body>
@@ -18,19 +24,22 @@
<div id="top-small">
<div class="top-small align-center">
<div>
- <img src="${request.static_url('tutorial:static/pyramid-small.png')}" width="220" height="50" alt="pyramid" />
+ <img width="220" height="50" alt="pyramid"
+ src="${request.static_url('tutorial:static/pyramid-small.png')}" />
</div>
</div>
</div>
<div id="middle">
<div class="middle align-right">
<div id="left" class="app-welcome align-left">
- Viewing <b><span tal:replace="page.name">Page Name Goes Here</span></b><br/>
- You can return to the <a href="${request.application_url}">FrontPage</a>.<br/>
+ Viewing <b><span tal:replace="page.name">Page Name
+ Goes Here</span></b><br/>
+ You can return to the
+ <a href="${request.application_url}">FrontPage</a>.<br/>
</div>
<div id="right" class="app-welcome align-right">
<span tal:condition="logged_in">
- <a href="${request.application_url}/logout">Logout</a>
+ <a href="${request.application_url}/logout">Logout</a>
</span>
</div>
</div>
@@ -52,4 +61,4 @@
<div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div>
</div>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/tests.py b/docs/tutorials/wiki2/src/authorization/tutorial/tests.py
index 1020a8b99..08916f43c 100644
--- a/docs/tutorials/wiki2/src/authorization/tutorial/tests.py
+++ b/docs/tutorials/wiki2/src/authorization/tutorial/tests.py
@@ -1,6 +1,5 @@
import unittest
-from pyramid.config import Configurator
from pyramid import testing
def _initTestingDB():
@@ -20,11 +19,10 @@ def _registerRoutes(config):
class ViewWikiTests(unittest.TestCase):
def setUp(self):
- self.config = Configurator(autocommit=True)
- self.config.begin()
+ self.config = testing.setUp()
def tearDown(self):
- self.config.end()
+ testing.tearDown()
def test_it(self):
from tutorial.views import view_wiki
@@ -36,12 +34,10 @@ class ViewWikiTests(unittest.TestCase):
class ViewPageTests(unittest.TestCase):
def setUp(self):
self.session = _initTestingDB()
- self.config = Configurator(autocommit=True)
- self.config.begin()
+ self.config = testing.setUp()
def tearDown(self):
- self.session.remove()
- self.config.end()
+ testing.tearDown()
def _callFUT(self, request):
from tutorial.views import view_page
@@ -71,12 +67,11 @@ class ViewPageTests(unittest.TestCase):
class AddPageTests(unittest.TestCase):
def setUp(self):
self.session = _initTestingDB()
- self.config = Configurator(autocommit=True)
- self.config.begin()
+ self.config = testing.setUp()
def tearDown(self):
self.session.remove()
- self.config.end()
+ testing.tearDown()
def _callFUT(self, request):
from tutorial.views import add_page
@@ -104,12 +99,11 @@ class AddPageTests(unittest.TestCase):
class EditPageTests(unittest.TestCase):
def setUp(self):
self.session = _initTestingDB()
- self.config = Configurator(autocommit=True)
- self.config.begin()
+ self.config = testing.setUp()
def tearDown(self):
self.session.remove()
- self.config.end()
+ testing.tearDown()
def _callFUT(self, request):
from tutorial.views import edit_page
diff --git a/docs/tutorials/wiki2/src/basiclayout/development.ini b/docs/tutorials/wiki2/src/basiclayout/development.ini
index b0cfd12a7..3b615f635 100644
--- a/docs/tutorials/wiki2/src/basiclayout/development.ini
+++ b/docs/tutorials/wiki2/src/basiclayout/development.ini
@@ -11,9 +11,13 @@ sqlalchemy.url = sqlite:///%(here)s/tutorial.db
[pipeline:main]
pipeline =
egg:WebError#evalerror
- egg:repoze.tm2#tm
+ tm
tutorial
+[filter:tm]
+use = egg:repoze.tm2#tm
+commit_veto = repoze.tm:default_commit_veto
+
[server:main]
use = egg:Paste#http
host = 0.0.0.0
diff --git a/docs/tutorials/wiki2/src/basiclayout/setup.py b/docs/tutorials/wiki2/src/basiclayout/setup.py
index 09764f40f..eaf1ddcfe 100644
--- a/docs/tutorials/wiki2/src/basiclayout/setup.py
+++ b/docs/tutorials/wiki2/src/basiclayout/setup.py
@@ -11,7 +11,7 @@ requires = [
'pyramid',
'SQLAlchemy',
'transaction',
- 'repoze.tm2',
+ 'repoze.tm2>=1.0b1', # default_commit_veto
'zope.sqlalchemy',
'WebError',
]
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/models.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/models.py
index 9da906752..4fd010c5c 100644
--- a/docs/tutorials/wiki2/src/basiclayout/tutorial/models.py
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/models.py
@@ -12,7 +12,8 @@ from sqlalchemy.orm import sessionmaker
from zope.sqlalchemy import ZopeTransactionExtension
-DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
+DBSession = scoped_session(sessionmaker(
+ extension=ZopeTransactionExtension()))
Base = declarative_base()
class MyModel(Base):
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt
index cac9ccaa7..e31a342b2 100644
--- a/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt
@@ -7,8 +7,7 @@
<meta name="description" content="pyramid web application" />
<link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" />
<link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
+ <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton|Nobile:regular,i,b,bi&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
<!--[if lte IE 6]>
<link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" />
<![endif]-->
@@ -32,7 +31,7 @@
<div class="bottom">
<div id="left" class="align-right">
<h2>Search documentation</h2>
- <form method="get" action="http://docs.pylonshq.com/pyramid/dev/search.html">
+ <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/dev/search.html">
<input type="text" id="q" name="q" value="" />
<input type="submit" id="x" value="Go" />
</form>
@@ -41,25 +40,25 @@
<h2>Pyramid links</h2>
<ul class="links">
<li>
- <a href="http://pylonshq.com">Pylons Website</a>
+ <a href="http://pylonsproject.org">Pylons Website</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#narrative-documentation">Narrative Documentation</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#api-documentation">API Documentation</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#tutorials">Tutorials</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#change-history">Change History</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#sample-applications">Sample Applications</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#support-and-development">Support and Development</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a>
</li>
<li>
<a href="irc://irc.freenode.net#pyramid">IRC Channel</a>
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/tests.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/tests.py
index fa3788340..5efa6affa 100644
--- a/docs/tutorials/wiki2/src/basiclayout/tutorial/tests.py
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/tests.py
@@ -1,5 +1,4 @@
import unittest
-from pyramid.config import Configurator
from pyramid import testing
def _initTestingDB():
@@ -10,12 +9,11 @@ def _initTestingDB():
class TestMyView(unittest.TestCase):
def setUp(self):
- self.config = Configurator(autocommit=True)
- self.config.begin()
+ self.config = testing.setUp()
_initTestingDB()
def tearDown(self):
- self.config.end()
+ testing.tearDown()
def test_it(self):
from tutorial.views import my_view
diff --git a/docs/tutorials/wiki2/src/models/development.ini b/docs/tutorials/wiki2/src/models/development.ini
index b0cfd12a7..3b615f635 100644
--- a/docs/tutorials/wiki2/src/models/development.ini
+++ b/docs/tutorials/wiki2/src/models/development.ini
@@ -11,9 +11,13 @@ sqlalchemy.url = sqlite:///%(here)s/tutorial.db
[pipeline:main]
pipeline =
egg:WebError#evalerror
- egg:repoze.tm2#tm
+ tm
tutorial
+[filter:tm]
+use = egg:repoze.tm2#tm
+commit_veto = repoze.tm:default_commit_veto
+
[server:main]
use = egg:Paste#http
host = 0.0.0.0
diff --git a/docs/tutorials/wiki2/src/models/setup.py b/docs/tutorials/wiki2/src/models/setup.py
index 09764f40f..eaf1ddcfe 100644
--- a/docs/tutorials/wiki2/src/models/setup.py
+++ b/docs/tutorials/wiki2/src/models/setup.py
@@ -11,7 +11,7 @@ requires = [
'pyramid',
'SQLAlchemy',
'transaction',
- 'repoze.tm2',
+ 'repoze.tm2>=1.0b1', # default_commit_veto
'zope.sqlalchemy',
'WebError',
]
diff --git a/docs/tutorials/wiki2/src/models/tutorial/models.py b/docs/tutorials/wiki2/src/models/tutorial/models.py
index 23b8afab8..797fff929 100644
--- a/docs/tutorials/wiki2/src/models/tutorial/models.py
+++ b/docs/tutorials/wiki2/src/models/tutorial/models.py
@@ -12,7 +12,8 @@ from sqlalchemy.orm import sessionmaker
from zope.sqlalchemy import ZopeTransactionExtension
-DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
+DBSession = scoped_session(sessionmaker(
+ extension=ZopeTransactionExtension()))
Base = declarative_base()
class Page(Base):
diff --git a/docs/tutorials/wiki2/src/models/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki2/src/models/tutorial/templates/mytemplate.pt
index cac9ccaa7..e31a342b2 100644
--- a/docs/tutorials/wiki2/src/models/tutorial/templates/mytemplate.pt
+++ b/docs/tutorials/wiki2/src/models/tutorial/templates/mytemplate.pt
@@ -7,8 +7,7 @@
<meta name="description" content="pyramid web application" />
<link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" />
<link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
+ <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton|Nobile:regular,i,b,bi&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
<!--[if lte IE 6]>
<link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" />
<![endif]-->
@@ -32,7 +31,7 @@
<div class="bottom">
<div id="left" class="align-right">
<h2>Search documentation</h2>
- <form method="get" action="http://docs.pylonshq.com/pyramid/dev/search.html">
+ <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/dev/search.html">
<input type="text" id="q" name="q" value="" />
<input type="submit" id="x" value="Go" />
</form>
@@ -41,25 +40,25 @@
<h2>Pyramid links</h2>
<ul class="links">
<li>
- <a href="http://pylonshq.com">Pylons Website</a>
+ <a href="http://pylonsproject.org">Pylons Website</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#narrative-documentation">Narrative Documentation</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#api-documentation">API Documentation</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#tutorials">Tutorials</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#change-history">Change History</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#sample-applications">Sample Applications</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#support-and-development">Support and Development</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a>
</li>
<li>
<a href="irc://irc.freenode.net#pyramid">IRC Channel</a>
diff --git a/docs/tutorials/wiki2/src/models/tutorial/tests.py b/docs/tutorials/wiki2/src/models/tutorial/tests.py
index 42b0aaada..71f5e21e3 100644
--- a/docs/tutorials/wiki2/src/models/tutorial/tests.py
+++ b/docs/tutorials/wiki2/src/models/tutorial/tests.py
@@ -1,5 +1,4 @@
import unittest
-from pyramid.config import Configurator
from pyramid import testing
def _initTestingDB():
@@ -9,12 +8,11 @@ def _initTestingDB():
class TestMyView(unittest.TestCase):
def setUp(self):
- self.config = Configurator(autocommit=True)
- self.config.begin()
+ self.config = testing.setUp()
_initTestingDB()
def tearDown(self):
- self.config.end()
+ testing.tearDown()
def test_it(self):
from tutorial.views import my_view
diff --git a/docs/tutorials/wiki2/src/views/development.ini b/docs/tutorials/wiki2/src/views/development.ini
index b0cfd12a7..3b615f635 100644
--- a/docs/tutorials/wiki2/src/views/development.ini
+++ b/docs/tutorials/wiki2/src/views/development.ini
@@ -11,9 +11,13 @@ sqlalchemy.url = sqlite:///%(here)s/tutorial.db
[pipeline:main]
pipeline =
egg:WebError#evalerror
- egg:repoze.tm2#tm
+ tm
tutorial
+[filter:tm]
+use = egg:repoze.tm2#tm
+commit_veto = repoze.tm:default_commit_veto
+
[server:main]
use = egg:Paste#http
host = 0.0.0.0
diff --git a/docs/tutorials/wiki2/src/views/setup.py b/docs/tutorials/wiki2/src/views/setup.py
index 58f464f8c..ae9869d50 100644
--- a/docs/tutorials/wiki2/src/views/setup.py
+++ b/docs/tutorials/wiki2/src/views/setup.py
@@ -11,7 +11,7 @@ requires = [
'pyramid',
'SQLAlchemy',
'transaction',
- 'repoze.tm2',
+ 'repoze.tm2>=1.0b1', # default_commit_veto
'zope.sqlalchemy',
'WebError',
'docutils',
diff --git a/docs/tutorials/wiki2/src/views/tutorial/templates/edit.pt b/docs/tutorials/wiki2/src/views/tutorial/templates/edit.pt
index b45cea3c6..f8f63af3b 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/templates/edit.pt
+++ b/docs/tutorials/wiki2/src/views/tutorial/templates/edit.pt
@@ -1,16 +1,22 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
+ xmlns:tal="http://xml.zope.org/namespaces/tal">
<head>
- <title>${page.name} - Pyramid tutorial wiki (based on TurboGears 20-Minute Wiki)</title>
+ <title>${page.name} - Pyramid tutorial wiki (based on
+ TurboGears 20-Minute Wiki)</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<meta name="keywords" content="python web application" />
<meta name="description" content="pyramid web application" />
- <link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" />
- <link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
+ <link rel="shortcut icon"
+ href="${request.static_url('tutorial:static/favicon.ico')}" />
+ <link rel="stylesheet"
+ href="${request.static_url('tutorial:static/pylons.css')}"
+ type="text/css" media="screen" charset="utf-8" />
<!--[if lte IE 6]>
- <link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" />
+ <link rel="stylesheet"
+ href="${request.static_url('tutorial:static/ie6.css')}"
+ type="text/css" media="screen" charset="utf-8" />
<![endif]-->
</head>
<body>
@@ -18,15 +24,18 @@
<div id="top-small">
<div class="top-small align-center">
<div>
- <img src="${request.static_url('tutorial:static/pyramid-small.png')}" width="220" height="50" alt="pyramid" />
+ <img width="220" height="50" alt="pyramid"
+ src="${request.static_url('tutorial:static/pyramid-small.png')}" />
</div>
</div>
</div>
<div id="middle">
<div class="middle align-right">
<div id="left" class="app-welcome align-left">
- Editing <b><span tal:replace="page.name">Page Name Goes Here</span></b><br/>
- You can return to the <a href="${request.application_url}">FrontPage</a>.<br/>
+ Editing <b><span tal:replace="page.name">Page Name Goes
+ Here</span></b><br/>
+ You can return to the
+ <a href="${request.application_url}">FrontPage</a>.<br/>
</div>
<div id="right" class="app-welcome align-right"></div>
</div>
@@ -34,9 +43,10 @@
<div id="bottom">
<div class="bottom">
<form action="${save_url}" method="post">
- <textarea name="body" tal:content="page.data" rows="10" cols="60"/><br/>
- <input type="submit" name="form.submitted" value="Save"/>
- </form>
+ <textarea name="body" tal:content="page.data" rows="10"
+ cols="60"/><br/>
+ <input type="submit" name="form.submitted" value="Save"/>
+ </form>
</div>
</div>
</div>
@@ -44,4 +54,4 @@
<div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div>
</div>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/docs/tutorials/wiki2/src/views/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki2/src/views/tutorial/templates/mytemplate.pt
index cac9ccaa7..e31a342b2 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/templates/mytemplate.pt
+++ b/docs/tutorials/wiki2/src/views/tutorial/templates/mytemplate.pt
@@ -7,8 +7,7 @@
<meta name="description" content="pyramid web application" />
<link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" />
<link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
+ <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton|Nobile:regular,i,b,bi&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
<!--[if lte IE 6]>
<link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" />
<![endif]-->
@@ -32,7 +31,7 @@
<div class="bottom">
<div id="left" class="align-right">
<h2>Search documentation</h2>
- <form method="get" action="http://docs.pylonshq.com/pyramid/dev/search.html">
+ <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/dev/search.html">
<input type="text" id="q" name="q" value="" />
<input type="submit" id="x" value="Go" />
</form>
@@ -41,25 +40,25 @@
<h2>Pyramid links</h2>
<ul class="links">
<li>
- <a href="http://pylonshq.com">Pylons Website</a>
+ <a href="http://pylonsproject.org">Pylons Website</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#narrative-documentation">Narrative Documentation</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#narrative-documentation">Narrative Documentation</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#api-documentation">API Documentation</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#api-documentation">API Documentation</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#tutorials">Tutorials</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#tutorials">Tutorials</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#change-history">Change History</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#change-history">Change History</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#sample-applications">Sample Applications</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#sample-applications">Sample Applications</a>
</li>
<li>
- <a href="http://docs.pylonshq.com/pyramid/dev/#support-and-development">Support and Development</a>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/dev/#support-and-development">Support and Development</a>
</li>
<li>
<a href="irc://irc.freenode.net#pyramid">IRC Channel</a>
diff --git a/docs/tutorials/wiki2/src/views/tutorial/templates/view.pt b/docs/tutorials/wiki2/src/views/tutorial/templates/view.pt
index cacb58788..7c8a39f53 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/templates/view.pt
+++ b/docs/tutorials/wiki2/src/views/tutorial/templates/view.pt
@@ -1,16 +1,22 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
+ xmlns:tal="http://xml.zope.org/namespaces/tal">
<head>
- <title>${page.name} - Pyramid tutorial wiki (based on TurboGears 20-Minute Wiki)</title>
+ <title>${page.name} - Pyramid tutorial wiki (based on
+ TurboGears 20-Minute Wiki)</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<meta name="keywords" content="python web application" />
<meta name="description" content="pyramid web application" />
- <link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" />
- <link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
- <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
+ <link rel="shortcut icon"
+ href="${request.static_url('tutorial:static/favicon.ico')}" />
+ <link rel="stylesheet"
+ href="${request.static_url('tutorial:static/pylons.css')}"
+ type="text/css" media="screen" charset="utf-8" />
<!--[if lte IE 6]>
- <link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" />
+ <link rel="stylesheet"
+ href="${request.static_url('tutorial:static/ie6.css')}"
+ type="text/css" media="screen" charset="utf-8" />
<![endif]-->
</head>
<body>
@@ -18,15 +24,18 @@
<div id="top-small">
<div class="top-small align-center">
<div>
- <img src="${request.static_url('tutorial:static/pyramid-small.png')}" width="220" height="50" alt="pyramid" />
+ <img width="220" height="50" alt="pyramid"
+ src="${request.static_url('tutorial:static/pyramid-small.png')}" />
</div>
</div>
</div>
<div id="middle">
<div class="middle align-right">
<div id="left" class="app-welcome align-left">
- Viewing <b><span tal:replace="page.name">Page Name Goes Here</span></b><br/>
- You can return to the <a href="${request.application_url}">FrontPage</a>.<br/>
+ Viewing <b><span tal:replace="page.name">Page Name
+ Goes Here</span></b><br/>
+ You can return to the
+ <a href="${request.application_url}">FrontPage</a>.<br/>
</div>
<div id="right" class="app-welcome align-right"></div>
</div>
@@ -48,4 +57,4 @@
<div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div>
</div>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/docs/tutorials/wiki2/src/views/tutorial/tests.py b/docs/tutorials/wiki2/src/views/tutorial/tests.py
index 7b770f927..b9797df67 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/tests.py
+++ b/docs/tutorials/wiki2/src/views/tutorial/tests.py
@@ -1,6 +1,5 @@
import unittest
-from pyramid.config import Configurator
from pyramid import testing
def _initTestingDB():
@@ -20,11 +19,10 @@ def _registerRoutes(config):
class ViewWikiTests(unittest.TestCase):
def setUp(self):
- self.config = Configurator(autocommit=True)
- self.config.begin()
+ self.config = testing.setUp()
def tearDown(self):
- self.config.end()
+ testing.tearDown()
def test_it(self):
from tutorial.views import view_wiki
@@ -36,12 +34,11 @@ class ViewWikiTests(unittest.TestCase):
class ViewPageTests(unittest.TestCase):
def setUp(self):
self.session = _initTestingDB()
- self.config = Configurator(autocommit=True)
- self.config.begin()
+ self.config = testing.setUp()
def tearDown(self):
self.session.remove()
- self.config.end()
+ testing.tearDown()
def _callFUT(self, request):
from tutorial.views import view_page
@@ -71,12 +68,12 @@ class ViewPageTests(unittest.TestCase):
class AddPageTests(unittest.TestCase):
def setUp(self):
self.session = _initTestingDB()
- self.config = Configurator(autocommit=True)
+ self.config = testing.setUp()
self.config.begin()
def tearDown(self):
self.session.remove()
- self.config.end()
+ testing.tearDown()
def _callFUT(self, request):
from tutorial.views import add_page
@@ -104,12 +101,11 @@ class AddPageTests(unittest.TestCase):
class EditPageTests(unittest.TestCase):
def setUp(self):
self.session = _initTestingDB()
- self.config = Configurator(autocommit=True)
- self.config.begin()
+ self.config = testing.setUp()
def tearDown(self):
self.session.remove()
- self.config.end()
+ testing.tearDown()
def _callFUT(self, request):
from tutorial.views import edit_page
diff --git a/docs/whatsnew-1.0.rst b/docs/whatsnew-1.0.rst
new file mode 100644
index 000000000..1baa1f5df
--- /dev/null
+++ b/docs/whatsnew-1.0.rst
@@ -0,0 +1,721 @@
+What's New In Pyramid 1.0
+=========================
+
+This article explains the new features in Pyramid version 1.0 as compared to
+its predecessor, :mod:`repoze.bfg` 1.3. It also documents backwards
+incompatibilities between the two versions and deprecations added to Pyramid
+1.0, as well as software dependency changes and notable documentation
+additions.
+
+Major Feature Additions
+-----------------------
+
+The major feature additions in Pyramid 1.0 are:
+
+- New name and branding association with the Pylons Project.
+
+- Paster template improvements
+
+- Terminology changes
+
+- Better platform compatibility and support
+
+- Direct built-in support for the Mako templating language.
+
+- Built-in support for sessions.
+
+- Updated URL dispatch features
+
+- Better imperative extensibility
+
+- ZCML externalized
+
+- Better support for global template variables during rendering
+
+- View mappers
+
+- Testing system improvements
+
+- Authentication support improvements
+
+- Documentation improvements
+
+New Name and Branding
+~~~~~~~~~~~~~~~~~~~~~
+
+The name of ``repoze.bfg`` has been changed to Pyramid. The project
+is now branded under a new entity, "The Pylons Project". The Pylons Project
+is the project name for a collection of web-framework-related technologies.
+Pyramid was the first package in the Pylons Project. Other packages to the
+collection have been added over time, such as support packages useful for
+Pylons 1 users as well as ex-Zope users. Pyramid is the successor to both
+:mod:`repoze.bfg` and :term:`Pylons` version 1.
+
+The Pyramid codebase is derived almost entirely from :mod:`repoze.bfg`
+with some changes made for the sake of Pylons 1 compatibility.
+
+Pyramid is technically backwards incompatible with :mod:`repoze.bfg`, as it
+has a new package name, so older imports from the ``repoze.bfg`` module will
+fail if you do nothing to your existing :mod:`repoze.bfg` application.
+However, you won't have to do much to use your existing BFG applications on
+Pyramid. There's automation which will change most of your import statements
+and ZCML declarations. See
+http://docs.pylonshq.com/pyramid/dev/tutorials/bfg/index.html for upgrade
+instructions.
+
+Pylons 1 users will need to do more work to use Pyramid, as Pyramid shares no
+"DNA" with Pylons. It is hoped that over time documentation and upgrade code
+will be developed to help Pylons 1 users transition to Pyramid more easily.
+
+:mod:`repoze.bfg` version 1.3 will be its last major release. Minor updates
+will be made for critical bug fixes. Pylons version 1 will continue to see
+maintenance releases, as well.
+
+The Repoze project will continue to exist. Repoze will be able to regain its
+original focus: bringing Zope technologies to WSGI. The popularity of
+:mod:`repoze.bfg` as its own web framework hindered this goal.
+
+We hope that people are attracted at first by the spirit of cooperation
+demonstrated by the Pylons Project and the merging of development
+communities. It takes humility to sacrifice a little sovereignty and work
+together. The opposite, forking or splintering of projects, is much more
+common in the open source world. We feel there is a limited amount of oxygen
+in the space of "top-tier" Python web frameworks and we don’t do the Python
+community a service by over-crowding. By merging the :mod:`repoze.bfg` and
+the philosophically-similar Pylons communities, both gain an expanded
+audience and a stronger chance of future success.
+
+Paster Template Improvements
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Normalized all paster templates: each now uses the name ``main`` to
+ represent the function that returns a WSGI application, each now uses
+ WebError, each now has roughly the same shape of development.ini style.
+
+- All preexisting paster templates now use "imperative" configuration
+ (``starter``, ``routesalchemy``, ``alchemy``, ``zodb``).
+
+- The ``pyramid_zodb``, ``pyramid_routesalchemy`` and ``pyramid_alchemy``
+ paster templates now use a default "commit veto" hook when configuring the
+ ``repoze.tm2`` transaction manager in ``development.ini``. This prevents a
+ transaction from being committed when the response status code is within
+ the 400 or 500 ranges. See also
+ http://docs.repoze.org/tm2/#using-a-commit-veto.
+
+- The paster templates now have much nicer CSS and graphics.
+
+Terminology Changes
+~~~~~~~~~~~~~~~~~~~
+
+- The Pyramid concept previously known as "model" is now known as "resource".
+ As a result:
+
+ - The following API changes have been made::
+
+ pyramid.url.model_url ->
+ pyramid.url.resource_url
+
+ pyramid.traversal.find_model ->
+ pyramid.url.find_resource
+
+ pyramid.traversal.model_path ->
+ pyramid.traversal.resource_path
+
+ pyramid.traversal.model_path_tuple ->
+ pyramid.traversal.resource_path_tuple
+
+ pyramid.traversal.ModelGraphTraverser ->
+ pyramid.traversal.ResourceTreeTraverser
+
+ pyramid.config.Configurator.testing_models ->
+ pyramid.config.Configurator.testing_resources
+
+ pyramid.testing.registerModels ->
+ pyramid.testing.registerResources
+
+ pyramid.testing.DummyModel ->
+ pyramid.testing.DummyResource
+
+ - All documentation which previously referred to "model" now refers to
+ "resource".
+
+ - The ``starter`` and ``starter_zcml`` paster templates now have a
+ ``resources.py`` module instead of a ``models.py`` module.
+
+ - Positional argument names of various APIs have been changed from
+ ``model`` to ``resource``.
+
+ Backwards compatibility shims have been left in place in all cases.
+
+- The Pyramid concept previously known as "resource" is now known as "asset".
+ As a result:
+
+ - The (non-API) module previously known as ``pyramid.resource`` is now
+ known as ``pyramid.asset``.
+
+ - All docs that previously referred to "resource specification" now refer
+ to "asset specification".
+
+ - The following API changes were made::
+
+ pyramid.config.Configurator.absolute_resource_spec ->
+ pyramid.config.Configurator.absolute_asset_spec
+
+ pyramid.config.Configurator.override_resource ->
+ pyramid.config.Configurator.override_asset
+
+ - The ZCML directive previously known as ``resource`` is now known as
+ ``asset``.
+
+ - The setting previously known as ``BFG_RELOAD_RESOURCES`` (envvar) or
+ ``reload_resources`` (config file) is now known, respectively, as
+ ``PYRAMID_RELOAD_ASSETS`` and ``reload_assets``.
+
+ Backwards compatibility shims have been left in place in all cases.
+
+Better Platform Compatibility and Support
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Make test suite pass on Jython (requires PasteScript trunk, presumably to
+ be 1.7.4).
+
+- Make test suite pass on PyPy (Chameleon doesn't work).
+
+Sessions
+~~~~~~~~
+
+- Using ``request.session`` now returns a (dictionary-like) session
+ object if a session factory has been configured.
+
+- New argument to configurator: ``session_factory``.
+
+- New method on configurator: ``set_session_factory``
+
+- New API methods in ``pyramid.session``: ``signed_serialize`` and
+ ``signed_deserialize``.
+
+- Added flash messaging, as described in the "Flash Messaging" narrative
+ documentation chapter.
+
+- Added CSRF token generation, as described in the narrative chapter entitled
+ "Preventing Cross-Site Request Forgery Attacks".
+
+Mako
+~~~~
+
+- Added Mako TemplateLookup settings for ``mako.error_handler``,
+ ``mako.default_filters``, and ``mako.imports``.
+
+- New boolean Mako settings variable ``mako.strict_undefined``. See `Mako
+ Context Variables
+ <http://www.makotemplates.org/docs/runtime.html#context-variables>`_ for
+ its meaning.
+
+URL Dispatch
+~~~~~~~~~~~~
+
+- URL Dispatch now allows for replacement markers to be located anywhere
+ in the pattern, instead of immediately following a ``/``.
+
+- URL Dispatch now uses the form ``{marker}`` to denote a replace marker in
+ the route pattern instead of ``:marker``. The old colon-style marker syntax
+ is still accepted for backwards compatibility. The new format allows a
+ regular expression for that marker location to be used instead of the
+ default ``[^/]+``, for example ``{marker:\d+}`` is now valid to require the
+ marker to be digits.
+
+- Add a new API ``pyramid.url.current_route_url``, which computes a URL based
+ on the "current" route (if any) and its matchdict values.
+
+- Add ``paster proute`` command which displays a summary of the routing
+ table. See the narrative documentation section within the "URL Dispatch"
+ chapter entitled "Displaying All Application Routes".
+
+- Added ``debug_routematch`` configuration setting that logs matched routes
+ (including the matchdict and predicates).
+
+- Add a ``pyramid.url.route_path`` API, allowing folks to generate relative
+ URLs. Calling ``route_path`` is the same as calling
+ ``pyramid.url.route_url`` with the argument ``_app_url`` equal to the empty
+ string.
+
+- Add a ``pyramid.request.Request.route_path`` API. This is a convenience
+ method of the request which calls ``pyramid.url.route_url``.
+
+- Added class vars ``matchdict`` and ``matched_route`` to
+ ``pyramid.request.Request``. Each is set to ``None``.
+
+ZCML Externalized
+~~~~~~~~~~~~~~~~~
+
+- The ``load_zcml`` method of a Configurator has been removed from the
+ Pyramid core. Loading ZCML is now a feature of the ``pyramid_zcml``
+ package, which can be downloaded from PyPI. Documentation for the package
+ should be available via
+ http://pylonsproject.org/projects/pyramid_zcml/dev/, which describes how
+ to add a configuration statement to your ``main`` block to reobtain this
+ method. You will also need to add an ``install_requires`` dependency upon
+ ``pyramid_zcml`` to your ``setup.py`` file.
+
+- The ``bfg2pyramid`` script now converts ZCML include tags that have
+ ``repoze.bfg.includes`` as a package attribute to the value
+ ``pyramid_zcml``. For example, ``<include package="repoze.bfg.includes">``
+ will be converted to ``<include package="pyramid_zcml">``.
+
+- The ``pyramid.includes`` subpackage has been removed. ZCML files which use
+ include the package ``pyramid.includes`` (e.g. ``<include
+ package="pyramid.includes"/>``) now must include the ``pyramid_zcml``
+ package instead (e.g. ``<include package="pyramid_zcml"/>``).
+
+- The "Declarative Configuration" narrative chapter has been removed (it was
+ moved to the ``pyramid_zcml`` package).
+
+- Most references to ZCML in narrative chapters have been removed or
+ redirected to ``pyramid_zcml`` locations.
+
+- The ``starter_zcml`` paster template has been moved to the ``pyramid_zcml``
+ package.
+
+- The ``make_app`` function has been removed from the ``pyramid.router``
+ module. It continues life within the ``pyramid_zcml`` package. This
+ leaves the ``pyramid.router`` module without any API functions.
+
+Imperative Two-Phase Configuration
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Imperative two-phase configuration with conflict detection.
+
+- Add ``add_directive`` method to configurator, which allows framework
+ extenders to add methods to the configurator (ala ZCML directives).
+
+- When ``Configurator.include`` is passed a *module* as an argument, it
+ defaults to attempting to find and use a callable named ``includeme``
+ within that module. This makes it possible to use
+ ``config.include('some.module')`` rather than
+ ``config.include('some.module.somefunc')`` as long as the include function
+ within ``some.module`` is named ``includeme``.
+
+- The new ``pyramid.config.Configurator` class has API methods that the older
+ ``pyramid.configuration.Configurator`` class did not: ``with_context`` (a
+ classmethod), ``include``, ``action``, and ``commit``. These methods exist
+ for imperative application extensibility purposes.
+
+- Surrounding application configuration with ``config.begin()`` and
+ ``config.end()`` is no longer necessary. All paster templates have been
+ changed to no longer call these functions.
+
+Better Support for Global Template Variables During Rendering
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- New event type: ``pyramid.interfaces.IBeforeRender``. An object of this type
+ is sent as an event before a renderer is invoked (but after the
+ application-level renderer globals factory added via
+ ``pyramid.configurator.configuration.set_renderer_globals_factory``, if any,
+ has injected its own keys). Applications may now subscribe to the
+ ``IBeforeRender`` event type in order to introspect the and modify the set of
+ renderer globals before they are passed to a renderer. The event object
+ iself has a dictionary-like interface that can be used for this purpose. For
+ example::
+
+ from repoze.events import subscriber
+ from pyramid.interfaces import IRendererGlobalsEvent
+
+ @subscriber(IRendererGlobalsEvent)
+ def add_global(event):
+ event['mykey'] = 'foo'
+
+ If a subscriber attempts to add a key that already exist in the renderer
+ globals dictionary, a ``KeyError`` is raised. This limitation is due to the
+ fact that subscribers cannot be ordered relative to each other. The set of
+ keys added to the renderer globals dictionary by all subscribers and
+ app-level globals factories must be unique.
+
+View Mappers
+~~~~~~~~~~~~
+
+- New constructor argument to Configurator: ``default_view_mapper``. Useful
+ to create systems that have alternate view calling conventions. A view
+ mapper allows objects that are meant to be used as view callables to have
+ an arbitrary argument list and an arbitrary result. The object passed as
+ ``default_view_mapper`` should implement the
+ ``pyramid.interfaces.IViewMapperFactory`` interface.
+
+- add a ``set_view_mapper`` API to Configurator. Has
+ the same result as passing ``default_view_mapper`` to the Configurator
+ constructor.
+
+- ``config.add_view`` now accepts a ``mapper`` keyword argument, which should
+ either be ``None``, a string representing a Python dotted name, or an
+ object which is an ``IViewMapperFactory``. This feature is not useful for
+ "civilians", only for extension writers.
+
+Testing Support Improvements
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- ``pyramid.testing.setUp`` and ``pyramid.testing.tearDown`` have been
+ undeprecated. They are now the canonical setup and teardown APIs for test
+ configuration, replacing "direct" creation of a Configurator. This is a
+ change designed to provide a facade that will protect against any future
+ Configurator deprecations.
+
+- Add ``charset`` attribute to ``pyramid.testing.DummyRequest``
+ (unconditionally ``UTF-8``).
+
+- Instances of ``pyramid.testing.DummyRequest`` now have a ``session``
+ object, which is mostly a dictionary, but also implements the other session
+ API methods for flash and CSRF.
+
+- ``pyramid.testing.DummyRequest`` now has a class variable,
+ ``query_string``, which defaults to the empty string.
+
+- The ``pyramid.testing.setUp`` function now accepts an ``autocommit``
+ keyword argument, which defaults to ``True``. If it is passed ``False``,
+ the Config object returned by ``setUp`` will be a non-autocommiting Config
+ object.
+
+Authentication Support Improvements
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- The ``pyramid.interfaces.IAuthenticationPolicy`` interface now specifies an
+ ``unauthenticated_userid`` method. This method supports an important
+ optimization required by people who are using persistent storages which do
+ not support object caching and whom want to create a "user object" as a
+ request attribute.
+
+- A new API has been added to the ``pyramid.security`` module named
+ ``unauthenticated_userid``. This API function calls the
+ ``unauthenticated_userid`` method of the effective security policy.
+
+- An ``unauthenticated_userid`` method has been added to the dummy
+ authentication policy returned by
+ ``pyramid.config.Configurator.testing_securitypolicy``. It returns the
+ same thing as that the dummy authentication policy's
+ ``authenticated_userid`` method.
+
+- The class ``pyramid.authentication.AuthTktCookieHelper`` is now an API.
+ This class can be used by third-party authentication policy developers to
+ help in the mechanics of authentication cookie-setting.
+
+- The AuthTktAuthenticationPolicy now accepts a ``tokens`` parameter via
+ ``pyramid.security.remember``. The value must be a sequence of strings.
+ Tokens are placed into the auth_tkt "tokens" field and returned in the
+ auth_tkt cookie.
+
+Documentation Improvements
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- Casey Duncan, a good friend, and an excellent technical writer has given us
+ the gift of professionally editing the entire Pyramid documentation set.
+ Any faults in the documentation are the development team's, and all
+ improvements are his.
+
+- The "Resource Location and View Lookup" chapter has been replaced with a
+ variant of Rob Miller's "Much Ado About Traversal" (originally published at
+ http://blog.nonsequitarian.org/2010/much-ado-about-traversal/).
+
+- Many users have contributed documentation fixes and improvements including
+ Ben Bangert, Blaise Laflamme, Rob Miller, Mike Orr, Carlos de la Guardia,
+ Paul Everitt, Tres Seaver, John Shipman, Marius Gedminas, Chris Rossi,
+ Joachim Krebs, Xavier Spriet, Reed O'Brien, William Chambers, Charlie
+ Choiniere, and Jamaludin Ahmad.
+
+Minor Feature Additions
+-----------------------
+
+- The ``settings`` object which used to be available only when
+ ``request.settings.get_settings`` was called is now available as
+ ``registry.settings`` (e.g. ``request.registry.settings`` in view code).
+
+- ``config.add_view`` now accepts a ``decorator`` keyword argument, a callable
+ which will decorate the view callable before it is added to the registry.
+
+- Allow static renderer provided during view registration to be overridden at
+ request time via a request attribute named ``override_renderer``, which
+ should be the name of a previously registered renderer. Useful to provide
+ "omnipresent" RPC using existing rendered views.
+
+- If a resource implements a ``__resource_url__`` method, it will be called
+ as the result of invoking the ``pyramid.url.resource_url`` function to
+ generate a URL, overriding the default logic. See the new "Generating The
+ URL Of A Resource" section within the Resources narrative chapter.
+
+- The name ``registry`` is now available in a ``pshell`` environment by
+ default. It is the application registry object.
+
+- Add support for json on GAE by catching ``NotImplementedError`` and
+ importing simplejson from django.utils.
+
+- Add ``pyramid.httpexceptions`` module, which is a facade for the
+ ``webob.exc`` module.
+
+- New class: ``pyramid.response.Response``. This is a pure facade for
+ ``webob.Response`` (old code need not change to use this facade, it's
+ existence is mostly for vanity and documentation-generation purposes).
+
+- The request now has a new attribute: ``tmpl_context`` for benefit of
+ Pylons users.
+
+- New interface: ``pyramid.interfaces.IRendererInfo``. An object of this type
+ is passed to renderer factory constructors (see "Backwards
+ Incompatibilities").
+
+- New API method: ``pyramid.settings.asbool``.
+
+- New API methods for ``pyramid.request.Request``: ``model_url``,
+ ``route_url``, and ``static_url``. These are simple passthroughs for their
+ respective functions in ``pyramid.url``.
+
+Backwards Incompatibilities
+---------------------------
+
+- When a ``pyramid.exceptions.Forbidden`` error is raised, its status code
+ now ``403 Forbidden``. It was previously ``401 Unauthorized``, for
+ backwards compatibility purposes with ``repoze.bfg``. This change will
+ cause problems for users of Pyramid with ``repoze.who``, which intercepts
+ ``401 Unauthorized`` by default, but allows ``403 Forbidden`` to pass
+ through. Those deployments will need to configure ``repoze.who`` to also
+ react to ``403 Forbidden``.
+
+- ``paster bfgshell`` is now known as ``paster pshell``.
+
+- There is no longer an ``IDebugLogger`` registered as a named utility
+ with the name ``repoze.bfg.debug``.
+
+- The logger which used to have the name of ``repoze.bfg.debug`` now
+ has the name ``pyramid.debug``.
+
+- The deprecated API ``pyramid.testing.registerViewPermission``
+ has been removed.
+
+- The deprecated API named ``pyramid.testing.registerRoutesMapper``
+ has been removed.
+
+- The deprecated API named ``pyramid.request.get_request`` was removed.
+
+- The deprecated API named ``pyramid.security.Unauthorized`` was
+ removed.
+
+- The deprecated API named ``pyramid.view.view_execution_permitted``
+ was removed.
+
+- The deprecated API named ``pyramid.view.NotFound`` was removed.
+
+- The ``bfgshell`` paster command is now named ``pshell``.
+
+- The Venusian "category" for all built-in Venusian decorators
+ (e.g. ``subscriber`` and ``view_config``/``bfg_view``) is now
+ ``pyramid`` instead of ``bfg``.
+
+- ``pyramid.renderers.rendered_response`` function removed; use
+ ``render_pyramid.renderers.render_to_response`` instead.
+
+- Renderer factories now accept a *renderer info object* rather than an
+ absolute resource specification or an absolute path. The object has the
+ following attributes: ``name`` (the ``renderer=`` value), ``package`` (the
+ 'current package' when the renderer configuration statement was found),
+ ``type``: the renderer type, ``registry``: the current registry, and
+ ``settings``: the deployment settings dictionary.
+
+ Third-party ``repoze.bfg`` renderer implementations that must be ported to
+ Pyramid will need to account for this.
+
+ This change was made primarily to support more flexible Mako template
+ rendering.
+
+- The presence of the key ``repoze.bfg.message`` in the WSGI environment when
+ an exception occurs is now deprecated. Instead, code which relies on this
+ environ value should use the ``exception`` attribute of the request
+ (e.g. ``request.exception[0]``) to retrieve the message.
+
+- The values ``bfg_localizer`` and ``bfg_locale_name`` kept on the request
+ during internationalization for caching purposes were never APIs. These
+ however have changed to ``localizer`` and ``locale_name``, respectively.
+
+- The default ``cookie_name`` value of the ``authtktauthenticationpolicy`` ZCML
+ now defaults to ``auth_tkt`` (it used to default to ``repoze.bfg.auth_tkt``).
+
+- The default ``cookie_name`` value of the
+ ``pyramid.authentication.AuthTktAuthenticationPolicy`` constructor now
+ defaults to ``auth_tkt`` (it used to default to ``repoze.bfg.auth_tkt``).
+
+- The ``request_type`` argument to the ``view`` ZCML directive, the
+ ``pyramid.configuration.Configurator.add_view`` method, or the
+ ``pyramid.view.view_config`` decorator (nee ``bfg_view``) is no longer
+ permitted to be one of the strings ``GET``, ``HEAD``, ``PUT``, ``POST`` or
+ ``DELETE``, and now must always be an interface. Accepting the
+ method-strings as ``request_type`` was a backwards compatibility strategy
+ servicing repoze.bfg 1.0 applications. Use the ``request_method``
+ parameter instead to specify that a view a string request-method predicate.
+
+- The ``pyramid.testing.zcml_configure`` API has been removed. It had been
+ advertised as removed since repoze.bfg 1.2a1, but hadn't actually been.
+
+- All environment variables which used to be prefixed with ``BFG_`` are now
+ prefixed with ``PYRAMID_`` (e.g. ``BFG_DEBUG_NOTFOUND`` is now
+ ``PYRAMID_DEBUG_NOTFOUND``)
+
+- Since the ``pyramid.interfaces.IAuthenticationPolicy`` interface now
+ specifies that a policy implementation must implement an
+ ``unauthenticated_userid`` method, all third-party custom authentication
+ policies now must implement this method. It, however, will only be called
+ when the global function named ``pyramid.security.unauthenticated_userid``
+ is invoked, so if you're not invoking that, you will not notice any issues.
+
+- The ``configure_zcml`` setting within the deployment settings (within
+ ``**settings`` passed to a Pyramid ``main`` function) has ceased to have any
+ meaning.
+
+Deprecations and Behavior Differences
+-------------------------------------
+
+- The ``pyramid.settings.get_settings`` API is now deprecated. Use
+ ``pyramid.threadlocals.get_current_registry().settings`` instead or use the
+ ``settings`` attribute of the registry available from the request
+ (``request.registry.settings``).
+
+- The decorator previously known as ``pyramid.view.bfg_view`` is now
+ known most formally as ``pyramid.view.view_config`` in docs and
+ paster templates.
+
+- Obtaining the ``settings`` object via
+ ``registry.{get|query}Utility(ISettings)`` is now deprecated. Instead,
+ obtain the ``settings`` object via the ``registry.settings`` attribute. A
+ backwards compatibility shim was added to the registry object to register
+ the settings object as an ISettings utility when ``setattr(registry,
+ 'settings', foo)`` is called, but it will be removed in a later release.
+
+- Obtaining the ``settings`` object via ``pyramid.settings.get_settings`` is
+ now deprecated. Obtain it as the ``settings`` attribute of the registry
+ now (obtain the registry via ``pyramid.threadlocal.get_registry`` or as
+ ``request.registry``).
+
+- ``pyramid.configuration.Configurator`` is now deprecated. Use
+ ``pyramid.config.Configurator``, passing its constructor
+ ``autocommit=True`` instead. The ``pyramid.configuration.Configurator``
+ alias will live for a long time, as every application uses it, but its
+ import now issues a deprecation warning. The
+ ``pyramid.config.Configurator`` class has the same API as
+ ``pyramid.configuration.Configurator`` class, which it means to replace,
+ except by default it is a *non-autocommitting* configurator. The
+ now-deprecated ``pyramid.configuration.Configurator`` will autocommit every
+ time a configuration method is called. The ``pyramid.configuration``
+ module remains, but it is deprecated. Use ``pyramid.config`` instead.
+
+Dependency Changes
+------------------
+
+- Depend on Venusian >= 0.5 (for scanning conflict exception decoration).
+
+Documentation Enhancements
+--------------------------
+
+- Added a ``pyramid.httpexceptions`` API documentation chapter.
+
+- Added a ``pyramid.session`` API documentation chapter.
+
+- Added a ``Session Objects`` narrative documentation chapter.
+
+- Added an API chapter for the ``pyramid.personality`` module.
+
+- Added an API chapter for the ``pyramid.response`` module.
+
+- All documentation which previously referred to ``webob.Response`` now uses
+ ``pyramid.response.Response`` instead.
+
+- The documentation has been overhauled to use imperative configuration,
+ moving declarative configuration (ZCML) explanations to a separate
+ narrative chapter ``declarative.rst``.
+
+- The ZODB Wiki tutorial was updated to take into account changes to the
+ ``pyramid_zodb`` paster template.
+
+- The SQL Wiki tutorial was updated to take into account changes to the
+ ``pyramid_routesalchemy`` paster template.
+
+- Removed ``zodbsessions`` tutorial chapter. It's still useful, but we now
+ have a SessionFactory abstraction which competes with it, and maintaining
+ documentation on both ways to do it is a distraction.
+
+- Merged many wording, readability, and correctness changes to narrative
+ documentation chapters from https://github.com/caseman/pyramid (up to and
+ including "Models" narrative chapter).
+
+- "Sample Applications" section of docs changed to note existence of Cluegun,
+ Shootout and Virginia sample applications, ported from their repoze.bfg
+ origin packages.
+
+- Add ``pyramid.interfaces.ITemplateRenderer`` interface to Interfaces API
+ chapter (has ``implementation()`` method, required to be used when getting
+ at Chameleon macros).
+
+- Add a "Modifying Package Structure" section to the project narrative
+ documentation chapter (explain turning a module into a package).
+
+- Added "Debugging Route Matching" section to the urldispatch narrative
+ documentation chapter.
+
+- Added reference to ``PYRAMID_DEBUG_ROUTEMATCH`` envvar and
+ ``debug_routematch`` config file setting to the Environment narrative docs
+ chapter.
+
+- Direct Jython users to Mako rather than Jinja2 in "Install" narrative
+ chapter.
+
+- Added an example of ``WebTest`` functional testing to the testing narrative
+ chapter.
+
+- Rearranged chapter ordering by popular demand (URL dispatch first, then
+ traversal). Put hybrid chapter after views chapter.
+
+- Split off "Renderers" as its own chapter from "Views" chapter in narrative
+ documentation.
+
+- Added "Generating The URL Of A Resource" section to the Resources narrative
+ chapter (includes information about overriding URL generation using
+ ``__resource_url__``).
+
+- Added "Generating the Path To a Resource" section to the Resources
+ narrative chapter.
+
+- Added "Finding a Resource by Path" section to the Resources narrative
+ chapter.
+
+- Added "Obtaining the Lineage of a Resource" to the Resources narrative
+ chapter.
+
+- Added "Determining if a Resource is In The Lineage of Another Resource" to
+ Resources narrative chapter.
+
+- Added "Finding the Root Resource" to Resources narrative chapter.
+
+- Added "Finding a Resource With a Class or Interface in Lineage" to
+ Resources narrative chapter.
+
+- Added a "Flash Messaging" narrative documentation chapter.
+
+- Added a narrative chapter entitled "Preventing Cross-Site Request Forgery
+ Attacks".
+
+- Changed the "ZODB + Traversal Wiki Tutorial" based on changes to
+ ``pyramid_zodb`` Paster template.
+
+- Added "Advanced Configuration" narrative chapter which documents how to
+ deal with configuration conflicts, two-phase configuration, ``include`` and
+ ``commit``.
+
+- Add "Pyramid Provides More Than One Way to Do It" to Design Defense
+ documentation.
+
+- Added narrative documentation section within the "URL Dispatch" chapter
+ entitled "Displaying All Application Routes" (for ``paster proutes``
+ command).
+
+- The (weak) "Converting a CMF Application to Pyramid" tutorial has been
+ removed from the tutorials section. It was moved to the
+ ``pyramid_tutorials`` Github repository.
+
+- Split views chapter into 2: View Callables and View Configuration.
+
+- Reorder Renderers and Templates chapters after View Callables but before
+ View Configuration.
+
diff --git a/docs/zcml.rst b/docs/zcml.rst
deleted file mode 100644
index e5bbe5d4b..000000000
--- a/docs/zcml.rst
+++ /dev/null
@@ -1,33 +0,0 @@
-.. _zcml_directives:
-
-ZCML Directives
-===============
-
-Comprehensive reference material for every ZCML directive provided by
-:app:`Pyramid` is available within this chapter. The ZCML directive
-documentation is organized alphabetically by directive name.
-
-.. toctree::
- :maxdepth: 1
-
- zcml/aclauthorizationpolicy
- zcml/adapter
- zcml/authtktauthenticationpolicy
- zcml/asset
- zcml/configure
- zcml/default_permission
- zcml/forbidden
- zcml/handler
- zcml/include
- zcml/localenegotiator
- zcml/notfound
- zcml/remoteuserauthenticationpolicy
- zcml/renderer
- zcml/repozewho1authenticationpolicy
- zcml/route
- zcml/scan
- zcml/static
- zcml/subscriber
- zcml/translationdir
- zcml/utility
- zcml/view
diff --git a/docs/zcml/aclauthorizationpolicy.rst b/docs/zcml/aclauthorizationpolicy.rst
deleted file mode 100644
index f09531415..000000000
--- a/docs/zcml/aclauthorizationpolicy.rst
+++ /dev/null
@@ -1,35 +0,0 @@
-.. _aclauthorizationpolicy_directive:
-
-``aclauthorizationpolicy``
---------------------------
-
-When this directive is used, authorization information is obtained
-from :term:`ACL` objects attached to :term:`resource` objects.
-
-Attributes
-~~~~~~~~~~
-
-None.
-
-Example
-~~~~~~~
-
-.. code-block:: xml
- :linenos:
-
- <aclauthorizationpolicy/>
-
-Alternatives
-~~~~~~~~~~~~
-
-You may create an instance of the
-:class:`pyramid.authorization.ACLAuthorizationPolicy` and pass it
-to the :class:`pyramid.config.Configurator` constructor as
-the ``authorization_policy`` argument during initial application
-configuration.
-
-See Also
-~~~~~~~~
-
-See also :ref:`authorization_policies_directives_section` and
-:ref:`security_chapter`.
diff --git a/docs/zcml/adapter.rst b/docs/zcml/adapter.rst
deleted file mode 100644
index 83cce0c39..000000000
--- a/docs/zcml/adapter.rst
+++ /dev/null
@@ -1,47 +0,0 @@
-.. _adapter_directive:
-
-``adapter``
------------
-
-Register a :term:`Zope Component Architecture` "adapter".
-
-Attributes
-~~~~~~~~~~
-
-``factory``
- The adapter factory (often a class).
-
-``provides``
- The :term:`interface` that an adapter instance resulting from a
- lookup will provide.
-
-``for``
- Interfaces or classes to be adapted, separated by spaces,
- e.g. ``interfaces.IFoo interfaces.IBar``.
-
-``name``
- The adapter name.
-
-Example
-~~~~~~~
-
-.. code-block:: xml
- :linenos:
-
- <adapter
- for=".foo.IFoo .bar.IBar"
- provides=".interfaces.IMyAdapter"
- factory=".adapters.MyAdapter"
- />
-
-Alternatives
-~~~~~~~~~~~~
-
-Use the ``registerAdapter`` method of the ``registry`` attribute of a
-:term:`Configurator` instance during initial application setup.
-
-See Also
-~~~~~~~~
-
-None.
-
diff --git a/docs/zcml/asset.rst b/docs/zcml/asset.rst
deleted file mode 100644
index af7a6db94..000000000
--- a/docs/zcml/asset.rst
+++ /dev/null
@@ -1,65 +0,0 @@
-.. _asset_directive:
-
-``asset``
----------
-
-The ``asset`` directive adds an asset override for a single
-static file/directory asset.
-
-Attributes
-~~~~~~~~~~
-
-``to_override``
- A :term:`asset specification` specifying the asset to be
- overridden.
-
-``override_with``
- A :term:`asset specification` specifying the asset which
- is used as the override.
-
-Examples
-~~~~~~~~
-
-.. topic:: Overriding a Single Asset File
-
- .. code-block:: xml
- :linenos:
-
- <asset
- to_override="some.package:templates/mytemplate.pt"
- override_with="another.package:othertemplates/anothertemplate.pt"
- />
-
-.. topic:: Overriding all Assets in a Package
-
- .. code-block:: xml
- :linenos:
-
- <asset
- to_override="some.package"
- override_with="another.package"
- />
-
-.. topic:: Overriding all Assets in a Subdirectory of a Package
-
- .. code-block:: xml
- :linenos:
-
- <asset
- to_override="some.package:templates/"
- override_with="another.package:othertemplates/"
- />
-
-Alternatives
-~~~~~~~~~~~~
-
-The :meth:`pyramid.config.Configurator.override_asset`
-method can be used instead of the ``resource`` ZCML directive.
-
-This directive can also be invoked as the ``resource`` ZCML directive for
-backwards compatibility purposes.
-
-See Also
-~~~~~~~~
-
-See also :ref:`asset_zcml_directive`.
diff --git a/docs/zcml/authtktauthenticationpolicy.rst b/docs/zcml/authtktauthenticationpolicy.rst
deleted file mode 100644
index 25be4186c..000000000
--- a/docs/zcml/authtktauthenticationpolicy.rst
+++ /dev/null
@@ -1,102 +0,0 @@
-.. _authtktauthenticationpolicy_directive:
-
-``authtktauthenticationpolicy``
--------------------------------
-
-When this directive is used, authentication information is obtained
-from an :mod:`paste.auth.auth_tkt` cookie value, assumed to be set by
-a custom login form.
-
-Attributes
-~~~~~~~~~~
-
-``secret``
- The ``secret`` is a string that will be used to sign the data
- stored by the cookie. It is required and has no default.
-
-``callback``
- The ``callback`` is a Python dotted name to a function passed the
- string representing the userid stored in the cookie and the
- request as positional arguments. The callback is expected to
- return None if the user represented by the string doesn't exist or
- a sequence of group identifiers (possibly empty) if the user does
- exist. If ``callback`` is None, the userid will be assumed to
- exist with no groups. It defaults to ``None``.
-
-``cookie_name``
- The ``cookie_name`` is the name used for the cookie that contains
- the user information. It defaults to ``auth_tkt``.
-
-``secure``
- ``secure`` is a boolean value. If it's set to "true", the cookie
- will only be sent back by the browser over a secure (HTTPS)
- connection. It defaults to "false".
-
-``include_ip``
- ``include_ip`` is a boolean value. If it's set to true, the
- requesting IP address is made part of the authentication data in
- the cookie; if the IP encoded in the cookie differs from the IP of
- the requesting user agent, the cookie is considered invalid. It
- defaults to "false".
-
-``timeout``
- ``timeout`` is an integer value. It represents the maximum age in
- seconds which the auth_tkt ticket will be considered valid. If
- ``timeout`` is specified, and ``reissue_time`` is also specified,
- ``reissue_time`` must be a smaller value than ``timeout``. It
- defaults to ``None``, meaning that the ticket will be considered
- valid forever.
-
-``reissue_time``
- ``reissue_time`` is an integer value. If ``reissue_time`` is
- specified, when we encounter a cookie that is older than the
- reissue time (in seconds), but younger that the ``timeout``, a new
- cookie will be issued. It defaults to ``None``, meaning that
- authentication cookies are never reissued. A value of ``0`` means
- reissue a cookie in the response to every request that requires
- authentication.
-
-``max_age``
- ``max_age`` is the maximum age of the auth_tkt *cookie*, in
- seconds. This differs from ``timeout`` inasmuch as ``timeout``
- represents the lifetime of the ticket contained in the cookie,
- while this value represents the lifetime of the cookie itself.
- When this value is set, the cookie's ``Max-Age`` and ``Expires``
- settings will be set, allowing the auth_tkt cookie to last between
- browser sessions. It is typically nonsensical to set this to a
- value that is lower than ``timeout`` or ``reissue_time``, although
- it is not explicitly prevented. It defaults to ``None``, meaning
- (on all major browser platforms) that auth_tkt cookies will last
- for the lifetime of the user's browser session.
-
-Example
-~~~~~~~
-
-.. code-block:: xml
- :linenos:
-
- <authtktauthenticationpolicy
- secret="goshiamsosecret"
- callback=".somemodule.somefunc"
- cookie_name="mycookiename"
- secure="false"
- include_ip="false"
- timeout="86400"
- reissue_time="600"
- max_age="31536000"
- />
-
-Alternatives
-~~~~~~~~~~~~
-
-You may create an instance of the
-:class:`pyramid.authentication.AuthTktAuthenticationPolicy` and
-pass it to the :class:`pyramid.config.Configurator`
-constructor as the ``authentication_policy`` argument during initial
-application configuration.
-
-See Also
-~~~~~~~~
-
-See also :ref:`authentication_policies_directives_section` and
-:class:`pyramid.authentication.AuthTktAuthenticationPolicy`.
diff --git a/docs/zcml/configure.rst b/docs/zcml/configure.rst
deleted file mode 100644
index cab8ec204..000000000
--- a/docs/zcml/configure.rst
+++ /dev/null
@@ -1,95 +0,0 @@
-.. _configure_directive:
-
-``configure``
--------------
-
-Because :term:`ZCML` is XML, and because XML requires a single root
-tag for each document, every ZCML file used by :app:`Pyramid` must
-contain a ``configure`` container directive, which acts as the root
-XML tag. It is a "container" directive because its only job is to
-contain other directives.
-
-Attributes
-~~~~~~~~~~
-
-``xmlns``
- The default XML namespace used for subdirectives.
-
-Example
-~~~~~~~
-
-.. code-block:: xml
- :linenos:
-
- <configure xmlns="http://pylonshq.com/pyramid">
-
- <!-- other directives -->
-
- </configure>
-
-.. _word_on_xml_namespaces:
-
-A Word On XML Namespaces
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-Usually, the start tag of the ``<configure>`` container tag has a
-default *XML namespace* associated with it. This is usually
-``http://pylonshq.com/pyramid``, named by the ``xmlns`` attribute of
-the ``configure`` start tag.
-
-Using the ``http://pylonshq.com/pyramid`` namespace as the default XML
-namespace isn't strictly necessary; you can use a different default
-namespace as the default. However, if you do, the declaration tags
-which are defined by :app:`Pyramid` such as the ``view`` declaration
-tag will need to be defined in such a way that the XML parser that
-:app:`Pyramid` uses knows which namespace the :mod:`pyramid` tags are
-associated with. For example, the following files are all completely
-equivalent:
-
-.. topic:: Use of A Non-Default XML Namespace
-
- .. code-block:: xml
- :linenos:
-
- <configure xmlns="http://namespaces.zope.org/zope"
- xmlns:pyramid="http://pylonshq.com/pyramid">
-
- <include package="pyramid.includes" />
-
- <pyramid:view
- view="helloworld.hello_world"
- />
-
- </configure>
-
-.. topic:: Use of A Per-Tag XML Namespace Without A Default XML Namespace
-
- .. code-block:: xml
- :linenos:
-
- <configure>
-
- <include package="pyramid.includes" />
-
- <view xmlns="http://pylonshq.com/pyramid"
- view="helloworld.hello_world"
- />
-
- </configure>
-
-For more information about XML namespaces, see `this older, but simple
-XML.com article <http://www.xml.com/pub/a/1999/01/namespaces.html>`_.
-
-The conventions in this document assume that the default XML namespace
-is ``http://pylonshq.com/pyramid``.
-
-Alternatives
-~~~~~~~~~~~~
-
-None.
-
-See Also
-~~~~~~~~
-
-See also :ref:`helloworld_declarative`.
-
diff --git a/docs/zcml/default_permission.rst b/docs/zcml/default_permission.rst
deleted file mode 100644
index 54e720ea6..000000000
--- a/docs/zcml/default_permission.rst
+++ /dev/null
@@ -1,57 +0,0 @@
-.. _default_permission_directive:
-
-``default_permission``
--------------------------------
-
-Set the default permission to be used by all :term:`view
-configuration` registrations.
-
-This directive accepts a single attribute ,``name``, which should be
-used as the default permission string. An example of a permission
-string: ``view``. Adding a default permission makes it unnecessary to
-protect each view configuration with an explicit permission, unless
-your application policy requires some exception for a particular view.
-
-If a default permission is *not* set, views represented by view
-configuration registrations which do not explicitly declare a
-permission will be executable by entirely anonymous users (any
-authorization policy is ignored).
-
-There can be only one default permission active at a time within an
-application, thus the ``default_permission`` directive can only be
-used once in any particular set of ZCML.
-
-Attributes
-~~~~~~~~~~
-
-``name``
- Must be a string representing a :term:`permission`,
- e.g. ``view``.
-
-
-Example
-~~~~~~~
-
-.. code-block:: xml
- :linenos:
-
- <default_permission
- name="view"
- />
-
-Alternatives
-~~~~~~~~~~~~
-
-Using the ``default_permission`` argument to the
-:class:`pyramid.config.Configurator` constructor can be used
-to achieve the same purpose.
-
-Using the
-:meth:`pyramid.config.Configurator.set_default_permission`
-method can be used to achieve the same purpose when using imperative
-configuration.
-
-See Also
-~~~~~~~~
-
-See also :ref:`setting_a_default_permission`.
diff --git a/docs/zcml/forbidden.rst b/docs/zcml/forbidden.rst
deleted file mode 100644
index 70f65069e..000000000
--- a/docs/zcml/forbidden.rst
+++ /dev/null
@@ -1,78 +0,0 @@
-.. _forbidden_directive:
-
-``forbidden``
--------------
-
-When :app:`Pyramid` can't authorize execution of a view based on
-the :term:`authorization policy` in use, it invokes a :term:`forbidden
-view`. The default forbidden response has a 401 status code and is
-very plain, but it can be overridden as necessary using the
-``forbidden`` ZCML directive.
-
-.. warning::
-
- The ``forbidden`` ZCML directive is deprecated in :app:`Pyramid`
- version 1.3. Instead, you should use the :ref:`view_directive`
- directive with a ``context`` that names the
- :exc:`pyramid.exceptions.Forbidden` class. See
- :ref:`changing_the_forbidden_view` form more information.
-
-Attributes
-~~~~~~~~~~
-
-``view``
- The :term:`dotted Python name` to a :term:`view callable`. This
- attribute is required unless a ``renderer`` attribute also exists.
- If a ``renderer`` attribute exists on the directive, this attribute
- defaults to a view that returns an empty dictionary (see
- :ref:`views_which_use_a_renderer`).
-
-``attr``
- The attribute of the view callable to use if ``__call__`` is not
- correct (has the same meaning as in the context of
- :ref:`view_directive`; see the description of ``attr``
- there).
-
-``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``) 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
- description of ``renderer`` there).
-
-``wrapper``
- The :term:`view name` (*not* an object dotted name) of another view
- declared elsewhere in ZCML (or via the ``@view_config`` decorator)
- which will receive the response body of this view as the
- ``request.wrapped_body`` attribute of its own request, and the
- response returned by this view as the ``request.wrapped_response``
- attribute of its own request. This attribute has the same meaning
- as it would in the context of :ref:`view_directive`; see the
- description of ``wrapper`` there). Note that the wrapper view
- *should not* be protected by any permission; behavior is undefined
- if it does.
-
-Example
-~~~~~~~
-
-.. code-block:: xml
- :linenos:
-
- <forbidden
- view="helloworld.views.forbidden_view"/>
-
-Alternatives
-~~~~~~~~~~~~
-
-Use the :ref:`view_directive` directive with a ``context`` that names
-the :exc:`pyramid.exceptions.Forbidden` class.
-
-Use the :meth:`pyramid.config.Configurator.add_view` method,
-passing it a ``context`` which is the
-:exc:`pyramid.exceptions.Forbidden` class.
-
-See Also
-~~~~~~~~
-
-See also :ref:`changing_the_forbidden_view`.
diff --git a/docs/zcml/handler.rst b/docs/zcml/handler.rst
deleted file mode 100644
index 64aac7e78..000000000
--- a/docs/zcml/handler.rst
+++ /dev/null
@@ -1,158 +0,0 @@
-.. _handler_directive:
-
-``handler``
------------
-
-The ``handler`` directive adds the configuration of a :term:`view handler` to
-the :term:`application registry`.
-
-Attributes
-~~~~~~~~~~
-
-``route_name``
- The name of the route, e.g. ``myroute``. This attribute is required. It
- must be unique among all defined handler and route names in a given
- configuration.
-
-``pattern``
- The pattern of the route e.g. ``ideas/{idea}``. This attribute is
- required. See :ref:`route_pattern_syntax` for information about the syntax
- of route patterns. The name ``{action}`` is treated specially in handler
- patterns. See :ref:`using_add_handler` for a discussion of how
- ``{action}`` in handler patterns is treated.
-
-``action``
- If the action name is not specified in the ``pattern``, use this name as the
- handler action (method name).
-
-``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.resources.MyResource``. If this argument is not
- specified, a default root factory will be used.
-
-``xhr``
- This value should be either ``True`` or ``False``. If this value is
- specified and is ``True``, the :term:`request` must possess an
- ``HTTP_X_REQUESTED_WITH`` (aka ``X-Requested-With``) header for this
- route to match. This is useful for detecting AJAX requests issued
- from jQuery, Prototype and other Javascript libraries. If this
- predicate returns false, route matching continues.
-
-``traverse``
- If you would like to cause the :term:`context` to be something other
- than the :term:`root` object when this route matches, you can spell
- a traversal pattern as the ``traverse`` argument. This traversal
- pattern will be used as the traversal path: traversal will begin at
- the root object implied by this route (either the global root, or
- the object returned by the ``factory`` associated with this route).
-
- The syntax of the ``traverse`` argument is the same as it is for
- ``pattern``. For example, if the ``pattern`` provided to the
- ``route`` directive is ``articles/{article}/edit``, and the
- ``traverse`` argument provided to the ``route`` directive is
- ``/{article}``, when a request comes in that causes the route to
- match in such a way that the ``article`` match value is '1' (when
- the request URI is ``/articles/1/edit``), the traversal path will be
- generated as ``/1``. This means that the root object's
- ``__getitem__`` will be called with the name ``1`` during the
- traversal phase. If the ``1`` object exists, it will become the
- :term:`context` of the request. :ref:`traversal_chapter` has more
- information about traversal.
-
- If the traversal path contains segment marker names which are not
- present in the ``pattern`` argument, a runtime error will occur.
- The ``traverse`` pattern should not contain segment markers that do
- not exist in the ``pattern``.
-
- A similar combining of routing and traversal is available when a
- route is matched which contains a ``*traverse`` remainder marker in
- its ``pattern`` (see :ref:`using_traverse_in_a_route_pattern`). The
- ``traverse`` argument to the ``route`` directive allows you to
- associate route patterns with an arbitrary traversal path without
- using a a ``*traverse`` remainder marker; instead you can use other
- match information.
-
- Note that the ``traverse`` argument to the ``handler`` directive is
- ignored when attached to a route that has a ``*traverse`` remainder
- marker in its pattern.
-
-``request_method``
- A string representing an HTTP method name, e.g. ``GET``, ``POST``,
- ``HEAD``, ``DELETE``, ``PUT``. If this argument is not specified,
- this route will match if the request has *any* request method. If
- this predicate returns false, route matching continues.
-
-``path_info``
- The value of this attribute represents a regular expression pattern
- that will be tested against the ``PATH_INFO`` WSGI environment
- variable. If the regex matches, this predicate will be true. If
- this predicate returns false, route matching continues.
-
-``request_param``
- This value can be any string. A view declaration with this
- attribute ensures that the associated route will only match when the
- request has a key in the ``request.params`` dictionary (an HTTP
- ``GET`` or ``POST`` variable) that has a name which matches the
- supplied value. If the value supplied to the attribute has a ``=``
- sign in it, e.g. ``request_params="foo=123"``, then the key
- (``foo``) must both exist in the ``request.params`` dictionary, and
- the value must match the right hand side of the expression (``123``)
- for the route to "match" the current request. If this predicate
- returns false, route matching continues.
-
-``header``
- The value of this attribute represents an HTTP header name or a
- header name/value pair. If the value contains a ``:`` (colon), it
- will be considered a name/value pair (e.g. ``User-Agent:Mozilla/.*``
- or ``Host:localhost``). The *value* of an attribute that represent
- a name/value pair should be a regular expression. If the value does
- not contain a colon, the entire value will be considered to be the
- header name (e.g. ``If-Modified-Since``). If the value evaluates to
- a header name only without a value, the header specified by the name
- must be present in the request for this predicate to be true. If
- the value evaluates to a header name/value pair, the header
- specified by the name must be present in the request *and* the
- regular expression specified as the value must match the header
- value. Whether or not the value represents a header name or a
- header name/value pair, the case of the header name is not
- significant. If this predicate returns false, route matching
- continues.
-
-``accept``
- The value of this attribute represents a match query for one or more
- mimetypes in the ``Accept`` HTTP request header. If this value is
- specified, it must be in one of the following forms: a mimetype
- match token in the form ``text/plain``, a wildcard mimetype match
- token in the form ``text/*`` or a match-all wildcard mimetype match
- token in the form ``*/*``. If any of the forms matches the
- ``Accept`` header of the request, this predicate will be true. If
- this predicate returns false, route matching continues.
-
-``custom_predicates``
- This value should be a sequence of references to custom predicate
- callables. Use custom predicates when no set of predefined
- predicates does what you need. Custom predicates can be combined
- with predefined predicates as necessary. Each custom predicate
- callable should accept two arguments: ``info`` and ``request``
- and should return either ``True`` or ``False`` after doing arbitrary
- evaluation of the info and/or the request. If all custom and
- non-custom predicate callables return ``True`` the associated route
- will be considered viable for a given request. If any predicate
- callable returns ``False``, route matching continues. Note that the
- value ``info`` passed to a custom route predicate is a dictionary
- containing matching information; see :ref:`custom_route_predicates`
- for more information about ``info``.
-
-
-Alternatives
-~~~~~~~~~~~~
-
-You can also add a :term:`route configuration` via:
-
-- Using the :meth:`pyramid.config.Configurator.add_handler` method.
-
-See Also
-~~~~~~~~
-
-See also :ref:`views_chapter`.
diff --git a/docs/zcml/include.rst b/docs/zcml/include.rst
deleted file mode 100644
index f55caa07c..000000000
--- a/docs/zcml/include.rst
+++ /dev/null
@@ -1,71 +0,0 @@
-.. _include_directive:
-
-``include``
------------
-
-The ``include`` directive includes configuration from an external ZCML
-file. Use of the ``include`` tag allows a user to split configuration
-across multiple ZCML files, and allows package distributors to provide
-default ZCML configuration for specific purposes which can be
-included by the integrator of the package as necessary.
-
-Attributes
-~~~~~~~~~~
-
-``package``
- A :term:`dotted Python name` which references a Python :term:`package`.
-
-``file``
- An absolute or relative filename which references a ZCML file.
-
-The ``package`` and ``file`` attributes can be used together or
-separately as necessary.
-
-Examples
-~~~~~~~~
-
-.. topic:: Loading the File Named ``configure.zcml`` from a Package Implicitly
-
- .. code-block:: xml
- :linenos:
-
- <include package="some.package" />
-
-.. topic:: Loading the File Named ``other.zcml`` From the Current Package
-
- .. code-block:: xml
- :linenos:
-
- <include file="other.zcml" />
-
-.. topic:: Loading a File From a Subdirectory of the Current Package
-
- .. code-block:: xml
- :linenos:
-
- <include file="subdir/other.zcml" />
-
-.. topic:: Loading the File Named ``/absolute/path/other.zcml``
-
- .. code-block:: xml
- :linenos:
-
- <include file="/absolute/path/other.zcml" />
-
-.. topic:: Loading the File Named ``other.zcml`` From a Package Explicitly
-
- .. code-block:: xml
- :linenos:
-
- <include package="some.package" file="other.zcml" />
-
-Alternatives
-~~~~~~~~~~~~
-
-None.
-
-See Also
-~~~~~~~~
-
-See also :ref:`helloworld_declarative`.
-
diff --git a/docs/zcml/localenegotiator.rst b/docs/zcml/localenegotiator.rst
deleted file mode 100644
index c90e649f6..000000000
--- a/docs/zcml/localenegotiator.rst
+++ /dev/null
@@ -1,39 +0,0 @@
-.. _localenegotiator_directive:
-
-``localenegotiator``
---------------------
-
-Set the :term:`locale negotiator` for the current configurator to
-support localization of text.
-
-Attributes
-~~~~~~~~~~
-
-``negotiator``
-
- The :term:`dotted Python name` to a :term:`locale negotiator`
- implementation. This attribute is required. If it begins with a
- dot (``.``), the name will be considered relative to the directory
- in which the ZCML file which contains this directive lives.
-
-Example
-~~~~~~~
-
-.. code-block:: xml
- :linenos:
-
- <localenegotiator
- negotiator="some.package.module.my_locale_negotiator"
- />
-
-Alternatives
-~~~~~~~~~~~~
-
-Use :meth:`pyramid.config.Configurator.set_locale_negotiator`
-method instance during initial application setup.
-
-See Also
-~~~~~~~~
-
-See also :ref:`activating_translation`.
-
diff --git a/docs/zcml/notfound.rst b/docs/zcml/notfound.rst
deleted file mode 100644
index 739eccd49..000000000
--- a/docs/zcml/notfound.rst
+++ /dev/null
@@ -1,78 +0,0 @@
-.. _notfound_directive:
-
-``notfound``
-------------
-
-.. warning::
-
- The ``notfound`` ZCML directive is deprecated in :app:`Pyramid`
- version 1.0. Instead, you should use the :ref:`view_directive`
- directive with a ``context`` that names the
- :exc:`pyramid.exceptions.NotFound` class. See
- :ref:`changing_the_notfound_view` form more information.
-
-When :app:`Pyramid` can't map a URL to view code, it invokes a
-:term:`not found view`. The default not found view is very plain, but
-the view callable used can be configured via the ``notfound`` ZCML
-tag.
-
-Attributes
-~~~~~~~~~~
-
-``view``
- The :term:`dotted Python name` to a :term:`view callable`. This
- attribute is required unless a ``renderer`` attribute also exists.
- If a ``renderer`` attribute exists on the directive, this attribute
- defaults to a view that returns an empty dictionary (see
- :ref:`views_which_use_a_renderer`).
-
-``attr``
- The attribute of the view callable to use if ``__call__`` is not
- correct (has the same meaning as in the context of
- :ref:`view_directive`; see the description of ``attr``
- there).
-
-``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``) 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
- description of ``renderer`` there).
-
-``wrapper``
- The :term:`view name` (*not* an object dotted name) of another view
- declared elsewhere in ZCML (or via the ``@view_config`` decorator)
- which will receive the response body of this view as the
- ``request.wrapped_body`` attribute of its own request, and the
- response returned by this view as the ``request.wrapped_response``
- attribute of its own request. This attribute has the same meaning
- as it would in the context of :ref:`view_directive`; see
- the description of ``wrapper`` there). Note that the wrapper view
- *should not* be protected by any permission; behavior is undefined
- if it does.
-
-Example
-~~~~~~~
-
-.. code-block:: xml
- :linenos:
-
- <notfound
- view="helloworld.views.notfound_view"/>
-
-Alternatives
-~~~~~~~~~~~~
-
-Use the :ref:`view_directive` directive with a ``context`` that names
-the :exc:`pyramid.exceptions.NotFound` class.
-
-Use the :meth:`pyramid.config.Configurator.add_view` method,
-passing it a ``context`` which is the
-:exc:`pyramid.exceptions.NotFound` class.
-
-See Also
-~~~~~~~~
-
-See also :ref:`changing_the_notfound_view`.
-
diff --git a/docs/zcml/remoteuserauthenticationpolicy.rst b/docs/zcml/remoteuserauthenticationpolicy.rst
deleted file mode 100644
index 56e73ee7a..000000000
--- a/docs/zcml/remoteuserauthenticationpolicy.rst
+++ /dev/null
@@ -1,51 +0,0 @@
-.. _remoteuserauthenticationpolicy_directive:
-
-``remoteuserauthenticationpolicy``
-----------------------------------
-
-When this directive is used, authentication information is obtained
-from a ``REMOTE_USER`` key in the WSGI environment, assumed to
-be set by a WSGI server or an upstream middleware component.
-
-Attributes
-~~~~~~~~~~
-
-``environ_key``
- The ``environ_key`` is the name that will be used to obtain the
- remote user value from the WSGI environment. It defaults to
- ``REMOTE_USER``.
-
-``callback``
- The ``callback`` is a Python dotted name to a function passed the
- string representing the remote user and the request as positional
- arguments. The callback is expected to return None if the user
- represented by the string doesn't exist or a sequence of group
- identifiers (possibly empty) if the user does exist. If
- ``callback`` is None, the userid will be assumed to exist with no
- groups. It defaults to ``None``.
-
-Example
-~~~~~~~
-
-.. code-block:: xml
- :linenos:
-
- <remoteuserauthenticationpolicy
- environ_key="REMOTE_USER"
- callback=".somemodule.somefunc"
- />
-
-Alternatives
-~~~~~~~~~~~~
-
-You may create an instance of the
-:class:`pyramid.authentication.RemoteUserAuthenticationPolicy` and
-pass it to the :class:`pyramid.config.Configurator`
-constructor as the ``authentication_policy`` argument during initial
-application configuration.
-
-See Also
-~~~~~~~~
-
-See also :ref:`authentication_policies_directives_section` and
-:class:`pyramid.authentication.RemoteUserAuthenticationPolicy`.
diff --git a/docs/zcml/renderer.rst b/docs/zcml/renderer.rst
deleted file mode 100644
index c7beead32..000000000
--- a/docs/zcml/renderer.rst
+++ /dev/null
@@ -1,51 +0,0 @@
-.. _renderer_directive:
-
-``renderer``
-------------
-
-The ``renderer`` ZCML directive can be used to override an existing
-existing :term:`renderer` or to add a new renderer.
-
-Attributes
-~~~~~~~~~~
-
-``factory``
- A :term:`dotted Python name` referencing a callable object that
- accepts a renderer name and returns a :term:`renderer` object.
-
-``name``
- The renderer name, which is a string.
-
-Examples
-~~~~~~~~
-
-.. topic:: Registering a Non-Template Renderer
-
- .. code-block:: xml
- :linenos:
-
- <renderer
- factory="some.renderer"
- name="mynewrenderer"
- />
-
-.. topic:: Registering a Template Renderer
-
- .. code-block:: xml
- :linenos:
-
- <renderer
- factory="some.jinja2.renderer"
- name=".jinja2"
- />
-
-Alternatives
-~~~~~~~~~~~~
-
-The :meth:`pyramid.config.Configurator.add_renderer` method
-is equivalent to the ``renderer`` ZCML directive.
-
-See Also
-~~~~~~~~
-
-See also :ref:`adding_and_overriding_renderers`.
diff --git a/docs/zcml/repozewho1authenticationpolicy.rst b/docs/zcml/repozewho1authenticationpolicy.rst
deleted file mode 100644
index 11907ce31..000000000
--- a/docs/zcml/repozewho1authenticationpolicy.rst
+++ /dev/null
@@ -1,53 +0,0 @@
-.. _repozewho1authenticationpolicy_directive:
-
-``repozewho1authenticationpolicy``
-----------------------------------
-
-When this directive is used, authentication information is obtained
-from a ``repoze.who.identity`` key in the WSGI environment, assumed to
-be set by :term:`repoze.who` middleware.
-
-Attributes
-~~~~~~~~~~
-
-``identifier_name``
- The ``identifier_name`` controls the name used to look up the
- :term:`repoze.who` "identifier" plugin within
- ``request.environ['repoze.who.plugins']`` which is used by this
- policy to "remember" and "forget" credentials. It defaults to
- ``auth_tkt``.
-
-``callback``
- The ``callback`` is a Python dotted name to a function passed the
- repoze.who identity and the request as positional arguments. The
- callback is expected to return None if the user represented by the
- identity doesn't exist or a sequence of group identifiers
- (possibly empty) if the user does exist. If ``callback`` is None,
- the userid will be assumed to exist with no groups. It defaults
- to ``None``.
-
-Example
-~~~~~~~
-
-.. code-block:: xml
- :linenos:
-
- <repozewho1authenticationpolicy
- identifier_name="auth_tkt"
- callback=".somemodule.somefunc"
- />
-
-Alternatives
-~~~~~~~~~~~~
-
-You may create an instance of the
-:class:`pyramid.authentication.RepozeWho1AuthenticationPolicy` and
-pass it to the :class:`pyramid.config.Configurator`
-constructor as the ``authentication_policy`` argument during initial
-application configuration.
-
-See Also
-~~~~~~~~
-
-See also :ref:`authentication_policies_directives_section` and
-:class:`pyramid.authentication.RepozeWho1AuthenticationPolicy`.
diff --git a/docs/zcml/route.rst b/docs/zcml/route.rst
deleted file mode 100644
index 0f94fa11b..000000000
--- a/docs/zcml/route.rst
+++ /dev/null
@@ -1,223 +0,0 @@
-.. _route_directive:
-
-``route``
----------
-
-The ``route`` directive adds a single :term:`route configuration` to
-the :term:`application registry`.
-
-Attributes
-~~~~~~~~~~
-
-``pattern``
- The pattern of the route e.g. ``ideas/{idea}``. This attribute is
- required. See :ref:`route_pattern_syntax` for information
- about the syntax of route patterns.
-
- .. note:: For backwards compatibility purposes, the ``path``
- attribute can also be used instead of ``pattern``.
-
-``name``
- The name of the route, e.g. ``myroute``. This attribute is
- required. It must be unique among all defined routes in a given
- configuration.
-
-``factory``
- The :term:`dotted Python name` to a function that will generate a
- :app:`Pyramid` context object when this route matches.
- e.g. ``mypackage.resources.MyResource``. If this argument is not
- specified, a default root factory will be used.
-
-``view``
- The :term:`dotted Python name` to a function that will be used as a
- view callable when this route matches.
- e.g. ``mypackage.views.my_view``.
-
-``xhr``
- This value should be either ``True`` or ``False``. If this value is
- specified and is ``True``, the :term:`request` must possess an
- ``HTTP_X_REQUESTED_WITH`` (aka ``X-Requested-With``) header for this
- route to match. This is useful for detecting AJAX requests issued
- from jQuery, Prototype and other Javascript libraries. If this
- predicate returns false, route matching continues.
-
-``traverse``
- If you would like to cause the :term:`context` to be something other
- than the :term:`root` object when this route matches, you can spell
- a traversal pattern as the ``traverse`` argument. This traversal
- pattern will be used as the traversal path: traversal will begin at
- the root object implied by this route (either the global root, or
- the object returned by the ``factory`` associated with this route).
-
- The syntax of the ``traverse`` argument is the same as it is for
- ``pattern``. For example, if the ``pattern`` provided to the
- ``route`` directive is ``articles/{article}/edit``, and the
- ``traverse`` argument provided to the ``route`` directive is
- ``/{article}``, when a request comes in that causes the route to
- match in such a way that the ``article`` match value is '1' (when
- the request URI is ``/articles/1/edit``), the traversal path will be
- generated as ``/1``. This means that the root object's
- ``__getitem__`` will be called with the name ``1`` during the
- traversal phase. If the ``1`` object exists, it will become the
- :term:`context` of the request. :ref:`traversal_chapter` has more
- information about traversal.
-
- If the traversal path contains segment marker names which are not
- present in the ``pattern`` argument, a runtime error will occur.
- The ``traverse`` pattern should not contain segment markers that do
- not exist in the ``pattern``.
-
- A similar combining of routing and traversal is available when a
- route is matched which contains a ``*traverse`` remainder marker in
- its ``pattern`` (see :ref:`using_traverse_in_a_route_pattern`). The
- ``traverse`` argument to the ``route`` directive allows you to
- associate route patterns with an arbitrary traversal path without
- using a a ``*traverse`` remainder marker; instead you can use other
- match information.
-
- Note that the ``traverse`` argument to the ``route`` directive is
- ignored when attached to a route that has a ``*traverse`` remainder
- marker in its pattern.
-
-``request_method``
- A string representing an HTTP method name, e.g. ``GET``, ``POST``,
- ``HEAD``, ``DELETE``, ``PUT``. If this argument is not specified,
- this route will match if the request has *any* request method. If
- this predicate returns false, route matching continues.
-
-``path_info``
- The value of this attribute represents a regular expression pattern
- that will be tested against the ``PATH_INFO`` WSGI environment
- variable. If the regex matches, this predicate will be true. If
- this predicate returns false, route matching continues.
-
-``request_param``
- This value can be any string. A view declaration with this
- attribute ensures that the associated route will only match when the
- request has a key in the ``request.params`` dictionary (an HTTP
- ``GET`` or ``POST`` variable) that has a name which matches the
- supplied value. If the value supplied to the attribute has a ``=``
- sign in it, e.g. ``request_params="foo=123"``, then the key
- (``foo``) must both exist in the ``request.params`` dictionary, and
- the value must match the right hand side of the expression (``123``)
- for the route to "match" the current request. If this predicate
- returns false, route matching continues.
-
-``header``
- The value of this attribute represents an HTTP header name or a
- header name/value pair. If the value contains a ``:`` (colon), it
- will be considered a name/value pair (e.g. ``User-Agent:Mozilla/.*``
- or ``Host:localhost``). The *value* of an attribute that represent
- a name/value pair should be a regular expression. If the value does
- not contain a colon, the entire value will be considered to be the
- header name (e.g. ``If-Modified-Since``). If the value evaluates to
- a header name only without a value, the header specified by the name
- must be present in the request for this predicate to be true. If
- the value evaluates to a header name/value pair, the header
- specified by the name must be present in the request *and* the
- regular expression specified as the value must match the header
- value. Whether or not the value represents a header name or a
- header name/value pair, the case of the header name is not
- significant. If this predicate returns false, route matching
- continues.
-
-``accept``
- The value of this attribute represents a match query for one or more
- mimetypes in the ``Accept`` HTTP request header. If this value is
- specified, it must be in one of the following forms: a mimetype
- match token in the form ``text/plain``, a wildcard mimetype match
- token in the form ``text/*`` or a match-all wildcard mimetype match
- token in the form ``*/*``. If any of the forms matches the
- ``Accept`` header of the request, this predicate will be true. If
- this predicate returns false, route matching continues.
-
-``custom_predicates``
-
- This value should be a sequence of references to custom predicate
- callables. Use custom predicates when no set of predefined
- predicates does what you need. Custom predicates can be combined
- with predefined predicates as necessary. Each custom predicate
- callable should accept two arguments: ``info`` and ``request``
- and should return either ``True`` or ``False`` after doing arbitrary
- evaluation of the info and/or the request. If all custom and
- non-custom predicate callables return ``True`` the associated route
- will be considered viable for a given request. If any predicate
- callable returns ``False``, route matching continues. Note that the
- value ``info`` passed to a custom route predicate is a dictionary
- containing matching information; see :ref:`custom_route_predicates`
- for more information about ``info``.
-
-``view_context``
- The :term:`dotted Python name` to a class or an interface that the
- :term:`context` of the view should match for the view named by the
- route to be used. This attribute is only useful if the ``view``
- attribute is used. If this attribute is not specified, the default
- (``None``) will be used.
-
- If the ``view`` attribute is not provided, this attribute has no
- effect.
-
- This attribute can also be spelled as ``view_for`` or ``for_``;
- these are valid older spellings.
-
-``view_permission``
- The permission name required to invoke the view associated with this
- route. e.g. ``edit``. (see :ref:`using_security_with_urldispatch`
- for more information about permissions).
-
- If the ``view`` attribute is not provided, this attribute has no
- effect.
-
- This attribute can also be spelled as ``permission``.
-
-``view_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``). 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
- implementation will be used to construct a response from the view
- return value. If the renderer term 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 response from the view
- return value. See :ref:`views_which_use_a_renderer` for more
- information.
-
- If the ``view`` attribute is not provided, this attribute has no
- effect.
-
- This attribute can also be spelled as ``renderer``.
-
-``view_attr``
- The view machinery defaults to using the ``__call__`` method of the
- view callable (or the function itself, if the view callable is a
- function) to obtain a response dictionary. The ``attr`` value allows
- you to vary the method attribute used to obtain the response. For
- example, if your view was a class, and the class has a method named
- ``index`` and you wanted to use this method instead of the class'
- ``__call__`` method to return the response, you'd say
- ``attr="index"`` in the view configuration for the view. This is
- most useful when the view definition is a class.
-
- If the ``view`` attribute is not provided, this attribute has no
- effect.
-
-``use_global_views``
- When a request matches this route, and view lookup cannot find a view
- which has a 'route_name' predicate argument that matches the route,
- try to fall back to using a view that otherwise matches the context,
- request, and view name (but does not match the route name predicate).
-
-Alternatives
-~~~~~~~~~~~~
-
-You can also add a :term:`route configuration` via:
-
-- Using the :meth:`pyramid.config.Configurator.add_route` method.
-
-See Also
-~~~~~~~~
-
-See also :ref:`urldispatch_chapter`.
diff --git a/docs/zcml/scan.rst b/docs/zcml/scan.rst
deleted file mode 100644
index df2cdd281..000000000
--- a/docs/zcml/scan.rst
+++ /dev/null
@@ -1,34 +0,0 @@
-.. _scan_directive:
-
-``scan``
---------
-
-To make use of :term:`configuration decoration` decorators, you must
-perform a :term:`scan`. A scan finds these decorators in code. The
-``scan`` ZCML directive tells :app:`Pyramid` to begin such a scan.
-
-Attributes
-~~~~~~~~~~
-
-``package``
- The package to scan or the single dot (``.``), meaning the
- "current" package (the package in which the ZCML file lives).
-
-Example
-~~~~~~~
-
-.. code-block:: xml
- :linenos:
-
- <scan package="."/>
-
-Alternatives
-~~~~~~~~~~~~
-
-The :meth:`pyramid.config.Configurator.scan` method performs
-the same job as the ``scan`` ZCML directive.
-
-See Also
-~~~~~~~~
-
-See also :ref:`mapping_views_using_a_decorator_section`.
diff --git a/docs/zcml/static.rst b/docs/zcml/static.rst
deleted file mode 100644
index 9538d18f0..000000000
--- a/docs/zcml/static.rst
+++ /dev/null
@@ -1,89 +0,0 @@
-.. _static_directive:
-
-``static``
-----------
-
-Use of the ``static`` ZCML directive or allows you to serve static
-resources (such as JavaScript and CSS files) within a
-:app:`Pyramid` application. This mechanism makes static files
-available at a name relative to the application root URL.
-
-Attributes
-~~~~~~~~~~
-
-``name``
- The (application-root-relative) URL prefix of the static directory.
- For example, to serve static files from ``/static`` in most
- applications, you would provide a ``name`` of ``static``.
-
-``path``
- A path to a directory on disk where the static files live. This
- path may either be 1) absolute (e.g. ``/foo/bar/baz``) 2)
- Python-package-relative (e.g. (``packagename:foo/bar/baz``) or 3)
- relative to the package directory in which the ZCML file which
- contains the directive (e.g. ``foo/bar/baz``).
-
-``cache_max_age``
- The number of seconds that the static resource can be cached, as
- represented in the returned response's ``Expires`` and/or
- ``Cache-Control`` headers, when any static file is served from this
- directive. This defaults to 3600 (5 minutes). Optional.
-
-``permission``
- Used to specify the :term:`permission` required by a user to execute
- this static view. This value defaults to the string
- ``__no_permission_required__``. The ``__no_permission_required__``
- string is a special sentinel which indicates that, even if a
- :term:`default permission` exists for the current application, the
- static view should be renderered to completely anonymous users.
- This default value is permissive because, in most web apps, static
- resources seldom need protection from viewing. You should use this
- option only if you register a static view which points at a
- directory that contains resources which should be shown only if the
- calling user has (according to the :term:`authorization policy`) a
- particular permission.
-
-Examples
-~~~~~~~~
-
-.. topic:: Serving Static Files from an Absolute Path
-
- .. code-block:: xml
- :linenos:
-
- <static
- name="static"
- path="/var/www/static"
- />
-
-.. topic:: Serving Static Files from a Package-Relative Path
-
- .. code-block:: xml
- :linenos:
-
- <static
- name="static"
- path="some_package:a/b/c/static"
- />
-
-.. topic:: Serving Static Files from a Current-Package-Relative Path
-
- .. code-block:: xml
- :linenos:
-
- <static
- name="static"
- path="static_files"
- />
-
-Alternatives
-~~~~~~~~~~~~
-
-:meth:`pyramid.config.Configurator.add_static_view` can also
-be used to add a static view.
-
-See Also
-~~~~~~~~
-
-See also :ref:`static_resources_section` and
-:ref:`generating_static_resource_urls`.
diff --git a/docs/zcml/subscriber.rst b/docs/zcml/subscriber.rst
deleted file mode 100644
index 25c4abf2e..000000000
--- a/docs/zcml/subscriber.rst
+++ /dev/null
@@ -1,45 +0,0 @@
-.. _subscriber_directive:
-
-``subscriber``
---------------
-
-The ``subscriber`` ZCML directive configures an :term:`subscriber`
-callable to listen for events broadcast by the :app:`Pyramid` web
-framework.
-
-Attributes
-~~~~~~~~~~
-
-``for``
- The class or :term:`interface` that you are subscribing the listener for,
- e.g. :class:`pyramid.events.NewRequest`. Registering a subscriber for a
- specific class or interface limits the event types that the subscriber
- will receive to those specified by the interface or class. Default:
- ``zope.interface.Interface`` (implying *any* event type).
-
-``handler``
- A :term:`dotted Python name` which references an event handler
- callable. The callable should accept a single argument: ``event``.
- The return value of the callable is ignored.
-
-Examples
-~~~~~~~~
-
-.. code-block:: xml
- :linenos:
-
- <subscriber
- for="pyramid.events.NewRequest"
- handler=".subscribers.handle_new_request"
- />
-
-Alternatives
-~~~~~~~~~~~~
-
-You can also register an event listener by using the
-:meth:`pyramid.config.Configurator.add_subscriber` method.
-
-See Also
-~~~~~~~~
-
-See also :ref:`events_chapter`.
diff --git a/docs/zcml/translationdir.rst b/docs/zcml/translationdir.rst
deleted file mode 100644
index 5cf615d26..000000000
--- a/docs/zcml/translationdir.rst
+++ /dev/null
@@ -1,64 +0,0 @@
-.. _translationdir_directive:
-
-``translationdir``
-------------------
-
-Add a :term:`gettext` :term:`translation directory` to the current
-configuration for use in localization of text.
-
-Attributes
-~~~~~~~~~~
-
-``dir``
- The path to the translation directory. This path may either be 1)
- absolute (e.g. ``/foo/bar/baz``) 2) Python-package-relative
- (e.g. ``packagename:foo/bar/baz``) or 3) relative to the package
- directory in which the ZCML file which contains the directive
- (e.g. ``foo/bar/baz``).
-
-Example 1
-~~~~~~~~~
-
-.. code-block:: xml
- :linenos:
-
- <!-- relative to configure.zcml file -->
-
- <translationdir
- dir="locale"
- />
-
-Example 2
-~~~~~~~~~
-
-.. code-block:: xml
- :linenos:
-
- <!-- relative to another package -->
-
- <translationdir
- dir="another.package:locale"
- />
-
-Example 3
-~~~~~~~~~
-
-.. code-block:: xml
- :linenos:
-
- <!-- an absolute directory name -->
-
- <translationdir
- dir="/usr/share/locale"
- />
-
-Alternatives
-~~~~~~~~~~~~
-
-Use :meth:`pyramid.config.Configurator.add_translation_dirs`
-method instance during initial application setup.
-
-See Also
-~~~~~~~~
-
-See also :ref:`activating_translation`.
diff --git a/docs/zcml/utility.rst b/docs/zcml/utility.rst
deleted file mode 100644
index 1341dfb83..000000000
--- a/docs/zcml/utility.rst
+++ /dev/null
@@ -1,46 +0,0 @@
-.. _utility_directive:
-
-``utility``
------------
-
-Register a :term:`Zope Component Architecture` "utility".
-
-Attributes
-~~~~~~~~~~
-
-``component``
- The utility component (cannot be specified if ``factory`` is
- specified).
-
-``factory``
- A factory that creates a component (cannot be specified if
- ``component`` is specified).
-
-``provides``
- The :term:`interface` that an utility instance resulting from a
- lookup will provide.
-
-``name``
- The utility name.
-
-Example
-~~~~~~~
-
-.. code-block:: xml
- :linenos:
-
- <utility
- provides=".interfaces.IMyUtility"
- component=".utilities.MyUtility"
- />
-
-Alternatives
-~~~~~~~~~~~~
-
-Use the ``registerUtility`` method of the ``registry`` attribute of a
-:term:`Configurator` instance during initial application setup.
-
-See Also
-~~~~~~~~
-
-None.
diff --git a/docs/zcml/view.rst b/docs/zcml/view.rst
deleted file mode 100644
index ba5c7bf23..000000000
--- a/docs/zcml/view.rst
+++ /dev/null
@@ -1,266 +0,0 @@
-.. _view_directive:
-
-``view``
---------
-
-A ``view`` declaration directs :app:`Pyramid` to create a single
-:term:`view configuration` registration in the current
-:term:`application registry`.
-
-The ``view`` ZCML directive has many possible attributes. Some of the
-attributes are descriptive or influence rendering. Other attributes
-are :term:`predicate` attributes, meaning that they imply an
-evaluation to true or false when view lookup is performed.
-
-*All* predicates named in a view configuration must evaluate to true
-in order for the view callable it names to be considered "invokable"
-for a given request. See :ref:`view_lookup` for a description of how
-a view configuration matches (or doesn't match) during a request.
-
-The possible attributes of the ``view`` ZCML directive are described
-below. They are divided into predicate and non-predicate categories.
-
-Attributes
-~~~~~~~~~~
-
-Non-Predicate Attributes
-########################
-
-``view``
- The :term:`dotted Python name` to a :term:`view callable`. This
- attribute is required unless a ``renderer`` attribute also exists.
- If a ``renderer`` attribute exists on the directive, this attribute
- defaults to a view that returns an empty dictionary (see
- :ref:`views_which_use_a_renderer`).
-
-``permission``
- The name of a *permission* that the user must possess in order to
- call the view. See :ref:`view_security_section` for more
- information about view security and permissions.
-
-``attr``
- The view machinery defaults to using the ``__call__`` method of the
- view callable (or the function itself, if the view callable is a
- function) to obtain a response dictionary. The ``attr`` value
- allows you to vary the method attribute used to obtain the response.
- For example, if your view was a class, and the class has a method
- named ``index`` and you wanted to use this method instead of the
- class' ``__call__`` method to return the response, you'd say
- ``attr="index"`` in the view configuration for the view. This is
- most useful when the view definition is a class.
-
-``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``). 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
- implementation will be used to construct a response from the view
- return value. If the renderer term 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 response from the view
- return value.
-
- Note that if the view itself returns a response (see
- :ref:`the_response`), the specified renderer implementation is never
- called.
-
- 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 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:`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
- is passed back to the upstream BFG machinery unmolested).
-
-``wrapper``
- The :term:`view name` (*not* an object dotted name) of another view
- declared elsewhere in ZCML (or via the ``@view_config`` decorator)
- which will receive the response body of this view as the
- ``request.wrapped_body`` attribute of its own request, and the
- response returned by this view as the ``request.wrapped_response``
- attribute of its own request. Using a wrapper makes it possible to
- "chain" views together to form a composite response. The response
- of the outermost wrapper view will be returned to the user. The
- wrapper view will be found as any view is found: see
- :ref:`view_lookup`. The "best" wrapper view will be found based on
- the lookup ordering: "under the hood" this wrapper view is looked up
- via ``pyramid.view.render_view_to_response(context, request,
- 'wrapper_viewname')``. The context and request of a wrapper view is
- the same context and request of the inner view. If this attribute
- is unspecified, no view wrapping is done.
-
-Predicate Attributes
-####################
-
-``name``
- The *view name*. Read the :ref:`traversal_chapter` to understand
- the concept of a view name.
-
-``context``
- A :term:`dotted Python name` representing the 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
- alternate name for this attribute is ``for`` (this is an older
- spelling).
-
-``route_name``
- *This attribute services an advanced feature that isn't often used
- unless you want to perform traversal after a route has matched.*
- This value must match the ``name`` of a ``<route>`` declaration (see
- :ref:`urldispatch_chapter`) that must match before this view will be
- called. Note that the ``route`` configuration referred to by
- ``route_name`` usually has a ``*traverse`` token in the value of its
- ``path``, representing a part of the path that will be used by
- traversal against the result of the route's :term:`root factory`.
- See :ref:`hybrid_chapter` for more information on using this
- advanced feature.
-
-``request_type``
- This value should be a :term:`dotted Python name` string
- representing the :term:`interface` that the :term:`request` must
- have in order for this view to be found and called. The presence of
- this attribute is largely for backwards compatibility with
- older iterations of this framework.
-
-``request_method``
- This value can either be one of the strings 'GET', 'POST', 'PUT',
- 'DELETE', or 'HEAD' representing an HTTP ``REQUEST_METHOD``. A view
- declaration with this attribute ensures that the view will only be
- called when the request's ``method`` (aka ``REQUEST_METHOD``) string
- matches the supplied value.
-
-``request_param``
- This value can be any string. A view declaration with this
- attribute ensures that the view will only be called when the request
- has a key in the ``request.params`` dictionary (an HTTP ``GET`` or
- ``POST`` variable) that has a name which matches the supplied value.
- If the value supplied to the attribute has a ``=`` sign in it,
- e.g. ``request_params="foo=123"``, then the key (``foo``) must both
- exist in the ``request.params`` dictionary, and the value must match
- the right hand side of the expression (``123``) for the view to
- "match" the current request.
-
-``containment``
- This value should be a :term:`dotted Python name` string
- 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 resources must be "location-aware" to use this feature.
- See :ref:`location_aware` for more information about
- location-awareness.
-
-``xhr``
- This value should be either ``True`` or ``False``. If this value is
- specified and is ``True``, the :term:`request` must possess an
- ``HTTP_X_REQUESTED_WITH`` (aka ``X-Requested-With``) header that has
- the value ``XMLHttpRequest`` for this view to be found and called.
- This is useful for detecting AJAX requests issued from jQuery,
- Prototype and other Javascript libraries.
-
-``accept``
- The value of this attribute represents a match query for one or more
- mimetypes in the ``Accept`` HTTP request header. If this value is
- specified, it must be in one of the following forms: a mimetype
- match token in the form ``text/plain``, a wildcard mimetype match
- token in the form ``text/*`` or a match-all wildcard mimetype match
- token in the form ``*/*``. If any of the forms matches the
- ``Accept`` header of the request, this predicate will be true.
-
-``header``
- The value of this attribute represents an HTTP header name or a
- header name/value pair. If the value contains a ``:`` (colon), it
- will be considered a name/value pair (e.g. ``User-Agent:Mozilla/.*``
- or ``Host:localhost``). The *value* of an attribute that represent
- a name/value pair should be a regular expression. If the value does
- not contain a colon, the entire value will be considered to be the
- header name (e.g. ``If-Modified-Since``). If the value evaluates to
- a header name only without a value, the header specified by the name
- must be present in the request for this predicate to be true. If
- the value evaluates to a header name/value pair, the header
- specified by the name must be present in the request *and* the
- regular expression specified as the value must match the header
- value. Whether or not the value represents a header name or a
- header name/value pair, the case of the header name is not
- significant.
-
-``path_info``
- The value of this attribute represents a regular expression pattern
- that will be tested against the ``PATH_INFO`` WSGI environment
- variable. If the regex matches, this predicate will be true.
-
-``custom_predicates``
- This value should be a sequence of references to custom predicate
- callables (e.g. ``dotted.name.one dotted.name.two``, if used in
- ZCML; a :term:`dotted Python name` to each callable separated by a
- space). Use custom predicates when no set of predefined predicates
- do what you need. Custom predicates can be combined with predefined
- predicates as necessary. Each custom predicate callable should
- accept two arguments: ``context`` and ``request`` and should return
- either ``True`` or ``False`` after doing arbitrary evaluation of the
- context and/or the request. If all callables return ``True``, the
- associated view callable will be considered viable for a given
- request.
-
-``decorator``
- A :term:`dotted Python name` to a function that will be used to decorate
- the registered :term:`view callable`. The decorator function will be
- called with the view callable as a single argument. The view callable it
- is passed will accept ``(context, request)``. The decorator must return a
- replacement view callable which also accepts ``(context, request)``.
-
-``mapper``
- A :term:`dotted Python name` which refers to a :term:`view mapper`, or
- ``None``. By default it is ``None``, which indicates that the view should
- use the default view mapper. This plug-point is useful for Pyramid
- extension developers, but it's not very useful for 'civilians' who are just
- developing stock Pyramid applications.
-
-Examples
-~~~~~~~~
-
-.. topic:: Registering A Default View for a Class
-
- .. code-block:: xml
- :linenos:
-
- <view
- context=".resources.MyResource"
- view=".views.hello_world"
- />
-
-.. topic:: Registering A View With a Predicate
-
- .. code-block:: xml
- :linenos:
-
- <view
- context=".resources.MyResource"
- view=".views.hello_world_post"
- request_method="POST"
- />
-
-Alternatives
-~~~~~~~~~~~~
-
-You can also add a :term:`view configuration` via:
-
-- Using the :class:`pyramid.view.view_config` class as a decorator.
-
-- Using the :meth:`pyramid.config.Configurator.add_view` method.
-
-See Also
-~~~~~~~~
-
-See also :ref:`views_chapter`.