summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorMichael Merickel <michael@merickel.org>2012-08-16 00:59:18 -0500
committerMichael Merickel <michael@merickel.org>2012-08-16 00:59:18 -0500
commit717537cdd6611511f783542034f00cf0099d515e (patch)
tree1f0a28530836a647713c22f2dd91767270f42458 /docs
parenta54b5e46f63ff3154c5d9f191ad3b78a2f506a8a (diff)
parent6b180cbb77d6c5bee0e75220d93fc1800d1217df (diff)
downloadpyramid-717537cdd6611511f783542034f00cf0099d515e.tar.gz
pyramid-717537cdd6611511f783542034f00cf0099d515e.tar.bz2
pyramid-717537cdd6611511f783542034f00cf0099d515e.zip
Merge branch 'master' into feature.instance-properties
Diffstat (limited to 'docs')
-rw-r--r--docs/.gitignore1
-rw-r--r--docs/Makefile6
m---------docs/_themes0
-rw-r--r--docs/api/config.rst3
-rw-r--r--docs/api/registry.rst14
-rw-r--r--docs/api/renderers.rst2
-rw-r--r--docs/conf.py16
-rw-r--r--docs/designdefense.rst112
-rw-r--r--docs/glossary.rst16
-rw-r--r--docs/index.rst12
-rw-r--r--docs/narr/advconfig.rst2
-rw-r--r--docs/narr/commandline.rst15
-rw-r--r--docs/narr/firstapp.rst3
-rw-r--r--docs/narr/hooks.rst134
-rw-r--r--docs/narr/introduction.rst49
-rw-r--r--docs/narr/introspector.rst2
-rw-r--r--docs/narr/logging.rst7
-rw-r--r--docs/narr/project.rst14
-rw-r--r--docs/narr/renderers.rst69
-rw-r--r--docs/narr/sessions.rst13
-rw-r--r--docs/narr/startup.rst14
-rw-r--r--docs/narr/templates.rst16
-rw-r--r--docs/narr/urldispatch.rst8
-rw-r--r--docs/tutorials/modwsgi/index.rst14
-rw-r--r--docs/tutorials/wiki/definingviews.rst92
-rw-r--r--docs/tutorials/wiki/design.rst19
-rw-r--r--docs/tutorials/wiki/installation.rst7
-rw-r--r--docs/tutorials/wiki2/authorization.rst2
-rw-r--r--docs/tutorials/wiki2/basiclayout.rst4
-rw-r--r--docs/tutorials/wiki2/definingviews.rst92
-rw-r--r--docs/tutorials/wiki2/design.rst17
-rw-r--r--docs/tutorials/wiki2/installation.rst10
-rw-r--r--docs/tutorials/wiki2/src/authorization/development.ini2
-rw-r--r--docs/tutorials/wiki2/src/authorization/production.ini2
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/development.ini2
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/production.ini2
-rw-r--r--docs/tutorials/wiki2/src/models/development.ini2
-rw-r--r--docs/tutorials/wiki2/src/models/production.ini2
-rw-r--r--docs/tutorials/wiki2/src/tests/development.ini2
-rw-r--r--docs/tutorials/wiki2/src/tests/production.ini2
-rw-r--r--docs/tutorials/wiki2/src/views/development.ini2
-rw-r--r--docs/tutorials/wiki2/src/views/production.ini2
42 files changed, 494 insertions, 311 deletions
diff --git a/docs/.gitignore b/docs/.gitignore
index da7abd0c0..30d731d4a 100644
--- a/docs/.gitignore
+++ b/docs/.gitignore
@@ -1,4 +1,3 @@
-_themes
_build
diff --git a/docs/Makefile b/docs/Makefile
index bb381fc53..e4a325022 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -25,7 +25,7 @@ help:
clean:
-rm -rf _build/*
-html:
+html: _themes
mkdir -p _build/html _build/doctrees
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html
@echo
@@ -47,7 +47,7 @@ pickle:
web: pickle
-htmlhelp:
+htmlhelp: _themes
mkdir -p _build/htmlhelp _build/doctrees
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp
@echo
@@ -84,3 +84,5 @@ epub:
@echo
@echo "Build finished. The epub file is in _build/epub."
+_themes:
+ git submodule update --init
diff --git a/docs/_themes b/docs/_themes
new file mode 160000
+Subproject f59f7bfce5259f50fbb67b9040c03ecb080130b
diff --git a/docs/api/config.rst b/docs/api/config.rst
index cd58e74d3..1b887988a 100644
--- a/docs/api/config.rst
+++ b/docs/api/config.rst
@@ -36,6 +36,7 @@
.. automethod:: set_authentication_policy
.. automethod:: set_authorization_policy
.. automethod:: set_default_permission
+ .. automethod:: add_permission
:methodcategory:`Setting Request Properties`
@@ -66,6 +67,8 @@
.. automethod:: add_response_adapter
.. automethod:: add_traverser
.. automethod:: add_tween
+ .. automethod:: add_route_predicate
+ .. automethod:: add_view_predicate
.. automethod:: set_request_factory
.. automethod:: set_root_factory
.. automethod:: set_session_factory
diff --git a/docs/api/registry.rst b/docs/api/registry.rst
index e62e2ba6f..1d5d52248 100644
--- a/docs/api/registry.rst
+++ b/docs/api/registry.rst
@@ -38,3 +38,17 @@
This class is new as of :app:`Pyramid` 1.3.
+.. autoclass:: Deferred
+
+ This class is new as of :app:`Pyramid` 1.4.
+
+.. autofunction:: undefer
+
+ This function is new as of :app:`Pyramid` 1.4.
+
+.. autoclass:: predvalseq
+
+ This class is new as of :app:`Pyramid` 1.4.
+
+
+
diff --git a/docs/api/renderers.rst b/docs/api/renderers.rst
index ab182365e..ea000ad02 100644
--- a/docs/api/renderers.rst
+++ b/docs/api/renderers.rst
@@ -15,8 +15,6 @@
.. autoclass:: JSONP
-.. autoclass:: ObjectJSONEncoder
-
.. attribute:: null_renderer
An object that can be used in advanced integration cases as input to the
diff --git a/docs/conf.py b/docs/conf.py
index db972261d..80ee0d2e5 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -48,6 +48,7 @@ extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.doctest',
'repoze.sphinx.autointerface',
+ 'sphinx.ext.viewcode',
# 'sphinx.ext.intersphinx'
]
@@ -132,18 +133,15 @@ if 'sphinx-build' in ' '.join(sys.argv): # protect against dumb importers
from subprocess import call, Popen, PIPE
p = Popen('which git', shell=True, stdout=PIPE)
- git = p.stdout.read().strip()
+
cwd = os.getcwd()
_themes = os.path.join(cwd, '_themes')
-
- if not os.path.isdir(_themes):
- call([git, 'clone', 'git://github.com/Pylons/pylons_sphinx_theme.git',
- '_themes'])
+ p = Popen('which git', shell=True, stdout=PIPE)
+ git = p.stdout.read().strip()
+ if not os.listdir(_themes):
+ call([git, 'submodule', '--init'])
else:
- os.chdir(_themes)
- call([git, 'checkout', 'master'])
- call([git, 'pull'])
- os.chdir(cwd)
+ call([git, 'submodule', 'update'])
sys.path.append(os.path.abspath('_themes'))
diff --git a/docs/designdefense.rst b/docs/designdefense.rst
index bbcf9c2ec..d896022e6 100644
--- a/docs/designdefense.rst
+++ b/docs/designdefense.rst
@@ -375,73 +375,6 @@ 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
--------------------------------------
-
-In this `TOPP Engineering blog entry
-<http://www.coactivate.org/projects/topp-engineering/blog/2008/10/20/what-bothers-me-about-the-component-architecture/>`_,
-Ian Bicking asserts that the way :mod:`repoze.bfg` used a Zope interface to
-represent an HTTP request method added too much indirection for not enough
-gain. We agreed in general, and for this reason, :mod:`repoze.bfg` version
-1.1 (and subsequent versions including :app:`Pyramid` 1.0+) added :term:`view
-predicate` and :term:`route predicate` modifiers to view configuration.
-Predicates are request-specific (or :term:`context` -specific) matching
-narrowers which don't use interfaces. Instead, each predicate uses a
-domain-specific string as a match value.
-
-For example, to write a view configuration which matches only requests with
-the ``POST`` HTTP request method, you might write a ``@view_config``
-decorator which mentioned the ``request_method`` predicate:
-
-.. code-block:: python
- :linenos:
-
- from pyramid.view import view_config
- @view_config(name='post_view', request_method='POST', renderer='json')
- def post_view(request):
- return 'POSTed'
-
-You might further narrow the matching scenario by adding an ``accept``
-predicate that narrows matching to something that accepts a JSON response:
-
-.. code-block:: python
- :linenos:
-
- from pyramid.view import view_config
- @view_config(name='post_view', request_method='POST',
- accept='application/json', renderer='json')
- def post_view(request):
- return 'POSTed'
-
-Such a view would only match when the request indicated that HTTP request
-method was ``POST`` and that the remote user agent passed
-``application/json`` (or, for that matter, ``application/*``) in its
-``Accept`` request header.
-
-Under the hood, these features make no use of interfaces.
-
-Many prebaked predicates exist. However, use of only prebaked predicates,
-however, doesn't entirely meet Ian's criterion. He would like to be able to
-match a request using a lambda or another function which interrogates the
-request imperatively. In :mod:`repoze.bfg` version 1.2, we acommodate this
-by allowing people to define custom view predicates:
-
-.. code-block:: python
- :linenos:
-
- from pyramid.view import view_config
- from pyramid.response import Response
-
- def subpath(context, request):
- return request.subpath and request.subpath[0] == 'abc'
-
- @view_config(custom_predicates=(subpath,))
- def aview(request):
- return Response('OK')
-
-The above view will only match when the first element of the request's
-:term:`subpath` is ``abc``.
-
.. _zcml_encouragement:
Pyramid "Encourages Use of ZCML"
@@ -711,33 +644,22 @@ over 2K lines of Python code, excluding tests.
Pyramid Has Too Many Dependencies
---------------------------------
-This is true. At the time of this writing, the total number of Python
-package distributions that :app:`Pyramid` depends upon transitively is 15 if
-you use Python 2.7, or 17 if you use Python 2.5 or 2.6. This is a lot more
-than zero package distribution dependencies: a metric which various Python
-microframeworks and Django boast.
-
-The :mod:`zope.component`, package on which :app:`Pyramid` depends has
-transitive dependencies on several other packages (:mod:`zope.event`, and
-:mod:`zope.interface`). :app:`Pyramid` also has its own direct dependencies,
-such as :term:`PasteDeploy`, :term:`Chameleon`, :term:`Mako`, :term:`WebOb`,
-:mod:`zope.deprecation` and some of these in turn have their own transitive
-dependencies.
-
-We try not to reinvent too many wheels (at least the ones that don't need
-reinventing), and this comes at the cost of some number of dependencies.
-However, "number of package distributions" is just not a terribly great
-metric to measure complexity. For example, the :mod:`zope.event`
-distribution on which :app:`Pyramid` depends has a grand total of four lines
-of runtime code.
-
-In the meantime, :app:`Pyramid` has a number of package distribution
-dependencies comparable to similarly-targeted frameworks such as Pylons 1.X.
-It may be in the future that we shed more dependencies as the result of a
-port to Python 3 (the less code we need to port, the better). In the future,
-we may also move templating system dependencies out of the core and place
-them in add-on packages, to be included by developers instead of by the
-framework. This would reduce the number of core dependencies by about five.
+This is true. At the time of this writing (Pyramid 1.3), the total number of
+Python package distributions that :app:`Pyramid` depends upon transitively is
+if you use Python 3.2 or Python 2.7 is 10. If you use Python 2.6, Pyramid
+will pull in 12 package distributions. This is a lot more than zero package
+distribution dependencies: a metric which various Python microframeworks and
+Django boast.
+
+However, Pyramid 1.2 relied on 15 packages under Python 2.7 and 17 packages
+under Python 2.6, so we've made progress here. A port to Python 3 completed
+in Pyramid 1.3 helped us shed a good number of dependencies by forcing us to
+make better packaging decisions.
+
+In the future, we may also move templating system dependencies out of the
+core and place them in add-on packages, to be included by developers instead
+of by the framework. This would reduce the number of core dependencies by
+about five, leaving us with only five remaining core dependencies.
Pyramid "Cheats" To Obtain Speed
--------------------------------
@@ -1647,7 +1569,7 @@ Pyramid Doesn't Offer Pluggable Apps
------------------------------------
It is "Pyramidic" to compose multiple external sources into the same
-configuration using :meth:`~pyramid.config.Configuration.include`. Any
+configuration using :meth:`~pyramid.config.Configurator.include`. Any
number of includes can be done to compose an application; includes can even
be done from within other includes. Any directive can be used within an
include that can be used outside of one (such as
diff --git a/docs/glossary.rst b/docs/glossary.rst
index 60920a73a..ba3203f89 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -290,7 +290,7 @@ Glossary
:term:`principal` (or principals) associated with a request.
WSGI
- `Web Server Gateway Interface <http://wsgi.org/>`_. This is a
+ `Web Server Gateway Interface <http://www.wsgi.org/>`_. This is a
Python standard for connecting web applications to web servers,
similar to the concept of Java Servlets. :app:`Pyramid` requires
that your application be served as a WSGI application.
@@ -299,7 +299,7 @@ Glossary
*Middleware* is a :term:`WSGI` concept. It is a WSGI component
that acts both as a server and an application. Interesting uses
for middleware exist, such as caching, content-transport
- encoding, and other functions. See `WSGI.org <http://wsgi.org>`_
+ encoding, and other functions. See `WSGI.org <http://www.wsgi.org>`_
or `PyPI <http://python.org/pypi>`_ to find middleware for your
application.
@@ -922,9 +922,9 @@ Glossary
http://docs.pylonsproject.org/projects/pyramid_debugtoolbar/dev/ .
scaffold
- A project template that helps users get started writing a Pyramid
- application quickly. Scaffolds are usually used via the ``pcreate``
- command.
+ A project template that generates some of the major parts of a Pyramid
+ application and helps users to quickly get started writing larger
+ applications. Scaffolds are usually used via the ``pcreate`` command.
pyramid_exclog
A package which logs Pyramid application exception (error) information
@@ -994,3 +994,9 @@ Glossary
Aka ``gunicorn``, a fast :term:`WSGI` server that runs on UNIX under
Python 2.5+ (although at the time of this writing does not support
Python 3). See http://gunicorn.org/ for detailed information.
+
+ predicate factory
+ A callable which is used by a third party during the registration of a
+ route or view predicates to extend the view and route configuration
+ system. See :ref:`registering_thirdparty_predicates` for more
+ information.
diff --git a/docs/index.rst b/docs/index.rst
index 31c2fde6b..c84314274 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -13,15 +13,9 @@ Here is one of the simplest :app:`Pyramid` applications you can make:
.. literalinclude:: narr/helloworld.py
-When saved to ``helloworld.py``, the above application can be run via:
-
-.. code-block:: text
-
- $ easy_install pyramid
- $ python helloworld.py
-
-When you visit ``http://localhost:8080/hello/world`` in a browser, you will
-see the text ``Hello, world!``.
+After you install :app:`Pyramid` and run this application, when you visit
+``http://localhost:8080/hello/world`` in a browser, you will see the text
+``Hello, world!``
See :ref:`firstapp_chapter` for a full explanation of how this application
works. Read the :ref:`html_narrative_documentation` to understand how
diff --git a/docs/narr/advconfig.rst b/docs/narr/advconfig.rst
index 9cb4db325..2949dc808 100644
--- a/docs/narr/advconfig.rst
+++ b/docs/narr/advconfig.rst
@@ -282,7 +282,7 @@ Pyramid application, and they want to customize the configuration of this
application without hacking its code "from outside", they can "include" a
configuration function from the package and override only some of its
configuration statements within the code that does the include. No conflicts
-will be generated by configuration statements within the code which does the
+will be generated by configuration statements within the code that does the
including, even if configuration statements in the included code would
conflict if it was moved "up" to the calling code.
diff --git a/docs/narr/commandline.rst b/docs/narr/commandline.rst
index 886e075e3..3bdf8c5cd 100644
--- a/docs/narr/commandline.rst
+++ b/docs/narr/commandline.rst
@@ -349,7 +349,7 @@ setting) orderings using the ``ptweens`` command. Tween factories
will show up represented by their standard Python dotted name in the
``ptweens`` output.
-For example, here's the ``pwteens`` command run against a system
+For example, here's the ``ptweens`` command run against a system
configured without any explicit tweens:
.. code-block:: text
@@ -367,7 +367,7 @@ configured without any explicit tweens:
1 pyramid.tweens.excview_tween_factory excview
- - MAIN
-Here's the ``pwteens`` command run against a system configured *with*
+Here's the ``ptweens`` command run against a system configured *with*
explicit tweens defined in its ``development.ini`` file:
.. code-block:: text
@@ -460,7 +460,7 @@ to the console.
You can add request header values by using the ``--header`` option::
- $ bin/prequest --header=Host=example.com development.ini /
+ $ bin/prequest --header=Host:example.com development.ini /
Headers are added to the WSGI environment by converting them to their
CGI/WSGI equivalents (e.g. ``Host=example.com`` will insert the ``HTTP_HOST``
@@ -654,8 +654,11 @@ use the following command:
.. code-block:: python
- import logging.config
- logging.config.fileConfig('/path/to/my/development.ini')
+ import pyramid.paster
+ pyramid.paster.setup_logging('/path/to/my/development.ini')
+
+See :ref:`logging_chapter` for more information on logging within
+:app:`Pyramid`.
.. index::
single: console script
@@ -718,7 +721,7 @@ we'll pretend you have a distribution with a package in it named
def settings_show():
description = """\
Print the deployment settings for a Pyramid application. Example:
- 'psettings deployment.ini'
+ 'show_settings deployment.ini'
"""
usage = "usage: %prog config_uri"
parser = optparse.OptionParser(
diff --git a/docs/narr/firstapp.rst b/docs/narr/firstapp.rst
index 1ca188d7e..a86826d86 100644
--- a/docs/narr/firstapp.rst
+++ b/docs/narr/firstapp.rst
@@ -8,7 +8,8 @@ Creating Your First :app:`Pyramid` Application
In this chapter, we will walk through the creation of a tiny :app:`Pyramid`
application. After we're finished creating the application, we'll explain in
-more detail how it works.
+more detail how it works. It assumes you already have :app:`Pyramid` installed.
+If you do not, head over to the :ref:`installing_chapter` section.
.. _helloworld_imperative:
diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst
index b6e3dd163..2c15cd690 100644
--- a/docs/narr/hooks.rst
+++ b/docs/narr/hooks.rst
@@ -145,7 +145,7 @@ the view which generates it can be overridden as necessary.
The :term:`forbidden view` callable is a view callable like any other. The
:term:`view configuration` which causes it to be a "forbidden" view consists
-of using the meth:`pyramid.config.Configurator.add_forbidden_view` API or the
+of using the :meth:`pyramid.config.Configurator.add_forbidden_view` API or the
:class:`pyramid.view.forbidden_view_config` decorator.
For example, you can add a forbidden view by using the
@@ -171,7 +171,7 @@ as a forbidden view:
from pyramid.view import forbidden_view_config
- forbidden_view_config()
+ @forbidden_view_config()
def forbidden(request):
return Response('forbidden')
@@ -289,6 +289,36 @@ keys added to the renderer globals dictionary by all
:class:`pyramid.events.BeforeRender` subscribers and renderer globals
factories must be unique.
+The dictionary returned from the view is accessible through the
+:attr:`rendering_val` attribute of a :class:`~pyramid.events.BeforeRender`
+event.
+
+Suppose you return ``{'mykey': 'somevalue', 'mykey2': 'somevalue2'}`` from
+your view callable, like so:
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.view import view_config
+
+ @view_config(renderer='some_renderer')
+ def myview(request):
+ return {'mykey': 'somevalue', 'mykey2': 'somevalue2'}
+
+:attr:`rendering_val` can be used to access these values from the
+:class:`~pyramid.events.BeforeRender` object:
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.events import subscriber
+ from pyramid.events import BeforeRender
+
+ @subscriber(BeforeRender)
+ def read_return(event):
+ # {'mykey': 'somevalue'} is returned from the view
+ print(event.rendering_val['mykey'])
+
See the API documentation for the :class:`~pyramid.events.BeforeRender` event
interface at :class:`pyramid.interfaces.IBeforeRender`.
@@ -625,7 +655,7 @@ converts the arbitrary return value into something that implements
:class:`~pyramid.interfaces.IResponse`.
For example, if you'd like to allow view callables to return bare string
-objects (without requiring a a :term:`renderer` to convert a string to a
+objects (without requiring a :term:`renderer` to convert a string to a
response object), you can register an adapter which converts the string to a
Response:
@@ -1202,3 +1232,101 @@ Displaying Tween Ordering
The ``ptweens`` command-line utility can be used to report the current
implict and explicit tween chains used by an application. See
:ref:`displaying_tweens`.
+
+.. _registering_thirdparty_predicates:
+
+Adding A Third Party View or Route Predicate
+--------------------------------------------
+
+.. note::
+
+ Third-party predicates are a feature new as of Pyramid 1.4.
+
+View and route predicates used during view configuration allow you to narrow
+the set of circumstances under which a view or route will match. For
+example, the ``request_method`` view predicate can be used to ensure a view
+callable is only invoked when the request's method is ``POST``:
+
+.. code-block:: python
+
+ @view_config(request_method='POST')
+ def someview(request):
+ ...
+
+Likewise, a similar predicate can be used as a *route* predicate:
+
+.. code-block:: python
+
+ config.add_route('name', '/foo', request_method='POST')
+
+Many other built-in predicates exists (``request_param``, and others). You
+can add third-party predicates to the list of available predicates by using
+one of :meth:`pyramid.config.Configurator.add_view_predicate` or
+:meth:`pyramid.config.Configurator.add_route_predicate`. The former adds a
+view predicate, the latter a route predicate.
+
+When using one of those APIs, you pass a *name* and a *factory* to add a
+predicate during Pyramid's configuration stage. For example:
+
+.. code-block:: python
+
+ config.add_view_predicate('content_type', ContentTypePredicate)
+
+The above example adds a new predicate named ``content_type`` to the list of
+available predicates for views. This will allow the following view
+configuration statement to work:
+
+.. code-block:: python
+ :linenos:
+
+ @view_config(content_type='File')
+ def aview(request): ...
+
+The first argument to :meth:`pyramid.config.Configurator.add_view_predicate`,
+the name, is a string representing the name that is expected to be passed to
+``view_config`` (or its imperative analogue ``add_view``).
+
+The second argument is a predicate factory. A predicate factory is most
+often a class with a constructor (``__init__``), a ``text`` method, a
+``phash`` method and a ``__call__`` method. For example:
+
+.. code-block:: python
+ :linenos:
+
+ class ContentTypePredicate(object):
+ def __init__(self, val, config):
+ self.val = val
+
+ def text(self):
+ return 'content_type = %s' % (self.val,)
+
+ phash = text
+
+ def __call__(self, context, request):
+ return getattr(context, 'content_type', None) == self.val
+
+The constructor of a predicate factory takes two arguments: ``val`` and
+``config``. The ``val`` argument will be the argument passed to
+``view_config`` (or ``add_view``). In the example above, it will be the
+string ``File``. The second arg, ``config`` will be the Configurator
+instance at the time of configuration.
+
+The ``text`` method must return a string. It should be useful to describe
+the behavior of the predicate in error messages.
+
+The ``phash`` method must return a string or a sequence of strings. It's
+most often the same as ``text``, as long as ``text`` uniquely describes the
+predicate's name and the value passed to the constructor. If ``text`` is
+more general, or doesn't describe things that way, ``phash`` should return a
+string with the name and the value serialized. The result of ``phash`` is
+not seen in output anywhere, it just informs the uniqueness constraints for
+view configuration.
+
+The ``__call__`` method of a predicate factory must accept a resource
+(``context``) and a request, and must return ``True`` or ``False``. It is
+the "meat" of the predicate.
+
+You can use the same predicate factory as both a view predicate and as a
+route predicate, but you'll need to call ``add_view_predicate`` and
+``add_route_predicate`` separately with the same factory.
+
diff --git a/docs/narr/introduction.rst b/docs/narr/introduction.rst
index 8f7b17dc3..7c0f9223f 100644
--- a/docs/narr/introduction.rst
+++ b/docs/narr/introduction.rst
@@ -534,14 +534,14 @@ Configuration extensibility
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unlike other systems, Pyramid provides a structured "include" mechanism (see
-:meth:`~pyramid.config.Configurator.include`) that allows you to compose
+:meth:`~pyramid.config.Configurator.include`) that allows you to combine
applications from multiple Python packages. All the configuration statements
that can be performed in your "main" Pyramid application can also be
performed by included packages including the addition of views, routes,
subscribers, and even authentication and authorization policies. You can even
extend or override an existing application by including another application's
configuration in your own, overriding or adding new views and routes to
-it. This has the potential to allow you to compose a big application out of
+it. This has the potential to allow you to create a big application out of
many other smaller ones. For example, if you want to reuse an existing
application that already has a bunch of routes, you can just use the
``include`` statement with a ``route_prefix``; the new application will live
@@ -593,11 +593,12 @@ it is to shoehorn a route into an ordered list of other routes, or to create
another entire instance of an application to service a department and glue
code to allow disparate apps to share data. It's a great fit for sites that
naturally lend themselves to changing departmental hierarchies, such as
-content management systems and document management systems. Traversal also lends itself well to
-systems that require very granular security ("Bob can edit *this* document"
-as opposed to "Bob can edit documents").
+content management systems and document management systems. Traversal also
+lends itself well to systems that require very granular security ("Bob can
+edit *this* document" as opposed to "Bob can edit documents").
-Example: :ref:`hello_traversal_chapter` and :ref:`much_ado_about_traversal_chapter`.
+Examples: :ref:`hello_traversal_chapter` and
+:ref:`much_ado_about_traversal_chapter`.
Tweens
~~~~~~
@@ -801,6 +802,42 @@ within a function called when another user uses the
See also :ref:`add_directive`.
+Programmatic Introspection
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you're building a large system that other users may plug code into, it's
+useful to be able to get an enumeration of what code they plugged in *at
+application runtime*. For example, you might want to show them a set of tabs
+at the top of the screen based on an enumeration of views they registered.
+
+This is possible using Pyramid's :term:`introspector`.
+
+Here's an example of using Pyramid's introspector from within a view
+callable:
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.view import view_config
+ from pyramid.response import Response
+
+ @view_config(route_name='bar')
+ def show_current_route_pattern(request):
+ introspector = request.registry.introspector
+ route_name = request.matched_route.name
+ route_intr = introspector.get('routes', route_name)
+ return Response(str(route_intr['pattern']))
+
+See also :ref:`using_introspection`.
+
+Python 3 Compatibility
+~~~~~~~~~~~~~~~~~~~~~~
+
+Pyramid and most of its add-ons are Python 3 compatible. If you develop a
+Pyramid application today, you won't need to worry that five years from now
+you'll be backwatered because there are language features you'd like to use
+but your framework doesn't support newer Python versions.
+
Testing
~~~~~~~
diff --git a/docs/narr/introspector.rst b/docs/narr/introspector.rst
index 74595cac8..6bfaf11c0 100644
--- a/docs/narr/introspector.rst
+++ b/docs/narr/introspector.rst
@@ -32,7 +32,7 @@ callable:
from pyramid.response import Response
@view_config(route_name='bar')
- def route_accepts(request):
+ def show_current_route_pattern(request):
introspector = request.registry.introspector
route_name = request.matched_route.name
route_intr = introspector.get('routes', route_name)
diff --git a/docs/narr/logging.rst b/docs/narr/logging.rst
index 044655c1f..f4c38abb6 100644
--- a/docs/narr/logging.rst
+++ b/docs/narr/logging.rst
@@ -14,7 +14,7 @@ how to send log messages to loggers that you've configured.
which help configure logging. All of the scaffolds which ship along with
:app:`Pyramid` do this. If you're not using a scaffold, or if you've used
a third-party scaffold which does not create these files, the
- configuration information in this chapter will not be applicable.
+ configuration information in this chapter may not be applicable.
.. _logging_config:
@@ -36,10 +36,11 @@ application-related and logging-related sections in the configuration file
can coexist peacefully, and the logging-related sections in the file are used
from when you run ``pserve``.
-The ``pserve`` command calls the `logging.fileConfig function
+The ``pserve`` command calls the :func:`pyramid.paster.setup_logging`
+function, a thin wrapper around the `logging.fileConfig
<http://docs.python.org/lib/logging-config-api.html>`_ using the specified
ini file if it contains a ``[loggers]`` section (all of the
-scaffold-generated ``.ini`` files do). ``logging.fileConfig`` reads the
+scaffold-generated ``.ini`` files do). ``setup_logging`` reads the
logging configuration from the ini file upon which ``pserve`` was
invoked.
diff --git a/docs/narr/project.rst b/docs/narr/project.rst
index 57073900f..1e2c225d2 100644
--- a/docs/narr/project.rst
+++ b/docs/narr/project.rst
@@ -144,13 +144,13 @@ directories which he creates within his ``~/projects`` directory. On
Windows, it's a good idea to put project directories within a directory that
contains no space characters, so it's wise to *avoid* a path that contains
i.e. ``My Documents``. As a result, the author, when he uses Windows, just
-puts his projects in ``C:\\projects``.
+puts his projects in ``C:\projects``.
.. warning::
You’ll need to avoid using ``pcreate`` to create a project with the same
- as a Python standard library component. In particular, this means you
- should avoid using names the names ``site`` or ``test``, both of which
+ name as a Python standard library component. In particular, this means you
+ should avoid using the names ``site`` or ``test``, both of which
conflict with Python standard library packages. You should also avoid
using the name ``pyramid``, which will conflict with Pyramid itself.
@@ -447,7 +447,7 @@ first column instead, for example like this:
pyramid.includes =
#pyramid_debugtoolbar
-When you attempt to restart the application with a section like the abvoe
+When you attempt to restart the application with a section like the above
you'll receive an error that ends something like this, and the application
will not start:
@@ -684,7 +684,7 @@ testing your application, packaging, and distributing your application.
.. note::
- ``setup.py`` is the defacto standard which Python developers use to
+ ``setup.py`` is the de facto standard which Python developers use to
distribute their reusable code. You can read more about ``setup.py`` files
and their usage in the `Setuptools documentation
<http://peak.telecommunity.com/DevCenter/setuptools>`_ and `The
@@ -966,7 +966,7 @@ named ``views`` instead of within a single ``views.py`` file, you might:
You can then continue to add view callable functions to the ``blog.py``
module, but you can also add other ``.py`` files which contain view callable
functions to the ``views`` directory. As long as you use the
-``@view_config`` directive to register views in conjuction with
+``@view_config`` directive to register views in conjunction with
``config.scan()`` they will be picked up automatically when the application
is restarted.
@@ -994,7 +994,7 @@ run a :app:`Pyramid` application is purely conventional based on the output
of its scaffolding. But we strongly recommend using while developing your
application, because many other convenience introspection commands (such as
``pviews``, ``prequest``, ``proutes`` and others) are also implemented in
-terms of configuration availaibility of this ``.ini`` file format. It also
+terms of configuration availability of this ``.ini`` file format. It also
configures Pyramid logging and provides the ``--reload`` switch for
convenient restarting of the server when code changes.
diff --git a/docs/narr/renderers.rst b/docs/narr/renderers.rst
index 34bee3c7f..57b5bc65b 100644
--- a/docs/narr/renderers.rst
+++ b/docs/narr/renderers.rst
@@ -177,13 +177,15 @@ using the API of the ``request.response`` attribute. See
.. index::
pair: renderer; JSON
+.. _json_renderer:
+
JSON Renderer
~~~~~~~~~~~~~
-The ``json`` renderer renders view callable results to :term:`JSON`. It
-passes the return value through the ``json.dumps`` standard library function,
-and wraps the result in a response object. It also sets the response
-content-type to ``application/json``.
+The ``json`` renderer renders view callable results to :term:`JSON`. By
+default, it passes the return value through the ``json.dumps`` standard
+library function, and wraps the result in a response object. It also sets
+the response content-type to ``application/json``.
Here's an example of a view that returns a dictionary. Since the ``json``
renderer is specified in the configuration for this view, the view will
@@ -207,11 +209,11 @@ representing the JSON serialization of the return value:
'{"content": "Hello!"}'
The return value needn't be a dictionary, but the return value must contain
-values serializable by ``json.dumps``.
+values serializable by the configured serializer (by default ``json.dumps``).
.. note::
- Extra arguments can be passed to ``json.dumps`` by overriding the default
+ Extra arguments can be passed to the serializer by overriding the default
``json`` renderer. See :class:`pyramid.renderers.JSON` and
:ref:`adding_and_overriding_renderers` for more information.
@@ -223,9 +225,9 @@ You can configure a view to use the JSON renderer by naming ``json`` as the
:linenos:
config.add_view('myproject.views.hello_world',
- name='hello',
- context='myproject.resources.Hello',
- renderer='json')
+ name='hello',
+ context='myproject.resources.Hello',
+ renderer='json')
Views which use the JSON renderer can vary non-body response attributes by
using the api of the ``request.response`` attribute. See
@@ -238,8 +240,9 @@ Serializing Custom Objects
Custom objects can be made easily JSON-serializable in Pyramid by defining a
``__json__`` method on the object's class. This method should return values
-natively serializable by ``json.dumps`` (such as ints, lists, dictionaries,
-strings, and so forth).
+natively JSON-serializable (such as ints, lists, dictionaries, strings, and
+so forth). It should accept a single additional argument, ``request``, which
+will be the active request object at render time.
.. code-block:: python
:linenos:
@@ -250,7 +253,7 @@ strings, and so forth).
def __init__(self, x):
self.x = x
- def __json__(self):
+ def __json__(self, request):
return {'x':self.x}
@view_config(renderer='json')
@@ -260,20 +263,40 @@ strings, and so forth).
# the JSON value returned by ``objects`` will be:
# [{"x": 1}, {"x": 2}]
-.. note::
+If you aren't the author of the objects being serialized, it won't be
+possible (or at least not reasonable) to add a custom ``__json__`` method to
+to their classes in order to influence serialization. If the object passed
+to the renderer is not a serializable type, and has no ``__json__`` method,
+usually a :exc:`TypeError` will be raised during serialization. You can
+change this behavior by creating a custom JSON renderer and adding adapters
+to handle custom types. The renderer will attempt to adapt non-serializable
+objects using the registered adapters. A short example follows:
+
+.. code-block:: python
+ :linenos:
- Honoring the ``__json__`` method of custom objects is a feature new in
- Pyramid 1.4.
+ from pyramid.renderers import JSON
-.. warning::
+ json_renderer = JSON()
+ def datetime_adapter(obj, request):
+ return obj.isoformat()
+ json_renderer.add_adapter(datetime.datetime, datetime_adapter)
+
+ # then during configuration ....
+ config = Configurator()
+ config.add_renderer('json', json_renderer)
+
+The adapter should accept two arguments: the object needing to be serialized
+and ``request``, which will be the current request object at render time.
+The adapter should raise a :exc:`TypeError` if it can't determine what to do
+with the object.
+
+See :class:`pyramid.renderers.JSON` and
+:ref:`adding_and_overriding_renderers` for more information.
+
+.. note::
- The machinery which performs the ``__json__`` method-calling magic is in
- the :class:`pyramid.renderers.ObjectJSONEncoder` class. This class will
- be used for encoding any non-basic Python object when you use the default
- ```json`` or ``jsonp`` renderers. But if you later define your own custom
- JSON renderer and pass it a "cls" argument signifying a different encoder,
- the encoder you pass will override Pyramid's use of
- :class:`pyramid.renderers.ObjectJSONEncoder`.
+ Serializing custom objects is a feature new in Pyramid 1.4.
.. index::
pair: renderer; JSONP
diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst
index 6ff9e3dea..1aa1b6341 100644
--- a/docs/narr/sessions.rst
+++ b/docs/narr/sessions.rst
@@ -151,13 +151,12 @@ Using Alternate Session Factories
---------------------------------
At the time of this writing, exactly one alternate session factory
-implementation exists, named ``pyramid_beaker``. This is a session
-factory that uses the `Beaker <http://beaker.groovie.org/>`_ library
-as a backend. Beaker has support for file-based sessions, database
-based sessions, and encrypted cookie-based sessions. See
-`http://github.com/Pylons/pyramid_beaker
-<http://github.com/Pylons/pyramid_beaker>`_ for more information about
-``pyramid_beaker``.
+implementation exists, named ``pyramid_beaker``. This is a session factory
+that uses the `Beaker <http://beaker.groovie.org/>`_ library as a backend.
+Beaker has support for file-based sessions, database based sessions, and
+encrypted cookie-based sessions. See `the pyramid_beaker documentation
+<http://docs.pylonsproject.org/projects/pyramid_beaker/en/latest/>`_ for more
+information about ``pyramid_beaker``.
.. index::
single: session factory (custom)
diff --git a/docs/narr/startup.rst b/docs/narr/startup.rst
index 8e28835af..f5c741f52 100644
--- a/docs/narr/startup.rst
+++ b/docs/narr/startup.rst
@@ -42,8 +42,8 @@ Here's a high-level time-ordered overview of what happens when you press
``[pipeline:main]``, or ``[composite:main]`` in the ``.ini`` file. This
section represents the configuration of a :term:`WSGI` application that
will be served. If you're using a simple application (e.g.
- ``[app:main]``), the application :term:`entry point` or :term:`dotted
- Python name` will be named on the ``use=`` line within the section's
+ ``[app:main]``), the application's ``paste.app_factory`` :term:`entry
+ point` will be named on the ``use=`` line within the section's
configuration. If, instead of a simple application, you're using a WSGI
:term:`pipeline` (e.g. a ``[pipeline:main]`` section), the application
named on the "last" element will refer to your :app:`Pyramid` application.
@@ -59,11 +59,11 @@ Here's a high-level time-ordered overview of what happens when you press
system for this application. See :ref:`logging_config` for more
information.
-#. The application's *constructor* named by the entry point reference or
- dotted Python name on the ``use=`` line of the section representing your
- :app:`Pyramid` application is passed the key/value parameters mentioned
- within the section in which it's defined. The constructor is meant to
- return a :term:`router` instance, which is a :term:`WSGI` application.
+#. The application's *constructor* named by the entry point reference on the
+ ``use=`` line of the section representing your :app:`Pyramid` application
+ is passed the key/value parameters mentioned within the section in which
+ it's defined. The constructor is meant to return a :term:`router`
+ instance, which is a :term:`WSGI` application.
For :app:`Pyramid` applications, the constructor will be a function named
``main`` in the ``__init__.py`` file within the :term:`package` in which
diff --git a/docs/narr/templates.rst b/docs/narr/templates.rst
index 9db0b1c4d..860010a1a 100644
--- a/docs/narr/templates.rst
+++ b/docs/narr/templates.rst
@@ -714,6 +714,22 @@ This template doesn't use any advanced features of Mako, only the
:term:`renderer globals`. See the `the Mako documentation
<http://www.makotemplates.org/>`_ to use more advanced features.
+Using def inside Mako Templates
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To use a def inside a Mako template, given a :term:`Mako` template file named
+``foo.mak`` and a def named ``bar``, you can configure the template as a
+:term:`renderer` like so:
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.view import view_config
+
+ @view_config(renderer='foo#bar.mak')
+ def my_view(request):
+ return {'project':'my project'}
+
.. index::
single: automatic reloading of templates
single: template automatic reload
diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst
index f036ce94e..ecf3d026a 100644
--- a/docs/narr/urldispatch.rst
+++ b/docs/narr/urldispatch.rst
@@ -547,7 +547,7 @@ add to your application:
config.add_route('idea', 'ideas/{idea}')
config.add_route('user', 'users/{user}')
- config.add_route('tag', 'tags/{tags}')
+ config.add_route('tag', 'tags/{tag}')
config.add_view('mypackage.views.idea_view', route_name='idea')
config.add_view('mypackage.views.user_view', route_name='user')
@@ -954,7 +954,7 @@ will be prepended with the first:
from pyramid.config import Configurator
def timing_include(config):
- config.add_route('show_times', /times')
+ config.add_route('show_times', '/times')
def users_include(config):
config.add_route('show_users', '/show')
@@ -966,7 +966,7 @@ will be prepended with the first:
In the above configuration, the ``show_users`` route will still have an
effective route pattern of ``/users/show``. The ``show_times`` route
-however, will have an effective pattern of ``/users/timing/show_times``.
+however, will have an effective pattern of ``/users/timing/times``.
Route prefixes have no impact on the requirement that the set of route
*names* in any given Pyramid configuration must be entirely unique. If you
@@ -981,7 +981,7 @@ that may be added in the future. For example:
from pyramid.config import Configurator
def timing_include(config):
- config.add_route('timing.show_times', /times')
+ config.add_route('timing.show_times', '/times')
def users_include(config):
config.add_route('users.show_users', '/show')
diff --git a/docs/tutorials/modwsgi/index.rst b/docs/tutorials/modwsgi/index.rst
index c2baa5bd8..d11167344 100644
--- a/docs/tutorials/modwsgi/index.rst
+++ b/docs/tutorials/modwsgi/index.rst
@@ -73,9 +73,10 @@ commands and files.
.. code-block:: python
- from pyramid.paster import get_app
- application = get_app(
- '/Users/chrism/modwsgi/env/myapp/production.ini', 'main')
+ from pyramid.paster import get_app, setup_logging
+ ini_path = '/Users/chrism/modwsgi/env/myapp/production.ini'
+ setup_logging(ini_path)
+ application = get_app(ini_path, 'main')
The first argument to ``get_app`` is the project configuration file
name. It's best to use the ``production.ini`` file provided by your
@@ -85,6 +86,10 @@ commands and files.
``application`` is important: mod_wsgi requires finding such an
assignment when it opens the file.
+ The call to ``setup_logging`` initializes the standard library's
+ `logging` module to allow logging within your application.
+ See :ref:`logging_config`.
+
#. Make the ``pyramid.wsgi`` script executable.
.. code-block:: text
@@ -99,7 +104,8 @@ commands and files.
.. code-block:: apache
# Use only 1 Python sub-interpreter. Multiple sub-interpreters
- # play badly with C extensions.
+ # play badly with C extensions. See
+ # http://stackoverflow.com/a/10558360/209039
WSGIApplicationGroup %{GLOBAL}
WSGIPassAuthorization On
WSGIDaemonProcess pyramid user=chrism group=staff threads=4 \
diff --git a/docs/tutorials/wiki/definingviews.rst b/docs/tutorials/wiki/definingviews.rst
index 12bfa8b84..529603546 100644
--- a/docs/tutorials/wiki/definingviews.rst
+++ b/docs/tutorials/wiki/definingviews.rst
@@ -229,60 +229,63 @@ this:
Adding Templates
================
-Most view callables we've added expected to be rendered via a
-:term:`template`. The default templating systems in :app:`Pyramid` are
-:term:`Chameleon` and :term:`Mako`. Chameleon is a variant of :term:`ZPT`,
-which is an XML-based templating language. Mako is a non-XML-based
-templating language. Because we had to pick one, we chose Chameleon for this
-tutorial.
-
-The templates we create will live in the ``templates`` directory of our
+The ``view_page``, ``add_page`` and ``edit_page`` views that we've added
+reference a :term:`template`. Each template is a :term:`Chameleon` :term:`ZPT`
+template. These templates will live in the ``templates`` directory of our
tutorial package. Chameleon templates must have a ``.pt`` extension to be
recognized as such.
The ``view.pt`` Template
------------------------
-The ``view.pt`` template is used for viewing a single Page. It is used by
-the ``view_page`` view function. It should have a div that is "structure
-replaced" with the ``content`` value provided by the view. It should also
-have a link on the rendered page that points at the "edit" URL (the URL which
-invokes the ``edit_page`` view for the page being viewed).
-
-Once we're done with the ``view.pt`` template, it will look a lot like
-the below:
+Create ``tutorial/tutorial/templates/view.pt`` and add the following
+content:
.. literalinclude:: src/views/tutorial/templates/view.pt
+ :linenos:
:language: xml
-.. note::
+This template is used by ``view_page()`` for displaying a single
+wiki page. It includes:
- 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
- templates make use of a ``request`` object that none of our tutorial views
- return in their dictionary. This value appears as if "by magic".
- However, ``request`` is one of several names that are available "by
- default" in a template when a template renderer is used. See
- :ref:`chameleon_template_renderers` for more information about other names
- that are available by default in a template when a template is used as a
- renderer.
+- A ``div`` element that is replaced with the ``content``
+ value provided by the view (rows 45-47). ``content``
+ contains HTML, so the ``structure`` keyword is used
+ to prevent escaping it (i.e. changing ">" to "&gt;", etc.)
+- A link that points
+ at the "edit" URL which invokes the ``edit_page`` view for
+ the page being viewed (rows 49-51).
The ``edit.pt`` Template
------------------------
-The ``edit.pt`` template is used for adding and editing a Page. It is used
-by the ``add_page`` and ``edit_page`` view functions. It should display a
-page containing a form that POSTs back to the "save_url" argument supplied by
-the view. The form should have a "body" textarea field (the page data), and
-a submit button that has the name "form.submitted". The textarea in the form
-should be filled with any existing page data when it is rendered.
-
-Once we're done with the ``edit.pt`` template, it will look a lot like the
-below:
+Create ``tutorial/tutorial/templates/edit.pt`` and add the following
+content:
.. literalinclude:: src/views/tutorial/templates/edit.pt
+ :linenos:
:language: xml
+This template is used by ``add_page()`` and ``edit_page()`` for adding
+and editing a wiki page. It displays
+a page containing a form that includes:
+
+- A 10 row by 60 column ``textarea`` field named ``body`` that is filled
+ with any existing page data when it is rendered (rows 46-47).
+- A submit button that has the name ``form.submitted`` (row 48).
+
+The form POSTs back to the "save_url" argument supplied
+by the view (row 45). The view will use the ``body`` and
+``form.submitted`` values.
+
+.. note:: Our templates use a ``request`` object that
+ none of our tutorial views return in their dictionary.
+ ``request`` is one of several
+ names that are available "by default" in a template when a template
+ renderer is used. See :ref:`chameleon_template_renderers` for
+ information about other names that are available by default
+ when a Chameleon template is used as a renderer.
+
Static Assets
-------------
@@ -302,24 +305,25 @@ Viewing the Application in a Browser
====================================
We can finally examine our application in a browser (See
-:ref:`wiki-start-the-application`). The views we'll try are as follows:
+:ref:`wiki-start-the-application`). Launch a browser and visit
+each of the following URLs, check that the result is as expected:
-- Visiting ``http://localhost:6543/`` in a browser invokes the ``view_wiki``
+- ``http://localhost:6543/`` invokes the ``view_wiki``
view. This always redirects to the ``view_page`` view of the ``FrontPage``
Page resource.
-- Visiting ``http://localhost:6543/FrontPage/`` in a browser invokes
+- ``http://localhost:6543/FrontPage/`` invokes
the ``view_page`` view of the front page resource. This is
- because it's the *default view* (a view without a ``name``) for Page
+ because it's the :term:`default view` (a view without a ``name``) for Page
resources.
-- Visiting ``http://localhost:6543/FrontPage/edit_page`` in a browser
+- ``http://localhost:6543/FrontPage/edit_page``
invokes the edit view for the ``FrontPage`` Page resource.
-- Visiting ``http://localhost:6543/add_page/SomePageName`` in a
- browser invokes the add view for a Page.
+- ``http://localhost:6543/add_page/SomePageName``
+ invokes the add view for a Page.
- To generate an error, visit ``http://localhost:6543/add_page`` which
- will generate an ``IndexError`` for the expression
- ``request.subpath[0]``. You'll see an interactive traceback
+ will generate an ``IndexErrorr: tuple index out of range`` error.
+ You'll see an interactive traceback
facility provided by :term:`pyramid_debugtoolbar`.
diff --git a/docs/tutorials/wiki/design.rst b/docs/tutorials/wiki/design.rst
index 2b613377a..c94612fb1 100644
--- a/docs/tutorials/wiki/design.rst
+++ b/docs/tutorials/wiki/design.rst
@@ -36,9 +36,16 @@ be used as the wiki home page.
Views
-----
-There will be four views to handle the normal operations of
-viewing, editing and adding wiki pages. Two additional views
-will handle the login and logout tasks related to security.
+There will be three views to handle the normal operations of adding,
+editing and viewing wiki pages, plus one view for the wiki front page.
+Two templates will be used, one for viewing, and one for both for adding
+and editing wiki pages.
+
+The default templating systems in :app:`Pyramid` are
+:term:`Chameleon` and :term:`Mako`. Chameleon is a variant of
+:term:`ZPT`, which is an XML-based templating language. Mako is a
+non-XML-based templating language. Because we had to pick one,
+we chose Chameleon for this tutorial.
Security
--------
@@ -52,11 +59,11 @@ use to do this are below.
- GROUPS, a dictionary mapping user names to a
list of groups they belong to.
-- *groupfinder*, an *authorization callback* that looks up
+- ``groupfinder``, an *authorization callback* that looks up
USERS and GROUPS. It will be provided in a new
*security.py* file.
-- An :term:`ACL` is attached to the root resource. Each
+- An :term:`ACL` is attached to the root :term:`resource`. Each
row below details an :term:`ACE`:
+----------+----------------+----------------+
@@ -70,6 +77,8 @@ use to do this are below.
- Permission declarations are added to the views to assert the security
policies as each request is handled.
+Two additional views and one template will handle the login and
+logout tasks.
Summary
-------
diff --git a/docs/tutorials/wiki/installation.rst b/docs/tutorials/wiki/installation.rst
index 63b30da5a..868c99dee 100644
--- a/docs/tutorials/wiki/installation.rst
+++ b/docs/tutorials/wiki/installation.rst
@@ -130,9 +130,10 @@ Preparation, Windows
Make a Project
==============
-Your next step is to create a project. :app:`Pyramid` supplies a variety of
-scaffolds to generate sample projects. For this tutorial, we will use the
-:term:`ZODB` -oriented scaffold named ``zodb``.
+Your next step is to create a project. For this tutorial, we will use the
+:term:`scaffold` named ``zodb``, which generates an application
+that uses :term:`ZODB` and :term:`traversal`. :app:`Pyramid`
+supplies a variety of scaffolds to generate sample projects.
The below instructions assume your current working directory is the
"virtualenv" named "pyramidtut".
diff --git a/docs/tutorials/wiki2/authorization.rst b/docs/tutorials/wiki2/authorization.rst
index 2ef55d15b..d7bd24a53 100644
--- a/docs/tutorials/wiki2/authorization.rst
+++ b/docs/tutorials/wiki2/authorization.rst
@@ -353,7 +353,7 @@ when we're done:
.. literalinclude:: src/authorization/tutorial/views.py
:linenos:
- :emphasize-lines: 11,14-18,31,37,58,61,73,76,88,91-117,119-123
+ :emphasize-lines: 11,14-18,25,31,37,58,61,73,76,88,91-117,119-123
:language: python
(Only the highlighted lines need to be added.)
diff --git a/docs/tutorials/wiki2/basiclayout.rst b/docs/tutorials/wiki2/basiclayout.rst
index 5f4ea671c..b3184c4fc 100644
--- a/docs/tutorials/wiki2/basiclayout.rst
+++ b/docs/tutorials/wiki2/basiclayout.rst
@@ -100,7 +100,7 @@ used when the URL is ``/``:
:language: py
Since this route has a ``pattern`` equalling ``/`` it is the route that will
-be matched when the URL ``/`` is visted, e.g. ``http://localhost:6543/``.
+be matched when the URL ``/`` is visited, e.g. ``http://localhost:6543/``.
``main`` next calls the ``scan`` method of the configurator, which will
recursively scan our ``tutorial`` package, looking for ``@view_config`` (and
@@ -190,7 +190,7 @@ Next we set up a SQLAlchemy "DBSession" object:
``scoped_session`` allows us to access our database connection globally.
``sessionmaker`` creates a database session object. We pass to
``sessionmaker`` the ``extension=ZopeTransactionExtension()`` extension
-option in order to allow the system to automatically manage datbase
+option in order to allow the system to automatically manage database
transactions. With ``ZopeTransactionExtension`` activated, our application
will automatically issue a transaction commit after every request unless an
exception is raised, in which case the transaction will be aborted.
diff --git a/docs/tutorials/wiki2/definingviews.rst b/docs/tutorials/wiki2/definingviews.rst
index ac58e1e46..24ac4338d 100644
--- a/docs/tutorials/wiki2/definingviews.rst
+++ b/docs/tutorials/wiki2/definingviews.rst
@@ -226,52 +226,63 @@ of the wiki page.
Adding Templates
================
-The views we've added all reference a :term:`template`. Each template is a
-:term:`Chameleon` :term:`ZPT` template. These templates will live in the
-``templates`` directory of our tutorial package.
+The ``view_page``, ``add_page`` and ``edit_page`` views that we've added
+reference a :term:`template`. Each template is a :term:`Chameleon` :term:`ZPT`
+template. These templates will live in the ``templates`` directory of our
+tutorial package. Chameleon templates must have a ``.pt`` extension to be
+recognized as such.
The ``view.pt`` Template
------------------------
-The ``view.pt`` template is used for viewing a single wiki page. It
-is used by the ``view_page`` view function. It should have a ``div``
-that is "structure replaced" with the ``content`` value provided by
-the view. It should also have a link on the rendered page that points
-at the "edit" URL (the URL which invokes the ``edit_page`` view for
-the page being viewed).
-
-Once we're done with the ``view.pt`` template, it will look a lot like the
-below:
+Create ``tutorial/tutorial/templates/view.pt`` and add the following
+content:
.. literalinclude:: src/views/tutorial/templates/view.pt
+ :linenos:
:language: xml
-.. 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 templates make use of a ``request`` object that
- none of our tutorial views return in their dictionary. This value
- appears as if "by magic". However, ``request`` is one of several
- names that are available "by default" in a template when a template
- renderer is used. See :ref:`chameleon_template_renderers` for more
- information about other names that are available by default in a
- template when a Chameleon template is used as a renderer.
+This template is used by ``view_page()`` for displaying a single
+wiki page. It includes:
+
+- A ``div`` element that is replaced with the ``content``
+ value provided by the view (rows 45-47). ``content``
+ contains HTML, so the ``structure`` keyword is used
+ to prevent escaping it (i.e. changing ">" to "&gt;", etc.)
+- A link that points
+ at the "edit" URL which invokes the ``edit_page`` view for
+ the page being viewed (rows 49-51).
The ``edit.pt`` Template
------------------------
-The ``edit.pt`` template is used for adding and editing a wiki page. It is
-used by the ``add_page`` and ``edit_page`` view functions. It should display
-a page containing a form that POSTs back to the "save_url" argument supplied
-by the view. The form should have a "body" textarea field (the page data),
-and a submit button that has the name "form.submitted". The textarea in the
-form should be filled with any existing page data when it is rendered.
-
-Once we're done with the ``edit.pt`` template, it will look a lot like
-the following:
+Create ``tutorial/tutorial/templates/edit.pt`` and add the following
+content:
.. literalinclude:: src/views/tutorial/templates/edit.pt
+ :linenos:
:language: xml
+This template is used by ``add_page()`` and ``edit_page()`` for adding
+and editing a wiki page. It displays
+a page containing a form that includes:
+
+- A 10 row by 60 column ``textarea`` field named ``body`` that is filled
+ with any existing page data when it is rendered (rows 46-47).
+- A submit button that has the name ``form.submitted`` (row 48).
+
+The form POSTs back to the "save_url" argument supplied
+by the view (row 45). The view will use the ``body`` and
+``form.submitted`` values.
+
+.. note:: Our templates use a ``request`` object that
+ none of our tutorial views return in their dictionary.
+ ``request`` is one of several
+ names that are available "by default" in a template when a template
+ renderer is used. See :ref:`chameleon_template_renderers` for
+ information about other names that are available by default
+ when a Chameleon template is used as a renderer.
+
Static Assets
-------------
@@ -339,25 +350,24 @@ Viewing the Application in a Browser
====================================
We can finally examine our application in a browser (See
-:ref:`wiki2-start-the-application`). The views we'll try are
-as follows:
+:ref:`wiki2-start-the-application`). Launch a browser and visit
+each of the following URLs, check that the result is as expected:
-- Visiting ``http://localhost:6543`` in a browser invokes the
+- ``http://localhost:6543`` in a browser invokes the
``view_wiki`` view. This always redirects to the ``view_page`` view
of the FrontPage page object.
-- Visiting ``http://localhost:6543/FrontPage`` in a browser invokes
+- ``http://localhost:6543/FrontPage`` in a browser invokes
the ``view_page`` view of the front page page object.
-- Visiting ``http://localhost:6543/FrontPage/edit_page`` in a browser
+- ``http://localhost:6543/FrontPage/edit_page`` in a browser
invokes the edit view for the front page object.
-- Visiting ``http://localhost:6543/add_page/SomePageName`` in a
+- ``http://localhost:6543/add_page/SomePageName`` in a
browser invokes the add view for a page.
-Try generating an error within the body of a view by adding code to
-the top of it that generates an exception (e.g. ``raise
-Exception('Forced Exception')``). Then visit the error-raising view
-in a browser. You should see an interactive exception handler in the
-browser which allows you to examine values in a post-mortem mode.
+- To generate an error, visit ``http://localhost:6543/add_page`` which
+ will generate a ``NoResultFound: No row was found for one()`` error.
+ You'll see an interactive traceback facility provided
+ by :term:`pyramid_debugtoolbar`.
diff --git a/docs/tutorials/wiki2/design.rst b/docs/tutorials/wiki2/design.rst
index 4481153a3..deaf32ef6 100644
--- a/docs/tutorials/wiki2/design.rst
+++ b/docs/tutorials/wiki2/design.rst
@@ -20,7 +20,7 @@ Models
We'll be using a SQLite database to hold our wiki data, and we'll be using
:term:`SQLAlchemy` to access the data in this database.
-Within the database, we define a single table named `tables`, whose elements
+Within the database, we define a single table named `pages`, whose elements
will store the wiki pages. There are two columns: `name` and `data`.
URLs like ``/PageName`` will try to find an element in
@@ -36,9 +36,16 @@ page.
Views
-----
-There will be four views to handle the normal operations of adding and
-editing wiki pages, and viewing pages and the wiki front page. Two
-additional views will handle the login and logout tasks related to security.
+There will be three views to handle the normal operations of adding,
+editing and viewing wiki pages, plus one view for the wiki front page.
+Two templates will be used, one for viewing, and one for both for adding
+and editing wiki pages.
+
+The default templating systems in :app:`Pyramid` are
+:term:`Chameleon` and :term:`Mako`. Chameleon is a variant of
+:term:`ZPT`, which is an XML-based templating language. Mako is a
+non-XML-based templating language. Because we had to pick one,
+we chose Chameleon for this tutorial.
Security
--------
@@ -67,6 +74,8 @@ use to do this are below.
- Permission declarations are added to the views to assert the security
policies as each request is handled.
+Two additional views and one template will handle the login and
+logout tasks.
Summary
-------
diff --git a/docs/tutorials/wiki2/installation.rst b/docs/tutorials/wiki2/installation.rst
index 4ee2728c2..6589a1557 100644
--- a/docs/tutorials/wiki2/installation.rst
+++ b/docs/tutorials/wiki2/installation.rst
@@ -67,10 +67,10 @@ Preparation, Windows
Making a Project
================
-Your next step is to create a project. :app:`Pyramid` supplies a
-variety of scaffolds to generate sample projects. We will use the
-``alchemy`` scaffold, which generates an application
-that uses :term:`SQLAlchemy` and :term:`URL dispatch`.
+Your next step is to create a project. For this tutorial, we will use the
+:term:`scaffold` named ``alchemy``, which generates an application
+that uses :term:`SQLAlchemy` and :term:`URL dispatch`. :app:`Pyramid`
+supplies a variety of scaffolds to generate sample projects.
The below instructions assume your current working directory is the
"virtualenv" named "pyramidtut".
@@ -254,7 +254,7 @@ The output to your console should be something like this::
2011-11-26 14:42:25,140 INFO [sqlalchemy.engine.base.Engine][MainThread]
COMMIT
-Success! You should now have a ``tutorial.db`` file in your current working
+Success! You should now have a ``tutorial.sqlite`` file in your current working
directory. This will be a SQLite database with a single table defined in it
(``models``).
diff --git a/docs/tutorials/wiki2/src/authorization/development.ini b/docs/tutorials/wiki2/src/authorization/development.ini
index 38738f3c6..eb2f878c5 100644
--- a/docs/tutorials/wiki2/src/authorization/development.ini
+++ b/docs/tutorials/wiki2/src/authorization/development.ini
@@ -10,7 +10,7 @@ pyramid.includes =
pyramid_debugtoolbar
pyramid_tm
-sqlalchemy.url = sqlite:///%(here)s/tutorial.db
+sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite
[server:main]
use = egg:waitress#main
diff --git a/docs/tutorials/wiki2/src/authorization/production.ini b/docs/tutorials/wiki2/src/authorization/production.ini
index c4034abad..4684d2f7a 100644
--- a/docs/tutorials/wiki2/src/authorization/production.ini
+++ b/docs/tutorials/wiki2/src/authorization/production.ini
@@ -9,7 +9,7 @@ pyramid.default_locale_name = en
pyramid.includes =
pyramid_tm
-sqlalchemy.url = sqlite:///%(here)s/tutorial.db
+sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite
[server:main]
use = egg:waitress#main
diff --git a/docs/tutorials/wiki2/src/basiclayout/development.ini b/docs/tutorials/wiki2/src/basiclayout/development.ini
index 38738f3c6..eb2f878c5 100644
--- a/docs/tutorials/wiki2/src/basiclayout/development.ini
+++ b/docs/tutorials/wiki2/src/basiclayout/development.ini
@@ -10,7 +10,7 @@ pyramid.includes =
pyramid_debugtoolbar
pyramid_tm
-sqlalchemy.url = sqlite:///%(here)s/tutorial.db
+sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite
[server:main]
use = egg:waitress#main
diff --git a/docs/tutorials/wiki2/src/basiclayout/production.ini b/docs/tutorials/wiki2/src/basiclayout/production.ini
index c4034abad..4684d2f7a 100644
--- a/docs/tutorials/wiki2/src/basiclayout/production.ini
+++ b/docs/tutorials/wiki2/src/basiclayout/production.ini
@@ -9,7 +9,7 @@ pyramid.default_locale_name = en
pyramid.includes =
pyramid_tm
-sqlalchemy.url = sqlite:///%(here)s/tutorial.db
+sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite
[server:main]
use = egg:waitress#main
diff --git a/docs/tutorials/wiki2/src/models/development.ini b/docs/tutorials/wiki2/src/models/development.ini
index 38738f3c6..eb2f878c5 100644
--- a/docs/tutorials/wiki2/src/models/development.ini
+++ b/docs/tutorials/wiki2/src/models/development.ini
@@ -10,7 +10,7 @@ pyramid.includes =
pyramid_debugtoolbar
pyramid_tm
-sqlalchemy.url = sqlite:///%(here)s/tutorial.db
+sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite
[server:main]
use = egg:waitress#main
diff --git a/docs/tutorials/wiki2/src/models/production.ini b/docs/tutorials/wiki2/src/models/production.ini
index c4034abad..4684d2f7a 100644
--- a/docs/tutorials/wiki2/src/models/production.ini
+++ b/docs/tutorials/wiki2/src/models/production.ini
@@ -9,7 +9,7 @@ pyramid.default_locale_name = en
pyramid.includes =
pyramid_tm
-sqlalchemy.url = sqlite:///%(here)s/tutorial.db
+sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite
[server:main]
use = egg:waitress#main
diff --git a/docs/tutorials/wiki2/src/tests/development.ini b/docs/tutorials/wiki2/src/tests/development.ini
index 38738f3c6..eb2f878c5 100644
--- a/docs/tutorials/wiki2/src/tests/development.ini
+++ b/docs/tutorials/wiki2/src/tests/development.ini
@@ -10,7 +10,7 @@ pyramid.includes =
pyramid_debugtoolbar
pyramid_tm
-sqlalchemy.url = sqlite:///%(here)s/tutorial.db
+sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite
[server:main]
use = egg:waitress#main
diff --git a/docs/tutorials/wiki2/src/tests/production.ini b/docs/tutorials/wiki2/src/tests/production.ini
index c4034abad..4684d2f7a 100644
--- a/docs/tutorials/wiki2/src/tests/production.ini
+++ b/docs/tutorials/wiki2/src/tests/production.ini
@@ -9,7 +9,7 @@ pyramid.default_locale_name = en
pyramid.includes =
pyramid_tm
-sqlalchemy.url = sqlite:///%(here)s/tutorial.db
+sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite
[server:main]
use = egg:waitress#main
diff --git a/docs/tutorials/wiki2/src/views/development.ini b/docs/tutorials/wiki2/src/views/development.ini
index 38738f3c6..eb2f878c5 100644
--- a/docs/tutorials/wiki2/src/views/development.ini
+++ b/docs/tutorials/wiki2/src/views/development.ini
@@ -10,7 +10,7 @@ pyramid.includes =
pyramid_debugtoolbar
pyramid_tm
-sqlalchemy.url = sqlite:///%(here)s/tutorial.db
+sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite
[server:main]
use = egg:waitress#main
diff --git a/docs/tutorials/wiki2/src/views/production.ini b/docs/tutorials/wiki2/src/views/production.ini
index c4034abad..4684d2f7a 100644
--- a/docs/tutorials/wiki2/src/views/production.ini
+++ b/docs/tutorials/wiki2/src/views/production.ini
@@ -9,7 +9,7 @@ pyramid.default_locale_name = en
pyramid.includes =
pyramid_tm
-sqlalchemy.url = sqlite:///%(here)s/tutorial.db
+sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite
[server:main]
use = egg:waitress#main