summaryrefslogtreecommitdiff
path: root/docs/narr
diff options
context:
space:
mode:
Diffstat (limited to 'docs/narr')
-rw-r--r--docs/narr/MyProject/myproject/__init__.py1
-rw-r--r--docs/narr/MyProject/myproject/templates/mytemplate.pt4
-rw-r--r--docs/narr/MyProject/setup.py1
-rw-r--r--docs/narr/advconfig.rst13
-rw-r--r--docs/narr/assets.rst32
-rw-r--r--docs/narr/commandline.rst88
-rw-r--r--docs/narr/configuration.rst1
-rw-r--r--docs/narr/environment.rst12
-rw-r--r--docs/narr/events.rst93
-rw-r--r--docs/narr/extconfig.rst8
-rw-r--r--docs/narr/extending.rst8
-rw-r--r--docs/narr/firstapp.rst7
-rw-r--r--docs/narr/hooks.rst160
-rw-r--r--docs/narr/hybrid.rst102
-rw-r--r--docs/narr/i18n.rst146
-rw-r--r--docs/narr/install.rst380
-rw-r--r--docs/narr/introduction.rst51
-rw-r--r--docs/narr/introspector.rst18
-rw-r--r--docs/narr/logging.rst30
-rw-r--r--docs/narr/muchadoabouttraversal.rst18
-rw-r--r--docs/narr/paste.rst4
-rw-r--r--docs/narr/project.rst181
-rw-r--r--docs/narr/renderers.rst319
-rw-r--r--docs/narr/resources.rst4
-rw-r--r--docs/narr/router.rst2
-rw-r--r--docs/narr/scaffolding.rst12
-rw-r--r--docs/narr/security.rst37
-rw-r--r--docs/narr/sessions.rst158
-rw-r--r--docs/narr/startup.rst10
-rw-r--r--docs/narr/subrequest.rst16
-rw-r--r--docs/narr/templates.rst439
-rw-r--r--docs/narr/testing.rst29
-rw-r--r--docs/narr/threadlocals.rst5
-rw-r--r--docs/narr/traversal.rst59
-rw-r--r--docs/narr/upgrading.rst4
-rw-r--r--docs/narr/urldispatch.rst69
-rw-r--r--docs/narr/viewconfig.rst88
-rw-r--r--docs/narr/views.rst47
-rw-r--r--docs/narr/webob.rst8
-rw-r--r--docs/narr/zca.rst12
40 files changed, 1220 insertions, 1456 deletions
diff --git a/docs/narr/MyProject/myproject/__init__.py b/docs/narr/MyProject/myproject/__init__.py
index 6c512f52f..ad5ecbc6f 100644
--- a/docs/narr/MyProject/myproject/__init__.py
+++ b/docs/narr/MyProject/myproject/__init__.py
@@ -5,6 +5,7 @@ def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
config = Configurator(settings=settings)
+ config.include('pyramid_chameleon')
config.add_static_view('static', 'static', cache_max_age=3600)
config.add_route('home', '/')
config.scan()
diff --git a/docs/narr/MyProject/myproject/templates/mytemplate.pt b/docs/narr/MyProject/myproject/templates/mytemplate.pt
index 0bfac946e..0fccba624 100644
--- a/docs/narr/MyProject/myproject/templates/mytemplate.pt
+++ b/docs/narr/MyProject/myproject/templates/mytemplate.pt
@@ -1,7 +1,7 @@
<!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>
+ <title>The Pyramid Web 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" />
@@ -24,7 +24,7 @@
<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.
+ the Pyramid Web Framework.
</p>
</div>
</div>
diff --git a/docs/narr/MyProject/setup.py b/docs/narr/MyProject/setup.py
index 6969c73e7..a23f46c91 100644
--- a/docs/narr/MyProject/setup.py
+++ b/docs/narr/MyProject/setup.py
@@ -10,6 +10,7 @@ with open(os.path.join(here, 'CHANGES.txt')) as f:
requires = [
'pyramid',
+ 'pyramid_chameleon',
'pyramid_debugtoolbar',
'waitress',
]
diff --git a/docs/narr/advconfig.rst b/docs/narr/advconfig.rst
index ba43f3ea6..d3431e39e 100644
--- a/docs/narr/advconfig.rst
+++ b/docs/narr/advconfig.rst
@@ -148,14 +148,14 @@ one:
config.add_route(...)
Don't call this function directly with ``config`` as an argument. Instead,
-use :meth:`pyramid.config.Configuration.include`:
+use :meth:`pyramid.config.Configurator.include`:
.. code-block:: python
:linenos:
config.include(add_routes)
-Using :meth:`~pyramid.config.Configuration.include` instead of calling the
+Using :meth:`~pyramid.config.Configurator.include` instead of calling the
function directly provides a modicum of automated conflict resolution, with
the configuration statements you define in the calling code overriding those
of the included function. See also :ref:`automatic_conflict_resolution` and
@@ -302,7 +302,6 @@ These are the methods of the configurator which provide conflict detection:
:meth:`~pyramid.config.Configurator.set_view_mapper`,
:meth:`~pyramid.config.Configurator.set_authentication_policy`,
:meth:`~pyramid.config.Configurator.set_authorization_policy`,
-:meth:`~pyramid.config.Configurator.set_renderer_globals_factory`,
:meth:`~pyramid.config.Configurator.set_locale_negotiator`,
:meth:`~pyramid.config.Configurator.set_default_permission`,
:meth:`~pyramid.config.Configurator.add_traverser`,
@@ -333,7 +332,7 @@ his application:
config.add_route(...)
Rather than calling this function directly with ``config`` as an argument.
-Instead, use :meth:`pyramid.config.Configuration.include`:
+Instead, use :meth:`pyramid.config.Configurator.include`:
.. code-block:: python
:linenos:
@@ -343,7 +342,7 @@ 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`
+:meth:`~pyramid.config.Configurator.include` can also accept a :term:`module`
as an argument:
.. code-block:: python
@@ -357,7 +356,7 @@ 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
+:meth:`~pyramid.config.Configurator.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
@@ -417,7 +416,7 @@ added in configuration execution order.
More Information
----------------
-For more information, see the article,`"A Whirlwind Tour of Advanced
+For more information, see the article, `"A Whirlwind Tour of Advanced
Configuration Tactics"
<http://docs.pylonsproject.org/projects/pyramid_cookbook/en/latest/configuration/whirlwind_tour.html>`_,
in the Pyramid Cookbook.
diff --git a/docs/narr/assets.rst b/docs/narr/assets.rst
index 7b620548d..b0a8d18b0 100644
--- a/docs/narr/assets.rst
+++ b/docs/narr/assets.rst
@@ -50,7 +50,6 @@ application might address the asset using the :term:`asset specification`
``myapp:templates/some_template.pt`` using that API within a ``views.py``
file inside a ``myapp`` package:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -120,7 +119,7 @@ from the ``/var/www/static`` directory of the computer which runs the
# config is an instance of pyramid.config.Configurator
config.add_static_view(name='static', path='/var/www/static')
-The ``name`` prepresents a URL *prefix*. In order for files that live in the
+The ``name`` represents a URL *prefix*. In order for files that live in the
``path`` directory to be served, a URL that requests one of them must begin
with that prefix. In the example above, ``name`` is ``static``, and ``path``
is ``/var/www/static``. In English, this means that you wish to serve the
@@ -228,14 +227,14 @@ API to generate them for you. For example:
.. code-block:: python
:linenos:
- from pyramid.chameleon_zpt import render_template_to_response
+ from pyramid.renderers import render_to_response
def my_view(request):
css_url = request.static_url('mypackage:assets/1/foo.css')
js_url = request.static_url('mypackage:assets/2/foo.js')
- return render_template_to_response('templates/my_template.pt',
- css_url = css_url,
- js_url = js_url)
+ return render_to_response('templates/my_template.pt',
+ dict(css_url=css_url, js_url=js_url),
+ request=request)
If the request "application URL" of the running system is
``http://example.com``, the ``css_url`` generated above would be:
@@ -272,7 +271,7 @@ assets which begin with ``mypackage:images`` will be prefixed with
# -> http://example.com/images/logo.png
Using :meth:`~pyramid.request.Request.static_url` in conjunction with a
-:meth:`~pyramid.configuration.Configurator.add_static_view` makes it possible
+:meth:`~pyramid.config.Configurator.add_static_view` makes it possible
to put static media on a separate webserver during production (if the
``name`` argument to :meth:`~pyramid.config.Configurator.add_static_view` is
a URL), while keeping static media package-internal and served by the
@@ -323,7 +322,7 @@ its behavior is almost exactly the same once it's configured.
``add_view`` (at least those without a ``route_name``). A
:class:`~pyramid.static.static_view` static view cannot be made
root-relative when you use traversal unless it's registered as a
- :term:`Not Found view`.
+ :term:`Not Found View`.
To serve files within a directory located on your filesystem at
``/path/to/static/dir`` as the result of a "catchall" route hanging from the
@@ -331,14 +330,15 @@ root that exists at the end of your routing table, create an instance of the
:class:`~pyramid.static.static_view` class inside a ``static.py`` file in
your application root as below.
-.. ignore-next-block
.. code-block:: python
:linenos:
from pyramid.static import static_view
static_view = static_view('/path/to/static/dir', use_subpath=True)
-.. note:: For better cross-system flexibility, use an :term:`asset
+.. note::
+
+ For better cross-system flexibility, use an :term:`asset
specification` as the argument to :class:`~pyramid.static.static_view`
instead of a physical absolute filesystem path, e.g. ``mypackage:static``
instead of ``/path/to/mypackage/static``.
@@ -434,9 +434,9 @@ feature, a :term:`Configurator` API exists named
:meth:`pyramid.config.Configurator.override_asset`. This API allows you to
*override* the following kinds of assets defined in any Python package:
-- Individual :term:`Chameleon` templates.
+- Individual template files.
-- A directory containing multiple Chameleon templates.
+- A directory containing multiple template files.
- Individual static files served up by an instance of the
``pyramid.static.static_view`` helper class.
@@ -458,13 +458,12 @@ The ``override_asset`` API
An individual call to :meth:`~pyramid.config.Configurator.override_asset`
can override a single asset. For example:
-.. ignore-next-block
.. code-block:: python
:linenos:
config.override_asset(
- to_override='some.package:templates/mytemplate.pt',
- override_with='another.package:othertemplates/anothertemplate.pt')
+ to_override='some.package:templates/mytemplate.pt',
+ override_with='another.package:othertemplates/anothertemplate.pt')
The string value passed to both ``to_override`` and ``override_with`` sent to
the ``override_asset`` API is called an :term:`asset specification`. The
@@ -473,7 +472,6 @@ colon separator in a specification separates the *package name* from the
are not specified, the override attempts to resolve every lookup into a
package from the directory of another package. For example:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -482,7 +480,6 @@ package from the directory of another package. For example:
Individual subdirectories within a package can also be overridden:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -511,7 +508,6 @@ construction file resides (or the ``package`` argument to the
:class:`~pyramid.config.Configurator` class construction).
For example:
-.. ignore-next-block
.. code-block:: python
:linenos:
diff --git a/docs/narr/commandline.rst b/docs/narr/commandline.rst
index 5c4d58548..0984b4daf 100644
--- a/docs/narr/commandline.rst
+++ b/docs/narr/commandline.rst
@@ -32,7 +32,7 @@ Here is an example for a simple view configuration using :term:`traversal`:
.. code-block:: text
:linenos:
- $ ../bin/pviews development.ini#tutorial /FrontPage
+ $ $VENV/bin/pviews development.ini#tutorial /FrontPage
URL = /FrontPage
@@ -56,7 +56,7 @@ A more complex configuration might generate something like this:
.. code-block:: text
:linenos:
- $ ../bin/pviews development.ini#shootout /about
+ $ $VENV/bin/pviews development.ini#shootout /about
URL = /about
@@ -146,7 +146,7 @@ name ``main`` as a section name:
.. code-block:: text
- chrism@thinko env26]$ bin/pshell starter/development.ini#main
+ $ $VENV/bin starter/development.ini#main
Python 2.6.5 (r265:79063, Apr 29 2010, 00:31:32)
[GCC 4.4.3] on linux2
Type "help" for more information.
@@ -172,8 +172,8 @@ name ``main`` as a section name:
The WSGI application that is loaded will be available in the shell as the
``app`` global. Also, if the application that is loaded is the :app:`Pyramid`
-app with no surrounding middleware, the ``root`` object returned by the
-default :term:`root factory`, ``registry``, and ``request`` will be
+app with no surrounding :term:`middleware`, the ``root`` object returned by
+the default :term:`root factory`, ``registry``, and ``request`` will be
available.
You can also simply rely on the ``main`` default section name by omitting any
@@ -181,7 +181,7 @@ hash after the filename:
.. code-block:: text
- chrism@thinko env26]$ bin/pshell starter/development.ini
+ $ $VENV/bin/pshell starter/development.ini
Press ``Ctrl-D`` to exit the interactive shell (or ``Ctrl-Z`` on Windows).
@@ -244,7 +244,7 @@ exposed, and the request is configured to generate urls from the host
.. code-block:: text
- chrism@thinko env26]$ bin/pshell starter/development.ini
+ $ $VENV/bin/pshell starter/development.ini
Python 2.6.5 (r265:79063, Apr 29 2010, 00:31:32)
[GCC 4.4.3] on linux2
Type "help" for more information.
@@ -286,8 +286,7 @@ specifically invoke one of your choice with the ``-p choice`` or
.. code-block:: text
- [chrism@vitaminf shellenv]$ ../bin/pshell -p ipython | bpython | python \
- development.ini#MyProject
+ $ $VENV/bin/pshell -p ipython | bpython | python development.ini#MyProject
.. index::
pair: routes; printing
@@ -312,7 +311,7 @@ For example:
.. code-block:: text
:linenos:
- [chrism@thinko MyProject]$ ../bin/proutes development.ini
+ $ $VENV/bin/proutes development.ini
Name Pattern View
---- ------- ----
home / <function my_view>
@@ -321,8 +320,8 @@ For example:
static/ static/*subpath <static_view object>
catchall /*subpath <function static_view>
-``proutes`` generates a table. The table has three columns: a Name
-column, a Pattern column, and a View column. The items listed in the
+``proutes`` generates a table with three columns: *Name*, *Pattern*,
+and *View*. The items listed in the
Name column are route names, the items listed in the Pattern column are route
patterns, and the items listed in the View column are representations of the
view callable that will be invoked when a request matches the associated
@@ -355,7 +354,7 @@ configured without any explicit tweens:
.. code-block:: text
:linenos:
- [chrism@thinko pyramid]$ myenv/bin/ptweens development.ini
+ $ $VENV/bin/ptweens development.ini
"pyramid.tweens" config value NOT set (implicitly ordered tweens used)
Implicit Tween Chain
@@ -373,7 +372,7 @@ explicit tweens defined in its ``development.ini`` file:
.. code-block:: text
:linenos:
- [chrism@thinko pyramid]$ ptweens development.ini
+ $ ptweens development.ini
"pyramid.tweens" config value set (explicitly ordered tweens used)
Explicit Tween Chain (used)
@@ -399,7 +398,7 @@ Here's the application configuration section of the ``development.ini`` used
by the above ``ptweens`` command which reports that the explicit tween chain
is used:
-.. code-block:: text
+.. code-block:: ini
:linenos:
[app:main]
@@ -442,7 +441,7 @@ There are two required arguments to ``prequest``:
For example::
- $ bin/prequest development.ini /
+ $ $VENV/bin/prequest development.ini /
This will print the body of the response to the console on which it was
invoked.
@@ -453,14 +452,14 @@ config file name or URL.
``prequest`` has a ``-d`` (aka ``--display-headers``) option which prints the
status and headers returned by the server before the output::
- $ bin/prequest -d development.ini /
+ $ $VENV/bin/prequest -d development.ini /
This will print the status, then the headers, then the body of the response
to the console.
You can add request header values by using the ``--header`` option::
- $ bin/prequest --header=Host:example.com development.ini /
+ $ $VENV/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``
@@ -473,7 +472,42 @@ using the ``-m`` (aka ``--method``) option. ``GET``, ``HEAD``, ``POST`` and
``DELETE`` are currently supported. When you use ``POST``, the standard
input of the ``prequest`` process is used as the ``POST`` body::
- $ bin/prequest -mPOST development.ini / < somefile
+ $ $VENV/bin/prequest -mPOST development.ini / < somefile
+
+Using Custom Arguments to Python when Running ``p*`` Scripts
+------------------------------------------------------------
+
+.. versionadded:: 1.5
+
+Each of Pyramid's console scripts (``pserve``, ``pviews``, etc) can be run
+directly using ``python -m``, allowing custom arguments to be sent to the
+python interpreter at runtime. For example::
+
+ python -3 -m pyramid.scripts.pserve development.ini
+
+Showing All Installed Distributions and their Versions
+------------------------------------------------------
+
+.. versionadded:: 1.5
+
+You can use the ``pdistreport`` command to show the Pyramid version in use, the
+Python version in use, and all installed versions of Python distributions in
+your Python environment::
+
+ $ $VENV/bin/pdistreport
+ Pyramid version: 1.5dev
+ Platform Linux-3.2.0-51-generic-x86_64-with-debian-wheezy-sid
+ Packages:
+ authapp 0.0
+ /home/chrism/projects/foo/src/authapp
+ beautifulsoup4 4.1.3
+ /home/chrism/projects/foo/lib/python2.7/site-packages/beautifulsoup4-4.1.3-py2.7.egg
+ ... more output ...
+
+``pdistreport`` takes no options. Its output is useful to paste into a
+pastebin when you are having problems and need someone with more familiarity
+with Python packaging and distribution than you have to look at your
+environment.
.. _writing_a_script:
@@ -515,7 +549,7 @@ representing Pyramid your application configuration as a single argument:
from pyramid.paster import bootstrap
env = bootstrap('/path/to/my/development.ini')
- print env['request'].route_url('home')
+ print(env['request'].route_url('home'))
:func:`pyramid.paster.bootstrap` returns a dictionary containing
framework-related information. This dictionary will always contain a
@@ -573,8 +607,8 @@ configuration implied by the ``[pipeline:main]`` section of your
configuration file by default. Specifying ``/path/to/my/development.ini`` is
logically equivalent to specifying ``/path/to/my/development.ini#main``. In
this case, we'll be using a configuration that includes an ``app`` object
-which is wrapped in the Paste "translogger" middleware (which logs requests
-to the console).
+which is wrapped in the Paste "translogger" :term:`middleware` (which logs
+requests to the console).
You can also specify a particular *section* of the PasteDeploy ``.ini`` file
to load instead of ``main``:
@@ -583,7 +617,7 @@ to load instead of ``main``:
from pyramid.paster import bootstrap
env = bootstrap('/path/to/my/development.ini#another')
- print env['request'].route_url('home')
+ print(env['request'].route_url('home'))
The above example specifies the ``another`` ``app``, ``pipeline``, or
``composite`` section of your PasteDeploy configuration file. The ``app``
@@ -620,7 +654,7 @@ the desired request and passing it into :func:`~pyramid.paster.bootstrap`:
request = Request.blank('/', base_url='https://example.com/prefix')
env = bootstrap('/path/to/my/development.ini#another', request=request)
- print env['request'].application_url
+ print(env['request'].application_url)
# will print 'https://example.com/prefix'
Now you can readily use Pyramid's APIs for generating URLs:
@@ -867,7 +901,7 @@ The result will be something like:
""",
)
-Once you've done this, invoking ``$somevirtualenv/bin/python setup.py
+Once you've done this, invoking ``$$VENV/bin/python setup.py
develop`` will install a file named ``show_settings`` into the
``$somevirtualenv/bin`` directory with a small bit of Python code that points
to your entry point. It will be executable. Running it without any
@@ -878,9 +912,7 @@ with ``foo``. Running it with two "omit" options (e.g. ``--omit=foo
--omit=bar``) will omit all settings that have keys that start with either
``foo`` or ``bar``::
- [chrism@thinko somevenv]$ bin/show_settings development.ini \
- --omit=pyramid \
- --omit=debugtoolbar
+ $ $VENV/bin/show_settings development.ini --omit=pyramid --omit=debugtoolbar
debug_routematch False
debug_templates True
reload_templates True
diff --git a/docs/narr/configuration.rst b/docs/narr/configuration.rst
index 6f82baf32..f7a69d613 100644
--- a/docs/narr/configuration.rst
+++ b/docs/narr/configuration.rst
@@ -140,7 +140,6 @@ In the example above, the scanner translates the arguments to
:class:`~pyramid.view.view_config` into a call to the
:meth:`pyramid.config.Configurator.add_view` method, effectively:
-.. ignore-next-block
.. code-block:: python
config.add_view(hello)
diff --git a/docs/narr/environment.rst b/docs/narr/environment.rst
index fb3c3d7e3..f0c0c18fe 100644
--- a/docs/narr/environment.rst
+++ b/docs/narr/environment.rst
@@ -212,7 +212,7 @@ sequence can take several different forms.
package1 package2 package3
- The package names can also be separated by carriage returns::
+ The package names can also be separated by carriage returns::
package1
package2
@@ -302,7 +302,7 @@ Ideally, you won't need to use the ``pyramid.tweens`` setting at all. Tweens
are generally ordered and included "implicitly" when an add-on package which
registers a tween is "included". Packages are included when you name a
``pyramid.includes`` setting in your configuration or when you call
-:meth:`pyramid.config.Configuration.include`.
+:meth:`pyramid.config.Configurator.include`.
Authors of included add-ons provide "implicit" tween configuration ordering
hints to Pyramid when their packages are included. However, the implicit
@@ -546,7 +546,7 @@ for settings documented as such. For example, you might start your
.. code-block:: text
$ PYRAMID_DEBUG_AUTHORIZATION=1 PYRAMID_RELOAD_TEMPLATES=1 \
- bin/pserve MyProject.ini
+ $VENV/bin/pserve MyProject.ini
If you started your application this way, your :app:`Pyramid`
application would behave in the same manner as if you had placed the
@@ -666,9 +666,9 @@ Here's how:
def includeme(config):
settings = config.registry.settings
debug_frobnosticator = settings['debug_frobnosticator']
-
-- In the runtime code that you need to access the new settings value, find
- the value in the ``registry.settings`` dictionary and use it. In
+
+- In the runtime code from where you need to access the new settings value,
+ find the value in the ``registry.settings`` dictionary and use it. In
:term:`view` code (or any other code that has access to the request), the
easiest way to do this is via ``request.registry.settings``. For example:
diff --git a/docs/narr/events.rst b/docs/narr/events.rst
index 929208083..2accb3dbe 100644
--- a/docs/narr/events.rst
+++ b/docs/narr/events.rst
@@ -26,7 +26,7 @@ subscriber is a function that accepts a single argument named `event`:
:linenos:
def mysubscriber(event):
- print event
+ print(event)
The above is a subscriber that simply prints the event to the console
when it's called.
@@ -53,7 +53,7 @@ method (see also :term:`Configurator`):
from subscribers import mysubscriber
- # "config" below is assumed to be an instance of a
+ # "config" below is assumed to be an instance of a
# pyramid.config.Configurator object
config.add_subscriber(mysubscriber, NewRequest)
@@ -77,7 +77,7 @@ type via the :func:`pyramid.events.subscriber` function.
@subscriber(NewRequest)
def mysubscriber(event):
- event.request.foo = 1
+ event.request.foo = 1
When the :func:`~pyramid.events.subscriber` decorator is used a
:term:`scan` must be performed against the package containing the
@@ -113,10 +113,10 @@ your application like so:
:linenos:
def handle_new_request(event):
- print 'request', event.request
+ print('request', event.request)
def handle_new_response(event):
- print 'response', event.response
+ print('response', event.response)
You may configure these functions to be called at the appropriate
times by adding the following code to your application's
@@ -150,3 +150,86 @@ application, because the interface defined at
:class:`pyramid.interfaces.INewResponse` says it must
(:class:`pyramid.events.NewResponse` objects also have a ``request``).
+.. _custom_events:
+
+Creating Your Own Events
+------------------------
+
+In addition to using the events that the Pyramid framework creates,
+you can create your own events for use in your application. This can
+be useful to decouple parts of your application.
+
+For example, suppose your application has to do many things when a new
+document is created. Rather than putting all this logic in the view
+that creates the document, you can create the document in your view
+and then fire a custom event. Subscribers to the custom event can take
+other actions, such as indexing the document, sending email, or
+sending a message to a remote system.
+
+An event is simply an object. There are no required attributes or
+method for your custom events. In general, your events should keep
+track of the information that subscribers will need. Here are some
+example custom event classes:
+
+.. code-block:: python
+ :linenos:
+
+ class DocCreated(object):
+ def __init__(self, doc, request):
+ self.doc = doc
+ self.request = request
+
+ class UserEvent(object):
+ def __init__(self, user):
+ self.user = user
+
+ class UserLoggedIn(UserEvent):
+ pass
+
+Some Pyramid applications choose to define custom events classes in an
+``events`` module.
+
+You can subscribe to custom events in the same way that you subscribe
+to Pyramid events -- either imperatively or with a decorator. You can
+also use custom events with :ref:`subscriber predicates
+<subscriber_predicates>`. Here's an example of subscribing to a custom
+event with a decorator:
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.events import subscriber
+ from .events import DocCreated
+ from .index import index_doc
+
+ @subscriber(DocCreated)
+ def index_doc(event):
+ # index the document using our application's index_doc function
+ index_doc(event.doc, event.request)
+
+The above example assumes that the application defines a
+``DocCreated`` event class and an ``index_doc`` function.
+
+To fire your custom events use the
+:meth:`pyramid.registry.Registry.notify` method, which is most often
+accessed as ``request.registry.notify``. For example:
+
+.. code-block:: python
+ :linenos:
+
+ from .events import DocCreated
+
+ def new_doc_view(request):
+ doc = MyDoc()
+ event = DocCreated(doc, request)
+ request.registry.notify(event)
+ return {'document': doc}
+
+This example view will notify all subscribers to the custom
+``DocCreated`` event.
+
+Note that when you fire an event, all subscribers are run
+synchronously so it's generally not a good idea
+to create event handlers that may take a long time to run. Although
+event handlers could be used as a central place to spawn tasks on your
+own message queues.
diff --git a/docs/narr/extconfig.rst b/docs/narr/extconfig.rst
index f33326279..6587aef92 100644
--- a/docs/narr/extconfig.rst
+++ b/docs/narr/extconfig.rst
@@ -55,7 +55,7 @@ method of the Configurator:
:linenos:
def mysubscriber(event):
- print event.request
+ print(event.request)
config.add_newrequest_subscriber(mysubscriber)
@@ -79,7 +79,7 @@ able to install it and subsequently do:
:linenos:
def mysubscriber(event):
- print event.request
+ print(event.request)
from pyramid.config import Configurator
config = Configurator()
@@ -129,8 +129,8 @@ called (either explicitly or as the result of calling
:meth:`~pyramid.config.Configurator.make_wsgi_app`), conflicting actions are
potentially automatically resolved as per
:ref:`automatic_conflict_resolution`. If a conflict cannot be automatically
-resolved, a :exc:`ConfigurationConflictError` is raised and application
-startup is prevented.
+resolved, a :exc:`pyramid.exceptions.ConfigurationConflictError` is raised
+and application startup is prevented.
In our above example, therefore, if a consumer of our ``add_jammyjam``
directive did this:
diff --git a/docs/narr/extending.rst b/docs/narr/extending.rst
index dd9281c73..a60a49fea 100644
--- a/docs/narr/extending.rst
+++ b/docs/narr/extending.rst
@@ -50,7 +50,7 @@ layers are apt to provide the necessary "opinions" (such as mandating a
storage layer, a templating system, and a structured, well-documented pattern
of registering that certain URLs map to certain bits of code) which makes the
concept of a "pluggable application" possible. "Pluggable applications",
-thus, should not plug in to Pyramid itself but should instead plug into a
+thus, should not plug into Pyramid itself but should instead plug into a
system written atop Pyramid.
Although it does not provide for "pluggable applications", Pyramid *does*
@@ -200,8 +200,8 @@ like this:
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. ``$myvenv/bin/python setup.py develop`` or
- ``$myvenv/bin/python setup.py install``).
+ application (e.g. ``$VENV/bin/python setup.py develop`` or
+ ``$VENV/bin/python setup.py install``).
- Change the ``main`` function in the new package's ``__init__.py`` to include
the original :app:`Pyramid` application's configuration functions via
@@ -209,7 +209,7 @@ like this:
- Wire the new views and assets created in the new package up using
imperative registrations within the ``main`` function of the
- ``__init__.py`` file of the new application. These wiring should happen
+ ``__init__.py`` file of the new application. This wiring should happen
*after* including the configuration functions of the old application.
These registrations will extend or override any registrations performed by
the original application. See :ref:`overriding_views`,
diff --git a/docs/narr/firstapp.rst b/docs/narr/firstapp.rst
index ab6a46c2f..e73ef66ac 100644
--- a/docs/narr/firstapp.rst
+++ b/docs/narr/firstapp.rst
@@ -29,13 +29,13 @@ On UNIX:
.. code-block:: text
- $ /path/to/your/virtualenv/bin/python helloworld.py
+ $ $VENV/bin/python helloworld.py
On Windows:
.. code-block:: text
- C:\> \path\to\your\virtualenv\Scripts\python.exe helloworld.py
+ C:\> %VENV%\Scripts\python.exe helloworld.py
This command will not return and nothing will be printed to the console.
When port 8080 is visited by a browser on the URL ``/hello/world``, the
@@ -166,7 +166,6 @@ the application.
Adding Configuration
~~~~~~~~~~~~~~~~~~~~
-.. ignore-next-block
.. literalinclude:: helloworld.py
:linenos:
:lines: 11-12
@@ -186,7 +185,6 @@ The second line registers the ``hello_world`` function as a
WSGI Application Creation
~~~~~~~~~~~~~~~~~~~~~~~~~
-.. ignore-next-block
.. literalinclude:: helloworld.py
:linenos:
:lines: 13
@@ -215,7 +213,6 @@ to its ``add_view`` and ``add_route`` methods.
WSGI Application Serving
~~~~~~~~~~~~~~~~~~~~~~~~
-.. ignore-next-block
.. literalinclude:: helloworld.py
:linenos:
:lines: 14-15
diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst
index f38d57e73..0c450fad7 100644
--- a/docs/narr/hooks.rst
+++ b/docs/narr/hooks.rst
@@ -14,26 +14,28 @@ in various ways.
Changing the Not Found View
---------------------------
-When :app:`Pyramid` can't map a URL to view code, it invokes a :term:`not
-found view`, which is a :term:`view callable`. The default Not Found View
+When :app:`Pyramid` can't map a URL to view code, it invokes a :term:`Not
+Found View`, which is a :term:`view callable`. The default Not Found View
can be overridden through application configuration.
If your application uses :term:`imperative configuration`, you can replace
-the Not Found view by using the
+the Not Found View by using the
:meth:`pyramid.config.Configurator.add_notfound_view` method:
.. code-block:: python
:linenos:
- from helloworld.views import notfound
- config.add_notfound_view(notfound)
+ def notfound(request):
+ return Response('Not Found, dude', status='404 Not Found')
+
+ def main(globals, **settings):
+ config = Configurator()
+ config.add_notfound_view(notfound)
-Replace ``helloworld.views.notfound`` with a reference to the :term:`view
-callable` you want to use to represent the Not Found view. The :term:`not
-found view` callable is a view callable like any other.
+The :term:`Not Found View` callable is a view callable like any other.
If your application instead uses :class:`pyramid.view.view_config` decorators
-and a :term:`scan`, you can replace the Not Found view by using the
+and a :term:`scan`, you can replace the Not Found View by using the
:class:`pyramid.view.notfound_view_config` decorator:
.. code-block:: python
@@ -46,17 +48,17 @@ and a :term:`scan`, you can replace the Not Found view by using the
return Response('Not Found, dude', status='404 Not Found')
def main(globals, **settings):
- config = Configurator()
- config.scan()
+ config = Configurator()
+ config.scan()
This does exactly what the imperative example above showed.
-Your application can define *multiple* not found views if necessary. Both
+Your application can define *multiple* Not Found Views if necessary. Both
:meth:`pyramid.config.Configurator.add_notfound_view` and
:class:`pyramid.view.notfound_view_config` take most of the same arguments as
:class:`pyramid.config.Configurator.add_view` and
-:class:`pyramid.view.view_config`, respectively. This means that not found
-views can carry predicates limiting their applicability. For example:
+:class:`pyramid.view.view_config`, respectively. This means that Not Found
+Views can carry predicates limiting their applicability. For example:
.. code-block:: python
:linenos:
@@ -79,7 +81,7 @@ The ``notfound_get`` view will be called when a view could not be found and
the request method was ``GET``. The ``notfound_post`` view will be called
when a view could not be found and the request method was ``POST``.
-Like any other view, the notfound view must accept at least a ``request``
+Like any other view, the Not Found View must accept at least a ``request``
parameter, or both ``context`` and ``request``. The ``request`` is the
current :term:`request` representing the denied action. The ``context`` (if
used in the call signature) will be the instance of the
@@ -91,7 +93,8 @@ Both :meth:`pyramid.config.Configurator.add_notfound_view` and
redirect requests to slash-appended routes. See
:ref:`redirecting_to_slash_appended_routes` for examples.
-Here's some sample code that implements a minimal NotFound view callable:
+Here's some sample code that implements a minimal :term:`Not Found View`
+callable:
.. code-block:: python
:linenos:
@@ -103,14 +106,13 @@ Here's some sample code that implements a minimal NotFound view callable:
.. note::
- When a NotFound view callable is invoked, it is passed a
+ When a Not Found View callable is invoked, it is passed a
:term:`request`. The ``exception`` attribute of the request will be an
instance of the :exc:`~pyramid.httpexceptions.HTTPNotFound` exception that
- caused the not found view to be called. The value of
- ``request.exception.message`` will be a value explaining why the not found
- error was raised. This message will be different when the
- ``pyramid.debug_notfound`` environment setting is true than it is when it
- is false.
+ caused the Not Found View to be called. The value of
+ ``request.exception.message`` will be a value explaining why the Not Found
+ error was raised. This message has different values depending whether the
+ ``pyramid.debug_notfound`` environment setting is true or false.
.. note::
@@ -122,7 +124,7 @@ Here's some sample code that implements a minimal NotFound view callable:
.. warning::
- When a NotFound view callable accepts an argument list as
+ When a Not Found View callable accepts an argument list as
described in :ref:`request_and_context_view_definitions`, the ``context``
passed as the first argument to the view callable will be the
:exc:`~pyramid.httpexceptions.HTTPNotFound` exception instance. If
@@ -154,12 +156,12 @@ forbidden view:
.. code-block:: python
:linenos:
- from helloworld.views import forbidden_view
- from pyramid.httpexceptions import HTTPForbidden
- config.add_forbidden_view(forbidden_view)
+ def forbidden(request):
+ return Response('forbidden')
-Replace ``helloworld.views.forbidden_view`` with a reference to the Python
-:term:`view callable` you want to use to represent the Forbidden view.
+ def main(globals, **settings):
+ config = Configurator()
+ config.add_forbidden_view(forbidden_view)
If instead you prefer to use decorators and a :term:`scan`, you can use the
:class:`pyramid.view.forbidden_view_config` decorator to mark a view callable
@@ -207,9 +209,9 @@ Here's some sample code that implements a minimal forbidden view:
that caused the forbidden view to be called. The value of
``request.exception.message`` will be a value explaining why the forbidden
was raised and ``request.exception.result`` will be extended information
- about the forbidden exception. These messages will be different when the
- ``pyramid.debug_authorization`` environment setting is true than it is when
- it is false.
+ about the forbidden exception. These messages have different values
+ depending whether the ``pyramid.debug_authorization`` environment setting
+ is true or false.
.. index::
single: request factory
@@ -289,7 +291,7 @@ actually execute the function until accessed.
return sum(args)
def prop(request):
- print "getting the property"
+ print("getting the property")
return "the property"
config = Configurator()
@@ -330,7 +332,7 @@ Here is an example of passing a class to ``Configurator.add_request_method``:
# use @property if you don't want to cache the result
@reify
def prop(self):
- print "getting the property"
+ print("getting the property")
return "the property"
config = Configurator()
@@ -370,10 +372,8 @@ that can be used for this purpose. For example:
def add_global(event):
event['mykey'] = 'foo'
-An object of this type is sent as an event just before a :term:`renderer` is
-invoked (but *after* the application-level renderer globals factory added via
-:class:`~pyramid.config.Configurator.set_renderer_globals_factory`, if any,
-has injected its own keys into the renderer globals dictionary).
+An object of this type is sent as an event just before a :term:`renderer`
+is invoked.
If a subscriber attempts to add a key that already exist in the renderer
globals dictionary, a :exc:`KeyError` is raised. This limitation is enforced
@@ -415,66 +415,6 @@ your view callable, like so:
See the API documentation for the :class:`~pyramid.events.BeforeRender` event
interface at :class:`pyramid.interfaces.IBeforeRender`.
-Another (deprecated) mechanism which allows event subscribers more control
-when adding renderer global values exists in :ref:`adding_renderer_globals`.
-
-.. index::
- single: adding renderer globals
-
-.. _adding_renderer_globals:
-
-Adding Renderer Globals (Deprecated)
-------------------------------------
-
-.. deprecated:: 1.1
- An alternative mechanism which allows event subscribers to add renderer
- global values is documented in :ref:`beforerender_event`.
-
-Whenever :app:`Pyramid` handles a request to perform a rendering (after a
-view with a ``renderer=`` configuration attribute is invoked, or when any of
-the methods beginning with ``render`` within the :mod:`pyramid.renderers`
-module are called), *renderer globals* can be injected into the *system*
-values sent to the renderer. By default, no renderer globals are injected,
-and the "bare" system values (such as ``request``, ``context``, ``view``, and
-``renderer_name``) are the only values present in the system dictionary
-passed to every renderer.
-
-A callback that :app:`Pyramid` will call every time a renderer is invoked can
-be added by passing a ``renderer_globals_factory`` argument to the
-constructor of the :term:`configurator`. This callback can either be a
-callable object or a :term:`dotted Python name` representing such a callable.
-
-.. code-block:: python
- :linenos:
-
- def renderer_globals_factory(system):
- return {'a': 1}
-
- config = Configurator(
- renderer_globals_factory=renderer_globals_factory)
-
-Such a callback must accept a single positional argument (notionally named
-``system``) which will contain the original system values. It must return a
-dictionary of values that will be merged into the system dictionary. See
-:ref:`renderer_system_values` for description of the values present in the
-system dictionary.
-
-If you're doing imperative configuration, and you'd rather do it after you've
-already constructed a :term:`configurator` it can also be registered via the
-:meth:`pyramid.config.Configurator.set_renderer_globals_factory` method:
-
-.. code-block:: python
- :linenos:
-
- from pyramid.config import Configurator
-
- def renderer_globals_factory(system):
- return {'a': 1}
-
- config = Configurator()
- config.set_renderer_globals_factory(renderer_globals_factory)
-
-
.. index::
single: response callback
@@ -512,7 +452,7 @@ callback will be an exception object instead of its default value of
``None``.
Response callbacks are called in the order they're added
-(first-to-most-recently-added). All response callbacks are called *after*
+(first-to-most-recently-added). All response callbacks are called *before*
the :class:`~pyramid.events.NewResponse` event is sent. Errors raised by
response callbacks are not handled specially. They will be propagated to the
caller of the :app:`Pyramid` router application.
@@ -673,7 +613,7 @@ traverser.
If you've added a traverser, you can change how
:meth:`~pyramid.request.Request.resource_url` generates a URL for a specific
type of resource by adding a call to
-:meth:`pyramid.config.add_resource_url_adapter`.
+:meth:`pyramid.config.Configurator.add_resource_url_adapter`.
For example:
@@ -693,7 +633,7 @@ represents the type of interface that must be possessed by the resource for
this resource url factory to be found. If the ``resource_iface`` argument is
omitted, this resource url adapter will be used for *all* resources.
-The API that must be implemented by your a class that provides
+The API that must be implemented by a class that provides
:class:`~pyramid.interfaces.IResourceURL` is as follows:
.. code-block:: python
@@ -711,7 +651,7 @@ The API that must be implemented by your a class that provides
The default context URL generator is available for perusal as the class
:class:`pyramid.traversal.ResourceURL` in the `traversal module
-<http://github.com/Pylons/pyramid/blob/master/pyramid/traversal.py>`_ of the
+<https://github.com/Pylons/pyramid/blob/master/pyramid/traversal.py>`_ of the
:term:`Pylons` GitHub Pyramid repository.
See :meth:`pyramid.config.add_resource_url_adapter` for more information.
@@ -929,7 +869,7 @@ set a *default* view mapper (overriding the superdefault view mapper used by
Pyramid itself).
A *single* view registration can use a view mapper by passing the mapper as
-the ``mapper`` argument to :meth:`~pyramid.config.Configuration.add_view`.
+the ``mapper`` argument to :meth:`~pyramid.config.Configurator.add_view`.
.. index::
single: configuration decorator
@@ -1035,7 +975,7 @@ upstream WSGI component that uses :app:`Pyramid` as its "app". This is a
feature that may be used by Pyramid framework extensions, to provide, for
example, Pyramid-specific view timing support bookkeeping code that examines
exceptions before they are returned to the upstream WSGI application. Tweens
-behave a bit like :term:`WSGI` middleware but they have the benefit of
+behave a bit like :term:`WSGI` :term:`middleware` but they have the benefit of
running in a context in which they have access to the Pyramid
:term:`application registry` as well as the Pyramid rendering machinery.
@@ -1109,8 +1049,8 @@ Once you've created a tween factory, you can register it into the implicit
tween chain using the :meth:`pyramid.config.Configurator.add_tween` method
using its :term:`dotted Python name`.
-Here's an example of registering the a tween factory as an "implicit"
-tween in a Pyramid application:
+Here's an example of registering a tween factory as an "implicit" tween in a
+Pyramid application:
.. code-block:: python
:linenos:
@@ -1382,9 +1322,11 @@ 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 view or route predicate factory. A view or route
-predicate factory is most often a class with a constructor (``__init__``), a
-``text`` method, a ``phash`` method and a ``__call__`` method. For example:
+The second argument is a view or route predicate factory, or a :term:`dotted
+Python name` which refers to a view or route predicate factory. A view or
+route 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:
@@ -1446,7 +1388,7 @@ view/route predicate:
subscriber predicates will assume a certain event type.
Here's an example of a subscriber predicate that can be used in conjunction
-with a subscriber that subscribes to the :class:`pyramid.events.NewReqest`
+with a subscriber that subscribes to the :class:`pyramid.events.NewRequest`
event type.
.. code-block:: python
diff --git a/docs/narr/hybrid.rst b/docs/narr/hybrid.rst
index 1773a6b8c..a29ccb2ac 100644
--- a/docs/narr/hybrid.rst
+++ b/docs/narr/hybrid.rst
@@ -549,3 +549,105 @@ be invoked when the request URI is ``/abc/bazbuz``, assuming there is
no object contained by the root object with the key ``bazbuz``. A
different request URI, such as ``/abc/foo/bar``, would invoke the
default ``myproject.views.abc`` view.
+
+.. index::
+ pair: hybrid urls; generating
+
+.. _generating_hybrid_urls:
+
+Generating Hybrid URLs
+----------------------
+
+.. versionadded:: 1.5
+
+The :meth:`pyramid.request.Request.resource_url` method and the
+:meth:`pyramid.request.Request.resource_path` method both accept optional
+keyword arguments that make it easier to generate route-prefixed URLs that
+contain paths to traversal resources:``route_name``, ``route_kw``, and
+``route_remainder_name``.
+
+Any route that has a pattern that contains a ``*remainder`` pattern (any
+stararg remainder pattern, such as ``*traverse`` or ``*subpath`` or ``*fred``)
+can be used as the target name for ``request.resource_url(..., route_name=)``
+and ``request.resource_path(..., route_name=)``.
+
+For example, let's imagine you have a route defined in your Pyramid application
+like so:
+
+.. code-block:: python
+
+ config.add_route('mysection', '/mysection*traverse')
+
+If you'd like to generate the URL ``http://example.com/mysection/a/``, you can
+use the following incantation, assuming that the variable ``a`` below points to
+a resource that is a child of the root with a ``__name__`` of ``a``:
+
+.. code-block:: python
+
+ request.resource_url(a, route_name='mysection')
+
+You can generate only the path portion ``/mysection/a/`` assuming the same:
+
+.. code-block:: python
+
+ request.resource_path(a, route_name='mysection')
+
+The path is virtual host aware, so if the ``X-Vhm-Root`` environ variable is
+present in the request, and it's set to ``/a``, the above call to
+``request.resource_url`` would generate ``http://example.com/mysection/``
+and the above call to ``request.resource_path`` would generate ``/mysection/``.
+See :ref:`virtual_root_support` for more information.
+
+If the route you're trying to use needs simple dynamic part values to be filled
+in to succesfully generate the URL, you can pass these as the ``route_kw``
+argument to ``resource_url`` and ``resource_path``. For example, assuming that
+the route definition is like so:
+
+.. code-block:: python
+
+ config.add_route('mysection', '/{id}/mysection*traverse')
+
+You can pass ``route_kw`` in to fill in ``{id}`` above:
+
+.. code-block:: python
+
+ request.resource_url(a, route_name='mysection', route_kw={'id':'1'})
+
+If you pass ``route_kw`` but do not pass ``route_name``, ``route_kw`` will
+be ignored.
+
+By default this feature works by calling ``route_url`` under the hood,
+and passing the value of the resource path to that function as ``traverse``.
+If your route has a different ``*stararg`` remainder name (such as
+``*subpath``), you can tell ``resource_url`` or ``resource_path`` to use that
+instead of ``traverse`` by passing ``route_remainder_name``. For example,
+if you have the following route:
+
+.. code-block:: python
+
+ config.add_route('mysection', '/mysection*subpath')
+
+You can fill in the ``*subpath`` value using ``resource_url`` by doing:
+
+.. code-block:: python
+
+ request.resource_path(a, route_name='mysection',
+ route_remainder_name='subpath')
+
+If you pass ``route_remainder_name`` but do not pass ``route_name``,
+``route_remainder_name`` will be ignored.
+
+If you try to use ``resource_path`` or ``resource_url`` when the ``route_name``
+argument points at a route that does not have a remainder stararg, an error
+will not be raised, but the generated URL will not contain any remainder
+information either.
+
+All other values that are normally passable to ``resource_path`` and
+``resource_url`` (such as ``query``, ``anchor``, ``host``, ``port``, and
+positional elements) work as you might expect in this configuration.
+
+Note that this feature is incompatible with the ``__resource_url__`` feature
+(see :ref:`overriding_resource_url_generation`) implemented on resource
+objects. Any ``__resource_url__`` supplied by your resource will be ignored
+when you pass ``route_name``.
+
diff --git a/docs/narr/i18n.rst b/docs/narr/i18n.rst
index 511464322..b62c16ff0 100644
--- a/docs/narr/i18n.rst
+++ b/docs/narr/i18n.rst
@@ -276,7 +276,7 @@ like so:
.. code-block:: text
$ cd /my/virtualenv
- $ bin/easy_install Babel lingua
+ $ $VENV/bin/easy_install Babel lingua
Installation on Windows
+++++++++++++++++++++++
@@ -287,8 +287,7 @@ like so:
.. code-block:: text
- C> cd \my\virtualenv
- C> Scripts\easy_install Babel lingua
+ C> %VENV%\Scripts\easy_install Babel lingua
.. index::
single: Babel; message extractors
@@ -347,7 +346,7 @@ extract the messages:
$ cd /place/where/myapplication/setup.py/lives
$ mkdir -p myapplication/locale
- $ $myvenv/bin/python setup.py extract_messages
+ $ $VENV/bin/python setup.py extract_messages
The message catalog ``.pot`` template will end up in:
@@ -439,7 +438,7 @@ init_catalog`` command:
.. code-block:: text
$ cd /place/where/myapplication/setup.py/lives
- $ $myvenv/bin/python setup.py init_catalog -l es
+ $ $VENV/bin/python setup.py init_catalog -l es
By default, the message catalog ``.po`` file will end up in:
@@ -471,7 +470,7 @@ Then use the ``setup.py update_catalog`` command.
.. code-block:: text
$ cd /place/where/myapplication/setup.py/lives
- $ $myvenv/bin/python setup.py update_catalog
+ $ $VENV/bin/python setup.py update_catalog
.. index::
pair: compiling; message catalog
@@ -487,7 +486,7 @@ translations, compile ``.po`` files to ``.mo`` files:
.. code-block:: text
$ cd /place/where/myapplication/setup.py/lives
- $ $myvenv/bin/python setup.py compile_catalog
+ $ $VENV/bin/python setup.py compile_catalog
This will create a ``.mo`` file for each ``.po`` file in your
application. As long as the :term:`translation directory` in which
@@ -496,7 +495,6 @@ translations will be available to :app:`Pyramid`.
.. index::
single: localizer
- single: get_localizer
single: translation
single: pluralization
@@ -504,19 +502,17 @@ Using a Localizer
-----------------
A :term:`localizer` is an object that allows you to perform translation or
-pluralization "by hand" in an application. You may use the
-:func:`pyramid.i18n.get_localizer` function to obtain a :term:`localizer`.
-This function will return either the localizer object implied by the active
-:term:`locale negotiator` or a default localizer object if no explicit locale
-negotiator is registered.
+pluralization "by hand" in an application. You may use the
+:attr:`pyramid.request.Request.localizer` attribute to obtain a
+:term:`localizer`. The localizer object will be configured to produce
+translations implied by the active :term:`locale negotiator` or a default
+localizer object if no explicit locale negotiator is registered.
.. code-block:: python
:linenos:
- from pyramid.i18n import get_localizer
-
def aview(request):
- locale = get_localizer(request)
+ localizer = request.localizer
.. note::
@@ -539,22 +535,20 @@ translation in a view component of an application might look like so:
.. code-block:: python
:linenos:
- from pyramid.i18n import get_localizer
from pyramid.i18n import TranslationString
ts = TranslationString('Add ${number}', mapping={'number':1},
domain='pyramid')
def aview(request):
- localizer = get_localizer(request)
+ localizer = request.localizer
translated = localizer.translate(ts) # translation string
# ... use translated ...
-The :func:`~pyramid.i18n.get_localizer` function will return a
-:class:`pyramid.i18n.Localizer` object bound to the locale name
-represented by the request. The translation returned from its
-:meth:`pyramid.i18n.Localizer.translate` method will depend on the
-``domain`` attribute of the provided translation string as well as the
+The ``request.localizer`` attribute will be a :class:`pyramid.i18n.Localizer`
+object bound to the locale name represented by the request. The translation
+returned from its :meth:`pyramid.i18n.Localizer.translate` method will depend
+on the ``domain`` attribute of the provided translation string as well as the
locale of the localizer.
.. note::
@@ -580,32 +574,63 @@ signature:
def pluralize(singular, plural, n, domain=None, mapping=None):
...
-The ``singular`` and ``plural`` arguments should each be a Unicode
-value representing a :term:`message identifier`. ``n`` should be an
-integer. ``domain`` should be a :term:`translation domain`, and
-``mapping`` should be a dictionary that is used for *replacement
-value* interpolation of the translated string. If ``n`` is plural
-for the current locale, ``pluralize`` will return a Unicode
-translation for the message id ``plural``, otherwise it will return a
-Unicode translation for the message id ``singular``.
-
-The arguments provided as ``singular`` and/or ``plural`` may also be
-:term:`translation string` objects, but the domain and mapping
-information attached to those objects is ignored.
+The simplest case is the ``singular`` and ``plural`` arguments being passed as
+unicode literals. This returns the appropriate literal according to the locale
+pluralization rules for the number ``n``, and interpolates ``mapping``.
.. code-block:: python
:linenos:
- from pyramid.i18n import get_localizer
-
def aview(request):
- localizer = get_localizer(request)
+ localizer = request.localizer
translated = localizer.pluralize('Item', 'Items', 1, 'mydomain')
# ... use translated ...
+However, for support of other languages, the ``singular`` argument should
+be a Unicode value representing a :term:`message identifier`. In this
+case the ``plural`` value is ignored.
+``domain`` should be a :term:`translation domain`, and
+``mapping`` should be a dictionary that is used for *replacement
+value* interpolation of the translated string.
+
+The value of ``n`` will be used to find the appropriate plural form for the
+current language and ``pluralize`` will return a Unicode translation for the
+message id ``singular``. The message file must have defined ``singular`` as a
+translation with plural forms.
+
+The argument provided as ``singular`` may be a :term:`translation string`
+object, but the domain and mapping information attached is ignored.
+
+.. code-block:: python
+ :linenos:
+
+ def aview(request):
+ localizer = request.localizer
+ num = 1
+ translated = localizer.pluralize(
+ _('item_plural', default="${number} items"),
+ None, num, 'mydomain', mapping={'number':num}
+ )
+
+The corresponding message catalog must have language plural definitions and
+plural alternatives set.
+
+.. code-block:: text
+ :linenos:
+
+ "Plural-Forms: nplurals=3; plural=n==0 ? 0 : n==1 ? 1 : 2;"
+
+ msgid "item_plural"
+ msgid_plural ""
+ msgstr[0] "No items"
+ msgstr[1] "${number} item"
+ msgstr[2] "${number} items"
+
+More information on complex plurals can be found in the `gettext documentation
+<https://www.gnu.org/savannah-checkouts/gnu/gettext/manual/html_node/Plural-forms.html>`_.
+
.. index::
single: locale name
- single: get_locale_name
single: negotiate_locale_name
.. _obtaining_the_locale_name:
@@ -614,25 +639,23 @@ Obtaining the Locale Name for a Request
---------------------------------------
You can obtain the locale name related to a request by using the
-:func:`pyramid.i18n.get_locale_name` function.
+:func:`pyramid.request.Request.locale_name` attribute of the request.
.. code-block:: python
:linenos:
- from pyramid.i18n import get_locale_name
-
def aview(request):
- locale_name = get_locale_name(request)
+ locale_name = request.locale_name
-This returns the locale name negotiated by the currently active
-:term:`locale negotiator` or the :term:`default locale name` if the
-locale negotiator returns ``None``. You can change the default locale
-name by changing the ``pyramid.default_locale_name`` setting; see
-:ref:`default_locale_name_setting`.
+The locale name of a request is dynamically computed; it will be the locale
+name negotiated by the currently active :term:`locale negotiator` or
+the :term:`default locale name` if the locale negotiator returns ``None``.
+You can change the default locale name by changing the
+``pyramid.default_locale_name`` setting; see :ref:`default_locale_name_setting`.
-Once :func:`~pyramid.i18n.get_locale_name` is first run, the locale
+Once :func:`~pyramid.request.Request.locale_name` is first run, the locale
name is stored on the request object. Subsequent calls to
-:func:`~pyramid.i18n.get_locale_name` will return the stored locale
+:func:`~pyramid.request.Request.locale_name` will return the stored locale
name without invoking the :term:`locale negotiator`. To avoid this
caching, you can use the :func:`pyramid.i18n.negotiate_locale_name`
function:
@@ -651,15 +674,13 @@ You can also obtain the locale name related to a request using the
.. code-block:: python
:linenos:
- from pyramid.i18n import get_localizer
-
def aview(request):
- localizer = get_localizer(request)
+ localizer = request.localizer
locale_name = localizer.locale_name
Obtaining the locale name as an attribute of a localizer is equivalent
-to obtaining a locale name by calling the
-:func:`~pyramid.i18n.get_locale_name` function.
+to obtaining a locale name by asking for the
+:func:`~pyramid.request.Request.locale_name` attribute.
.. index::
single: date and currency formatting (i18n)
@@ -687,10 +708,9 @@ obtain the locale name for a request to pass to the
:linenos:
from babel.core import Locale
- from pyramid.i18n import get_locale_name
def aview(request):
- locale_name = get_locale_name(request)
+ locale_name = request.locale_name
locale = Locale(locale_name)
.. index::
@@ -736,9 +756,7 @@ through translation before being rendered:
The features represented by attributes of the ``i18n`` namespace of
Chameleon will also consult the :app:`Pyramid` translations.
-See
-`http://chameleon.repoze.org/docs/latest/i18n.html#the-i18n-namespace
-<http://chameleon.repoze.org/docs/latest/i18n.html#the-i18n-namespace>`_.
+See http://chameleon.readthedocs.org/en/latest/reference.html#id50.
.. note::
@@ -811,7 +829,7 @@ If this setting is supplied within the :app:`Pyramid` application
default_locale_name = settings['pyramid.default_locale_name']
.. index::
- single: detecting langauges
+ single: detecting languages
"Detecting" Available Languages
-------------------------------
@@ -974,8 +992,8 @@ a particular request. A locale negotiator is a bit of code which
accepts a request and which returns a :term:`locale name`. It is
consulted when :meth:`pyramid.i18n.Localizer.translate` or
:meth:`pyramid.i18n.Localizer.pluralize` is invoked. It is also
-consulted when :func:`~pyramid.i18n.get_locale_name` or
-:func:`~pyramid.i18n.negotiate_locale_name` is invoked.
+consulted when :func:`~pyramid.request.Request.locale_name` is accessed or
+when :func:`~pyramid.i18n.negotiate_locale_name` is invoked.
.. _default_locale_negotiator:
@@ -987,7 +1005,7 @@ requires no additional coding or configuration.
The default locale negotiator implementation named
:class:`~pyramid.i18n.default_locale_negotiator` uses the following
-set of steps to dermine the locale name.
+set of steps to determine the locale name.
- First, the negotiator looks for the ``_LOCALE_`` attribute of the
request object (possibly set directly by view code or by a listener
diff --git a/docs/narr/install.rst b/docs/narr/install.rst
index 85dfd5bf4..e419a8b20 100644
--- a/docs/narr/install.rst
+++ b/docs/narr/install.rst
@@ -9,30 +9,54 @@ Installing :app:`Pyramid`
Before You Install
------------------
-You will need `Python <http://python.org>`_ version 2.6 or better to
-run :app:`Pyramid`.
+You will need `Python <http://python.org>`_ version 2.6 or better to run
+:app:`Pyramid`.
.. sidebar:: Python Versions
- As of this writing, :app:`Pyramid` has been tested under Python 2.6,
- Python 2.7, Python 3.2, and Python 3.3. :app:`Pyramid` does not
- run under any version of Python before 2.6.
+ As of this writing, :app:`Pyramid` has been tested under Python 2.6, Python
+ 2.7, Python 3.2, and Python 3.3. :app:`Pyramid` does not run under any
+ version of Python before 2.6.
-:app:`Pyramid` is known to run on all popular UNIX-like systems such as
-Linux, MacOS X, and FreeBSD as well as on Windows platforms. It is also
-known to run on :term:`PyPy` (1.9+).
+:app:`Pyramid` is known to run on all popular UNIX-like systems such as Linux,
+Mac OS X, and FreeBSD as well as on Windows platforms. It is also known to run
+on :term:`PyPy` (1.9+).
-:app:`Pyramid` installation does not require the compilation of any
-C code, so you need only a Python interpreter that meets the
-requirements mentioned.
+:app:`Pyramid` installation does not require the compilation of any C code, so
+you need only a Python interpreter that meets the requirements mentioned.
+
+Some :app:`Pyramid` dependencies may attempt to build C extensions for
+performance speedups. If a compiler or Python headers are unavailable the
+dependency will fall back to using pure Python instead.
+
+For Mac OS X Users
+~~~~~~~~~~~~~~~~~~
+
+From `Python.org <http://python.org/download/mac/>`_:
+
+ Python comes pre-installed on Mac OS X, but due to Apple's release cycle,
+ it's often one or even two years old. The overwhelming recommendation of
+ the "MacPython" community is to upgrade your Python by downloading and
+ installing a newer version from `the Python standard release page
+ <http://python.org/download/releases/>`_.
+
+It is recommended to download one of the *installer* versions, unless you
+prefer to install your Python through a packgage manager (e.g., macports or
+homebrew) or to build your Python from source.
+
+Unless you have a need for a specific earlier version, it is recommended to
+install the latest 2.x or 3.x version of Python.
+
+If you use an installer for your Python, then you can skip to the section
+:ref:`installing_unix`.
If You Don't Yet Have A Python Interpreter (UNIX)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-If your system doesn't have a Python interpreter, and you're on UNIX,
-you can either install Python using your operating system's package
-manager *or* you can install Python from source fairly easily on any
-UNIX system that has development tools.
+If your system doesn't have a Python interpreter, and you're on UNIX, you can
+either install Python using your operating system's package manager *or* you
+can install Python from source fairly easily on any UNIX system that has
+development tools.
.. index::
pair: install; Python (from package, UNIX)
@@ -40,9 +64,8 @@ UNIX system that has development tools.
Package Manager Method
++++++++++++++++++++++
-You can use your system's "package manager" to install Python.
-Each package manager is slightly different, but the "flavor" of
-them is usually the same.
+You can use your system's "package manager" to install Python. Each package
+manager is slightly different, but the "flavor" of them is usually the same.
For example, on a Debian or Ubuntu system, use the following command:
@@ -63,28 +86,27 @@ invokable via ``python2.7`` from a shell prompt.
Source Compile Method
+++++++++++++++++++++
-It's useful to use a Python interpreter that *isn't* the "system"
-Python interpreter to develop your software. The authors of
-:app:`Pyramid` tend not to use the system Python for development
-purposes; always a self-compiled one. Compiling Python is usually
-easy, and often the "system" Python is compiled with options that
-aren't optimal for web development. For an explanation, see
+It's useful to use a Python interpreter that *isn't* the "system" Python
+interpreter to develop your software. The authors of :app:`Pyramid` tend not
+to use the system Python for development purposes; always a self-compiled one.
+Compiling Python is usually easy, and often the "system" Python is compiled
+with options that aren't optimal for web development. For an explanation, see
https://github.com/Pylons/pyramid/issues/747.
-To compile software on your UNIX system, typically you need
-development tools. Often these can be installed via the package
-manager. For example, this works to do so on an Ubuntu Linux system:
+To compile software on your UNIX system, typically you need development tools.
+Often these can be installed via the package manager. For example, this works
+to do so on an Ubuntu Linux system:
.. code-block:: text
$ sudo apt-get install build-essential
-On Mac OS X, installing `XCode
-<http://developer.apple.com/tools/xcode/>`_ has much the same effect.
+On Mac OS X, installing `XCode <http://developer.apple.com/tools/xcode/>`_ has
+much the same effect.
-Once you've got development tools installed on your system, you can
-install a Python 2.7 interpreter from *source*, on the same system,
-using the following commands:
+Once you've got development tools installed on your system, you can install a
+Python 2.7 interpreter from *source*, on the same system, using the following
+commands:
.. code-block:: text
@@ -98,9 +120,8 @@ using the following commands:
$ ./configure --prefix=$HOME/opt/Python-2.7.3
$ make && make install
-Once these steps are performed, the Python interpreter will be
-invokable via ``$HOME/opt/Python-2.7.3/bin/python`` from a shell
-prompt.
+Once these steps are performed, the Python interpreter will be invokable via
+``$HOME/opt/Python-2.7.3/bin/python`` from a shell prompt.
.. index::
pair: install; Python (from package, Windows)
@@ -108,24 +129,21 @@ prompt.
If You Don't Yet Have A Python Interpreter (Windows)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-If your Windows system doesn't have a Python interpreter, you'll need
-to install it by downloading a Python 2.7-series interpreter
-executable from `python.org's download section
-<http://python.org/download/>`_ (the files labeled "Windows
-Installer"). Once you've downloaded it, double click on the
-executable and accept the defaults during the installation process.
-You may also need to download and install the `Python for Windows
-extensions <http://sourceforge.net/projects/pywin32/files/>`_.
+If your Windows system doesn't have a Python interpreter, you'll need to
+install it by downloading a Python 2.7-series interpreter executable from
+`python.org's download section <http://python.org/download/>`_ (the files
+labeled "Windows Installer"). Once you've downloaded it, double click on the
+executable and accept the defaults during the installation process. You may
+also need to download and install the Python for Windows extensions.
.. warning::
- After you install Python on Windows, you may need to add the
- ``C:\Python27`` directory to your environment's ``Path`` in order
- to make it possible to invoke Python from a command prompt by
- typing ``python``. To do so, right click ``My Computer``, select
- ``Properties`` --> ``Advanced Tab`` --> ``Environment Variables``
- and add that directory to the end of the ``Path`` environment
- variable.
+ After you install Python on Windows, you may need to add the ``C:\Python27``
+ directory to your environment's ``Path`` in order to make it possible to
+ invoke Python from a command prompt by typing ``python``. To do so, right
+ click ``My Computer``, select ``Properties`` --> ``Advanced Tab`` -->
+ ``Environment Variables`` and add that directory to the end of the ``Path``
+ environment variable.
.. index::
single: installing on UNIX
@@ -135,27 +153,26 @@ extensions <http://sourceforge.net/projects/pywin32/files/>`_.
Installing :app:`Pyramid` on a UNIX System
---------------------------------------------
-It is best practice to install :app:`Pyramid` into a "virtual"
-Python environment in order to obtain isolation from any "system"
-packages you've got installed in your Python version. This can be
-done by using the :term:`virtualenv` package. Using a virtualenv will
-also prevent :app:`Pyramid` from globally installing versions of
-packages that are not compatible with your system Python.
+It is best practice to install :app:`Pyramid` into a "virtual" Python
+environment in order to obtain isolation from any "system" packages you've got
+installed in your Python version. This can be done by using the
+:term:`virtualenv` package. Using a virtualenv will also prevent
+:app:`Pyramid` from globally installing versions of packages that are not
+compatible with your system Python.
To set up a virtualenv in which to install :app:`Pyramid`, first ensure that
-:term:`setuptools` or :term:`distribute` is installed. To do so, invoke
-``import setuptools`` within the Python interpreter you'd like to run
-:app:`Pyramid` under.
+:term:`setuptools` is installed. To do so, invoke ``import setuptools`` within
+the Python interpreter you'd like to run :app:`Pyramid` under.
-The following command will not display anything if setuptools or distribute is
-already installed:
+The following command will not display anything if setuptools is already
+installed:
.. code-block:: text
$ python2.7 -c 'import setuptools'
-Running the same command will yield the following output if setuptools or
-distribute is not yet installed:
+Running the same command will yield the following output if setuptools is not
+yet installed:
.. code-block:: text
@@ -164,62 +181,35 @@ distribute is not yet installed:
ImportError: No module named setuptools
If ``import setuptools`` raises an :exc:`ImportError` as it does above, you
-will need to install setuptools or distribute manually.
+will need to install setuptools manually.
If you are using a "system" Python (one installed by your OS distributor or a
-3rd-party packager such as Fink or MacPorts), you can usually install the
-setuptools or distribute package by using your system's package manager. If
-you cannot do this, or if you're using a self-installed version of Python,
-you will need to install setuptools or distribute "by hand". Installing
-setuptools or distribute "by hand" is always a reasonable thing to do, even
-if your package manager already has a pre-chewed version of setuptools for
-installation.
-
-If you're using Python 2, you'll want to install ``setuptools``. If you're
-using Python 3, you'll want to install ``distribute``. Below we tell you how
-to do both.
+third-party packager such as Fink or MacPorts), you can usually install the
+setuptools package by using your system's package manager. If you cannot do
+this, or if you're using a self-installed version of Python, you will need to
+install setuptools "by hand". Installing setuptools "by hand" is always a
+reasonable thing to do, even if your package manager already has a pre-chewed
+version of setuptools for installation.
-Installing Setuptools On Python 2
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Installing Setuptools
+~~~~~~~~~~~~~~~~~~~~~
To install setuptools by hand under Python 2, first download `ez_setup.py
-<http://peak.telecommunity.com/dist/ez_setup.py>`_ then invoke it using the
-Python interpreter into which you want to install setuptools.
+<https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py>`_ then invoke
+it using the Python interpreter into which you want to install setuptools.
.. code-block:: text
$ python ez_setup.py
-Once this command is invoked, setuptools should be installed on your
-system. If the command fails due to permission errors, you may need
-to be the administrative user on your system to successfully invoke
-the script. To remediate this, you may need to do:
-
-.. code-block:: text
-
- $ sudo python ez_setup.py
-
-Installing Distribute On Python 3
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-``setuptools`` doesn't work under Python 3. Instead, you can use
-``distribute``, which is a fork of setuptools. To
-install it, first download `distribute_setup.py
-<http://python-distribute.org/distribute_setup.py>`_ then invoke it using the
-Python interpreter into which you want to install setuptools.
-
-.. code-block:: text
-
- $ python3 distribute_setup.py
-
-Once this command is invoked, distribute should be installed on your system.
+Once this command is invoked, setuptools should be installed on your system.
If the command fails due to permission errors, you may need to be the
administrative user on your system to successfully invoke the script. To
remediate this, you may need to do:
.. code-block:: text
- $ sudo python3 distribute_setup.py
+ $ sudo python ez_setup.py
.. index::
pair: install; virtualenv
@@ -227,9 +217,9 @@ remediate this, you may need to do:
Installing the ``virtualenv`` Package
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Once you've got setuptools or distribute installed, you should install the
-:term:`virtualenv` package. To install the :term:`virtualenv` package into
-your setuptools-enabled Python interpreter, use the ``easy_install`` command.
+Once you've got setuptools installed, you should install the :term:`virtualenv`
+package. To install the :term:`virtualenv` package into your
+setuptools-enabled Python interpreter, use the ``easy_install`` command.
.. warning::
@@ -242,16 +232,16 @@ your setuptools-enabled Python interpreter, use the ``easy_install`` command.
Turing-complete.
If you insist on using ``pyvenv``, you'll need to understand how to install
- software such as ``distribute`` into the virtual environment manually,
- which this guide does not cover.
+ software such as ``setuptools`` into the virtual environment manually, which
+ this guide does not cover.
.. code-block:: text
$ easy_install virtualenv
This command should succeed, and tell you that the virtualenv package is now
-installed. If it fails due to permission errors, you may need to install it
-as your system's administrative user. For example:
+installed. If it fails due to permission errors, you may need to install it as
+your system's administrative user. For example:
.. code-block:: text
@@ -264,49 +254,55 @@ as your system's administrative user. For example:
Creating the Virtual Python Environment
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Once the :term:`virtualenv` package is installed in your Python, you
-can then create a virtual environment. To do so, invoke the
-following:
+Once the :term:`virtualenv` package is installed in your Python environment,
+you can then create a virtual environment. To do so, invoke the following:
.. code-block:: text
- $ virtualenv --no-site-packages env
- New python executable in env/bin/python
+ $ export VENV=~/env
+ $ virtualenv $VENV
+ New python executable in /home/foo/env/bin/python
Installing setuptools.............done.
+You can either follow the use of the environment variable, ``$VENV``, or
+replace it with the root directory of the :term:`virtualenv`. In that case, the
+`export` command can be skipped. If you choose the former approach, ensure that
+it's an absolute path.
+
.. warning::
- Using ``--no-site-packages`` when generating your
- virtualenv is *very important*. This flag provides the necessary
- isolation for running the set of packages required by
- :app:`Pyramid`. If you do not specify ``--no-site-packages``,
- it's possible that :app:`Pyramid` will not install properly into
- the virtualenv, or, even if it does, may not run properly,
- depending on the packages you've already got installed into your
- Python's "main" site-packages dir.
+ Avoid using the ``--system-site-packages`` option when creating the
+ virtualenv unless you know what you are doing. For versions of virtualenv
+ prior to 1.7, make sure to use the ``--no-site-packages`` option, because
+ this option was formerly not the default and may produce undesirable
+ results.
+
+.. warning::
-.. warning:: *do not* use ``sudo`` to run the
- ``virtualenv`` script. It's perfectly acceptable (and desirable)
- to create a virtualenv as a normal user.
+ *do not* use ``sudo`` to run the ``virtualenv`` script. It's perfectly
+ acceptable (and desirable) to create a virtualenv as a normal user.
-You should perform any following commands that mention a "bin"
-directory from within the ``env`` virtualenv dir.
Installing :app:`Pyramid` Into the Virtual Python Environment
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-After you've got your ``env`` virtualenv installed, you may install
-:app:`Pyramid` itself using the following commands from within the
-virtualenv (``env``) directory you created in the last step.
+After you've got your virtualenv installed, you may install :app:`Pyramid`
+itself using the following commands:
-.. code-block:: text
-
- $ cd env
- $ bin/easy_install pyramid
+.. parsed-literal::
+
+ $ $VENV/bin/easy_install "pyramid==\ |release|\ "
The ``easy_install`` command will take longer than the previous ones to
complete, as it downloads and installs a number of dependencies.
+.. note::
+
+ If you see any warnings and/or errors related to failing to compile the C
+ extensions, in most cases you may safely ignore those errors. If you wish
+ to use the C extensions, please verify that you have a functioning compiler
+ and the Python header files installed.
+
.. index::
single: installing on Windows
@@ -315,106 +311,66 @@ complete, as it downloads and installs a number of dependencies.
Installing :app:`Pyramid` on a Windows System
-------------------------------------------------
-You can use Pyramid on Windows under Python 2 or under Python 3. Directions
-for both versions are included below.
-
-Windows Using Python 2
-~~~~~~~~~~~~~~~~~~~~~~
+You can use Pyramid on Windows under Python 2 or 3.
-#. Install, or find `Python 2.7
- <http://www.python.org/download/releases/2.7.3/>`_ for your system.
+#. Download and install the most recent `Python 2.7.x or 3.3.x version
+ <http://www.python.org/download/>`_ for your system.
-#. Install the `Python for Windows extensions
- <http://sourceforge.net/projects/pywin32/files/>`_. Make sure to
- pick the right download for Python 2.7 and install it using the
- same Python installation from the previous step.
+#. Download and install the `Python for Windows extensions
+ <http://sourceforge.net/projects/pywin32/files/pywin32/>`_. Carefully read
+ the README.txt file at the end of the list of builds, and follow its
+ directions. Make sure you get the proper 32- or 64-bit build and Python
+ version.
-#. Install latest :term:`setuptools` distribution into the Python you
- obtained/installed/found in the step above: download `ez_setup.py
- <http://peak.telecommunity.com/dist/ez_setup.py>`_ and run it using
- the ``python`` interpreter of your Python 2.7 installation using a
- command prompt:
+#. Install latest :term:`setuptools` distribution into the Python from step 1
+ above: download `ez_setup.py
+ <https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py>`_ and run
+ it using the ``python`` interpreter of your Python 2.7 or 3.3 installation
+ using a command prompt:
.. code-block:: text
+ # modify the command according to the python version, e.g.:
+ # for Python 2.7:
c:\> c:\Python27\python ez_setup.py
+ # for Python 3.3:
+ c:\> c:\Python33\python ez_setup.py
-#. Use that Python's `bin/easy_install` to install `virtualenv`:
+#. Install `virtualenv`:
.. code-block:: text
+ # modify the command according to the python version, e.g.:
+ # for Python 2.7:
c:\> c:\Python27\Scripts\easy_install virtualenv
+ # for Python 3.3:
+ c:\> c:\Python33\Scripts\easy_install virtualenv
-#. Use that Python's virtualenv to make a workspace:
+#. Make a :term:`virtualenv` workspace:
.. code-block:: text
- c:\> c:\Python27\Scripts\virtualenv --no-site-packages env
-
-#. Switch to the ``env`` directory:
-
- .. code-block:: text
+ c:\> set VENV=c:\env
+ # modify the command according to the python version, e.g.:
+ # for Python 2.7:
+ c:\> c:\Python27\Scripts\virtualenv %VENV%
+ # for Python 3.3:
+ c:\> c:\Python33\Scripts\virtualenv %VENV%
- c:\> cd env
+ You can either follow the use of the environment variable, ``%VENV%``, or
+ replace it with the root directory of the :term:`virtualenv`. In that case,
+ the `set` command can be skipped. If you choose the former approach, ensure
+ that it's an absolute path.
-#. (Optional) Consider using ``Scripts\activate.bat`` to make your shell
+#. (Optional) Consider using ``%VENV%\Scripts\activate.bat`` to make your shell
environment wired to use the virtualenv.
#. Use ``easy_install`` to get :app:`Pyramid` and its direct dependencies
installed:
- .. code-block:: text
-
- c:\env> Scripts\easy_install pyramid
-
-Windows Using Python 3
-~~~~~~~~~~~~~~~~~~~~~~
-
-#. Install, or find `Python 3.2
- <http://www.python.org/download/releases/3.2.3/>`_ for your system.
-
-#. Install the `Python for Windows extensions
- <http://sourceforge.net/projects/pywin32/files/>`_. Make sure to
- pick the right download for Python 3.2 and install it using the
- same Python installation from the previous step.
-
-#. Install latest :term:`distribute` distribution into the Python you
- obtained/installed/found in the step above: download `distribute_setup.py
- <http://python-distribute.org/distribute_setup.py>`_ and run it using the
- ``python`` interpreter of your Python 3.2 installation using a command
- prompt:
-
- .. code-block:: text
-
- c:\> c:\Python32\python distribute_setup.py
-
-#. Use that Python's `bin/easy_install` to install `virtualenv`:
-
- .. code-block:: text
-
- c:\> c:\Python32\Scripts\easy_install virtualenv
-
-#. Use that Python's virtualenv to make a workspace:
-
- .. code-block:: text
-
- c:\> c:\Python32\Scripts\virtualenv --no-site-packages env
-
-#. Switch to the ``env`` directory:
-
- .. code-block:: text
-
- c:\> cd env
-
-#. (Optional) Consider using ``Scripts\activate.bat`` to make your shell
- environment wired to use the virtualenv.
-
-#. Use ``easy_install`` to get :app:`Pyramid` and its direct dependencies
- installed:
-
- .. code-block:: text
-
- c:\env> Scripts\easy_install pyramid
+ .. parsed-literal::
+
+ c:\\env> %VENV%\\Scripts\\easy_install "pyramid==\ |release|\ "
What Gets Installed
-------------------
diff --git a/docs/narr/introduction.rst b/docs/narr/introduction.rst
index 3540ee5c4..a9c5fdfbd 100644
--- a/docs/narr/introduction.rst
+++ b/docs/narr/introduction.rst
@@ -52,9 +52,7 @@ Documentation
Speed
:app:`Pyramid` is designed to provide noticeably fast execution for common
- tasks such as templating and simple response generation. Although "hardware
- is cheap", the limits of this approach become painfully evident when one
- finds him or herself responsible for managing a great many machines.
+ tasks such as templating and simple response generation.
Reliability
:app:`Pyramid` is developed conservatively and tested exhaustively. Where
@@ -178,8 +176,13 @@ static file server in production without changing any code.
Example: :ref:`static_assets_section`.
-Debug Toolbar
-~~~~~~~~~~~~~
+Fully Interactive Development
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When developing a Pyramid application, several interactive features are
+available. Pyramid can automatically utilize changed templates when rendering
+pages and automatically restart the application to incorporate changed python
+code. Plain old ``print()`` calls used for debugging can display to a console.
Pyramid's debug toolbar comes activated when you use a Pyramid scaffold to
render a project. This toolbar overlays your application in the browser, and
@@ -219,7 +222,8 @@ that the Pyramid core doesn't. Add-on packages already exist which let you
easily send email, let you use the Jinja2 templating system, let you use
XML-RPC or JSON-RPC, let you integrate with jQuery Mobile, etc.
-Examples: http://docs.pylonsproject.org/docs/pyramid.html#pyramid-add-on-documentation
+Examples: http://docs.pylonsproject.org/en/latest/docs/pyramid.html#pyramid-add-on-documentation
+
Class-based and function-based views
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -322,7 +326,14 @@ assertion instead that the view returns "the right stuff" in the dictionary
it returns. You can write "real" unit tests instead of functionally testing
all of your views.
-For example, instead of:
+.. index::
+ pair: renderer; explicitly calling
+ pair: view renderer; explictly calling
+
+.. _example_render_to_response_call:
+
+For example, instead of returning a ``Response`` object from a
+``render_to_response`` call:
.. code-block:: python
:linenos:
@@ -333,7 +344,7 @@ For example, instead of:
return render_to_response('myapp:templates/mytemplate.pt', {'a':1},
request=request)
-You can do this:
+You can return a Python dictionary:
.. code-block:: python
:linenos:
@@ -406,12 +417,12 @@ Sessions
Pyramid has built-in HTTP sessioning. This allows you to associate data with
otherwise anonymous users between requests. Lots of systems do this. But
-Pyramid also allows you to plug in your own sessioning system by creating
-some code that adheres to a documented interface. Currently there is a
-binding package for the third-party Beaker sessioning system that does exactly
-this. But if you have a specialized need (perhaps you want to store your
-session data in MongoDB), you can. You can even switch between
-implementations without changing your application code.
+Pyramid also allows you to plug in your own sessioning system by creating some
+code that adheres to a documented interface. Currently there is a binding
+package for the third-party Redis sessioning system that does exactly this.
+But if you have a specialized need (perhaps you want to store your session data
+in MongoDB), you can. You can even switch between implementations without
+changing your application code.
Example: :ref:`sessions_chapter`.
@@ -603,10 +614,10 @@ Examples: :ref:`hello_traversal_chapter` and
Tweens
~~~~~~
-Pyramid has a sort of internal WSGI-middleware-ish pipeline that can be
-hooked by arbitrary add-ons named "tweens". The debug toolbar is a "tween",
-and the ``pyramid_tm`` transaction manager is also. Tweens are more useful
-than WSGI middleware in some circumstances because they run in the context of
+Pyramid has a sort of internal WSGI-middleware-ish pipeline that can be hooked
+by arbitrary add-ons named "tweens". The debug toolbar is a "tween", and the
+``pyramid_tm`` transaction manager is also. Tweens are more useful than WSGI
+:term:`middleware` in some circumstances because they run in the context of
Pyramid itself, meaning you have access to templates and other renderers, a
"real" request object, and other niceties.
@@ -778,7 +789,7 @@ automate some of the tedium away:
for method in ('GET', 'POST', 'HEAD'):
view = getattr(module, 'xhr_%s_view' % method, None)
if view is not None:
- config.add_view(view, route_name='xhr_route', xhr=True,
+ config.add_view(view, route_name='xhr_route', xhr=True,
permission='view', request_method=method)
config = Configurator()
@@ -860,7 +871,7 @@ It's our goal that no Pyramid question go unanswered. Whether you ask a
question on IRC, on the Pylons-discuss maillist, or on StackOverflow, you're
likely to get a reasonably prompt response. We don't tolerate "support
trolls" or other people who seem to get their rocks off by berating fellow
-users in our various offical support channels. We try to keep it well-lit
+users in our various official support channels. We try to keep it well-lit
and new-user-friendly.
Example: Visit irc\://freenode.net#pyramid (the ``#pyramid`` channel on
diff --git a/docs/narr/introspector.rst b/docs/narr/introspector.rst
index 7784e8960..3c0a6744f 100644
--- a/docs/narr/introspector.rst
+++ b/docs/narr/introspector.rst
@@ -7,6 +7,8 @@
Pyramid Configuration Introspection
===================================
+.. versionadded:: 1.3
+
When Pyramid starts up, each call to a :term:`configuration directive` causes
one or more :term:`introspectable` objects to be registered with an
:term:`introspector`. The introspector can be queried by application code to
@@ -15,10 +17,6 @@ feature is useful for debug toolbars, command-line scripts which show some
aspect of configuration, and for runtime reporting of startup-time
configuration settings.
-.. warning::
-
- Introspection is new in Pyramid 1.3.
-
Using the Introspector
----------------------
@@ -234,18 +232,6 @@ introspectables in categories not described here.
The factory object (the resolved ``factory`` argument to
``add_renderer``).
-``renderer globals factory``
-
- There will be one and only one introspectable in the ``renderer globals
- factory`` category. It represents a call to
- :meth:`pyramid.config.Configurator.set_renderer_globals_factory`; it will
- have the following data.
-
- ``factory``
-
- The factory object (the resolved ``factory`` argument to
- ``set_renderer_globals_factory``).
-
``routes``
Each introspectable in the ``routes`` category represents a call to
diff --git a/docs/narr/logging.rst b/docs/narr/logging.rst
index f4d1d051d..b3bfb8a1e 100644
--- a/docs/narr/logging.rst
+++ b/docs/narr/logging.rst
@@ -22,25 +22,23 @@ Logging Configuration
---------------------
A :app:`Pyramid` project created from a :term:`scaffold` is configured to
-allow you to send messages to `Python standard library logging package
-<http://docs.python.org/library/logging.html>`_ loggers from within your
+allow you to send messages to :mod:`Python standard library logging package
+<logging>` loggers from within your
application. In particular, the :term:`PasteDeploy` ``development.ini`` and
``production.ini`` files created when you use a scaffold include a basic
configuration for the Python :mod:`logging` package.
-PasteDeploy ``.ini`` files use the Python standard library `ConfigParser
-format <http://docs.python.org/lib/module-ConfigParser.html>`_; this the same
-format used as the Python `logging module's Configuration file format
-<http://docs.python.org/lib/logging-config-fileformat.html>`_. The
-application-related and logging-related sections in the configuration file
+PasteDeploy ``.ini`` files use the Python standard library :mod:`ConfigParser
+format <ConfigParser>`; this is the same format used as the Python
+:ref:`logging module's Configuration file format <logging-config-fileformat>`.
+The 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 :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). ``setup_logging`` reads the
+function, a thin wrapper around the :func:`logging.config.fileConfig`
+using the specified ``.ini`` file if it contains a ``[loggers]`` section
+(all of the scaffold-generated ``.ini`` files do). ``setup_logging`` reads the
logging configuration from the ini file upon which ``pserve`` was
invoked.
@@ -300,14 +298,14 @@ Request Logging with Paste's TransLogger
----------------------------------------
Paste provides the `TransLogger
-<http://pythonpaste.org/modules/translogger.html>`_ middleware for logging
-requests using the `Apache Combined Log Format
+<http://pythonpaste.org/modules/translogger.html>`_ :term:`middleware` for
+logging requests using the `Apache Combined Log Format
<http://httpd.apache.org/docs/2.2/logs.html#combined>`_. TransLogger combined
with a FileHandler can be used to create an ``access.log`` file similar to
Apache's.
-Like any standard middleware with a Paste entry point, TransLogger can be
-configured to wrap your application using ``.ini`` file syntax. First,
+Like any standard :term:`middleware` with a Paste entry point, TransLogger can
+be configured to wrap your application using ``.ini`` file syntax. First,
rename your Pyramid ``.ini`` file's ``[app:main]`` section to
``[app:mypyramidapp]``, then add a ``[filter:translogger]`` section, then use
a ``[pipeline:main]`` section file to form a WSGI pipeline with both the
@@ -334,7 +332,7 @@ To this:
mypyramidapp
Using PasteDeploy this way to form and serve a pipeline is equivalent to
-wrapping your app in a TransLogger instance via the bottom the ``main``
+wrapping your app in a TransLogger instance via the bottom of the ``main``
function of your project's ``__init__`` file:
.. code-block:: python
diff --git a/docs/narr/muchadoabouttraversal.rst b/docs/narr/muchadoabouttraversal.rst
index 40d498391..483b1bb16 100644
--- a/docs/narr/muchadoabouttraversal.rst
+++ b/docs/narr/muchadoabouttraversal.rst
@@ -168,18 +168,12 @@ 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:
-.. code-block:: text
- :linenos:
-
- Python 2.4.6 (#2, Apr 29 2010, 00:31:48)
- [GCC 4.4.3] on linux2
- Type "help", "copyright", "credits" or "license" for more information.
- >>> adict = {}
- >>> adict['a'] = 1
- >>> adict['a']
- 1
- >>> adict.__getitem__('a')
- 1
+>>> adict = {}
+>>> adict['a'] = 1
+>>> adict['a']
+1
+>>> adict.__getitem__('a')
+1
The dictionary-like root object stores the ids of all of its subresources as
diff --git a/docs/narr/paste.rst b/docs/narr/paste.rst
index aee5f9069..3427b6d53 100644
--- a/docs/narr/paste.rst
+++ b/docs/narr/paste.rst
@@ -21,7 +21,7 @@ of starting, stopping, and debugging an application.
This chapter is not a replacement for documentation about PasteDeploy; it
only contextualizes the use of PasteDeploy within Pyramid. For detailed
-documentation, see http://pythonpaste.org.
+documentation, see http://pythonpaste.org/deploy/.
PasteDeploy
-----------
@@ -85,6 +85,8 @@ function. This is the function called by :term:`PasteDeploy` when the
``pserve`` command is invoked against our application. It accepts a global
configuration object and *returns* an instance of our application.
+.. _defaults_section_of_pastedeploy_file:
+
``[DEFAULTS]`` Section of a PasteDeploy ``.ini`` File
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/narr/project.rst b/docs/narr/project.rst
index 214440328..d7292d187 100644
--- a/docs/narr/project.rst
+++ b/docs/narr/project.rst
@@ -49,9 +49,7 @@ The included scaffolds are these:
URL mapping via :term:`URL dispatch` and no persistence mechanism.
``zodb``
- URL mapping via :term:`traversal` and persistence via :term:`ZODB`. *Note
- that, as of this writing, this scaffold will not run under Python 3, only
- under Python 2.*
+ URL mapping via :term:`traversal` and persistence via :term:`ZODB`.
``alchemy``
URL mapping via :term:`URL dispatch` and persistence via
@@ -80,13 +78,13 @@ On UNIX:
.. code-block:: text
- $ bin/pcreate -s starter MyProject
+ $ $VENV/bin/pcreate -s starter MyProject
Or on Windows:
.. code-block:: text
- > Scripts\pcreate -s starter MyProject
+ > %VENV%\Scripts\pcreate -s starter MyProject
The above command uses the ``pcreate`` command to create a project with the
``starter`` scaffold. To use a different scaffold, such as
@@ -95,20 +93,20 @@ on UNIX:
.. code-block:: text
- $ bin/pcreate -s alchemy MyProject
+ $ $VENV/bin/pcreate -s alchemy MyProject
Or on Windows:
.. code-block:: text
- > Scripts\pcreate -s alchemy MyProject
+ > %VENV%\Scripts\pcreate -s alchemy MyProject
Here's sample output from a run of ``pcreate`` on UNIX for a project we name
``MyProject``:
.. code-block:: text
- $ bin/pcreate -s starter MyProject
+ $ $VENV/bin/pcreate -s starter MyProject
Creating template pyramid
Creating directory ./MyProject
# ... more output ...
@@ -146,9 +144,9 @@ 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``.
-.. warning::
+.. warning::
- You’ll need to avoid using ``pcreate`` to create a project with the same
+ You'll need to avoid using ``pcreate`` to create a project with the same
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
@@ -177,28 +175,28 @@ On UNIX:
.. code-block:: text
$ cd MyProject
- $ ../bin/python setup.py develop
+ $ $VENV/bin/python setup.py develop
Or on Windows:
.. code-block:: text
> cd MyProject
- > ..\Scripts\python.exe setup.py develop
+ > %VENV%\Scripts\python.exe setup.py develop
Elided output from a run of this command on UNIX is shown below:
.. code-block:: text
$ cd MyProject
- $ ../bin/python setup.py develop
+ $ $VENV/bin/python setup.py develop
...
Finished processing dependencies for MyProject==0.0
-This will install a :term:`distribution` representing your project into the
-interpreter's library set so it can be found by ``import`` statements and by
-other console scripts such as ``pserve``, ``pshell``, ``proutes`` and
-``pviews``.
+This will install a :term:`distribution` representing your project
+into the virtual environment interpreter's library set so it can be
+found by ``import`` statements and by other console scripts such as
+``pserve``, ``pshell``, ``proutes`` and ``pviews``.
.. index::
single: running tests
@@ -216,19 +214,19 @@ On UNIX:
.. code-block:: text
- $ ../bin/python setup.py test -q
+ $ $VENV/bin/python setup.py test -q
Or on Windows:
.. code-block:: text
- > ..\Scripts\python.exe setup.py test -q
+ > %VENV%\Scripts\python.exe setup.py test -q
Here's sample output from a test run on UNIX:
.. code-block:: text
- $ ../bin/python setup.py test -q
+ $ $VENV/bin/python setup.py test -q
running test
running egg_info
writing requirements to MyProject.egg-info/requires.txt
@@ -245,22 +243,24 @@ Here's sample output from a test run on UNIX:
OK
-.. note::
-
- The ``-q`` option is passed to the ``setup.py test`` command to limit the
- output to a stream of dots. If you don't pass ``-q``, you'll see more
- verbose test result output (which normally isn't very useful).
-
The tests themselves are found in the ``tests.py`` module in your ``pcreate``
generated project. Within a project generated by the ``starter`` scaffold, a
single sample test exists.
+.. note::
+
+ The ``-q`` option is passed to the ``setup.py test`` command to limit the
+ output to a stream of dots. If you don't pass ``-q``, you'll see more
+ verbose test result output (which normally isn't very useful).
+
.. index::
single: running an application
single: pserve
single: reload
single: startup
+.. _running_the_project_application:
+
Running The Project Application
-------------------------------
@@ -272,19 +272,19 @@ On UNIX:
.. code-block:: text
- $ ../bin/pserve development.ini
+ $ $VENV/bin/pserve development.ini
On Windows:
.. code-block:: text
- > ..\Scripts\pserve development.ini
+ > %VENV%\Scripts\pserve development.ini
Here's sample output from a run of ``pserve`` on UNIX:
.. code-block:: text
- $ ../bin/pserve development.ini
+ $ $VENV/bin/pserve development.ini
Starting server in PID 16601.
serving on http://0.0.0.0:6543
@@ -305,7 +305,9 @@ If you want to restrict access such that only a browser running on the same
machine as Pyramid will be able to access your Pyramid application, edit the
``development.ini`` file, and replace the ``host`` value in the
``[server:main]`` section. Change it from ``0.0.0.0`` to ``127.0.0.1``. For
-example::
+example:
+
+.. code-block:: ini
[server:main]
use = egg:waitress#main
@@ -357,7 +359,7 @@ For example, on UNIX:
.. code-block:: text
- $ ../bin/pserve development.ini --reload
+ $ $VENV/bin/pserve development.ini --reload
Starting subprocess with file monitor
Starting server in PID 16601.
serving on http://0.0.0.0:6543
@@ -414,7 +416,7 @@ If you don't see the debug toolbar image on the right hand top of the page,
it means you're browsing from a system that does not have debugging access.
By default, for security reasons, only a browser originating from
``localhost`` (``127.0.0.1``) can see the debug toolbar. To allow your
-browser on a remote system to access the server, add the a line within the
+browser on a remote system to access the server, add a line within the
``[app:main]`` section of the ``development.ini`` file in the form
``debugtoolbar.hosts = X.X.X.X``. For example, if your Pyramid application
is running on a remote system, and you're browsing from a host with the IP
@@ -570,8 +572,8 @@ adding more settings to this section.
The ``pyramid.reload_templates`` setting in the ``[app:main]`` section is a
:app:`Pyramid` -specific setting which is passed into the framework. If it
-exists, and its value is ``true``, :term:`Chameleon` and :term:`Mako`
-template changes will not require an application restart to be detected. See
+exists, and its value is ``true``, supported template changes will not
+require an application restart to be detected. See
:ref:`reload_templates_section` for more information.
.. warning:: The ``pyramid.reload_templates`` option should be turned off for
@@ -600,6 +602,8 @@ server which listens on TCP port 6543. It is configured to listen on all
interfaces (``0.0.0.0``). This means that any remote system which has TCP
access to your system can see your Pyramid application.
+.. _MyProject_ini_logging:
+
The sections that live between the markers ``# Begin logging configuration``
and ``# End logging configuration`` represent Python's standard library
:mod:`logging` module configuration for your application. The sections
@@ -696,11 +700,11 @@ testing, packaging, and distributing your application.
.. note::
- ``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
- Hitchhiker's Guide to Packaging <http://guide.python-distribute.org/>`_.
+ ``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
+ Hitchhiker's Guide to Packaging <http://guide.python-distribute.org/>`_.
Our generated ``setup.py`` looks like this:
@@ -818,7 +822,7 @@ also informs Python that the directory which contains it is a *package*.
#. Line 1 imports the :term:`Configurator` class from :mod:`pyramid.config`
that we use later.
-#. Lines 4-11 define a function named ``main`` that returns a :app:`Pyramid`
+#. Lines 4-12 define a function named ``main`` that returns a :app:`Pyramid`
WSGI application. This function is meant to be called by the
:term:`PasteDeploy` framework as a result of running ``pserve``.
@@ -826,17 +830,20 @@ also informs Python that the directory which contains it is a *package*.
Line 7 creates an instance of a :term:`Configurator`.
- Line 8 registers a static view, which will serve up the files from the
+ Line 8 adds support for Chameleon templating bindings, allowing us to
+ specify renderers with the ``.pt`` extension.
+
+ Line 9 registers a static view, which will serve up the files from the
``myproject:static`` :term:`asset specification` (the ``static``
directory of the ``myproject`` package).
- Line 9 adds a :term:`route` to the configuration. This route is later
+ Line 10 adds a :term:`route` to the configuration. This route is later
used by a view in the ``views`` module.
- Line 10 calls ``config.scan()``, which picks up view registrations declared
+ Line 11 calls ``config.scan()``, which picks up view registrations declared
elsewhere in the package (in this case, in the ``views.py`` module).
- Line 11 returns a :term:`WSGI` application to the caller of the function
+ Line 12 returns a :term:`WSGI` application to the caller of the function
(Pyramid's pserve).
.. index::
@@ -868,31 +875,48 @@ specification` that specifies the ``mytemplate.pt`` file within the
``templates`` directory of the ``myproject`` package. The asset
specification could have also been specified as
``myproject:templates/mytemplate.pt``; the leading package name and colon is
-optional. The template file it actually points to is a :term:`Chameleon` ZPT
-template file.
+optional. The template file pointed to is a :term:`Chameleon` ZPT
+template file (``templates/my_template.pt``).
This view callable function is handed a single piece of information: the
:term:`request`. The *request* is an instance of the :term:`WebOb`
``Request`` class representing the browser's request to our server.
-This view returns a dictionary. When this view is invoked, a
-:term:`renderer` converts the dictionary returned by the view into HTML, and
-returns the result as the :term:`response`. This view is configured to
-invoke a renderer which uses a :term:`Chameleon` ZPT template
-(``templates/my_template.pt``).
-
-See :ref:`views_which_use_a_renderer` for more information about how views,
-renderers, and templates relate and cooperate.
-
-.. note:: Because our ``development.ini`` has a ``pyramid.reload_templates =
- true`` directive indicating that templates should be reloaded when
- they change, you won't need to restart the application server to
- see changes you make to templates. During development, this is
- handy. If this directive had been ``false`` (or if the directive
- did not exist), you would need to restart the application server
- for each template change. For production applications, you should
- set your project's ``pyramid.reload_templates`` to ``false`` to increase
- the speed at which templates may be rendered.
+This view is configured to invoke a :term:`renderer` on a template. The
+dictionary the view returns (on line 6) provides the value the renderer
+substitutes into the template when generating HTML. The renderer then
+returns the HTML in a :term:`response`.
+
+.. note:: Dictionaries provide values to :term:`template`\s.
+
+.. note:: When the application is run with the scaffold's :ref:`default
+ development.ini <MyProject_ini>` configuration :ref:`logging is set up
+ <MyProject_ini_logging>` to aid debugging. If an exception is raised,
+ uncaught tracebacks are displayed after the startup messages on :ref:`the
+ console running the server <running_the_project_application>`. Also
+ ``print()`` statements may be inserted into the application for debugging
+ to send output to this console.
+
+.. note:: ``development.ini`` has a setting that controls how templates are
+ reloaded, ``pyramid.reload_templates``.
+
+ - When set to ``True`` (as in the scaffold ``development.ini``) changed
+ templates automatically reload without a server restart. This is
+ convenient while developing, but slows template rendering speed.
+
+ - When set to ``False`` (the default value), changing templates requires
+ a server restart to reload them. Production applications should use
+ ``pyramid.reload_templates = False``.
+
+.. seealso:: See also :ref:`views_which_use_a_renderer` for more information
+ about how views, renderers, and templates relate and cooperate.
+
+.. seealso:: Pyramid can also dynamically reload changed Python files. For
+ more on this see :ref:`reloading_code`.
+
+.. seealso:: The :ref:`debug_toolbar` provides interactive access to your
+ application's internals and, should an exception occur, allows interactive
+ access to traceback execution stack frames from the Python interpreter.
.. index::
single: static directory
@@ -968,12 +992,15 @@ named ``views`` instead of within a single ``views.py`` file, you might:
- Create a ``views`` directory inside your ``myproject`` package directory
(the same directory which holds ``views.py``).
-- *Move* the existing ``views.py`` file to a file inside the new ``views``
- directory named, say, ``blog.py``.
+- Create a file within the new ``views`` directory named ``__init__.py``. (It
+ can be empty. This just tells Python that the ``views`` directory is a
+ *package*.)
-- Create a file within the new ``views`` directory named ``__init__.py`` (it
- can be empty, this just tells Python that the ``views`` directory is a
- *package*.
+- *Move* the content from the existing ``views.py`` file to a file inside the
+ new ``views`` directory named, say, ``blog.py``. Because the ``templates``
+ directory remains in the ``myproject`` package, the template :term:`asset
+ specification` values in ``blog.py`` must now be fully qualified with the
+ project's package name (``myproject:templates/blog.pt``).
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
@@ -990,6 +1017,8 @@ prompt with a similar configuration as would be loaded if you were running
your Pyramid application via ``pserve``. This can be a useful debugging tool.
See :ref:`interactive_shell` for more details.
+.. _what_is_this_pserve_thing:
+
What Is This ``pserve`` Thing
-----------------------------
@@ -1003,12 +1032,12 @@ Pyramid application based on the data in the file.
application. As we saw in :ref:`firstapp_chapter`, ``pserve`` needn't be
invoked at all to run a :app:`Pyramid` application. The use of ``pserve`` to
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 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.
+of its scaffolding. But we strongly recommend using ``pserve`` while
+developing your application, because many other convenience introspection
+commands (such as ``pviews``, ``prequest``, ``proutes`` and others) are also
+implemented in 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.
.. _alternate_wsgi_server:
@@ -1020,7 +1049,7 @@ server. Waitress is a server that is suited for development and light
production usage. It's not the fastest nor the most featureful WSGI server.
Instead, its main feature is that it works on all platforms that Pyramid
needs to run on, making it a good choice as a default server from the
-perspective of Pyramid's developers.
+perspective of Pyramid's developers.
Any WSGI server is capable of running a :app:`Pyramid` application. But we
suggest you stick with the default server for development, and that you wait
diff --git a/docs/narr/renderers.rst b/docs/narr/renderers.rst
index 08ebd881e..740c81555 100644
--- a/docs/narr/renderers.rst
+++ b/docs/narr/renderers.rst
@@ -33,14 +33,11 @@ by the view must be compatible with the particular kind of renderer used, or
an error may occur during view invocation.
One exception exists: it is *always* OK to return a Response object, even
-when a ``renderer`` is configured. If a view callable returns a response
-object from a view that is configured with a renderer, the renderer is
+when a ``renderer`` is configured. In such cases, the renderer is
bypassed entirely.
Various types of renderers exist, including serialization renderers
-and renderers which use templating systems. See also
-:ref:`views_which_use_a_renderer`.
-
+and renderers which use templating systems.
.. index::
single: renderer
@@ -51,16 +48,20 @@ and renderers which use templating systems. See also
Writing View Callables Which Use a Renderer
-------------------------------------------
-As we've seen, view callables needn't always return a Response object.
-Instead, they may return an arbitrary Python object, with the expectation
-that a :term:`renderer` will convert that object into a response instance on
-your behalf. Some renderers use a templating system; other renderers use
-object serialization techniques.
-
-View configuration can vary the renderer associated with a view callable via
-the ``renderer`` attribute. For example, this call to
-:meth:`~pyramid.config.Configurator.add_view` associates the ``json`` renderer
-with a view callable:
+As we've seen, a view callable needn't always return a Response object.
+Instead, it may return an arbitrary Python object, with the expectation that
+a :term:`renderer` will convert that object into a response instance on your
+behalf. Some renderers use a templating system; other renderers use object
+serialization techniques. In practice, renderers obtain application data
+values from Python dictionaries so, in practice, view callables which use
+renderers return Python dictionaries.
+
+View callables can :ref:`explicitly call <example_render_to_response_call>`
+renderers, but typically don't. Instead view configuration declares the
+renderer used to render a view callable's results. This is done with the
+``renderer`` attribute. For example, this call to
+:meth:`~pyramid.config.Configurator.add_view` associates the ``json``
+renderer with a view callable:
.. code-block:: python
@@ -70,9 +71,8 @@ When this configuration is added to an application, the
``myproject.views.my_view`` view callable will now use a ``json`` renderer,
which renders view return values to a :term:`JSON` response serialization.
-Other built-in renderers include renderers which use the :term:`Chameleon`
-templating language to render a dictionary to a response. Additional
-renderers can be added by developers to the system as necessary.
+Pyramid defines several :ref:`built_in_renderers`, and additional renderers
+can be added by developers to the system as necessary.
See :ref:`adding_and_overriding_renderers`.
Views which use a renderer and return a non-Response value can vary non-body
@@ -80,12 +80,10 @@ response attributes (such as headers and the HTTP status code) by attaching a
property to the ``request.response`` attribute.
See :ref:`request_response_attr`.
-If the :term:`view callable` associated with a :term:`view configuration`
-returns a Response object directly, any renderer associated with the view
-configuration is ignored, and the response is passed back to :app:`Pyramid`
-unchanged. For example, if your view callable returns an instance of the
-:class:`pyramid.response.Response` class as a response, no renderer
-will be employed.
+As already mentioned, if the :term:`view callable` associated with a
+:term:`view configuration` returns a Response object (or its instance),
+any renderer associated with the view configuration is ignored,
+and the response is passed back to :app:`Pyramid` unchanged. For example:
.. code-block:: python
:linenos:
@@ -134,13 +132,18 @@ Built-In Renderers
Several built-in renderers exist in :app:`Pyramid`. These renderers can be
used in the ``renderer`` attribute of view configurations.
+.. note::
+
+ Bindings for officially supported templating languages can be found
+ at :ref:`available_template_system_bindings`.
+
.. index::
pair: renderer; string
``string``: String Renderer
~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The ``string`` renderer is a renderer which renders a view callable result to
+The ``string`` renderer renders a view callable result to
a string. If a view callable returns a non-Response object, and the
``string`` renderer is associated in that view's configuration, the result
will be to run the object through the Python ``str`` function to generate a
@@ -203,18 +206,12 @@ representing the JSON serialization of the return value:
.. code-block:: python
- '{"content": "Hello!"}'
+ {"content": "Hello!"}
The return value needn't be a dictionary, but the return value must contain
values serializable by the configured serializer (by default ``json.dumps``).
-.. note::
-
- 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.
-
-You can configure a view to use the JSON renderer by naming ``json`` as the
+You can configure a view to use the JSON renderer by naming``json`` as the
``renderer`` argument of a view configuration, e.g. by using
:meth:`~pyramid.config.Configurator.add_view`:
@@ -235,6 +232,18 @@ using the api of the ``request.response`` attribute. See
Serializing Custom Objects
++++++++++++++++++++++++++
+Some objects are not, by default, JSON-serializable (such as datetimes and
+other arbitrary Python objects). You can, however, register code that makes
+non-serializable objects serializable in two ways:
+
+- By defining a ``__json__`` method on objects in your application.
+
+- For objects you don't "own", you can register JSON renderer that knows about
+ an *adapter* for that kind of object.
+
+Using a Custom ``__json__`` Method
+**********************************
+
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 JSON-serializable (such as ints, lists, dictionaries, strings, and
@@ -260,6 +269,9 @@ will be the active request object at render time.
# the JSON value returned by ``objects`` will be:
# [{"x": 1}, {"x": 2}]
+Using the ``add_adapter`` Method of a Custom JSON Renderer
+**********************************************************
+
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 their classes in order to influence serialization. If the object passed
@@ -274,19 +286,21 @@ objects using the registered adapters. A short example follows:
from pyramid.renderers import JSON
- json_renderer = JSON()
- def datetime_adapter(obj, request):
- return obj.isoformat()
- json_renderer.add_adapter(datetime.datetime, datetime_adapter)
+ if __name__ == '__main__':
+ config = Configurator()
+ json_renderer = JSON()
+ def datetime_adapter(obj, request):
+ return obj.isoformat()
+ json_renderer.add_adapter(datetime.datetime, datetime_adapter)
+ config.add_renderer('json', json_renderer)
- # then during configuration ....
- config = Configurator()
- config.add_renderer('json', json_renderer)
+The ``add_adapter`` method should accept two arguments: the *class* of the object that you want this adapter to run for (in the example above,
+``datetime.datetime``), and the adapter itself.
-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.
+The adapter should be a callable. It 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.
@@ -362,7 +376,7 @@ For example (Javascript):
jqhxr = $.getJSON(api_url);
The string ``callback=?`` above in the ``url`` param to the JQuery
-``getAjax`` function indicates to jQuery that the query should be made as
+``getJSON`` function indicates to jQuery that the query should be made as
a JSONP request; the ``callback`` parameter will be automatically filled
in for you and used.
@@ -371,136 +385,6 @@ renderer in :ref:`json_serializing_custom_objects` can be used when passing
values to a JSONP renderer too.
.. index::
- pair: renderer; chameleon
-
-.. _chameleon_template_renderers:
-
-``*.pt`` or ``*.txt``: Chameleon Template Renderers
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Two built-in renderers exist for :term:`Chameleon` templates.
-
-If the ``renderer`` attribute of a view configuration is an absolute path, a
-relative path or :term:`asset specification` which has a final path element
-with a filename extension of ``.pt``, the Chameleon ZPT renderer is used.
-See :ref:`chameleon_zpt_templates` for more information about ZPT templates.
-
-If the ``renderer`` attribute of a view configuration is an absolute path or
-a :term:`asset specification` which has a final path element with a filename
-extension of ``.txt``, the :term:`Chameleon` text renderer is used. See
-:ref:`chameleon_text_templates` for more information about Chameleon text
-templates.
-
-The behavior of these renderers is the same, except for the engine
-used to render the template.
-
-When a ``renderer`` attribute that names a template path or :term:`asset
-specification` (e.g. ``myproject:templates/foo.pt`` or
-``myproject:templates/foo.txt``) is used, the view must return a
-:term:`Response` object or a Python *dictionary*. If the view callable with
-an associated template returns a Python dictionary, the named template will
-be passed the dictionary as its keyword arguments, and the template renderer
-implementation will return the resulting rendered template in a response to
-the user. If the view callable returns anything but a Response object or a
-dictionary, an error will be raised.
-
-Before passing keywords to the template, the keyword arguments derived from
-the dictionary returned by the view are augmented. The callable object --
-whatever object was used to define the view -- will be automatically inserted
-into the set of keyword arguments passed to the template as the ``view``
-keyword. If the view callable was a class, the ``view`` keyword will be an
-instance of that class. Also inserted into the keywords passed to the
-template are ``renderer_name`` (the string used in the ``renderer`` attribute
-of the directive), ``renderer_info`` (an object containing renderer-related
-information), ``context`` (the context resource of the view used to render
-the template), and ``request`` (the request passed to the view used to render
-the template). ``request`` is also available as ``req`` in Pyramid 1.3+.
-
-Here's an example view configuration which uses a Chameleon ZPT renderer:
-
-.. code-block:: python
- :linenos:
-
- # config is an instance of pyramid.config.Configurator
-
- config.add_view('myproject.views.hello_world',
- name='hello',
- context='myproject.resources.Hello',
- renderer='myproject:templates/foo.pt')
-
-Here's an example view configuration which uses a Chameleon text renderer:
-
-.. code-block:: python
- :linenos:
-
- config.add_view('myproject.views.hello_world',
- name='hello',
- context='myproject.resources.Hello',
- renderer='myproject:templates/foo.txt')
-
-Views which use a Chameleon renderer can vary response attributes by using
-the API of the ``request.response`` attribute. See
-:ref:`request_response_attr`.
-
-.. index::
- pair: renderer; mako
-
-.. _mako_template_renderers:
-
-``*.mak`` or ``*.mako``: Mako Template Renderer
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The ``Mako`` template renderer renders views using a Mako template. When
-used, the view must return a Response object or a Python *dictionary*. The
-dictionary items will then be used in the global template space. If the view
-callable returns anything but a Response object or a dictionary, an error
-will be raised.
-
-When using a ``renderer`` argument to a :term:`view configuration` to specify
-a Mako template, the value of the ``renderer`` may be a path relative to the
-``mako.directories`` setting (e.g. ``some/template.mak``) or, alternately,
-it may be a :term:`asset specification`
-(e.g. ``apackage:templates/sometemplate.mak``). Mako templates may
-internally inherit other Mako templates using a relative filename or a
-:term:`asset specification` as desired.
-
-Here's an example view configuration which uses a relative path:
-
-.. code-block:: python
- :linenos:
-
- # config is an instance of pyramid.config.Configurator
-
- config.add_view('myproject.views.hello_world',
- name='hello',
- context='myproject.resources.Hello',
- renderer='foo.mak')
-
-It's important to note that in Mako's case, the 'relative' path name
-``foo.mak`` above is not relative to the package, but is relative to the
-directory (or directories) configured for Mako via the ``mako.directories``
-configuration file setting.
-
-The renderer can also be provided in :term:`asset specification`
-format. Here's an example view configuration which uses one:
-
-.. code-block:: python
- :linenos:
-
- config.add_view('myproject.views.hello_world',
- name='hello',
- context='myproject.resources.Hello',
- renderer='mypackage:templates/foo.mak')
-
-The above configuration will use the file named ``foo.mak`` in the
-``templates`` directory of the ``mypackage`` package.
-
-The ``Mako`` template renderer can take additional arguments beyond the
-standard ``pyramid.reload_templates`` setting, see the
-:ref:`environment_chapter` for additional
-:ref:`mako_template_renderer_settings`.
-
-.. index::
single: response headers (from a renderer)
single: renderer response headers
@@ -561,40 +445,6 @@ For more information on attributes of the request, see the API documentation
in :ref:`request_module`. For more information on the API of
``request.response``, see :attr:`pyramid.request.Request.response`.
-.. _response_prefixed_attrs:
-
-Deprecated Mechanism to Vary Attributes of Rendered Responses
--------------------------------------------------------------
-
-In previous releases of Pyramid (1.0 and before), the ``request.response``
-attribute did not exist. Instead, Pyramid required users to set special
-``response_`` -prefixed attributes of the request to influence response
-behavior. As of Pyramid 1.1, those request attributes are deprecated and
-their use will cause a deprecation warning to be issued when used. Until
-their existence is removed completely, we document them below, for benefit of
-people with older code bases.
-
-``response_content_type``
- Defines the content-type of the resulting response,
- e.g. ``text/xml``.
-
-``response_headerlist``
- A sequence of tuples describing header values that should be set in the
- response, e.g. ``[('Set-Cookie', 'abc=123'), ('X-My-Header', 'foo')]``.
-
-``response_status``
- A WSGI-style status code (e.g. ``200 OK``) describing the status of the
- response.
-
-``response_charset``
- The character set (e.g. ``UTF-8``) of the response.
-
-``response_cache_for``
- A value in seconds which will influence ``Cache-Control`` and ``Expires``
- headers in the returned response. The same can also be achieved by
- returning various values in the ``response_headerlist``, this is purely a
- convenience.
-
.. _adding_and_overriding_renderers:
Adding and Changing Renderers
@@ -720,7 +570,7 @@ factory, which expects to be passed a filesystem path:
Adding the above code to your application startup 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
+configurations by referring to any ``renderer`` which *ends in* ``.jinja2`` in
the ``renderer`` attribute of a :term:`view configuration`:
.. code-block:: python
@@ -744,44 +594,37 @@ ending with ``.jinja2`` in its ``renderer`` value. The ``name`` passed
to the ``MyJinja2Renderer`` constructor will be the full value that was
set as ``renderer=`` in the view configuration.
-.. index::
- pair: renderer; changing
+Adding a Default Renderer
+~~~~~~~~~~~~~~~~~~~~~~~~~
-Changing 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 the
-:meth:`pyramid.config.Configurator.add_renderer` method:
+To associate a *default* renderer with *all* view configurations (even
+ones which do not possess a ``renderer`` attribute), pass ``None`` as
+the ``name`` attribute to the renderer tag:
.. code-block:: python
- config.add_renderer('.zpt', '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 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:
-
-.. code-block:: python
+ config.add_renderer(None, 'mypackage.json_renderer_factory')
- config.add_renderer('.pt', 'mypackage.pt_renderer')
+.. index::
+ pair: renderer; changing
-After you do this, the :term:`renderer factory` in
-``mypackage.pt_renderer`` will be used to render templates which end
-in ``.pt``, replacing the default Chameleon ZPT renderer.
+Changing an Existing Renderer
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-To associate a *default* renderer with *all* view configurations (even
-ones which do not possess a ``renderer`` attribute), pass ``None`` as
-the ``name`` attribute to the renderer tag:
+Pyramid supports overriding almost every aspect of its setup through its
+:ref:`Conflict Resolution <automatic_conflict_resolution>` mechanism. This
+means that in most cases overriding a renderer is as simple as using the
+:meth:`pyramid.config.Configurator.add_renderer` method to re-define the
+template extension. For example, if you would like to override the ``.txt``
+extension to specify a new renderer you could do the following:
.. code-block:: python
- config.add_renderer(None, 'mypackage.json_renderer_factory')
+ json_renderer = pyramid.renderers.JSON()
+ config.add_renderer('json', json_renderer)
+
+After doing this, any views registered with the ``json`` renderer will use
+the new renderer.
.. index::
pair: renderer; overriding at runtime
diff --git a/docs/narr/resources.rst b/docs/narr/resources.rst
index a24c44f29..b1bb611e5 100644
--- a/docs/narr/resources.rst
+++ b/docs/narr/resources.rst
@@ -171,7 +171,7 @@ you will reach the filesystem root directory.
URL generated (as opposed to a single leading slash or empty tuple
element).
-.. sidebar:: Using :mod:`pyramid_traversalwrapper`
+.. sidebar:: For your convenience
If you'd rather not manage the ``__name__`` and ``__parent__`` attributes
of your resources "by hand", an add-on package named
@@ -300,7 +300,7 @@ the resource by :meth:`~pyramid.request.Request.resource_url`.
The ``__resource_url__`` hook is passed two arguments: ``request`` and
``info``. ``request`` is the :term:`request` object passed to
:meth:`~pyramid.request.Request.resource_url`. ``info`` is a dictionary with
-two keys:
+the following keys:
``physical_path``
A string representing the "physical path" computed for the resource, as
diff --git a/docs/narr/router.rst b/docs/narr/router.rst
index b78362066..ac3deefdc 100644
--- a/docs/narr/router.rst
+++ b/docs/narr/router.rst
@@ -46,7 +46,7 @@ request enters a :app:`Pyramid` application through to the point that
:class:`~pyramid.interfaces.IRoute` object representing the route which
matched. The root object associated with the route found is also
generated: if the :term:`route configuration` which matched has an
- associated a ``factory`` argument, this factory is used to generate the
+ associated ``factory`` argument, this factory is used to generate the
root object, otherwise a default :term:`root factory` is used.
#. If a route match was *not* found, and a ``root_factory`` argument was
diff --git a/docs/narr/scaffolding.rst b/docs/narr/scaffolding.rst
index 9ac579a87..534b2caf4 100644
--- a/docs/narr/scaffolding.rst
+++ b/docs/narr/scaffolding.rst
@@ -74,10 +74,14 @@ concrete examples of scaffold directories (``zodb``, ``alchemy``, and
After you've created the template directory, add the following to the
``entry_points`` value of your distribution's ``setup.py``:
- [pyramid.scaffold]
- coolextension=coolextension.scaffolds:CoolExtensionTemplate
+.. code-block:: ini
+
+ [pyramid.scaffold]
+ coolextension=coolextension.scaffolds:CoolExtensionTemplate
-For example::
+For example:
+
+.. code-block:: python
def setup(
...,
@@ -95,7 +99,7 @@ because that's the name we gave it in the entry point setup. Running
output directory named ``MyStuff``.
See the module documentation for :mod:`pyramid.scaffolds` for information
-about the API of the :class:`pyramid.scaffolds.PyramidScaffold` class and
+about the API of the :class:`pyramid.scaffolds.Template` class and
related classes. You can override methods of this class to get special
behavior.
diff --git a/docs/narr/security.rst b/docs/narr/security.rst
index 5a1a92e08..6517fedf8 100644
--- a/docs/narr/security.rst
+++ b/docs/narr/security.rst
@@ -85,7 +85,6 @@ during application setup to specify the authentication policy.
For example:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -151,7 +150,6 @@ API:
The equivalent view registration including the ``add`` permission name
may be performed via the ``@view_config`` decorator:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -234,8 +232,8 @@ class:
.. code-block:: python
:linenos:
- from pyramid.security import Everyone
from pyramid.security import Allow
+ from pyramid.security import Everyone
class Blog(object):
__acl__ = [
@@ -250,8 +248,8 @@ Or, if your resources are persistent, an ACL might be specified via the
.. code-block:: python
:linenos:
- from pyramid.security import Everyone
from pyramid.security import Allow
+ from pyramid.security import Everyone
class Blog(object):
pass
@@ -270,6 +268,27 @@ resource instances with an ACL (as opposed to just decorating their class) in
applications such as "CMS" systems where fine-grained access is required on
an object-by-object basis.
+Dynamic ACLs are also possible by turning the ACL into a callable on the
+resource. This may allow the ACL to dynamically generate rules based on
+properties of the instance.
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.security import Allow
+ from pyramid.security import Everyone
+
+ class Blog(object):
+ def __acl__(self):
+ return [
+ (Allow, Everyone, 'view'),
+ (Allow, self.owner, 'edit'),
+ (Allow, 'group:editors', 'edit'),
+ ]
+
+ def __init__(self, owner):
+ self.owner = owner
+
.. index::
single: ACE
single: access control entry
@@ -282,8 +301,8 @@ Here's an example ACL:
.. code-block:: python
:linenos:
- from pyramid.security import Everyone
from pyramid.security import Allow
+ from pyramid.security import Everyone
__acl__ = [
(Allow, Everyone, 'view'),
@@ -312,7 +331,7 @@ A principal is usually a user id, however it also may be a group id if your
authentication system provides group information and the effective
:term:`authentication policy` policy is written to respect group information.
For example, the
-:class:`pyramid.authentication.RepozeWho1AuthenicationPolicy` respects group
+:class:`pyramid.authentication.RepozeWho1AuthenticationPolicy` respects group
information if you configure it with a ``callback``.
Each ACE in an ACL is processed by an authorization policy *in the
@@ -321,9 +340,9 @@ order dictated by the ACL*. So if you have an ACL like this:
.. code-block:: python
:linenos:
- from pyramid.security import Everyone
from pyramid.security import Allow
from pyramid.security import Deny
+ from pyramid.security import Everyone
__acl__ = [
(Allow, Everyone, 'view'),
@@ -359,8 +378,8 @@ ACE, as below.
.. code-block:: python
:linenos:
- from pyramid.security import Everyone
from pyramid.security import Allow
+ from pyramid.security import Everyone
__acl__ = [
(Allow, Everyone, 'view'),
@@ -507,7 +526,7 @@ example:
.. code-block:: text
- $ PYRAMID_DEBUG_AUTHORIZATION=1 bin/pserve myproject.ini
+ $ PYRAMID_DEBUG_AUTHORIZATION=1 $VENV/bin/pserve myproject.ini
When any authorization takes place during a top-level view rendering,
a message will be logged to the console (to stderr) about what ACE in
diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst
index fa4affd8a..f33bc6132 100644
--- a/docs/narr/sessions.rst
+++ b/docs/narr/sessions.rst
@@ -99,6 +99,11 @@ example:
else:
return Response('Fred was not in the session')
+The first time this view is invoked produces ``Fred was not in the
+session``. Subsequent invocations produce ``Fred was in the
+session``, assuming of course that the client side maintains the
+session's identity across multiple requests.
+
You can use a session much like a Python dictionary. It supports all
dictionary methods, along with some extra attributes, and methods.
@@ -146,8 +151,7 @@ Some gotchas:
you've changed sessioning data.
.. index::
- single: pyramid_beaker
- single: Beaker
+ single: pyramid_redis_sessions
single: session factory (alternates)
.. _using_alternate_session_factories:
@@ -155,13 +159,10 @@ Some gotchas:
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 `the pyramid_beaker documentation
-<http://docs.pylonsproject.org/projects/pyramid_beaker/en/latest/>`_ for more
-information about ``pyramid_beaker``.
+At the time of this writing, exactly one project-endorsed alternate session
+factory exists named :term:`pyramid_redis_sessions`. It can be downloaded from
+PyPI. It uses the Redis database as a backend. It is the recommended
+persistent session solution at the time of this writing.
.. index::
single: session factory (custom)
@@ -181,6 +182,8 @@ implementation in the :mod:`pyramid.session` module as inspiration.
.. index::
single: flash messages
+.. _flash_messages:
+
Flash Messages
--------------
@@ -252,25 +255,19 @@ that were added to the flash queue, and empties the queue.
.. method:: pop_flash(queue='')
-.. code-block:: python
- :linenos:
-
- >>> request.session.flash('info message')
- >>> request.session.pop_flash()
- ['info message']
+>>> request.session.flash('info message')
+>>> request.session.pop_flash()
+['info message']
Calling ``session.pop_flash()`` again like above without a corresponding call
to ``session.flash()`` will return an empty list, because the queue has already
been popped.
-.. code-block:: python
- :linenos:
-
- >>> request.session.flash('info message')
- >>> request.session.pop_flash()
- ['info message']
- >>> request.session.pop_flash()
- []
+>>> request.session.flash('info message')
+>>> request.session.pop_flash()
+['info message']
+>>> request.session.pop_flash()
+[]
.. index::
single: session.peek_flash
@@ -285,18 +282,15 @@ popped from flash storage.
.. method:: peek_flash(queue='')
-.. code-block:: python
- :linenos:
-
- >>> request.session.flash('info message')
- >>> request.session.peek_flash()
- ['info message']
- >>> request.session.peek_flash()
- ['info message']
- >>> request.session.pop_flash()
- ['info message']
- >>> request.session.peek_flash()
- []
+>>> request.session.flash('info message')
+>>> request.session.peek_flash()
+['info message']
+>>> request.session.peek_flash()
+['info message']
+>>> request.session.pop_flash()
+['info message']
+>>> request.session.peek_flash()
+[]
.. index::
single: preventing cross-site request forgery attacks
@@ -307,14 +301,15 @@ Preventing Cross-Site Request Forgery Attacks
`Cross-site request forgery
<http://en.wikipedia.org/wiki/Cross-site_request_forgery>`_ attacks are a
-phenomenon whereby a user with an identity on your website might click on a
-URL or button on another website which secretly redirects the user to your
-application to perform some command that requires elevated privileges.
-
-You can avoid most of these attacks by making sure that the correct *CSRF
-token* has been set in an :app:`Pyramid` session object before performing any
-actions in code which requires elevated privileges that is invoked via a form
-post. To use CSRF token support, you must enable a :term:`session factory`
+phenomenon whereby a user who is logged in to your website might inadvertantly
+load a URL because it is linked from, or embedded in, an attacker's website.
+If the URL is one that may modify or delete data, the consequences can be dire.
+
+You can avoid most of these attacks by issuing a unique token to the browser
+and then requiring that it be present in all potentially unsafe requests.
+:app:`Pyramid` sessions provide facilities to create and check CSRF tokens.
+
+To use CSRF tokens, you must first enable a :term:`session factory`
as described in :ref:`using_the_default_session_factory` or
:ref:`using_alternate_session_factories`.
@@ -333,33 +328,84 @@ To get the current CSRF token from the session, use the
The ``session.get_csrf_token()`` method accepts no arguments. It returns a
CSRF *token* string. If ``session.get_csrf_token()`` or
-``session.new_csrf_token()`` was invoked previously for this session, the
+``session.new_csrf_token()`` was invoked previously for this session, then the
existing token will be returned. If no CSRF token previously existed for
-this session, a new token will be will be set into the session and returned.
+this session, then a new token will be will be set into the session and returned.
The newly created token will be opaque and randomized.
You can use the returned token as the value of a hidden field in a form that
-posts to a method that requires elevated privileges. The handler for the
-form post should use ``session.get_csrf_token()`` *again* to obtain the
-current CSRF token related to the user from the session, and compare it to
-the value of the hidden form field. For example, if your form rendering
-included the CSRF token obtained via ``session.get_csrf_token()`` as a hidden
-input field named ``csrf_token``:
+posts to a method that requires elevated privileges, or supply it as a request
+header in AJAX requests.
+
+For example, include the CSRF token as a hidden field:
+
+.. code-block:: html
+
+ <form method="post" action="/myview">
+ <input type="hidden" name="csrf_token" value="${request.session.get_csrf_token()}">
+ <input type="submit" value="Delete Everything">
+ </form>
+
+Or, include it as a header in a jQuery AJAX request:
+
+.. code-block:: javascript
+
+ var csrfToken = ${request.session.get_csrf_token()};
+ $.ajax({
+ type: "POST",
+ url: "/myview",
+ headers: { 'X-CSRF-Token': csrfToken }
+ }).done(function() {
+ alert("Deleted");
+ });
+
+
+The handler for the URL that receives the request
+should then require that the correct CSRF token is supplied.
+
+Checking CSRF Tokens Manually
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In request handling code, you can check the presence and validity of a CSRF
+token with :func:`pyramid.session.check_csrf_token(request)``. If the token is
+valid, it will return ``True``, otherwise it will raise ``HTTPBadRequest``.
+Optionally, you can specify ``raises=False`` to have the check return ``False``
+instead of raising an exception.
+
+By default, it checks for a GET or POST parameter named ``csrf_token`` or a
+header named ``X-CSRF-Token``.
.. code-block:: python
- :linenos:
- token = request.session.get_csrf_token()
- if token != request.POST['csrf_token']:
- raise ValueError('CSRF token did not match')
+ from pyramid.session import check_csrf_token
+
+ def myview(request):
+ # Require CSRF Token
+ check_csrf_token(request)
+
+ # ...
.. index::
single: session.new_csrf_token
+Checking CSRF Tokens With A View Predicate
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A convenient way to require a valid CSRF Token for a particular view is to
+include ``check_csrf=True`` as a view predicate.
+See :meth:`pyramid.config.Configurator.add_route`.
+
+.. code-block:: python
+
+ @view_config(request_method='POST', check_csrf=True, ...)
+ def myview(request):
+ ...
+
+
Using the ``session.new_csrf_token`` Method
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-To explicitly add a new CSRF token to the session, use the
+To explicitly create a new CSRF token, use the
``session.new_csrf_token()`` method. This differs only from
``session.get_csrf_token()`` inasmuch as it clears any existing CSRF token,
creates a new CSRF token, sets the token into the session, and returns the
diff --git a/docs/narr/startup.rst b/docs/narr/startup.rst
index f5c741f52..1affa1758 100644
--- a/docs/narr/startup.rst
+++ b/docs/narr/startup.rst
@@ -8,12 +8,12 @@ you'll see something much like this show up on the console:
.. code-block:: text
- $ pserve myproject/MyProject.ini
+ $ pserve development.ini
Starting server in PID 16601.
serving on 0.0.0.0:6543 view at http://127.0.0.1:6543
This chapter explains what happens between the time you press the "Return"
-key on your keyboard after typing ``pserve myproject/MyProject.ini``
+key on your keyboard after typing ``pserve development.ini``
and the time the line ``serving on 0.0.0.0:6543 ...`` is output to your
console.
@@ -77,9 +77,9 @@ Here's a high-level time-ordered overview of what happens when you press
Note that the constructor function accepts a ``global_config`` argument,
which is a dictionary of key/value pairs mentioned in the ``[DEFAULT]``
- section of an ``.ini`` file (if `[DEFAULT]
- <http://docs.pylonsproject.org/projects/pyramid/dev/narr/paste.html#defaults-section-of-a-pastedeploy-ini-file>`__
- is present). It also accepts a ``**settings`` argument, which collects
+ section of an ``.ini`` file
+ (if :ref:`[DEFAULT] <defaults_section_of_pastedeploy_file>` is present).
+ It also accepts a ``**settings`` argument, which collects
another set of arbitrary key/value pairs. The arbitrary key/value pairs
received by this function in ``**settings`` will be composed of all the
key/value pairs that are present in the ``[app:main]`` section (except for
diff --git a/docs/narr/subrequest.rst b/docs/narr/subrequest.rst
index 033f045a6..4b4e99d41 100644
--- a/docs/narr/subrequest.rst
+++ b/docs/narr/subrequest.rst
@@ -155,7 +155,7 @@ In the example above, the call to
exception. This is because it's using the default value for ``use_tweens``,
which is ``False``. You can pass ``use_tweens=True`` instead to ensure that
it will convert an exception to a Response if an :term:`exception view` is
-configured instead of raising the exception. This because exception views
+configured instead of raising the exception. This is because exception views
are called by the exception view :term:`tween` as described in
:ref:`exception_views` when any view raises an exception.
@@ -223,21 +223,21 @@ unconditionally:
:meth:`~pyramid.config.Configurator.set_request_property`) on the subrequest
object passed as ``request``
-- causes a :class:`~pyramid.event.NewRequest` event to be sent at the
+- causes a :class:`~pyramid.events.NewRequest` event to be sent at the
beginning of request processing.
-- causes a :class:`~pyramid.event.ContextFound` event to be sent when a
+- causes a :class:`~pyramid.events.ContextFound` event to be sent when a
context resource is found.
-
+
- Ensures that the user implied by the request passed has the necessary
authorization to invoke view callable before calling it.
-- causes a :class:`~pyramid.event.NewResponse` event to be sent when the
- Pyramid application returns a response.
-
- Calls any :term:`response callback` functions defined within the subrequest's
lifetime if a response is obtained from the Pyramid application.
+- causes a :class:`~pyramid.events.NewResponse` event to be sent if a response
+ is obtained.
+
- Calls any :term:`finished callback` functions defined within the subrequest's
lifetime.
@@ -250,7 +250,7 @@ It's a poor idea to use the original ``request`` object as an argument to
:meth:`~pyramid.request.Request.invoke_subrequest`. You should construct a
new request instead as demonstrated in the above example, using
:meth:`pyramid.request.Request.blank`. Once you've constructed a request
-object, you'll need to massage the it to match the view callable you'd like
+object, you'll need to massage it to match the view callable you'd like
to be executed during the subrequest. This can be done by adjusting the
subrequest's URL, its headers, its request method, and other attributes. The
documentation for :class:`pyramid.request.Request` exposes the methods you
diff --git a/docs/narr/templates.rst b/docs/narr/templates.rst
index 08fa9883e..3e19f7198 100644
--- a/docs/narr/templates.rst
+++ b/docs/narr/templates.rst
@@ -8,10 +8,6 @@ dynamic data provided by a :term:`view`. :app:`Pyramid` offers a
number of ways to perform templating tasks out of the box, and
provides add-on templating support through a set of bindings packages.
-Out of the box, :app:`Pyramid` provides templating via the :term:`Chameleon`
-and :term:`Mako` templating libraries. :term:`Chameleon` provides support for
-two different types of templates: :term:`ZPT` templates, and text templates.
-
Before discussing how built-in templates are used in
detail, we'll discuss two ways to render templates within
:app:`Pyramid` in general: directly, and via renderer
@@ -32,7 +28,7 @@ given templating engine to do so.
:app:`Pyramid` provides various APIs that allow you to render templates
directly from within a view callable. For example, if there is a
-:term:`Chameleon` ZPT template named ``foo.pt`` in a directory named
+:term:`Chameleon` ZPT template named ``foo.pt`` in a directory named
``templates`` in your application, you can render the template from
within the body of a view callable like so:
@@ -60,19 +56,8 @@ In this case, this is the directory containing the file that
defines the ``sample_view`` function. Although a renderer path is
usually just a simple relative pathname, a path named as a renderer
can be absolute, starting with a slash on UNIX or a drive letter
-prefix on Windows.
-
-.. warning::
-
- Only :term:`Chameleon` templates support defining a renderer for a
- template relative to the location of the module where the view callable is
- defined. Mako templates, and other templating system bindings work
- differently. In particular, Mako templates use a "lookup path" as defined
- by the ``mako.directories`` configuration file instead of treating
- relative paths as relative to the current view module. See
- :ref:`mako_templates`.
-
-The path can alternately be a :term:`asset specification` in the form
+prefix on Windows. The path can alternately be a
+:term:`asset specification` in the form
``some.dotted.package_name:relative/path``. This makes it possible to
address template assets which live in another package. For example:
@@ -90,16 +75,9 @@ An asset specification points at a file within a Python *package*.
In this case, it points at a file named ``foo.pt`` within the
``templates`` directory of the ``mypackage`` package. Using a
asset specification instead of a relative template name is usually
-a good idea, because calls to ``render_to_response`` using asset
-specifications will continue to work properly if you move the code
-containing them around.
-
-.. note::
-
- Mako templating system bindings also respect absolute asset
- specifications as an argument to any of the ``render*`` commands. If a
- template name defines a ``:`` (colon) character and is not an absolute
- path, it is treated as an absolute asset specification.
+a good idea, because calls to :func:`~pyramid.renderers.render_to_response`
+using asset specifications will continue to work properly if you move the
+code containing them around.
In the examples above we pass in a keyword argument named ``request``
representing the current :app:`Pyramid` request. Passing a request
@@ -147,10 +125,9 @@ import its API functions into your views module, use those APIs to generate a
string, then return that string as the body of a :app:`Pyramid`
:term:`Response` object.
-For example, here's an example of using "raw" `Mako
-<http://www.makotemplates.org/>`_ from within a :app:`Pyramid` :term:`view`:
+For example, here's an example of using "raw" Mako_ from within a
+:app:`Pyramid` :term:`view`:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -164,10 +141,10 @@ For example, here's an example of using "raw" `Mako
return response
You probably wouldn't use this particular snippet in a project, because it's
-easier to use the Mako renderer bindings which already exist in
-:app:`Pyramid`. But if your favorite templating system is not supported as a
-renderer extension for :app:`Pyramid`, you can create your own simple
-combination as shown above.
+easier to use the supported
+:ref:`Mako bindings <available_template_system_bindings>`. But if your
+favorite templating system is not supported as a renderer extension for
+:app:`Pyramid`, you can create your own simple combination as shown above.
.. note::
@@ -282,8 +259,8 @@ You can define more values which will be passed to every template executed as
a result of rendering by defining :term:`renderer globals`.
What any particular renderer does with these system values is up to the
-renderer itself, but most template renderers, including Chameleon and Mako
-renderers, make these names available as top-level template variables.
+renderer itself, but most template renderers make these names available as
+top-level template variables.
.. index::
pair: renderer; templates
@@ -323,7 +300,9 @@ template renderer:
def my_view(request):
return {'foo':1, 'bar':2}
-.. note:: You do not need to supply the ``request`` value as a key
+.. note::
+
+ You do not need to supply the ``request`` value as a key
in the dictionary result returned from a renderer-configured view
callable. :app:`Pyramid` automatically supplies this value for
you so that the "most correct" system values are provided to
@@ -351,11 +330,7 @@ it possible to address template assets which live in another package.
Not just any template from any arbitrary templating system may be used as a
renderer. Bindings must exist specifically for :app:`Pyramid` to use a
-templating language template as a renderer. Currently, :app:`Pyramid` has
-built-in support for two Chameleon templating languages: ZPT and text, and
-the Mako templating system. See :ref:`built_in_renderers` for a discussion
-of their details. :app:`Pyramid` also supports the use of :term:`Jinja2`
-templates as renderers. See :ref:`available_template_system_bindings`.
+templating language template as a renderer.
.. sidebar:: Why Use A Renderer via View Configuration
@@ -384,239 +359,11 @@ The same set of system values are provided to templates rendered via a
renderer view configuration as those provided to templates rendered
imperatively. See :ref:`renderer_system_values`.
-
-.. index::
- single: Chameleon ZPT templates
- single: ZPT templates (Chameleon)
-
-.. _chameleon_zpt_templates:
-
-:term:`Chameleon` ZPT Templates
--------------------------------
-
-Like :term:`Zope`, :app:`Pyramid` uses :term:`ZPT` (Zope Page
-Templates) as its default templating language. However,
-:app:`Pyramid` uses a different implementation of the :term:`ZPT`
-specification than Zope does: the :term:`Chameleon` templating
-engine. The Chameleon engine complies largely with the `Zope Page
-Template <http://wiki.zope.org/ZPT/FrontPage>`_ template
-specification. However, it is significantly faster.
-
-The language definition documentation for Chameleon ZPT-style
-templates is available from `the Chameleon website
-<http://chameleon.repoze.org/>`_.
-
-Given a :term:`Chameleon` ZPT template named ``foo.pt`` in a directory
-in your application named ``templates``, you can render the template as
-a :term:`renderer` like so:
-
-.. code-block:: python
- :linenos:
-
- from pyramid.view import view_config
-
- @view_config(renderer='templates/foo.pt')
- def my_view(request):
- return {'foo':1, 'bar':2}
-
-See also :ref:`built_in_renderers` for more general information about
-renderers, including Chameleon ZPT renderers.
-
-.. index::
- single: ZPT template (sample)
-
-A Sample ZPT Template
-~~~~~~~~~~~~~~~~~~~~~
-
-Here's what a simple :term:`Chameleon` ZPT template used under
-:app:`Pyramid` might look like:
-
-.. code-block:: xml
- :linenos:
-
- <!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"
- xmlns:tal="http://xml.zope.org/namespaces/tal">
- <head>
- <meta http-equiv="content-type" content="text/html; charset=utf-8" />
- <title>${project} Application</title>
- </head>
- <body>
- <h1 class="title">Welcome to <code>${project}</code>, an
- application generated by the <a
- href="http://docs.pylonsproject.org/projects/pyramid/current/"
- >pyramid</a> web
- application framework.</h1>
- </body>
- </html>
-
-Note the use of :term:`Genshi` -style ``${replacements}`` above. This
-is one of the ways that :term:`Chameleon` ZPT differs from standard
-ZPT. The above template expects to find a ``project`` key in the set
-of keywords passed in to it via :func:`~pyramid.renderers.render` or
-:func:`~pyramid.renderers.render_to_response`. Typical ZPT
-attribute-based syntax (e.g. ``tal:content`` and ``tal:replace``) also
-works in these templates.
-
-.. index::
- single: ZPT macros
- single: Chameleon ZPT macros
-
-Using ZPT Macros in :app:`Pyramid`
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When a :term:`renderer` is used to render a template, :app:`Pyramid` makes at
-least two top-level names available to the template by default: ``context``
-and ``request``. One of the common needs in ZPT-based templates is to use
-one template's "macros" from within a different template. In Zope, this is
-typically handled by retrieving the template from the ``context``. But the
-context in :app:`Pyramid` is a :term:`resource` object, and templates cannot
-usually be retrieved from resources. To use macros in :app:`Pyramid`, you
-need to make the macro template itself available to the rendered template by
-passing the macro template, or even the macro itself, *into* the rendered
-template. To do this you can use the :func:`pyramid.renderers.get_renderer`
-API to retrieve the macro template, and pass it into the template being
-rendered via the dictionary returned by the view. For example, using a
-:term:`view configuration` via a :class:`~pyramid.view.view_config` decorator
-that uses a :term:`renderer`:
-
-.. code-block:: python
- :linenos:
-
- from pyramid.renderers import get_renderer
- from pyramid.view import view_config
-
- @view_config(renderer='templates/mytemplate.pt')
- def my_view(request):
- main = get_renderer('templates/master.pt').implementation()
- return {'main':main}
-
-Where ``templates/master.pt`` might look like so:
-
-.. code-block:: xml
- :linenos:
-
- <html xmlns="http://www.w3.org/1999/xhtml"
- xmlns:tal="http://xml.zope.org/namespaces/tal"
- xmlns:metal="http://xml.zope.org/namespaces/metal">
- <span metal:define-macro="hello">
- <h1>
- Hello <span metal:define-slot="name">Fred</span>!
- </h1>
- </span>
- </html>
-
-And ``templates/mytemplate.pt`` might look like so:
-
-.. code-block:: xml
- :linenos:
-
- <html xmlns="http://www.w3.org/1999/xhtml"
- xmlns:tal="http://xml.zope.org/namespaces/tal"
- xmlns:metal="http://xml.zope.org/namespaces/metal">
- <span metal:use-macro="main.macros['hello']">
- <span metal:fill-slot="name">Chris</span>
- </span>
- </html>
-
-
-Using A Chameleon Macro Name Within a Renderer Name
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-At times, you may want to render a macro inside of a Chameleon ZPT template
-instead of the full Chameleon ZPT template. To render the content of a
-``define-macro`` field inside a Chameleon ZPT template, given a Chameleon
-template file named ``foo.pt`` and a macro named ``bar`` defined within it
-(e.g. ``<div metal:define-macro="bar">...</div>``), 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.pt')
- def my_view(request):
- return {'project':'my project'}
-
-The above will render only the ``bar`` macro defined within the ``foo.pt``
-template instead of the entire template.
-
-.. versionadded:: 1.4
-
-.. index::
- single: Chameleon text templates
-
-.. _chameleon_text_templates:
-
-Templating with :term:`Chameleon` Text Templates
-------------------------------------------------
-
-:app:`Pyramid` also allows for the use of templates which are
-composed entirely of non-XML text via :term:`Chameleon`. To do so,
-you can create templates that are entirely composed of text except for
-``${name}`` -style substitution points.
-
-Here's an example usage of a Chameleon text template. Create a file
-on disk named ``mytemplate.txt`` in your project's ``templates``
-directory with the following contents:
-
-.. code-block:: text
-
- Hello, ${name}!
-
-Then in your project's ``views.py`` module, you can create a view
-which renders this template:
-
-.. code-block:: python
- :linenos:
-
- from pyramid.view import view_config
-
- @view_config(renderer='templates/mytemplate.txt')
- def my_view(request):
- return {'name':'world'}
-
-When the template is rendered, it will show:
-
-.. code-block:: text
-
- Hello, world!
-
-See also :ref:`built_in_renderers` for more general information about
-renderers, including Chameleon text renderers.
-
-.. index::
- single: template renderer side effects
-
-Side Effects of Rendering a Chameleon Template
-----------------------------------------------
-
-When a Chameleon template is rendered from a file, the templating
-engine writes a file in the same directory as the template file itself
-as a kind of cache, in order to do less work the next time the
-template needs to be read from disk. If you see "strange" ``.py``
-files showing up in your ``templates`` directory (or otherwise
-directly "next" to your templates), it is due to this feature.
-
-If you're using a version control system such as Subversion, you
-should configure it to ignore these files. Here's the contents of the
-author's ``svn propedit svn:ignore .`` in each of my ``templates``
-directories.
-
-.. code-block:: text
-
- *.pt.py
- *.txt.py
-
-Note that I always name my Chameleon ZPT template files with a ``.pt``
-extension and my Chameleon text template files with a ``.txt``
-extension so that these ``svn:ignore`` patterns work.
-
.. index::
pair: debugging; templates
+.. _debugging_templates:
+
Debugging Templates
-------------------
@@ -643,107 +390,6 @@ The output tells you which template the error occurred in, as well as
displaying the arguments passed to the template itself.
.. index::
- single: template internationalization
- single: internationalization (of templates)
-
-:term:`Chameleon` Template Internationalization
------------------------------------------------
-
-See :ref:`chameleon_translation_strings` for information about
-supporting internationalized units of text within :term:`Chameleon`
-templates.
-
-.. index::
- single: Mako
-
-.. _mako_templates:
-
-Templating With Mako Templates
-------------------------------
-
-:term:`Mako` is a templating system written by Mike Bayer. :app:`Pyramid`
-has built-in bindings for the Mako templating system. The language
-definition documentation for Mako templates is available from `the Mako
-website <http://www.makotemplates.org/>`_.
-
-To use a Mako template, given a :term:`Mako` template file named ``foo.mak``
-in the ``templates`` subdirectory in your application package named
-``mypackage``, 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.mak')
- def my_view(request):
- return {'project':'my project'}
-
-For the above view callable to work, the following setting needs to be
-present in the application stanza of your configuration's ``ini`` file:
-
-.. code-block:: ini
-
- mako.directories = mypackage:templates
-
-This lets the Mako templating system know that it should look for templates
-in the ``templates`` subdirectory of the ``mypackage`` Python package. See
-:ref:`mako_template_renderer_settings` for more information about the
-``mako.directories`` setting and other Mako-related settings that can be
-placed into the application's ``ini`` file.
-
-.. index::
- single: Mako template (sample)
-
-A Sample Mako Template
-~~~~~~~~~~~~~~~~~~~~~~
-
-Here's what a simple :term:`Mako` template used under :app:`Pyramid` might
-look like:
-
-.. code-block:: xml
- :linenos:
-
- <html>
- <head>
- <title>${project} Application</title>
- </head>
- <body>
- <h1 class="title">Welcome to <code>${project}</code>, an
- application generated by the <a
- href="http://docs.pylonsproject.org/projects/pyramid/current/"
- >pyramid</a> web application framework.</h1>
- </body>
- </html>
-
-This template doesn't use any advanced features of Mako, only the
-``${}`` replacement syntax for names that are passed in as
-:term:`renderer globals`. See the `the Mako documentation
-<http://www.makotemplates.org/>`_ to use more advanced features.
-
-Using A Mako def name Within a Renderer Name
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Sommetime you'd like to render a ``def`` inside of a Mako template instead of
-the full Mako template. To render 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'}
-
-The above will render the ``bar`` def from within the ``foo.mak`` template
-instead of the entire template.
-
-.. versionadded:: 1.4
-
-.. index::
single: automatic reloading of templates
single: template automatic reload
@@ -758,9 +404,11 @@ appear immediately without needing to restart the application process.
environment so that a change to a template will be automatically
detected, and the template will be reloaded on the next rendering.
-.. warning:: Auto-template-reload behavior is not recommended for
- production sites as it slows rendering slightly; it's
- usually only desirable during development.
+.. warning::
+
+ Auto-template-reload behavior is not recommended for
+ production sites as it slows rendering slightly; it's
+ usually only desirable during development.
In order to turn on automatic reloading of templates, you can use an
environment variable, or a configuration file setting.
@@ -771,31 +419,48 @@ variable set to ``1``, For example:
.. code-block:: text
- $ PYRAMID_RELOAD_TEMPLATES=1 bin/pserve myproject.ini
+ $ PYRAMID_RELOAD_TEMPLATES=1 $VENV/bin/pserve myproject.ini
To use a setting in the application ``.ini`` file for the same
purpose, set the ``pyramid.reload_templates`` key to ``true`` within the
application's configuration section, e.g.:
.. code-block:: ini
- :linenos:
+ :linenos:
- [app:main]
- use = egg:MyProject
- pyramid.reload_templates = true
+ [app:main]
+ use = egg:MyProject
+ pyramid.reload_templates = true
.. index::
single: template system bindings
+ single: Chameleon
single: Jinja2
+ single: Mako
.. _available_template_system_bindings:
Available Add-On Template System Bindings
-----------------------------------------
-Jinja2 template bindings are available for :app:`Pyramid` in the
-``pyramid_jinja2`` package. You can get the latest release of
-this package from the
-`Python package index <http://pypi.python.org/pypi/pyramid_jinja2>`_
-(pypi).
+The Pylons Project maintains several packages providing bindings to different
+templating languages including the following:
+
++------------------------------+------------------------------+
+| Template Language | Pyramid Bindings |
++==============================+==============================+
+| Chameleon_ | pyramid_chameleon_ |
++------------------------------+------------------------------+
+| Jinja2_ | pyramid_jinja2_ |
++------------------------------+------------------------------+
+| Mako_ | pyramid_mako_ |
++------------------------------+------------------------------+
+
+.. _Chameleon: http://chameleon.readthedocs.org/en/latest/
+.. _pyramid_chameleon: https://pypi.python.org/pypi/pyramid_chameleon
+
+.. _Jinja2: http://jinja.pocoo.org/docs/
+.. _pyramid_jinja2: https://pypi.python.org/pypi/pyramid_jinja2
+.. _Mako: http://www.makotemplates.org/
+.. _pyramid_mako: https://pypi.python.org/pypi/pyramid_mako
diff --git a/docs/narr/testing.rst b/docs/narr/testing.rst
index 0801a8eae..88d6904c7 100644
--- a/docs/narr/testing.rst
+++ b/docs/narr/testing.rst
@@ -125,10 +125,10 @@ method attached to ``MyTest`` will use an isolated registry.
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
+test. See the :ref:`testing_module` API for information about the extra
arguments supported by these functions.
-If you also want to make :func:`~pyramid.get_current_request` return something
+If you also want to make :func:`~pyramid.threadlocal.get_current_request` return something
other than ``None`` during the course of a single test, you can pass a
:term:`request` object into the :func:`pyramid.testing.setUp` within the
``setUp`` method of your test:
@@ -202,7 +202,7 @@ any ``get_current*`` function.
Using the ``Configurator`` and ``pyramid.testing`` APIs in Unit Tests
---------------------------------------------------------------------
-The ``Configurator`` API and the ``pyramid.testing`` module provide a number
+The ``Configurator`` API and the :mod:`pyramid.testing` module provide a number
of functions which can be used during unit testing. These functions make
:term:`configuration declaration` calls to the current :term:`application
registry`, but typically register a "stub" or "dummy" feature in place of the
@@ -222,6 +222,12 @@ function.
raise HTTPForbidden
return {'greeting':'hello'}
+.. note::
+
+ This code implies that you have defined a renderer imperatively in a
+ relevant :class:`pyramid.config.Configurator` instance,
+ otherwise it would fail when run normally.
+
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,
@@ -231,7 +237,7 @@ 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:`HTTPForbidden`?
+view function that raises :exc:`~pyramid.httpexceptions.HTTPForbidden`?
The testing API provided by :app:`Pyramid` allows you to simulate various
application registry registrations for use under a unit testing framework
@@ -272,7 +278,7 @@ without needing to invoke the actual application configuration implied by its
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
+:class:`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_forbidden`` tests the ``view_fn`` when
@@ -287,10 +293,11 @@ 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.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:`HTTPForbidden` error.
+:meth:`~pyramid.config.Configurator.testing_securitypolicy`, which denies
+access. We check that the view function raises a
+:exc:`~pyramid.httpexceptions.HTTPForbidden` error.
-The second test method, named ``test_view_fn_allowed`` tests the alternate
+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
@@ -372,7 +379,7 @@ after accessing some values that require a fully set up environment.
result = my_view(request)
self.assertEqual(result.status, '200 OK')
body = result.app_iter[0]
- self.failUnless('Welcome to' in body)
+ self.assertTrue('Welcome to' in body)
self.assertEqual(len(result.headerlist), 2)
self.assertEqual(result.headerlist[0],
('Content-Type', 'text/html; charset=UTF-8'))
@@ -415,7 +422,7 @@ functional testing package written by Ian Bicking.
def test_root(self):
res = self.testapp.get('/', status=200)
- self.failUnless('Pyramid' in res.body)
+ self.assertTrue('Pyramid' in res.body)
When this test is run, each test creates a "real" WSGI application using the
``main`` function in your ``myapp.__init__`` module and uses :term:`WebTest`
@@ -425,4 +432,4 @@ invoke the root URL. We then assert that the returned HTML has the string
``Pyramid`` in it.
See the :term:`WebTest` documentation for further information about the
-methods available to a :class:`webtest.TestApp` instance.
+methods available to a :class:`webtest.app.TestApp` instance.
diff --git a/docs/narr/threadlocals.rst b/docs/narr/threadlocals.rst
index 909f643a0..a90ee4905 100644
--- a/docs/narr/threadlocals.rst
+++ b/docs/narr/threadlocals.rst
@@ -62,8 +62,7 @@ Because one :app:`Pyramid` application is permitted to call
(perhaps as a :term:`WSGI` app with help from the
:func:`pyramid.wsgi.wsgiapp2` decorator), these variables are
managed in a *stack* during normal system operations. The stack
-instance itself is a `threading.local
-<http://docs.python.org/library/threading.html#threading.local>`_.
+instance itself is a :class:`threading.local`.
During normal operations, the thread locals stack is managed by a
:term:`Router` object. At the beginning of a request, the Router
@@ -130,7 +129,7 @@ follows:
ever be called within application-specific forks of third-party
library code. The library you've forked almost certainly has
nothing to do with :app:`Pyramid`, and making it dependent on
- :app:`Pyramid` (rather than making your :mod:`pyramid`
+ :app:`Pyramid` (rather than making your :app:`pyramid`
application depend upon it) means you're forming a dependency in the
wrong direction.
diff --git a/docs/narr/traversal.rst b/docs/narr/traversal.rst
index 8e7f93a1b..454bb5620 100644
--- a/docs/narr/traversal.rst
+++ b/docs/narr/traversal.rst
@@ -22,10 +22,13 @@ resource found as the result of a traversal becomes the
subsystem is used to find some view code willing to "publish" this
resource by generating a :term:`response`.
-Using :term:`Traversal` to map a URL to code is optional. It is often
-less easy to understand than :term:`URL dispatch`, so if you're a rank
-beginner, it probably makes sense to use URL dispatch to map URLs to
-code instead of traversal. In that case, you can skip this chapter.
+.. note::
+
+ Using :term:`Traversal` to map a URL to code is optional. If you're creating
+ your first Pyramid application it probably makes more sense to use :term:`URL
+ dispatch` to map URLs to code instead of traversal, as new Pyramid developers
+ tend to find URL dispatch slightly easier to understand. If you use URL
+ dispatch, you needn't read this chapter.
.. index::
single: traversal details
@@ -143,35 +146,15 @@ refer to a root factory defined in a different module.
If no :term:`root factory` is passed to the :app:`Pyramid`
:term:`Configurator` constructor, or if the ``root_factory`` value
-specified is ``None``, a *default* root factory is used. The default
+specified is ``None``, a :term:`default root factory` is used. The default
root factory always returns a resource that has no child resources; it
is effectively empty.
Usually a root factory for a traversal-based application will be more
-complicated than the above ``Root`` class; in particular it may be
-associated with a database connection or another persistence mechanism.
-
-.. sidebar:: Emulating the Default Root Factory
-
- For purposes of understanding the default root factory better, we'll note
- that you can emulate the default root factory by using this code as an
- explicit root factory in your application setup:
-
- .. code-block:: python
- :linenos:
-
- class Root(object):
- def __init__(self, request):
- pass
-
- config = Configurator(root_factory=Root)
-
- The default root factory is just a really stupid object that has no
- behavior or state. Using :term:`traversal` against an application that
- uses the resource tree supplied by the default root resource is not very
- interesting, because the default root resource has no children. Its
- availability is more useful when you're developing an application using
- :term:`URL dispatch`.
+complicated than the above ``Root`` class; in particular it may be associated
+with a database connection or another persistence mechanism. The above
+``Root`` class is analogous to the default root factory present in Pyramid. The
+default root factory is very simple and not very useful.
.. note::
@@ -286,7 +269,7 @@ system uses this algorithm to find a :term:`context` resource and a
return resource "C".
#. Traversal ends when a) the entire path is exhausted or b) when any
- resouce raises a :exc:`KeyError` from its ``__getitem__`` or c) when any
+ resource raises a :exc:`KeyError` from its ``__getitem__`` or c) when any
non-final path element traversal does not have a ``__getitem__`` method
(resulting in a :exc:`AttributeError`) or d) when any path element is
prefixed with the set of characters ``@@`` (indicating that the characters
@@ -356,13 +339,13 @@ when this request comes in that we're traversing the following resource tree:
Here's what happens:
-- :mod:`traversal` traverses the root, and attempts to find "foo", which it
+- :term:`traversal` traverses the root, and attempts to find "foo", which it
finds.
-- :mod:`traversal` traverses "foo", and attempts to find "bar", which it
+- :term:`traversal` traverses "foo", and attempts to find "bar", which it
finds.
-- :mod:`traversal` traverses "bar", and attempts to find "baz", which it does
+- :term:`traversal` traverses "bar", and attempts to find "baz", which it does
not find (the "bar" resource raises a :exc:`KeyError` when asked for
"baz").
@@ -389,7 +372,7 @@ Using the :term:`view name` (``baz``) and the type, view lookup asks the
Let's say that view lookup finds no matching view type. In this
circumstance, the :app:`Pyramid` :term:`router` returns the result of the
-:term:`not found view` and the request ends.
+:term:`Not Found View` and the request ends.
However, for this tree:
@@ -407,16 +390,16 @@ However, for this tree:
The user asks for ``http://example.com/foo/bar/baz/biz/buz.txt``
-- :mod:`traversal` traverses "foo", and attempts to find "bar", which it
+- :term:`traversal` traverses "foo", and attempts to find "bar", which it
finds.
-- :mod:`traversal` traverses "bar", and attempts to find "baz", which it
+- :term:`traversal` traverses "bar", and attempts to find "baz", which it
finds.
-- :mod:`traversal` traverses "baz", and attempts to find "biz", which it
+- :term:`traversal` traverses "baz", and attempts to find "biz", which it
finds.
-- :mod:`traversal` traverses "biz", and attempts to find "buz.txt" which it
+- :term:`traversal` traverses "biz", and attempts to find "buz.txt" which it
does not find.
The fact that it does not find a resource related to "buz.txt" at this point
diff --git a/docs/narr/upgrading.rst b/docs/narr/upgrading.rst
index 20487b448..64343ca3e 100644
--- a/docs/narr/upgrading.rst
+++ b/docs/narr/upgrading.rst
@@ -150,7 +150,7 @@ do things the newer way:
.. code-block:: python
:linenos:
- from pyramid.view. import view_config
+ from pyramid.view import view_config
from pyramid.static import static_view
myview = static_view('static', 'static', use_subpath=True)
@@ -183,7 +183,7 @@ server run with the ``PYTHONWARNINGS`` environment variable set to
.. code-block:: bash
- $ PYTHONWARNINGS=default bin/pserve development.ini
+ $ PYTHONWARNINGS=default $VENV/bin/pserve development.ini
On Windows, you need to issue two commands:
diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst
index 2a7adea81..61849c3c0 100644
--- a/docs/narr/urldispatch.rst
+++ b/docs/narr/urldispatch.rst
@@ -16,12 +16,13 @@ receives the :term:`request` and returns a :term:`response` object.
High-Level Operational Overview
-------------------------------
-If route configuration is present in an application, the :app:`Pyramid`
+If any route configuration is present in an application, the :app:`Pyramid`
:term:`Router` checks every incoming request against an ordered set of URL
matching patterns present in a *route map*.
If any route pattern matches the information in the :term:`request`,
-:app:`Pyramid` will invoke :term:`view lookup` to find a matching view.
+:app:`Pyramid` will invoke the :term:`view lookup` process to find a
+matching view.
If no route pattern in the route map matches the information in the
:term:`request` provided in your application, :app:`Pyramid` will fail over
@@ -54,7 +55,6 @@ The :meth:`pyramid.config.Configurator.add_route` method adds a single
:term:`route configuration` to the :term:`application registry`. Here's an
example:
-.. ignore-next-block
.. code-block:: python
# "config" below is presumed to be an instance of the
@@ -70,8 +70,8 @@ via its ``route_name`` predicate, that view callable will always be found and
invoked when the associated route pattern matches during a request.
More commonly, you will not use any ``add_view`` statements in your project's
-"setup" code, instead only using ``add_route`` statements using a
-:term:`scan` for to associate view callables with routes. For example, if
+"setup" code. You will instead use ``add_route`` statements, and use a
+:term:`scan` to associate view callables with routes. For example, if
this is a portion of your project's ``__init__.py``:
.. code-block:: python
@@ -81,7 +81,7 @@ this is a portion of your project's ``__init__.py``:
Note that we don't call :meth:`~pyramid.config.Configurator.add_view` in this
setup code. However, the above :term:`scan` execution
-``config.scan('mypackage')`` will pick up all :term:`configuration
+``config.scan('mypackage')`` will pick up each :term:`configuration
decoration`, including any objects decorated with the
:class:`pyramid.view.view_config` decorator in the ``mypackage`` Python
package. For example, if you have a ``views.py`` in your package, a scan will
@@ -105,6 +105,7 @@ to using the previous combination of ``add_route`` and ``add_view``.
.. _route_pattern_syntax:
+
Route Pattern Syntax
~~~~~~~~~~~~~~~~~~~~
@@ -127,6 +128,10 @@ and:
/{foo}/bar/baz
+If a pattern is a valid URL it won't be ever matched against an incoming
+request. Instead it can be useful for generating external URLs. See
+:ref:`External routes <external_route_narr>` for details.
+
A pattern segment (an individual item between ``/`` characters in the
pattern) may either be a literal string (e.g. ``foo``) *or* it may be a
replacement marker (e.g. ``{foo}``) or a certain combination of both. A
@@ -394,13 +399,6 @@ process. Examples of route predicate arguments are ``pattern``, ``xhr``, and
Other arguments are ``name`` and ``factory``. These arguments represent
neither predicates nor view configuration information.
-.. warning::
-
- Some arguments are view-configuration related arguments, such as
- ``view_renderer``. These only have an effect when the route configuration
- names a ``view`` and these arguments have been deprecated as of
- :app:`Pyramid` 1.1.
-
.. index::
single: route matching
@@ -754,9 +752,39 @@ other non-``name`` and non-``pattern`` arguments to
exception to this rule is use of the ``pregenerator`` argument, which is not
ignored when ``static`` is ``True``.
+:ref:`External routes <external_route_narr>` are implicitly static.
+
.. versionadded:: 1.1
the ``static`` argument to :meth:`~pyramid.config.Configurator.add_route`
+.. _external_route_narr:
+
+
+External Routes
+---------------
+
+.. versionadded:: 1.5
+
+Route patterns that are valid URLs, are treated as external routes. Like
+:ref:`static routes <static_route_narr>` they are useful for URL generation
+purposes only and are never considered for matching at request time.
+
+.. code-block:: python
+ :linenos:
+
+ >>> config = Configurator()
+ >>> config.add_route('youtube', 'https://youtube.com/watch/{video_id}')
+ ...
+ >>> request.route_url('youtube', video_id='oHg5SJYRHA0')
+ >>> "https://youtube.com/watch/oHg5SJYRHA0"
+
+Most pattern replacements and calls to
+:meth:`pyramid.request.Request.route_url` will work as expected. However, calls
+to :meth:`pyramid.request.Request.route_path` against external patterns will
+raise an exception, and passing ``_app_url`` to
+:meth:`~pyramid.request.Request.route_url` to generate a URL against a route
+that has an external pattern will also raise an exception.
+
.. index::
single: redirecting to slash-appended routes
@@ -814,7 +842,7 @@ bro." body.
If a request enters the application with the ``PATH_INFO`` value of
``/has_slash/``, the second route will match. If a request enters the
application with the ``PATH_INFO`` value of ``/has_slash``, a route *will* be
-found by the slash-appending not found view. An HTTP redirect to
+found by the slash-appending :term:`Not Found View`. An HTTP redirect to
``/has_slash/`` will be returned to the user's browser. As a result, the
``notfound`` view will never actually be called.
@@ -849,12 +877,12 @@ exactly the same job:
.. warning::
You **should not** rely on this mechanism to redirect ``POST`` requests.
- The redirect of the slash-appending not found view will turn a ``POST``
- request into a ``GET``, losing any ``POST`` data in the original
+ The redirect of the slash-appending :term:`Not Found View` will turn a
+ ``POST`` request into a ``GET``, losing any ``POST`` data in the original
request.
See :ref:`view_module` and :ref:`changing_the_notfound_view` for a more
-general description of how to configure a view and/or a not found view.
+general description of how to configure a view and/or a :term:`Not Found View`.
.. index::
pair: debugging; route matching
@@ -865,7 +893,7 @@ Debugging Route Matching
------------------------
It's useful to be able to take a peek under the hood when requests that enter
-your application arent matching your routes as you expect them to. To debug
+your application aren't matching your routes as you expect them to. To debug
route matching, use the ``PYRAMID_DEBUG_ROUTEMATCH`` environment variable or the
``pyramid.debug_routematch`` configuration file setting (set either to ``true``).
Details of the route matching decision for a particular request to the
@@ -875,8 +903,7 @@ which you started the application from. For example:
.. code-block:: text
:linenos:
- [chrism@thinko pylonsbasic]$ PYRAMID_DEBUG_ROUTEMATCH=true \
- bin/pserve development.ini
+ $ PYRAMID_DEBUG_ROUTEMATCH=true $VENV/bin/pserve development.ini
Starting server in PID 13586.
serving on 0.0.0.0:6543 view at http://127.0.0.1:6543
2010-12-16 14:45:19,956 no route matched for url \
@@ -1264,7 +1291,7 @@ invoked with the request that caused the invocation.
For most usage, you needn't understand more than this; how it works is an
implementation detail. In the interest of completeness, however, we'll
-explain how it *does* work in the this section. You can skip it if you're
+explain how it *does* work in this section. You can skip it if you're
uninterested.
When a view is associated with a route configuration, :app:`Pyramid` ensures
diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst
index 9f3b91c26..7c76116f7 100644
--- a/docs/narr/viewconfig.rst
+++ b/docs/narr/viewconfig.rst
@@ -38,11 +38,11 @@ A view configuration statement is made about information present in the
View configuration is performed in one of two ways:
-- by running a :term:`scan` against application source code which has a
+- By running a :term:`scan` against application source code which has a
:class:`pyramid.view.view_config` decorator attached to a Python object as
per :ref:`mapping_views_using_a_decorator_section`.
-- by using the :meth:`pyramid.config.Configurator.add_view` method as per
+- By using the :meth:`pyramid.config.Configurator.add_view` method as per
:ref:`mapping_views_using_imperative_config_section`.
.. index::
@@ -62,13 +62,13 @@ particular view callable.
:term:`View predicate` attributes are an important part of view configuration
that enables the :term:`view lookup` subsystem to find and invoke the
-appropriate view. The greater number of predicate attributes possessed by a
+appropriate view. The greater the number of predicate attributes possessed by a
view's configuration, the more specific the circumstances need to be before
-the registered view callable will be invoked. The fewer number of predicates
+the registered view callable will be invoked. The fewer the number of predicates
which are supplied to a particular view configuration, the more likely it is
that the associated view callable will be invoked. A view with five
predicates will always be found and evaluated before a view with two, for
-example. All predicates must match for the associated view to be called.
+example.
This does not mean however, that :app:`Pyramid` "stops looking" when it
finds a view registration with predicates that don't match. If one set
@@ -81,7 +81,7 @@ invoked.
If no view can be found with predicates which allow it to be matched up with
the request, :app:`Pyramid` will return an error to the user's browser,
representing a "not found" (404) page. See :ref:`changing_the_notfound_view`
-for more information about changing the default notfound view.
+for more information about changing the default :term:`Not Found View`.
Other view configuration arguments are non-predicate arguments. These tend
to modify the response of the view callable or prevent the view callable from
@@ -290,9 +290,9 @@ configured view.
of the ``REQUEST_METHOD`` of the :term:`WSGI` environment.
``request_param``
- This value can be any string or a sequence of strings. A view declaration
- with this argument ensures that the view will only be called when the
- :term:`request` has a key in the ``request.params`` dictionary (an HTTP
+ This value can be any string or a sequence of strings. A view declaration
+ with this argument ensures that the view will only be called when the
+ :term:`request` has a key in the ``request.params`` dictionary (an HTTP
``GET`` or ``POST`` variable) that has a name which matches the
supplied value.
@@ -306,16 +306,14 @@ configured view.
consideration of keys and values in the ``request.params`` dictionary.
``match_param``
- .. versionadded:: 1.2
-
This param may be either a single string of the format "key=value" or a
dict of key/value pairs.
This argument ensures that the view will only be called when the
:term:`request` has key/value pairs in its :term:`matchdict` that equal
- those supplied in the predicate. e.g. ``match_param="action=edit" would
+ those supplied in the predicate. e.g. ``match_param="action=edit"`` would
require the ``action`` parameter in the :term:`matchdict` match the right
- hande side of the expression (``edit``) for the view to "match" the current
+ hand side of the expression (``edit``) for the view to "match" the current
request.
If the ``match_param`` is a dict, every key/value pair must match for the
@@ -324,6 +322,8 @@ configured view.
If ``match_param`` is not supplied, the view will be invoked without
consideration of the keys and values in ``request.matchdict``.
+ .. versionadded:: 1.2
+
``containment``
This value should be a reference to a Python class or :term:`interface`
that a parent object in the context resource's :term:`lineage` must provide
@@ -465,6 +465,36 @@ configured view.
.. versionadded:: 1.4a1
+Inverting Predicate Values
+++++++++++++++++++++++++++
+
+You can invert the meaning of any predicate value by wrapping it in a call to
+:class:`pyramid.config.not_`.
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.config import not_
+
+ config.add_view(
+ 'mypackage.views.my_view',
+ route_name='ok',
+ request_method=not_('POST')
+ )
+
+The above example will ensure that the view is called if the request method
+is *not* ``POST``, at least if no other view is more specific.
+
+This technique of wrapping a predicate value in ``not_`` can be used anywhere
+predicate values are accepted:
+
+- :meth:`pyramid.config.Configurator.add_view`
+
+- :meth:`pyramid.view.view_config`
+
+.. versionadded:: 1.5
+
+
.. index::
single: view_config decorator
@@ -488,7 +518,6 @@ acts as a :app:`Pyramid` view callable.
Here's an example of the :class:`~pyramid.view.view_config` decorator that
lives within a :app:`Pyramid` application module ``views.py``:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -503,11 +532,10 @@ lives within a :app:`Pyramid` application module ``views.py``:
Using this decorator as above replaces the need to add this imperative
configuration stanza:
-.. ignore-next-block
.. code-block:: python
:linenos:
- config.add_view('mypackage.views.my_view', route_name='ok',
+ config.add_view('mypackage.views.my_view', route_name='ok',
request_method='POST', permission='read')
All arguments to ``view_config`` may be omitted. For example:
@@ -686,11 +714,10 @@ this method are very similar to the arguments that you provide to the
# pyramid.config.Configurator class
config.add_view(hello_world, route_name='hello')
-The first argument, ``view``, is required. It must either be a Python object
-which is the view itself or a :term:`dotted Python name` to such an object.
-In the above example, ``view`` is the ``hello_world`` function. All other
-arguments are optional. See :meth:`pyramid.config.Configurator.add_view` for
-more information.
+The first argument, a :term:`view callable`, is the only required argument.
+It must either be a Python object which is the view itself or a
+:term:`dotted Python name` to such an object.
+In the above example, the ``view callable`` is the ``hello_world`` function.
When you use only :meth:`~pyramid.config.Configurator.add_view` to add view
configurations, you don't need to issue a :term:`scan` in order for the view
@@ -795,7 +822,7 @@ of this:
def delete(self):
return Response('delete')
- if __name__ == '__main__':
+ def main(global_config, **settings):
config = Configurator()
config.add_route('rest', '/rest')
config.add_view(
@@ -804,9 +831,10 @@ of this:
RESTView, route_name='rest', attr='post', request_method='POST')
config.add_view(
RESTView, route_name='rest', attr='delete', request_method='DELETE')
+ return config.make_wsgi_app()
-To reduce the amount of repetion in the ``config.add_view`` statements, we
-can move the ``route_name='rest'`` argument to a ``@view_default`` class
+To reduce the amount of repetition in the ``config.add_view`` statements, we
+can move the ``route_name='rest'`` argument to a ``@view_defaults`` class
decorator on the RESTView class:
.. code-block:: python
@@ -830,12 +858,13 @@ decorator on the RESTView class:
def delete(self):
return Response('delete')
- if __name__ == '__main__':
+ def main(global_config, **settings):
config = Configurator()
config.add_route('rest', '/rest')
config.add_view(RESTView, attr='get', request_method='GET')
config.add_view(RESTView, attr='post', request_method='POST')
config.add_view(RESTView, attr='delete', request_method='DELETE')
+ return config.make_wsgi_app()
:class:`pyramid.view.view_defaults` accepts the same set of arguments that
:class:`pyramid.view.view_config` does, and they have the same meaning. Each
@@ -911,10 +940,11 @@ per :ref:`protecting_views`.
.. _debug_notfound_section:
-:exc:`NotFound` Errors
-~~~~~~~~~~~~~~~~~~~~~~
+:exc:`~pyramid.exceptions.NotFound` Errors
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-It's useful to be able to debug :exc:`NotFound` error responses when they
+It's useful to be able to debug :exc:`~pyramid.exceptions.NotFound`
+error responses when they
occur unexpectedly due to an application registry misconfiguration. To debug
these errors, use the ``PYRAMID_DEBUG_NOTFOUND`` environment variable or the
``pyramid.debug_notfound`` configuration file setting. Details of why a view
@@ -978,6 +1008,8 @@ invoked as the result of the ``http_cache`` argument to view configuration.
.. index::
pair: view configuration; debugging
+.. _debugging_view_configuration:
+
Debugging View Configuration
----------------------------
diff --git a/docs/narr/views.rst b/docs/narr/views.rst
index 8ebdfe219..b2dd549ce 100644
--- a/docs/narr/views.rst
+++ b/docs/narr/views.rst
@@ -39,7 +39,7 @@ object. A request object represents a :term:`WSGI` environment provided to
object contains everything your application needs to know about the specific
HTTP request being made.
-A view callable's ultimate responsibility is to create a :mod:`Pyramid`
+A view callable's ultimate responsibility is to create a :app:`Pyramid`
:term:`Response` object. This can be done by creating a :term:`Response`
object in the view callable code and returning it directly or by raising
special kinds of exceptions from within the body of a view callable.
@@ -264,9 +264,9 @@ also be used by application developers to convert arbitrary exceptions to
responses.
To register a view that should be called whenever a particular exception is
-raised from with :app:`Pyramid` view code, use the exception class or one of
-its superclasses as the ``context`` of a view configuration which points at a
-view callable you'd like to generate a response.
+raised from within :app:`Pyramid` view code, use the exception class (or one of
+its superclasses) as the :term:`context` of a view configuration which points
+at a view callable you'd like to generate a response for.
For example, given the following exception class in a module named
``helloworld.exceptions``:
@@ -353,7 +353,7 @@ Exception views can be configured with any view registration mechanism:
.. _http_redirect:
-Using a View Callable to Do an HTTP Redirect
+Using a View Callable to do an HTTP Redirect
--------------------------------------------
You can issue an HTTP redirect by using the
@@ -524,7 +524,6 @@ The :term:`context` and :term:`request` arguments passed to a view function
defined in this style can be defined as follows:
context
-
The :term:`resource` object found via tree :term:`traversal` or :term:`URL
dispatch`.
@@ -537,41 +536,41 @@ The following types work as view callables in this style:
e.g.:
.. code-block:: python
- :linenos:
+ :linenos:
- from pyramid.response import Response
+ from pyramid.response import Response
- def view(context, request):
- return Response('OK')
+ def view(context, request):
+ return Response('OK')
#. Classes that have an ``__init__`` method that accepts ``context,
request`` and a ``__call__`` method which accepts no arguments, e.g.:
.. code-block:: python
- :linenos:
+ :linenos:
- from pyramid.response import Response
+ from pyramid.response import Response
- class view(object):
- def __init__(self, context, request):
- self.context = context
- self.request = request
+ class view(object):
+ def __init__(self, context, request):
+ self.context = context
+ self.request = request
- def __call__(self):
- return Response('OK')
+ def __call__(self):
+ return Response('OK')
#. Arbitrary callables that have a ``__call__`` method that accepts
``context, request``, e.g.:
.. code-block:: python
- :linenos:
+ :linenos:
- from pyramid.response import Response
+ from pyramid.response import Response
- class View(object):
- def __call__(self, context, request):
- return Response('OK')
- view = View() # this is the view callable
+ class View(object):
+ def __call__(self, context, request):
+ return Response('OK')
+ view = View() # this is the view callable
This style of calling convention is most useful for :term:`traversal` based
applications, where the context object is frequently used within the view
diff --git a/docs/narr/webob.rst b/docs/narr/webob.rst
index 44940f9e6..f0a4b5a0b 100644
--- a/docs/narr/webob.rst
+++ b/docs/narr/webob.rst
@@ -287,7 +287,7 @@ When such a request reaches a view in your application, the
@view_config(renderer='string')
def aview(request):
- print request.json_body
+ print(request.json_body)
return 'OK'
For the above view, printed to the console will be:
@@ -326,7 +326,6 @@ package that uses SQLAlchemy, and you'd like the current SQLAlchemy database
session to be removed after each request. Put the following in the
``mypackage.__init__`` module:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -355,7 +354,7 @@ initialization.
cause ``DBSession.remove`` to be called in an application generated from
any :app:`Pyramid` scaffold, because these all use the ``pyramid_tm``
package. The cleanup done by ``DBSession.remove`` is unnecessary when
- ``pyramid_tm`` middleware is configured into the application.
+ ``pyramid_tm`` :term:`middleware` is configured into the application.
More Details
++++++++++++
@@ -488,10 +487,9 @@ module.
Each class is named ``pyramid.httpexceptions.HTTP*``, where ``*`` is the
reason for the error. For instance,
:class:`pyramid.httpexceptions.HTTPNotFound` subclasses
-:class:`pyramid.Response`, so you can manipulate the instances in the same
+:class:`pyramid.response.Response`, so you can manipulate the instances in the same
way. A typical example is:
-.. ignore-next-block
.. code-block:: python
:linenos:
diff --git a/docs/narr/zca.rst b/docs/narr/zca.rst
index f7707ea29..b0e9b1709 100644
--- a/docs/narr/zca.rst
+++ b/docs/narr/zca.rst
@@ -21,7 +21,6 @@ application can be opaque. For example, here is a typical "unnamed
utility" lookup using the :func:`zope.component.getUtility` global API
as it might appear in a traditional Zope application:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -45,7 +44,7 @@ framework implementation detail.
However, developers who are already used to writing :term:`Zope`
applications often still wish to use the ZCA while building a
-:app:`Pyramid` application; :mod:`pyramid` makes this possible.
+:app:`Pyramid` application; :app:`Pyramid` makes this possible.
.. index::
single: get_current_registry
@@ -84,7 +83,7 @@ While this services a reasonable goal, it causes some issues when
trying to use patterns which you might use to build a typical
:term:`Zope` application to build a :app:`Pyramid` application.
Without special help, ZCA "global" APIs such as
-``zope.component.getUtility`` and ``zope.component.getSiteManager``
+:func:`zope.component.getUtility` and :func:`zope.component.getSiteManager`
will use the ZCA "global" registry. Therefore, these APIs
will appear to fail when used in a :app:`Pyramid` application,
because they'll be consulting the ZCA global registry rather than the
@@ -105,8 +104,8 @@ Disusing the Global ZCA API
+++++++++++++++++++++++++++
ZCA "global" API functions such as ``zope.component.getSiteManager``,
-``zope.component.getUtility``, ``zope.component.getAdapter``, and
-``zope.component.getMultiAdapter`` aren't strictly necessary. Every
+``zope.component.getUtility``, :func:`zope.component.getAdapter`, and
+:func:`zope.component.getMultiAdapter` aren't strictly necessary. Every
component registry has a method API that offers the same
functionality; it can be used instead. For example, presuming the
``registry`` value below is a Zope Component Architecture component
@@ -114,7 +113,6 @@ registry, the following bit of code is equivalent to
``zope.component.getUtility(IFoo)``:
.. code-block:: python
- :linenos:
registry.getUtility(IFoo)
@@ -152,7 +150,6 @@ Consider the following bit of idiomatic :app:`Pyramid` startup code:
.. code-block:: python
:linenos:
- from zope.component import getGlobalSiteManager
from pyramid.config import Configurator
def app(global_settings, **settings):
@@ -189,7 +186,6 @@ For example:
.. code-block:: python
:linenos:
- from zope.component import getGlobalSiteManager
from pyramid.config import Configurator
def app(global_settings, **settings):