summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@plope.com>2013-03-23 03:08:04 -0400
committerChris McDonough <chrism@plope.com>2013-03-23 03:08:04 -0400
commite34541a752384e5fa432c2b14003211dc11f223a (patch)
tree132794de4f52160d99586d91701880ebb6f9ddcd
parent35d88c65d7b4ca7c75c3cf767be040ff9e0253f9 (diff)
parent79112298e7cb27ee2d80e85429969cb005c31066 (diff)
downloadpyramid-e34541a752384e5fa432c2b14003211dc11f223a.tar.gz
pyramid-e34541a752384e5fa432c2b14003211dc11f223a.tar.bz2
pyramid-e34541a752384e5fa432c2b14003211dc11f223a.zip
Merge branch 'master' of github.com:Pylons/pyramid
-rw-r--r--BFG_HISTORY.txt5
-rw-r--r--CHANGES.txt84
-rw-r--r--CONTRIBUTORS.txt4
-rw-r--r--HACKING.txt14
-rw-r--r--HISTORY.txt12
-rw-r--r--docs/api.rst41
-rw-r--r--docs/api/config.rst10
-rw-r--r--docs/api/exceptions.rst2
-rw-r--r--docs/api/paster.rst2
-rw-r--r--docs/api/registry.rst17
-rw-r--r--docs/api/request.rst6
-rw-r--r--docs/conf.py25
-rw-r--r--docs/conventions.rst12
-rw-r--r--docs/designdefense.rst9
-rw-r--r--docs/glossary.rst52
-rw-r--r--docs/index.rst13
-rw-r--r--docs/narr/MyProject/setup.py6
-rw-r--r--docs/narr/advconfig.rst4
-rw-r--r--docs/narr/assets.rst8
-rw-r--r--docs/narr/commandline.rst60
-rw-r--r--docs/narr/configuration.rst42
-rw-r--r--docs/narr/environment.rst17
-rw-r--r--docs/narr/extconfig.rst4
-rw-r--r--docs/narr/extending.rst6
-rw-r--r--docs/narr/firstapp.rst21
-rw-r--r--docs/narr/hooks.rst140
-rw-r--r--docs/narr/i18n.rst17
-rw-r--r--docs/narr/install.rst152
-rw-r--r--docs/narr/introduction.rst7
-rw-r--r--docs/narr/introspector.rst6
-rw-r--r--docs/narr/logging.rst43
-rw-r--r--docs/narr/paste.rst6
-rw-r--r--docs/narr/project.rst55
-rw-r--r--docs/narr/renderers.rst41
-rw-r--r--docs/narr/router.rst2
-rw-r--r--docs/narr/security.rst41
-rw-r--r--docs/narr/sessions.rst2
-rw-r--r--docs/narr/startup.rst6
-rw-r--r--docs/narr/subrequest.rst4
-rw-r--r--docs/narr/templates.rst15
-rw-r--r--docs/narr/testing.rst2
-rw-r--r--docs/narr/threadlocals.rst3
-rw-r--r--docs/narr/traversal.rst2
-rw-r--r--docs/narr/upgrading.rst2
-rw-r--r--docs/narr/urldispatch.rst38
-rw-r--r--docs/narr/viewconfig.rst57
-rw-r--r--docs/narr/views.rst62
-rw-r--r--docs/narr/webob.rst4
-rw-r--r--docs/narr/zca.rst1
-rw-r--r--docs/tutorials/bfg/index.rst6
-rw-r--r--docs/tutorials/modwsgi/index.rst6
-rw-r--r--docs/tutorials/wiki/NOTE-relocatable.txt2
-rw-r--r--docs/tutorials/wiki/authorization.rst67
-rw-r--r--docs/tutorials/wiki/background.rst2
-rw-r--r--docs/tutorials/wiki/basiclayout.rst31
-rw-r--r--docs/tutorials/wiki/definingmodels.rst7
-rw-r--r--docs/tutorials/wiki/definingviews.rst42
-rw-r--r--docs/tutorials/wiki/design.rst8
-rw-r--r--docs/tutorials/wiki/distributing.rst4
-rw-r--r--docs/tutorials/wiki/index.rst5
-rw-r--r--docs/tutorials/wiki/installation.rst33
-rw-r--r--docs/tutorials/wiki/src/authorization/setup.py6
-rw-r--r--docs/tutorials/wiki/src/basiclayout/setup.py6
-rw-r--r--docs/tutorials/wiki/src/models/setup.py6
-rw-r--r--docs/tutorials/wiki/src/tests/setup.py6
-rw-r--r--docs/tutorials/wiki/src/views/setup.py6
-rw-r--r--docs/tutorials/wiki/tests.rst13
-rw-r--r--docs/tutorials/wiki2/authorization.rst3
-rw-r--r--docs/tutorials/wiki2/basiclayout.rst30
-rw-r--r--docs/tutorials/wiki2/definingmodels.rst14
-rw-r--r--docs/tutorials/wiki2/definingviews.rst37
-rw-r--r--docs/tutorials/wiki2/distributing.rst4
-rw-r--r--docs/tutorials/wiki2/index.rst6
-rw-r--r--docs/tutorials/wiki2/installation.rst188
-rw-r--r--docs/tutorials/wiki2/src/authorization/README.txt6
-rw-r--r--docs/tutorials/wiki2/src/authorization/setup.py6
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/README.txt6
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/setup.py6
-rw-r--r--docs/tutorials/wiki2/src/models/README.txt6
-rw-r--r--docs/tutorials/wiki2/src/models/setup.py6
-rw-r--r--docs/tutorials/wiki2/src/tests/README.txt6
-rw-r--r--docs/tutorials/wiki2/src/tests/setup.py6
-rw-r--r--docs/tutorials/wiki2/src/views/README.txt6
-rw-r--r--docs/tutorials/wiki2/src/views/setup.py6
-rw-r--r--docs/tutorials/wiki2/tests.rst13
-rw-r--r--docs/whatsnew-1.0.rst2
-rw-r--r--docs/whatsnew-1.1.rst5
-rw-r--r--docs/whatsnew-1.3.rst14
-rw-r--r--docs/whatsnew-1.4.rst2
-rw-r--r--pyramid/authentication.py25
-rw-r--r--pyramid/authorization.py3
-rw-r--r--pyramid/config/__init__.py83
-rw-r--r--pyramid/config/adapters.py16
-rw-r--r--pyramid/config/factories.py4
-rw-r--r--pyramid/config/rendering.py8
-rw-r--r--pyramid/config/routes.py28
-rw-r--r--pyramid/config/testing.py14
-rw-r--r--pyramid/config/tweens.py2
-rw-r--r--pyramid/config/views.py62
-rw-r--r--pyramid/exceptions.py30
-rw-r--r--pyramid/httpexceptions.py10
-rw-r--r--pyramid/interfaces.py16
-rw-r--r--pyramid/paster.py22
-rw-r--r--pyramid/path.py42
-rw-r--r--pyramid/renderers.py51
-rw-r--r--pyramid/request.py2
-rw-r--r--pyramid/response.py12
-rw-r--r--pyramid/router.py21
-rw-r--r--pyramid/scaffolds/alchemy/+package+/scripts/initializedb.py9
-rw-r--r--pyramid/scaffolds/alchemy/README.txt_tmpl6
-rw-r--r--pyramid/scaffolds/alchemy/setup.py_tmpl6
-rw-r--r--pyramid/scaffolds/starter/setup.py_tmpl6
-rw-r--r--pyramid/scaffolds/zodb/setup.py_tmpl6
-rw-r--r--pyramid/session.py12
-rw-r--r--pyramid/tests/fixtures/dummy.ini4
-rw-r--r--pyramid/tests/fixtures/static/héhé.html1
-rw-r--r--pyramid/tests/fixtures/static/héhé/index.html1
-rw-r--r--pyramid/tests/test_authentication.py52
-rw-r--r--pyramid/tests/test_authorization.py9
-rw-r--r--pyramid/tests/test_config/test_views.py7
-rw-r--r--pyramid/tests/test_integration.py71
-rw-r--r--pyramid/tests/test_paster.py44
-rw-r--r--pyramid/tests/test_router.py98
-rw-r--r--pyramid/tests/test_scaffolds/fixture_scaffold/setup.py_tmpl6
-rw-r--r--pyramid/tests/test_url.py15
-rw-r--r--pyramid/threadlocal.py4
-rw-r--r--pyramid/url.py5
-rw-r--r--pyramid/view.py37
-rw-r--r--setup.py8
129 files changed, 1570 insertions, 1106 deletions
diff --git a/BFG_HISTORY.txt b/BFG_HISTORY.txt
index 10d926c70..8a2d40920 100644
--- a/BFG_HISTORY.txt
+++ b/BFG_HISTORY.txt
@@ -4611,8 +4611,9 @@ Bug Fixes
of the Routes trunk was put into the "dev" index named
``Routes-1.11dev-chrism-home``. The source for the fork exists at
`http://bitbucket.org/chrism/routes-home/
- <http://bitbucket.org/chrism/routes-home/>`_; its contents have been
- merged into the Routes trunk (what will be Routes 1.11).
+ <http://bitbucket.org/chrism/routes-home/>`_ (broken link);
+ its contents have been merged into the Routes trunk
+ (what will be Routes 1.11).
0.8a5 (2009-05-08)
==================
diff --git a/CHANGES.txt b/CHANGES.txt
index adf448945..2366522df 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,83 @@
+next release
+============
+
+Features
+--------
+
+- ``ACLAuthorizationPolicy`` supports ``__acl__`` as a callable. This
+ removes the ambiguity between the potential ``AttributeError`` that would
+ be raised on the ``context`` when the property was not defined and the
+ ``AttributeError`` that could be raised from any user-defined code within
+ a dynamic property. It is recommended to define a dynamic ACL as a callable
+ to avoid this ambiguity. See https://github.com/Pylons/pyramid/issues/735.
+
+- Allow a protocol-relative URL (e.g. ``//example.com/images``) to be passed to
+ ``pyramid.config.Configurator.add_static_view``. This allows
+ externally-hosted static URLs to be generated based on the current protocol.
+
+- The ``AuthTktAuthenticationPolicy`` now supports IPv6 addresses when using
+ the ``include_ip=True`` option. This is possibly incompatible with
+ alternative ``auth_tkt`` implementations, as the specification does not
+ define how to properly handle IPv6. See
+ https://github.com/Pylons/pyramid/issues/831.
+
+- Make it possible to use variable arguments via
+ ``pyramid.paster.get_appsettings``. This also allowed the generated
+ ``initialize_db`` script from the ``alchemy`` scaffold to grow support
+ for options in the form ``a=1 b=2`` so you can fill in
+ values in a parameterized ``.ini`` file, e.g.
+ ``initialize_myapp_db etc/development.ini a=1 b=2``.
+ See https://github.com/Pylons/pyramid/pull/911
+
+Bug Fixes
+---------
+
+- View lookup will now search for valid views based on the inheritance
+ hierarchy of the context. It tries to find views based on the most
+ specific context first, and upon predicate failure, will move up the
+ inheritance chain to test views found by the super-type of the context.
+ In the past, only the most specific type containing views would be checked
+ and if no matching view could be found then a PredicateMismatch would be
+ raised. Now predicate mismatches don't hide valid views registered on
+ super-types. Here's an example that now works::
+
+ .. code-block:: python
+
+ class IResource(Interface):
+
+ ...
+
+ @view_config(context=IResource)
+ def get(context, request):
+
+ ...
+
+ @view_config(context=IResource, request_method='POST')
+ def post(context, request):
+
+ ...
+
+ @view_config(context=IResource, request_method='DELETE')
+ def delete(context, request):
+
+ ...
+
+ @implementor(IResource)
+ class MyResource:
+
+ ...
+
+ @view_config(context=MyResource, request_method='POST')
+ def override_post(context, request):
+
+ ...
+
+ Previously the override_post view registration would hide the get
+ and delete views in the context of MyResource -- leading to a
+ predicate mismatch error when trying to use GET or DELETE
+ methods. Now the views are found and no predicate mismatch is
+ raised.
+
1.4 (2012-12-18)
================
@@ -274,7 +354,7 @@ Bug Fixes
- ``pyramid.view.render_view`` was not functioning properly under Python 3.x
due to a byte/unicode discrepancy. See
- http://github.com/Pylons/pyramid/issues/721
+ https://github.com/Pylons/pyramid/issues/721
Deprecations
------------
@@ -511,7 +591,7 @@ Features
- The static view machinery now raises (rather than returns) ``HTTPNotFound``
and ``HTTPMovedPermanently`` exceptions, so these can be caught by the
- NotFound view (and other exception views).
+ Not Found View (and other exception views).
- The Mako renderer now supports a def name in an asset spec. When the def
name is present in the asset spec, the system will render the template def
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index 971c172f8..94eee9443 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -192,3 +192,7 @@ Contributors
- Robert Jackiewicz, 2012/11/12
- John Anderson, 2012/11/14
+
+- Bert JW Regeer, 2013/02/01
+
+- Georges Dubus, 2013/03/21
diff --git a/HACKING.txt b/HACKING.txt
index 64c8f461a..26e85ee80 100644
--- a/HACKING.txt
+++ b/HACKING.txt
@@ -27,7 +27,7 @@ checkout.
- Install ``setuptools-git`` into the virtualenv (for good measure, as we're
using git to do version control)::
- $ env/bin/easy_install setuptools-git
+ $ $VENV/bin/easy_install setuptools-git
- Install Pyramid from the checkout into the virtualenv using ``setup.py
dev``. ``setup.py dev`` is an alias for "setup.py develop" which also
@@ -36,19 +36,19 @@ checkout.
``pyramid`` checkout directory::
$ cd pyramid
- $ ../env/bin/python setup.py dev
+ $ $VENV/bin/python setup.py dev
- At that point, you should be able to create new Pyramid projects by using
``pcreate``::
$ cd ../env
- $ bin/pcreate -s starter starter
+ $ $VENV/bin/pcreate -s starter starter
- And install those projects (also using ``setup.py develop``) into the
virtualenv::
$ cd starter
- $ ../bin/python setup.py develop
+ $ $VENV/bin/python setup.py develop
Adding Features
---------------
@@ -88,7 +88,7 @@ Coding Style
mandatory.
- Please do not remove trailing whitespace. Configure your editor to reduce
- diff noise.
+ diff noise. See https://github.com/Pylons/pyramid/issues/788 for more.
Running Tests
--------------
@@ -129,7 +129,7 @@ or adds the feature.
To build and review docs (where ``$yourvenv`` refers to the virtualenv you're
using to develop Pyramid):
-1. Run ``$yourvenv/bin/python setup.py dev docs``. This will cause Sphinx
+1. Run ``$VENV/bin/python setup.py dev docs``. This will cause Sphinx
and all development requirements to be installed in your virtualenv.
2. Update all git submodules from the top-level of your Pyramid checkout, like
@@ -139,7 +139,7 @@ using to develop Pyramid):
HTML docs are generated.
3. cd to the ``docs`` directory within your Pyramid checkout and execute
- ``make clean html SPHINXBUILD=$yourvenv/bin/sphinx-build``. The
+ ``make clean html SPHINXBUILD=$VENV/bin/sphinx-build``. The
``SPHINXBUILD=...`` hair is there in order to tell it to use the
virtualenv Python, which will have both Sphinx and Pyramid (for API
documentation generation) installed.
diff --git a/HISTORY.txt b/HISTORY.txt
index f10cfa3ab..67de56998 100644
--- a/HISTORY.txt
+++ b/HISTORY.txt
@@ -537,7 +537,7 @@ Documentation
- Removed the "Running Pyramid on Google App Engine" tutorial from the main
docs. It survives on in the Cookbook
- (http://docs.pylonsproject.org/projects/pyramid_cookbook/en/latest/gae.html).
+ (http://docs.pylonsproject.org/projects/pyramid_cookbook/en/latest/deployment/gae.html).
Rationale: it provides the correct info for the Python 2.5 version of GAE
only, and this version of Pyramid does not support Python 2.5.
@@ -1189,7 +1189,7 @@ Scaffolds
package at all; configuration in the ``production.ini`` file which used to
require its ``error_catcher`` middleware has been removed. Configuring
error catching / email sending is now the domain of the ``pyramid_exclog``
- package (see http://docs.pylonsproject.org/projects/pyramid_exclog/dev/).
+ package (see http://docs.pylonsproject.org/projects/pyramid_exclog/en/latest/).
Bug Fixes
---------
@@ -2047,7 +2047,7 @@ Documentation
- Moved "Using ZODB With ZEO" and "Using repoze.catalog Within Pyramid"
tutorials out of core documentation and into the Pyramid Tutorials site
- (http://docs.pylonsproject.org/projects/pyramid_tutorials/dev/).
+ (http://docs.pylonsproject.org/projects/pyramid_tutorials/en/latest/).
- Changed "Cleaning up After a Request" section in the URL Dispatch chapter
to use ``request.add_finished_callback`` instead of jamming an object with
@@ -2249,7 +2249,8 @@ Backwards Incompatibilities
Pyramid core. Handlers are now a feature of the ``pyramid_handlers``
package, which can be downloaded from PyPI. Documentation for the package
should be available via
- http://pylonsproject.org/projects/pyramid_handlers/dev/, which describes how
+ http://docs.pylonsproject.org/projects/pyramid_handlers/en/latest/,
+ which describes how
to add a configuration statement to your ``main`` block to reobtain this
method. You will also need to add an ``install_requires`` dependency upon
``pyramid_handlers`` to your ``setup.py`` file.
@@ -2258,7 +2259,8 @@ Backwards Incompatibilities
Pyramid core. Loading ZCML is now a feature of the ``pyramid_zcml``
package, which can be downloaded from PyPI. Documentation for the package
should be available via
- http://pylonsproject.org/projects/pyramid_zcml/dev/, which describes how
+ http://docs.pylonsproject.org/projects/pyramid_zcml/en/latest/,
+ which describes how
to add a configuration statement to your ``main`` block to reobtain this
method. You will also need to add an ``install_requires`` dependency upon
``pyramid_zcml`` to your ``setup.py`` file.
diff --git a/docs/api.rst b/docs/api.rst
deleted file mode 100644
index 9e540b49b..000000000
--- a/docs/api.rst
+++ /dev/null
@@ -1,41 +0,0 @@
-API Documentation
-=================
-
-Comprehensive reference material for every public API exposed by
-:app:`Pyramid` is available within this chapter. The API
-documentation is organized alphabetically by module name.
-
-.. toctree::
- :maxdepth: 1
-
- api/authorization
- api/authentication
- api/compat
- api/config
- api/decorator
- api/events
- api/exceptions
- api/httpexceptions
- api/i18n
- api/interfaces
- api/location
- api/paster
- api/path
- api/registry
- api/renderers
- api/request
- api/response
- api/scaffolds
- api/scripting
- api/security
- api/session
- api/settings
- api/static
- api/testing
- api/threadlocal
- api/traversal
- api/tweens
- api/url
- api/view
- api/wsgi
-
diff --git a/docs/api/config.rst b/docs/api/config.rst
index 5d2bce23e..39d504348 100644
--- a/docs/api/config.rst
+++ b/docs/api/config.rst
@@ -108,9 +108,7 @@
:class:`pyramid.registry.Introspectable` class (used during
directives to provide introspection to actions).
- .. note::
-
- This attribute is new as of :app:`Pyramid` 1.3.
+ .. versionadded:: 1.3
.. attribute:: introspector
@@ -118,9 +116,7 @@
instance implementing the :class:`pyramid.interfaces.IIntrospector`
interface.
- .. note::
-
- This attribute is new as of :app:`Pyramid` 1.3.
+ .. versionadded:: 1.3
.. attribute:: registry
@@ -130,7 +126,7 @@
.. attribute:: global_registries
The set of registries that have been created for :app:`Pyramid`
- applications, one per each call to
+ applications, one for each call to
:meth:`pyramid.config.Configurator.make_wsgi_app` in the current
process. The object itself supports iteration and has a ``last`` property
containing the last registry loaded.
diff --git a/docs/api/exceptions.rst b/docs/api/exceptions.rst
index 1dfbf46fd..ab158f18d 100644
--- a/docs/api/exceptions.rst
+++ b/docs/api/exceptions.rst
@@ -5,6 +5,8 @@
.. automodule:: pyramid.exceptions
+ .. autoclass:: PredicateMismatch
+
.. autoclass:: Forbidden
.. autoclass:: NotFound
diff --git a/docs/api/paster.rst b/docs/api/paster.rst
index bde128e05..edc3738fc 100644
--- a/docs/api/paster.rst
+++ b/docs/api/paster.rst
@@ -9,6 +9,6 @@
.. autofunction:: get_app(config_uri, name=None, options=None)
- .. autofunction:: get_appsettings(config_uri, name=None)
+ .. autofunction:: get_appsettings(config_uri, name=None, options=None)
.. autofunction:: setup_logging(config_uri)
diff --git a/docs/api/registry.rst b/docs/api/registry.rst
index a7879d3d5..db348495c 100644
--- a/docs/api/registry.rst
+++ b/docs/api/registry.rst
@@ -16,6 +16,8 @@
.. attribute:: introspector
+ .. versionadded:: 1.3
+
When a registry is set up (or created) by a :term:`Configurator`, the
registry will be decorated with an instance named ``introspector``
implementing the :class:`pyramid.interfaces.IIntrospector` interface.
@@ -27,28 +29,23 @@
This attribute is often accessed as ``request.registry.introspector`` in
a typical Pyramid application.
- This attribute is new as of :app:`Pyramid` 1.3.
-
.. class:: Introspectable
+ .. versionadded:: 1.3
+
The default implementation of the interface
:class:`pyramid.interfaces.IIntrospectable` used by framework exenders.
An instance of this class is created when
:attr:`pyramid.config.Configurator.introspectable` is called.
- This class is new as of :app:`Pyramid` 1.3.
-
.. autoclass:: Deferred
- This class is new as of :app:`Pyramid` 1.4.
+ .. versionadded:: 1.4
.. autofunction:: undefer
- This function is new as of :app:`Pyramid` 1.4.
+ .. versionadded:: 1.4
.. autoclass:: predvalseq
- This class is new as of :app:`Pyramid` 1.4.
-
-
-
+ .. versionadded:: 1.4
diff --git a/docs/api/request.rst b/docs/api/request.rst
index e4034c635..7b843f86e 100644
--- a/docs/api/request.rst
+++ b/docs/api/request.rst
@@ -163,9 +163,7 @@
.. method:: invoke_subrequest(request, use_tweens=False)
- .. warning::
-
- This API was added in Pyramid 1.4a1.
+ .. versionadded:: 1.4a1
Obtain a response object from the Pyramid application based on
information in the ``request`` object provided. The ``request`` object
@@ -247,7 +245,7 @@
influence response values from a view that uses a renderer (such as the
status code, a header, the content type, etc) you would set these
attributes. See :ref:`response_prefixed_attrs` for further discussion.
- As of Pyramid 1.1, assignment to ``response_*`` attrs are deprecated.
+ As of Pyramid 1.1, assignment to ``response_*`` attrs is deprecated.
Assigning to one is still supported but will cause a deprecation
warning to be emitted, and eventually the feature will be removed. For
new code, instead of assigning ``response_*`` attributes to the
diff --git a/docs/conf.py b/docs/conf.py
index 6eb76af9d..eff6db488 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -50,20 +50,21 @@ extensions = [
'sphinx.ext.doctest',
'repoze.sphinx.autointerface',
'sphinx.ext.viewcode',
-# 'sphinx.ext.intersphinx'
+ 'sphinx.ext.intersphinx'
]
-# Looks for objects in other Pyramid projects
-## intersphinx_mapping = {
-## 'cookbook':
-## ('http://docs.pylonsproject.org/projects/pyramid_cookbook/dev/', None),
-## 'handlers':
-## ('http://docs.pylonsproject.org/projects/pyramid_handlers/dev/', None),
-## 'zcml':
-## ('http://docs.pylonsproject.org/projects/pyramid_zcml/dev/', None),
-## 'jinja2':
-## ('http://docs.pylonsproject.org/projects/pyramid_jinja2/dev/', None),
-## }
+# Looks for objects in external projects
+intersphinx_mapping = {
+ 'sqla': ('http://docs.sqlalchemy.org/en/latest', None),
+ 'who': ('http://docs.repoze.org/who/latest', None),
+ 'python': ('http://docs.python.org', None),
+ 'python3': ('http://docs.python.org/3', None),
+ 'tstring':
+ ('http://docs.pylonsproject.org/projects/translationstring/en/latest',
+ None),
+ 'venusian':
+ ('http://docs.pylonsproject.org/projects/venusian/en/latest', None),
+}
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
diff --git a/docs/conventions.rst b/docs/conventions.rst
index 0c38e11d8..4cffd1084 100644
--- a/docs/conventions.rst
+++ b/docs/conventions.rst
@@ -55,21 +55,25 @@ character, e.g.:
.. code-block:: text
- $ ../bin/nosetests
+ $ $VENV/bin/nosetests
+
+(See :term:`virtualenv` for the meaning of ``$VENV``)
Example blocks representing Windows ``cmd.exe`` commands are prefixed with a
drive letter and/or a directory name, e.g.:
.. code-block:: text
- c:\examples> ..\Scripts\nosetests
+ c:\examples> %VENV%\Scripts\nosetests
+
+(See :term:`virtualenv` for the meaning of ``%VENV%``)
Sometimes, when it's unknown which directory is current, Windows ``cmd.exe``
example block commands are prefixed only with a ``>`` character, e.g.:
.. code-block:: text
- > ..\Scripts\nosetests
+ > %VENV%\Scripts\nosetests
When a command that should be typed on one line is too long to fit on a page,
the backslash ``\`` is used to indicate that the following printed line
@@ -77,7 +81,7 @@ should actually be part of the command:
.. code-block:: text
- c:\bigfntut\tutorial> ..\Scripts\nosetests --cover-package=tutorial \
+ c:\bigfntut\tutorial> %VENV%\Scripts\nosetests --cover-package=tutorial \
--cover-erase --with-coverage
A sidebar, which presents a concept tangentially related to content
diff --git a/docs/designdefense.rst b/docs/designdefense.rst
index f51ef10a9..7bc37ac06 100644
--- a/docs/designdefense.rst
+++ b/docs/designdefense.rst
@@ -120,7 +120,6 @@ that uses the ZCA global API is somewhat high. Consider a ZCA neophyte
reading the code that performs a typical "unnamed utility" lookup using the
:func:`zope.component.getUtility` global API:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -190,7 +189,6 @@ special-purpose API functions that *do* use ZCA APIs. Take for example the
present in the current request or ``None`` if no userid is present in the
current request. The application developer calls it like so:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -238,7 +236,7 @@ registry API.
:app:`Pyramid` framework developers were so concerned about conceptual load
issues of the ZCA registry API for framework developers that a `replacement
-registry implementation <http://svn.repoze.org/repoze.component/trunk>`_
+registry implementation <https://github.com/repoze/repoze.component>`_
named :mod:`repoze.component` was actually developed. Though this package
has a registry implementation which is fully functional and well-tested, and
its API is much nicer than the ZCA registry API, work on it was largely
@@ -500,7 +498,6 @@ which match information in an associated "urlconf" such as
Zope, likewise allows you to add arbitrary keyword and positional
arguments to any method of a resource object found via traversal:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -919,7 +916,7 @@ creating a more Zope3-like environment without much effort.
Pyramid Uses its Own HTTP Exception Class Hierarchy Rather Than ``webob.exc``
-----------------------------------------------------------------------------
-.. note:: This defense is new as of Pyramid 1.1.
+.. versionadded:: 1.1
The HTTP exception classes defined in :mod:`pyramid.httpexceptions` are very
much like the ones defined in ``webob.exc``
@@ -1030,7 +1027,7 @@ but its intended userbase is much the same. Many others exist. We've
actually even (only as a teaching tool, not as any sort of official project)
`created one using Pyramid <http://bfg.repoze.org/videos#groundhog1>`_ (the
videos use BFG, a precursor to Pyramid, but the resulting code is `available
-for Pyramid too <http://github.com/Pylons/groundhog>`_). Microframeworks are
+for Pyramid too <https://github.com/Pylons/groundhog>`_). Microframeworks are
small frameworks with one common feature: each allows its users to create a
fully functional application that lives in a single Python file.
diff --git a/docs/glossary.rst b/docs/glossary.rst
index 5b165db0a..1b7a5f307 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -18,7 +18,7 @@ Glossary
response
An object returned by a :term:`view callable` that represents response
- data returned to the requesting user agent. It must implements the
+ data returned to the requesting user agent. It must implement the
:class:`pyramid.interfaces.IResponse` interface. A response object is
typically an instance of the :class:`pyramid.response.Response` class or
a subclass such as :class:`pyramid.httpexceptions.HTTPFound`. See
@@ -146,10 +146,13 @@ Glossary
request before it returns a :term:`context` resource.
virtualenv
- An isolated Python environment. Allows you to control which
- packages are used on a particular project by cloning your main
- Python. `virtualenv <http://pypi.python.org/pypi/virtualenv>`_
- was created by Ian Bicking.
+ A term referring both to an isolated Python environment,
+ or `the leading tool <http://www.virtualenv.org>`_ that allows one to
+ create such environments.
+
+ Note: whenever you encounter commands prefixed with ``$VENV`` (Unix)
+ or ``%VENV`` (Windows), know that that is the environment variable whose
+ value is the root of the virtual environment in question.
resource
An object representing a node in the :term:`resource tree` of an
@@ -324,25 +327,19 @@ Glossary
`A full-featured Python web framework <http://djangoproject.com>`_.
Pylons
- `A lightweight Python web framework <http://pylonshq.com>`_ and a
- predecessor of Pyramid.
+ `A lightweight Python web framework <http://docs.pylonsproject.org/projects/pylons-webframework/en/latest/>`_
+ and a predecessor of Pyramid.
ZODB
`Zope Object Database <http://zodb.org>`_, a
persistent Python object store.
- ZEO
- `Zope Enterprise Objects
- <http://www.zope.org/Documentation/Books/ZopeBook/2_6Edition/ZEO.stx>`_
- allows multiple simultaneous processes to access a single
- :term:`ZODB` database.
-
WebOb
`WebOb <http://webob.org>`_ is a WSGI request/response
library created by Ian Bicking.
PasteDeploy
- `PasteDeploy <http://pythonpaste.org>`_ is a library used by
+ `PasteDeploy <http://pythonpaste.org/deploy/>`_ is a library used by
:app:`Pyramid` which makes it possible to configure
:term:`WSGI` components together declaratively within an ``.ini``
file. It was developed by Ian Bicking.
@@ -400,10 +397,9 @@ Glossary
dispatching and other application configuration tasks.
reStructuredText
- A `plain text format <http://docutils.sourceforge.net/rst.html>`_
- that is the defacto standard for descriptive text shipped in
- :term:`distribution` files, and Python docstrings. This
- documentation is authored in ReStructuredText format.
+ A `plain text markup format <http://docutils.sourceforge.net/rst.html>`_
+ that is the defacto standard for documenting Python projects.
+ The Pyramid documentation is written in reStructuredText.
root
The object at which :term:`traversal` begins when :app:`Pyramid`
@@ -618,13 +614,13 @@ Glossary
:term:`configuration decoration` and a :term:`scan` to configure your
Pyramid application.
- Not Found view
+ Not Found View
An :term:`exception view` invoked by :app:`Pyramid` when the developer
explicitly raises a :class:`pyramid.httpexceptions.HTTPNotFound`
exception from within :term:`view` code or :term:`root factory` code,
or when the current request doesn't match any :term:`view
configuration`. :app:`Pyramid` provides a default implementation of a
- not found view; it can be overridden. See
+ Not Found View; it can be overridden. See
:ref:`changing_the_notfound_view`.
Forbidden view
@@ -654,10 +650,9 @@ Glossary
<http://en.wikipedia.org/wiki/Thread_(computer_science)>`_ used by the
application may have a different value for this same "global" variable.
:app:`Pyramid` uses a small number of thread local variables, as
- described in :ref:`threadlocals_chapter`. See also the `threading.local
- documentation
- <http://docs.python.org/library/threading.html#threading.local>`_ for
- more information.
+ described in :ref:`threadlocals_chapter`.
+ See also the :class:`stdlib documentation <threading.local>`
+ for more information.
multidict
An ordered dictionary that can have multiple values for each key. Adds
@@ -685,11 +680,11 @@ Glossary
The C implementation of the Python language. This is the
reference implementation that most people refer to as simply
"Python"; :term:`Jython`, Google's App Engine, and `PyPy
- <http://codespeak.net/pypy/dist/pypy/doc/>`_ are examples of
+ <http://doc.pypy.org/en/latest/>`_ are examples of
non-C based Python implementations.
View Lookup
- The act of finding and invoking the "best" :term:`view callable`
+ The act of finding and invoking the "best" :term:`view callable`,
given a :term:`request` and a :term:`context` resource.
Resource Location
@@ -959,7 +954,7 @@ Glossary
console script
A script written to the ``bin`` (on UNIX, or ``Scripts`` on Windows)
- directory of a Python installation or virtualenv as the result of
+ directory of a Python installation or :term:`virtualenv` as the result of
running ``setup.py install`` or ``setup.py develop``.
introspector
@@ -1015,8 +1010,7 @@ Glossary
Green Unicorn
Aka ``gunicorn``, a fast :term:`WSGI` server that runs on UNIX under
- Python 2.5+ (although at the time of this writing does not support
- Python 3). See http://gunicorn.org/ for detailed information.
+ Python 2.6+ or Python 3.1+. See http://gunicorn.org/ for detailed information.
predicate factory
A callable which is used by a third party during the registration of a
diff --git a/docs/index.rst b/docs/index.rst
index 0d6113c15..bc711f8ff 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -14,7 +14,7 @@ Here is one of the simplest :app:`Pyramid` applications you can make:
.. literalinclude:: narr/helloworld.py
After you install :app:`Pyramid` and run this application, when you visit
-``http://localhost:8080/hello/world`` in a browser, you will see the text
+`<http://localhost:8080/hello/world>`_ in a browser, you will see the text
``Hello, world!``
See :ref:`firstapp_chapter` for a full explanation of how this application
@@ -112,12 +112,13 @@ platforms.
API Documentation
==================
-Documentation for every :app:`Pyramid` API.
+Comprehensive reference material for every public API exposed by :app:`Pyramid`:
.. toctree::
- :maxdepth: 2
+ :maxdepth: 1
+ :glob:
- api
+ api/*
Change History
==============
@@ -188,7 +189,7 @@ The `Pylons Project web site <http://pylonsproject.org/>`_ is the main online
source of :app:`Pyramid` support and development information.
To report bugs, use the `issue tracker
-<http://github.com/Pylons/pyramid/issues>`_.
+<https://github.com/Pylons/pyramid/issues>`_.
If you've got questions that aren't answered by this documentation,
contact the `Pylons-discuss maillist
@@ -196,7 +197,7 @@ contact the `Pylons-discuss maillist
IRC channel <irc://irc.freenode.net/#pyramid>`_.
Browse and check out tagged and trunk versions of :app:`Pyramid` via
-the `Pyramid GitHub repository <http://github.com/Pylons/pyramid/>`_.
+the `Pyramid GitHub repository <https://github.com/Pylons/pyramid/>`_.
To check out the trunk via ``git``, use this command:
.. code-block:: text
diff --git a/docs/narr/MyProject/setup.py b/docs/narr/MyProject/setup.py
index f24b6984e..6969c73e7 100644
--- a/docs/narr/MyProject/setup.py
+++ b/docs/narr/MyProject/setup.py
@@ -3,8 +3,10 @@ import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, 'README.txt')).read()
-CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = [
'pyramid',
diff --git a/docs/narr/advconfig.rst b/docs/narr/advconfig.rst
index ad22a82c9..434e2bd6c 100644
--- a/docs/narr/advconfig.rst
+++ b/docs/narr/advconfig.rst
@@ -417,7 +417,7 @@ added in configuration execution order.
More Information
----------------
-For more information, see the article entitled `"A Whirlwind Rour 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>`_
+<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..99bcb187f 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:
@@ -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,7 +330,6 @@ 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:
@@ -458,7 +456,6 @@ 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:
@@ -473,7 +470,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 +478,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 +506,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 8d6b9d984..07c892439 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.
@@ -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.
@@ -276,18 +276,17 @@ exposed, and the request is configured to generate urls from the host
IPython or bpython
~~~~~~~~~~~~~~~~~~
-If you have `IPython <http://en.wikipedia.org/wiki/IPython>`_ or
-`bpython <http://bpython-interpreter.org/>`_ or both installed in
+If you have `IPython <http://en.wikipedia.org/wiki/IPython>`_ and/or
+`bpython <http://bpython-interpreter.org/>`_ in
the interpreter you use to invoke the ``pshell`` command, ``pshell`` will
-autodiscover them and use the first respectively found in this order :
+autodiscover and use the first one found, in this order:
IPython, bpython, standard Python interpreter. However you could
specifically invoke one of your choice with the ``-p choice`` or
``--python-shell choice`` option.
.. 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,7 @@ 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
.. _writing_a_script:
@@ -504,7 +503,8 @@ environment much like the environment produced when a particular
using the :func:`pyramid.paster.bootstrap` command in the body of your
script.
-.. note:: This feature is new as of :app:`Pyramid` 1.1.
+.. versionadded:: 1.1
+ :func:`pyramid.paster.bootstrap`
In the simplest case, :func:`pyramid.paster.bootstrap` can be used with a
single argument, which accepts the :term:`PasteDeploy` ``.ini`` file
@@ -774,8 +774,10 @@ top-level directory your ``setup.py`` file will look something like this:
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
- README = open(os.path.join(here, 'README.txt')).read()
- CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+ with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+ with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = ['pyramid', 'pyramid_debugtoolbar']
@@ -829,8 +831,10 @@ The result will be something like:
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
- README = open(os.path.join(here, 'README.txt')).read()
- CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+ with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+ with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = ['pyramid', 'pyramid_debugtoolbar']
@@ -862,7 +866,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
@@ -873,9 +877,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 cd3dab099..f7a69d613 100644
--- a/docs/narr/configuration.rst
+++ b/docs/narr/configuration.rst
@@ -101,27 +101,25 @@ for decorations happens when the :meth:`pyramid.config.Configurator.scan`
method is invoked: scanning implies searching for configuration declarations
in a package and its subpackages. For example:
-.. topic:: Starting A Scan
-
- .. code-block:: python
- :linenos:
-
- from wsgiref.simple_server import make_server
- from pyramid.config import Configurator
- from pyramid.response import Response
- from pyramid.view import view_config
-
- @view_config()
- def hello(request):
- return Response('Hello')
-
- if __name__ == '__main__':
- from pyramid.config import Configurator
- config = Configurator()
- config.scan()
- app = config.make_wsgi_app()
- server = make_server('0.0.0.0', 8080, app)
- server.serve_forever()
+.. code-block:: python
+ :linenos:
+
+ from wsgiref.simple_server import make_server
+ from pyramid.config import Configurator
+ from pyramid.response import Response
+ from pyramid.view import view_config
+
+ @view_config()
+ def hello(request):
+ return Response('Hello')
+
+ if __name__ == '__main__':
+ from pyramid.config import Configurator
+ config = Configurator()
+ config.scan()
+ app = config.make_wsgi_app()
+ server = make_server('0.0.0.0', 8080, app)
+ server.serve_forever()
The scanning machinery imports each module and subpackage in a package or
module recursively, looking for special attributes attached to objects
@@ -142,9 +140,7 @@ 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
- :linenos:
config.add_view(hello)
diff --git a/docs/narr/environment.rst b/docs/narr/environment.rst
index 8206e0bcb..e059acc4e 100644
--- a/docs/narr/environment.rst
+++ b/docs/narr/environment.rst
@@ -203,7 +203,7 @@ Using the setting is equivalent to using the
| |
+---------------------------------+
-The value supplied as ``pyramid.includes`` should be a sequence. The
+The value assigned to ``pyramid.includes`` should be a sequence. The
sequence can take several different forms.
1) It can be a string.
@@ -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
@@ -323,7 +323,7 @@ the behest of an add-on author.
| |
+---------------------------------+
-The value supplied as ``pyramid.tweens`` should be a sequence. The
+The value assigned to ``pyramid.tweens`` should be a sequence. The
sequence can take several different forms.
1) It can be a string.
@@ -504,12 +504,13 @@ default, this is ``false``.
Mako Preprocessor
~~~~~~~~~~~~~~~~~
+.. versionadded:: 1.1
+
A callable (or a :term:`dotted Python name` which names a callable) which is
called to preprocess the source before the template is called. The callable
will be passed the full template source before it is parsed. The return
result of the callable will be used as the template source code.
-.. note:: This feature is new in Pyramid 1.1.
+-----------------------------+
| Config File Setting Name |
@@ -545,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/paster serve 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
@@ -665,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/extconfig.rst b/docs/narr/extconfig.rst
index 875bc9006..f33326279 100644
--- a/docs/narr/extconfig.rst
+++ b/docs/narr/extconfig.rst
@@ -227,9 +227,7 @@ augment Pyramid's configuration introspection system.
Adding Configuration Introspection
----------------------------------
-.. note::
-
- The introspection subsystem is new in Pyramid 1.3.
+.. versionadded:: 1.3
Pyramid provides a configuration introspection system that can be used by
debugging tools to provide visibility into the configuration of a running
diff --git a/docs/narr/extending.rst b/docs/narr/extending.rst
index c464203f0..beece7640 100644
--- a/docs/narr/extending.rst
+++ b/docs/narr/extending.rst
@@ -84,7 +84,7 @@ function in your application's ``__init__.py``. For example, rather than:
config.add_view('myapp.views.view1', name='view1')
config.add_view('myapp.views.view2', name='view2')
-You should do move the calls to ``add_view`` outside of the (non-reusable)
+You should move the calls to ``add_view`` outside of the (non-reusable)
``if __name__ == '__main__'`` block, and into a reusable function:
.. code-block:: python
@@ -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
diff --git a/docs/narr/firstapp.rst b/docs/narr/firstapp.rst
index 0b85d68d3..e73ef66ac 100644
--- a/docs/narr/firstapp.rst
+++ b/docs/narr/firstapp.rst
@@ -29,18 +29,18 @@ 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
server will simply serve up the text "Hello world!". If your application is
-running on your local system, using ``http://localhost:8080/hello/world``
+running on your local system, using `<http://localhost:8080/hello/world>`_
in a browser will show this result.
Each time you visit a URL served by the application in a browser, a logging
@@ -166,7 +166,6 @@ the application.
Adding Configuration
~~~~~~~~~~~~~~~~~~~~
-.. ignore-next-block
.. literalinclude:: helloworld.py
:linenos:
:lines: 11-12
@@ -175,9 +174,9 @@ First line above calls the :meth:`pyramid.config.Configurator.add_route`
method, which registers a :term:`route` to match any URL path that begins
with ``/hello/`` followed by a string.
-The second line, ``config.add_view(hello_world, route_name='hello')``,
-registers the ``hello_world`` function as a :term:`view callable` and makes
-sure that it will be called when the ``hello`` route is matched.
+The second line registers the ``hello_world`` function as a
+:term:`view callable` and makes sure that it will be called when the
+``hello`` route is matched.
.. index::
single: make_wsgi_app
@@ -186,7 +185,6 @@ sure that it will be called when the ``hello`` route is matched.
WSGI Application Creation
~~~~~~~~~~~~~~~~~~~~~~~~~
-.. ignore-next-block
.. literalinclude:: helloworld.py
:linenos:
:lines: 13
@@ -194,13 +192,13 @@ WSGI Application Creation
After configuring views and ending configuration, the script creates a WSGI
*application* via the :meth:`pyramid.config.Configurator.make_wsgi_app`
method. A call to ``make_wsgi_app`` implies that all configuration is
-finished (meaning all method calls to the configurator which set up views,
-and various other configuration settings have been performed). The
+finished (meaning all method calls to the configurator, which sets up views
+and various other configuration settings, have been performed). The
``make_wsgi_app`` method returns a :term:`WSGI` application object that can
be used by any WSGI server to present an application to a requestor.
:term:`WSGI` is a protocol that allows servers to talk to Python
applications. We don't discuss :term:`WSGI` in any depth within this book,
-however, you can learn more about it by visiting `wsgi.org
+but you can learn more about it by visiting `wsgi.org
<http://wsgi.org>`_.
The :app:`Pyramid` application object, in particular, is an instance of a
@@ -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 b5efc0df1..330eb0cd3 100644
--- a/docs/narr/hooks.rst
+++ b/docs/narr/hooks.rst
@@ -15,12 +15,11 @@ 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`. A default notfound view
-exists. The default not found view can be overridden through application
-configuration.
+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
@@ -30,7 +29,7 @@ the Not Found view by using the
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
+callable` you want to use to represent the Not Found View. The :term:`not
found view` callable is a view callable like any other.
If your application instead uses :class:`pyramid.view.view_config` decorators
@@ -52,12 +51,12 @@ and a :term:`scan`, you can replace the Not Found view by using the
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:
@@ -80,7 +79,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
@@ -92,7 +91,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:
@@ -104,11 +104,11 @@ 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
+ 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.
@@ -123,7 +123,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
@@ -257,6 +257,97 @@ already constructed a :term:`configurator` it can also be registered via the
config.set_request_factory(MyRequest)
.. index::
+ single: request method
+
+.. _adding_request_method:
+
+Adding Methods or Properties to Request Object
+----------------------------------------------
+
+.. versionadded:: 1.4.
+
+Since each Pyramid application can only have one :term:`request` factory,
+:ref:`changing the request factory <changing_the_request_factory>`
+is not that extensible, especially if you want to build composable features
+(e.g., Pyramid add-ons and plugins).
+
+A lazy property can be registered to the request object via the
+:meth:`pyramid.config.Configurator.add_request_method` API. This allows you
+to specify a callable that will be available on the request object, but will not
+actually execute the function until accessed.
+
+.. warning::
+
+ This will silently override methods and properties from :term:`request
+ factory` that have the same name.
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.config import Configurator
+
+ def total(request, *args):
+ return sum(args)
+
+ def prop(request):
+ print "getting the property"
+ return "the property"
+
+ config = Configurator()
+ config.add_request_method(total)
+ config.add_request_method(prop, reify=True)
+
+In the above example, ``total`` is added as a method. However, ``prop`` is added
+as a property and its result is cached per-request by setting ``reify=True``.
+This way, we eliminate the overhead of running the function multiple times.
+
+ >>> request.total(1, 2, 3)
+ 6
+ >>> request.prop
+ getting the property
+ the property
+ >>> request.prop
+ the property
+
+To not cache the result of ``request.prop``, set ``property=True`` instead of
+``reify=True``.
+
+Here is an example of passing a class to ``Configurator.add_request_method``:
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.config import Configurator
+ from pyramid.decorator import reify
+
+ class ExtraStuff(object):
+
+ def __init__(self, request):
+ self.request = request
+
+ def total(self, *args):
+ return sum(args)
+
+ # use @property if you don't want to cache the result
+ @reify
+ def prop(self):
+ print "getting the property"
+ return "the property"
+
+ config = Configurator()
+ config.add_request_method(ExtraStuff, 'extra', reify=True)
+
+We attach and cache an object named ``extra`` to the ``request`` object.
+
+ >>> request.extra.total(1, 2, 3)
+ 6
+ >>> request.extra.prop
+ getting the property
+ the property
+ >>> request.extra.prop
+ the property
+
+.. index::
single: before render event
single: adding renderer globals
@@ -336,9 +427,9 @@ when adding renderer global values exists in :ref:`adding_renderer_globals`.
Adding Renderer Globals (Deprecated)
------------------------------------
-.. warning:: this feature is deprecated as of Pyramid 1.1. A non-deprecated
- mechanism which allows event subscribers to add renderer global values
- is documented in :ref:`beforerender_event`.
+.. 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
@@ -621,7 +712,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.
@@ -635,13 +726,13 @@ See :meth:`pyramid.config.add_resource_url_adapter` for more information.
Changing How Pyramid Treats View Responses
------------------------------------------
+.. versionadded:: 1.1
+
It is possible to control how Pyramid treats the result of calling a view
callable on a per-type basis by using a hook involving
:meth:`pyramid.config.Configurator.add_response_adapter` or the
:class:`~pyramid.response.response_adapter` decorator.
-.. note:: This feature is new as of Pyramid 1.1.
-
Pyramid, in various places, adapts the result of calling a view callable to
the :class:`~pyramid.interfaces.IResponse` interface to ensure that the
object returned by the view callable is a "true" response object. The vast
@@ -936,8 +1027,8 @@ For full details, please read the `Venusian documentation
Registering "Tweens"
--------------------
-.. note:: Tweens are a feature which were added in Pyramid 1.2. They are
- not available in any previous version.
+.. versionadded:: 1.2
+ Tweens
A :term:`tween` (a contraction of the word "between") is a bit of code that
sits between the Pyramid router's main request handling function and the
@@ -1241,10 +1332,7 @@ implict and explicit tween chains used by an application. See
Adding A Third Party View, Route, or Subscriber Predicate
---------------------------------------------------------
-.. note::
-
- Third-party view, route, and subscriber predicates are a feature new as of
- Pyramid 1.4.
+.. versionadded:: 1.4
.. _view_and_route_predicates:
diff --git a/docs/narr/i18n.rst b/docs/narr/i18n.rst
index 511464322..74765f8e2 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
@@ -736,9 +735,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::
diff --git a/docs/narr/install.rst b/docs/narr/install.rst
index a78c1b2bd..7f4742ee2 100644
--- a/docs/narr/install.rst
+++ b/docs/narr/install.rst
@@ -14,18 +14,37 @@ run :app:`Pyramid`.
.. sidebar:: Python Versions
- As of this writing, :app:`Pyramid` has been tested under Python 2.6.8,
- Python 2.7.3, Python 3.2.3, and Python 3.3b1. :app:`Pyramid` does not
+ 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+).
+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.
+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)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -40,13 +59,11 @@ UNIX system that has development tools.
Package Manager Method
++++++++++++++++++++++
-You can use your system's "package manager" to install Python. Every
-system's package manager is slightly different, but the "flavor" of
+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 an Ubuntu Linux system, to use the system package
-manager to install a Python 2.7 interpreter, use the following
-command:
+For example, on a Debian or Ubuntu system, use the following command:
.. code-block:: text
@@ -70,7 +87,8 @@ 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.
+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
@@ -89,17 +107,15 @@ using the following commands:
.. code-block:: text
- [chrism@vitaminf ~]$ cd ~
- [chrism@vitaminf ~]$ mkdir tmp
- [chrism@vitaminf ~]$ mkdir opt
- [chrism@vitaminf ~]$ cd tmp
- [chrism@vitaminf tmp]$ wget \
- http://www.python.org/ftp/python/2.7.3/Python-2.7.3.tgz
- [chrism@vitaminf tmp]$ tar xvzf Python-2.7.3.tgz
- [chrism@vitaminf tmp]$ cd Python-2.7.3
- [chrism@vitaminf Python-2.7.3]$ ./configure \
- --prefix=$HOME/opt/Python-2.7.3
- [chrism@vitaminf Python-2.7.3]$ make; make install
+ $ cd ~
+ $ mkdir tmp
+ $ mkdir opt
+ $ cd tmp
+ $ wget http://www.python.org/ftp/python/2.7.3/Python-2.7.3.tgz
+ $ tar xvzf Python-2.7.3.tgz
+ $ cd Python-2.7.3
+ $ ./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
@@ -167,9 +183,7 @@ 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. Note that above
-we're using a Python 2.7-series interpreter on Mac OS X; your output may
-differ if you're using a later Python version or a different platform.
+will need to install setuptools or distribute 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
@@ -208,7 +222,7 @@ Installing Distribute On Python 3
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``setuptools`` doesn't work under Python 3. Instead, you can use
-``distribute``, which is a fork of setuptools that does work on Python 3. To
+``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.
@@ -269,16 +283,21 @@ 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 --no-site-packages $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
@@ -294,20 +313,16 @@ following:
``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
+ $ $VENV/bin/easy_install pyramid
The ``easy_install`` command will take longer than the previous ones to
complete, as it downloads and installs a number of dependencies.
@@ -326,8 +341,8 @@ for both versions are included below.
Windows Using Python 2
~~~~~~~~~~~~~~~~~~~~~~
-#. Install, or find `Python 2.7
- <http://www.python.org/download/releases/2.7.3/>`_ for your system.
+#. Install, or find the most recent `Python 2.7.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
@@ -344,25 +359,25 @@ Windows Using Python 2
c:\> c:\Python27\python ez_setup.py
-#. Use that Python's `bin/easy_install` to install `virtualenv`:
+#. Install `virtualenv`:
.. code-block:: text
c:\> c:\Python27\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
+ c:\> set VENV=c:\env
+ c:\> c:\Python27\Scripts\virtualenv --no-site-packages %VENV%
-#. Switch to the ``env`` directory:
+ 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.
- .. code-block:: text
-
- c:\> cd env
-
-#. (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
@@ -370,48 +385,59 @@ Windows Using Python 2
.. code-block:: text
- c:\env> Scripts\easy_install pyramid
+ c:\env> %VENV%\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, or find the latest version of `Python 3.x
+ <http://www.python.org/download/>`_ for your system and which is
+ supported by Pyramid.
#. 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
+ pick the right download for Python 3.x 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
+ ``python`` interpreter of your Python 3.x installation using a command
prompt:
.. code-block:: text
+ # modify the command according to the python version, e.g.:
+ # for Python 3.2.x:
c:\> c:\Python32\python distribute_setup.py
+ # for Python 3.3.x:
+ c:\> c:\Python33\python distribute_setup.py
-#. Use that Python's `bin/easy_install` to install `virtualenv`:
+#. Install :term:`virtualenv`:
.. code-block:: text
+ # for Python 3.2.x:
c:\> c:\Python32\Scripts\easy_install virtualenv
+ # for Python 3.3.x:
+ 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:\Python32\Scripts\virtualenv --no-site-packages env
-
-#. Switch to the ``env`` directory:
-
- .. code-block:: text
+ c:\> set VENV=c:\env
+ # for Python 3.2.x:
+ c:\> c:\Python32\Scripts\virtualenv --no-site-packages %VENV%
+ # for Python 3.3.x:
+ c:\> c:\Python33\Scripts\virtualenv --no-site-packages %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
@@ -419,7 +445,7 @@ Windows Using Python 3
.. code-block:: text
- c:\env> Scripts\easy_install pyramid
+ c:\env> %VENV%\Scripts\easy_install pyramid
What Gets Installed
-------------------
diff --git a/docs/narr/introduction.rst b/docs/narr/introduction.rst
index c4f2ea512..f9c25c69c 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
@@ -219,7 +217,6 @@ 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
Class-based and function-based views
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -749,7 +746,7 @@ that we change Pyramid? You can extend Pyramid's :term:`Configurator` with
your own directives. For example, let's say you find yourself calling
:meth:`pyramid.config.Configurator.add_view` repetitively. Usually you can
take the boring away by using existing shortcuts, but let's say that this is
-a case such a way that no existing shortcut works to take the boring away:
+a case where there is no such shortcut:
.. code-block:: python
:linenos:
diff --git a/docs/narr/introspector.rst b/docs/narr/introspector.rst
index 7784e8960..dec22c5b1 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
----------------------
diff --git a/docs/narr/logging.rst b/docs/narr/logging.rst
index f4c38abb6..3b903be4d 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.
@@ -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
@@ -350,7 +348,7 @@ called with no arguments, so it 'just works' in environments that don't
configure logging. Since we've configured our own logging handlers, we need
to disable that option via ``setup_console_handler = False``.
-With the filter in place, TransLogger's logger (named the 'wsgi' logger) will
+With the filter in place, TransLogger's logger (named the ``wsgi`` logger) will
propagate its log messages to the parent logger (the root logger), sending
its output to the console when we request a page:
@@ -364,14 +362,18 @@ its output to the console when we request a page:
Firefox/2.0.0.6"
To direct TransLogger to an ``access.log`` FileHandler, we need to add that
-FileHandler to the wsgi logger's list of handlers:
+FileHandler to the list of handlers (named ``accesslog``), and ensure that the
+``wsgi`` logger is configured and uses this handler accordingly:
.. code-block:: ini
# Begin logging configuration
- [loggers]
- keys = root, myapp, wsgi
+ [loggers]
+ keys = root, myapp, wsgi
+
+ [handlers]
+ keys = console, accesslog
[logger_wsgi]
level = INFO
@@ -387,20 +389,19 @@ FileHandler to the wsgi logger's list of handlers:
As mentioned above, non-root loggers by default propagate their log records
to the root logger's handlers (currently the console handler). Setting
-``propagate`` to 0 (false) here disables this; so the ``wsgi`` logger directs
-its records only to the ``accesslog`` handler.
+``propagate`` to ``0`` (``False``) here disables this; so the ``wsgi`` logger
+directs its records only to the ``accesslog`` handler.
Finally, there's no need to use the ``generic`` formatter with TransLogger as
TransLogger itself provides all the information we need. We'll use a
-formatter that passes-through the log messages as is:
+formatter that passes-through the log messages as is. Add a new formatter
+called ``accesslog`` by include the following in your configuration file:
.. code-block:: ini
[formatters]
keys = generic, accesslog
-.. code-block:: ini
-
[formatter_accesslog]
format = %(message)s
diff --git a/docs/narr/paste.rst b/docs/narr/paste.rst
index 86b047aec..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
-----------
@@ -62,7 +62,7 @@ Take a look at the generated ``setup.py`` file for this project.
:language: python
:linenos:
-Note that the ``entry_point`` line in ``setup.py`` points at a string which
+Note that ``entry_points`` is assigned a string which
looks a lot like an ``.ini`` file. This string representation of an ``.ini``
file has a section named ``[paste.app_factory]``. Within this section, there
is a key named ``main`` (the entry point name) which has a value
@@ -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 fb62f4bd2..a168c24eb 100644
--- a/docs/narr/project.rst
+++ b/docs/narr/project.rst
@@ -80,13 +80,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 +95,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 ...
@@ -177,21 +177,21 @@ 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
@@ -216,19 +216,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
@@ -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
@@ -297,7 +297,7 @@ For example, your system might be configured to have an external IP address
``192.168.1.50``. If that's the case, if you use a browser running on the
same system as Pyramid, it will be able to access the application via
``http://127.0.0.1:6543/`` as well as via
-``http://129.168.1.50:6543/``. However, *other people* on other computers on
+``http://192.168.1.50:6543/``. However, *other people* on other computers on
the same network will also be able to visit your Pyramid application in their
browser by visiting ``http://192.168.1.50: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
@@ -459,20 +461,9 @@ Put a hash mark at the beginning of the ``pyramid_debugtoolbar`` line:
Then restart the application to see that the toolbar has been turned off.
Note that if you comment out the ``pyramid_debugtoolbar`` line, the ``#``
-*must* be in the first column. If you put the hash mark anywhere except the
-first column instead, for example like this:
-
-.. code-block:: ini
- :linenos:
-
- [app:main]
- ...
- pyramid.includes =
- #pyramid_debugtoolbar
-
-When you attempt to restart the application with a section like the above
-you'll receive an error that ends something like this, and the application
-will not start:
+*must* be in the first column. If you put it anywhere else,
+and then attempt to restart the application,
+you'll receive an error that ends something like this:
.. code-block:: text
@@ -703,7 +694,7 @@ work properly.
The ``setup.py`` file is a :term:`setuptools` setup file. It is meant to be
run directly from the command line to perform a variety of functions, such as
-testing your application, packaging, and distributing your application.
+testing, packaging, and distributing your application.
.. note::
diff --git a/docs/narr/renderers.rst b/docs/narr/renderers.rst
index ecf625251..08ebd881e 100644
--- a/docs/narr/renderers.rst
+++ b/docs/narr/renderers.rst
@@ -63,7 +63,6 @@ the ``renderer`` attribute. For example, this call to
with a view callable:
.. code-block:: python
- :linenos:
config.add_view('myproject.views.my_view', renderer='json')
@@ -73,13 +72,13 @@ 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 (see
-:ref:`adding_and_overriding_renderers`).
+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
response attributes (such as headers and the HTTP status code) by attaching a
-property to the ``request.response`` attribute See
-:ref:`request_response_attr`.
+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
@@ -166,7 +165,6 @@ The body of the response returned by such a view will be a string
representing the ``str()`` serialization of the return value:
.. code-block:: python
- :linenos:
{'content': 'Hello!'}
@@ -204,7 +202,6 @@ The body of the response returned by such a view will be a string
representing the JSON serialization of the return value:
.. code-block:: python
- :linenos:
'{"content": "Hello!"}'
@@ -294,9 +291,8 @@ with the object.
See :class:`pyramid.renderers.JSON` and
:ref:`adding_and_overriding_renderers` for more information.
-.. note::
-
- Serializing custom objects is a feature new in Pyramid 1.4.
+.. versionadded:: 1.4
+ Serializing custom objects.
.. index::
pair: renderer; JSONP
@@ -306,9 +302,7 @@ See :class:`pyramid.renderers.JSON` and
JSONP Renderer
~~~~~~~~~~~~~~
-.. note::
-
- This feature is new in Pyramid 1.1.
+.. versionadded:: 1.1
:class:`pyramid.renderers.JSONP` is a `JSONP
<http://en.wikipedia.org/wiki/JSONP>`_ renderer factory helper which
@@ -322,6 +316,7 @@ time "by hand". Configure a JSONP renderer using the
.. code-block:: python
from pyramid.config import Configurator
+ from pyramid.renderers import JSONP
config = Configurator()
config.add_renderer('jsonp', JSONP(param_name='callback'))
@@ -571,8 +566,6 @@ in :ref:`request_module`. For more information on the API of
Deprecated Mechanism to Vary Attributes of Rendered Responses
-------------------------------------------------------------
-.. warning:: This section describes behavior deprecated in Pyramid 1.1.
-
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
@@ -619,7 +612,6 @@ For example, to add a renderer which renders views which have a
``renderer`` attribute that is a path that ends in ``.jinja2``:
.. code-block:: python
- :linenos:
config.add_renderer('.jinja2', 'mypackage.MyJinja2Renderer')
@@ -689,12 +681,10 @@ There are essentially two different kinds of renderer factories:
:term:`package`.
Here's an example of the registration of a simple renderer factory via
-:meth:`~pyramid.config.Configurator.add_renderer`:
+:meth:`~pyramid.config.Configurator.add_renderer`, where ``config``
+is an instance of :meth:`pyramid.config.Configurator`:
.. code-block:: python
- :linenos:
-
- # config is an instance of pyramid.config.Configurator
config.add_renderer(name='amf', factory='my.package.MyAMFRenderer')
@@ -725,10 +715,8 @@ Here's an example of the registration of a more complicated renderer
factory, which expects to be passed a filesystem path:
.. code-block:: python
- :linenos:
- config.add_renderer(name='.jinja2',
- factory='my.package.MyJinja2Renderer')
+ config.add_renderer(name='.jinja2', factory='my.package.MyJinja2Renderer')
Adding the above code to your application startup will allow you to use the
``my.package.MyJinja2Renderer`` renderer factory implementation in view
@@ -769,7 +757,6 @@ extension for the same kinds of templates. For example, to associate the
:meth:`pyramid.config.Configurator.add_renderer` method:
.. code-block:: python
- :linenos:
config.add_renderer('.zpt', 'pyramid.chameleon_zpt.renderer_factory')
@@ -781,7 +768,6 @@ rendered via a Chameleon ZPT page template renderer, use a variation on the
following in your application's startup code:
.. code-block:: python
- :linenos:
config.add_renderer('.pt', 'mypackage.pt_renderer')
@@ -794,7 +780,6 @@ ones which do not possess a ``renderer`` attribute), pass ``None`` as
the ``name`` attribute to the renderer tag:
.. code-block:: python
- :linenos:
config.add_renderer(None, 'mypackage.json_renderer_factory')
@@ -823,8 +808,8 @@ sets an ``override_renderer`` attribute on the request itself, which is the
.. code-block:: python
:linenos:
- from pyramid.event import subscriber
- from pyramid.event import NewRequest
+ from pyramid.events import subscriber
+ from pyramid.events import NewRequest
@subscriber(NewRequest)
def set_xmlrpc_params(event):
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/security.rst b/docs/narr/security.rst
index 3a94b4f7d..e91e8c542 100644
--- a/docs/narr/security.rst
+++ b/docs/narr/security.rst
@@ -65,7 +65,7 @@ policies.
Enabling an Authorization Policy
--------------------------------
-By default, :app:`Pyramid` enables no authorization policy. All
+:app:`Pyramid` does not enable any authorization policy by default. All
views are accessible by completely anonymous users. In order to begin
protecting views from execution based on security settings, you need
to enable an authorization policy.
@@ -80,12 +80,11 @@ policy.
You must also enable an :term:`authentication policy` in order to enable the
authorization policy. This is because authorization, in general, depends
upon authentication. Use the
-:meth:`~pyramid.config.Configurator.set_authentication_policy` and method
+:meth:`~pyramid.config.Configurator.set_authentication_policy` method
during application setup to specify the authentication policy.
For example:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -98,7 +97,7 @@ For example:
config.set_authentication_policy(authn_policy)
config.set_authorization_policy(authz_policy)
-.. note:: the ``authentication_policy`` and ``authorization_policy``
+.. note:: The ``authentication_policy`` and ``authorization_policy``
arguments may also be passed to their respective methods mentioned above
as :term:`dotted Python name` values, each representing the dotted name
path to a suitable implementation global defined at Python module scope.
@@ -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'),
@@ -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 f7da7838e..fa4affd8a 100644
--- a/docs/narr/sessions.rst
+++ b/docs/narr/sessions.rst
@@ -29,7 +29,7 @@ during your :app:`Pyramid` configuration.
A very basic, insecure sample session factory implementation is
provided in the :app:`Pyramid` core. It uses a cookie to store
session information. This implementation has the following
-limitation:
+limitations:
- The session information in the cookies used by this implementation
is *not* encrypted, so it can be viewed by anyone with access to the
diff --git a/docs/narr/startup.rst b/docs/narr/startup.rst
index f5c741f52..3a9225032 100644
--- a/docs/narr/startup.rst
+++ b/docs/narr/startup.rst
@@ -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 b5bc5ec48..033f045a6 100644
--- a/docs/narr/subrequest.rst
+++ b/docs/narr/subrequest.rst
@@ -6,9 +6,7 @@
Invoking a Subrequest
=====================
-.. warning::
-
- This feature was added in Pyramid 1.4a1.
+.. versionadded:: 1.4
:app:`Pyramid` allows you to invoke a subrequest at any point during the
processing of a request. Invoking a subrequest allows you to obtain a
diff --git a/docs/narr/templates.rst b/docs/narr/templates.rst
index 1cec26fbc..d4cf20b93 100644
--- a/docs/narr/templates.rst
+++ b/docs/narr/templates.rst
@@ -150,7 +150,6 @@ string, then return that string as the body of a :app:`Pyramid`
For example, here's an example of using "raw" `Mako
<http://www.makotemplates.org/>`_ from within a :app:`Pyramid` :term:`view`:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -524,7 +523,7 @@ And ``templates/mytemplate.pt`` might look like so:
Using A Chameleon Macro Name Within a Renderer Name
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Sommetime you'd like to render a macro inside of a Chameleon ZPT template
+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
@@ -543,9 +542,7 @@ template as a :term:`renderer` like so:
The above will render only the ``bar`` macro defined within the ``foo.pt``
template instead of the entire template.
-.. note::
-
- This feature is new in Pyramid 1.4.
+.. versionadded:: 1.4
.. index::
single: Chameleon text templates
@@ -623,7 +620,7 @@ Debugging Templates
-------------------
A :exc:`NameError` exception resulting from rendering a template with an
-undefined variable (e.g. ``${wrong}``) might will end like this:
+undefined variable (e.g. ``${wrong}``) might end up looking like this:
.. code-block:: text
@@ -743,9 +740,7 @@ configure the template as a :term:`renderer` like so:
The above will render the ``bar`` def from within the ``foo.mak`` template
instead of the entire template.
-.. note::
-
- This feature is new in Pyramid 1.4.
+.. versionadded:: 1.4
.. index::
single: automatic reloading of templates
@@ -775,7 +770,7 @@ 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
diff --git a/docs/narr/testing.rst b/docs/narr/testing.rst
index 20017064b..0801a8eae 100644
--- a/docs/narr/testing.rst
+++ b/docs/narr/testing.rst
@@ -70,7 +70,7 @@ Test Set Up and Tear Down
--------------------------
:app:`Pyramid` uses a "global" (actually :term:`thread local`) data structure
-to hold on to two items: the current :term:`request` and the current
+to hold two items: the current :term:`request` and the current
:term:`application registry`. These data structures are available via the
:func:`pyramid.threadlocal.get_current_request` and
:func:`pyramid.threadlocal.get_current_registry` functions, respectively.
diff --git a/docs/narr/threadlocals.rst b/docs/narr/threadlocals.rst
index 909f643a0..5ff70565c 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
diff --git a/docs/narr/traversal.rst b/docs/narr/traversal.rst
index 8e7f93a1b..1234620c2 100644
--- a/docs/narr/traversal.rst
+++ b/docs/narr/traversal.rst
@@ -389,7 +389,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:
diff --git a/docs/narr/upgrading.rst b/docs/narr/upgrading.rst
index 20487b448..ca6dc565b 100644
--- a/docs/narr/upgrading.rst
+++ b/docs/narr/upgrading.rst
@@ -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 46f908b7c..bcd5fff94 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
@@ -38,7 +39,7 @@ application. A route has a *name*, which acts as an identifier to be used
for URL generation. The name also allows developers to associate a view
configuration with the route. A route also has a *pattern*, meant to match
against the ``PATH_INFO`` portion of a URL (the portion following the scheme
-and port, e.g. ``/foo/bar`` in the URL ``http://localhost:8080/foo/bar``). It
+and port, e.g. ``/foo/bar`` in the URL `<http://localhost:8080/foo/bar>`_). It
also optionally has a ``factory`` and a set of :term:`route predicate`
attributes.
@@ -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,20 +70,18 @@ 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
- # in your project's __init__.py (mypackage.__init__)
-
config.add_route('myroute', '/prefix/{one}/{two}')
config.scan('mypackage')
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
@@ -92,8 +90,6 @@ that references ``myroute`` as a ``route_name`` parameter:
.. code-block:: python
- # in your project's views.py module (mypackage.views)
-
from pyramid.view import view_config
from pyramid.response import Response
@@ -758,11 +754,8 @@ 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``.
-.. note::
-
- the ``static`` argument to
- :meth:`~pyramid.config.Configurator.add_route` is new as of :app:`Pyramid`
- 1.1.
+.. versionadded:: 1.1
+ the ``static`` argument to :meth:`~pyramid.config.Configurator.add_route`
.. index::
single: redirecting to slash-appended routes
@@ -821,7 +814,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.
@@ -856,12 +849,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
@@ -882,8 +875,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 \
@@ -906,7 +898,7 @@ routes configured in your application; for more information, see
Using a Route Prefix to Compose Applications
--------------------------------------------
-.. note:: This feature is new as of :app:`Pyramid` 1.2.
+.. versionadded:: 1.2
The :meth:`pyramid.config.Configurator.include` method allows configuration
statements to be included from separate files. See
diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst
index f00dae451..14a2fc807 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
@@ -293,7 +293,7 @@ configured view.
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 a
+ ``GET`` or ``POST`` variable) that has a name which matches the
supplied value.
If any value supplied has a ``=`` sign in it,
@@ -306,7 +306,7 @@ configured view.
consideration of keys and values in the ``request.params`` dictionary.
``match_param``
- .. note:: This feature is new as of :app:`Pyramid` 1.2.
+ .. versionadded:: 1.2
This param may be either a single string of the format "key=value" or a
dict of key/value pairs.
@@ -475,7 +475,7 @@ Adding View Configuration Using the ``@view_config`` Decorator
.. warning::
- Using this feature tends to slows down application startup slightly, as
+ Using this feature tends to slow down application startup slightly, as
more work is performed at application startup to scan for view
configuration declarations. For maximum startup performance, use the view
configuration method described in
@@ -488,7 +488,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,7 +502,6 @@ 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:
@@ -583,8 +581,7 @@ If your view callable is a function, it may be used as a function decorator:
return Response('edited!')
If your view callable is a class, the decorator can also be used as a class
-decorator in Python 2.6 and better (Python 2.5 and below do not support class
-decorators). All the arguments to the decorator are the same when applied
+decorator. All the arguments to the decorator are the same when applied
against a class as when they are applied against a function. For example:
.. code-block:: python
@@ -601,25 +598,6 @@ against a class as when they are applied against a function. For example:
def __call__(self):
return Response('hello')
-You can use the :class:`~pyramid.view.view_config` decorator as a simple
-callable to manually decorate classes in Python 2.5 and below without the
-decorator syntactic sugar, if you wish:
-
-.. code-block:: python
- :linenos:
-
- from pyramid.response import Response
- from pyramid.view import view_config
-
- class MyView(object):
- def __init__(self, request):
- self.request = request
-
- def __call__(self):
- return Response('hello')
-
- my_view = view_config(route_name='hello')(MyView)
-
More than one :class:`~pyramid.view.view_config` decorator can be stacked on
top of any number of others. Each decorator creates a separate view
registration. For example:
@@ -706,11 +684,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
@@ -724,9 +701,7 @@ configuration to take effect.
``@view_defaults`` Class Decorator
----------------------------------
-.. note::
-
- This feature is new in Pyramid 1.3.
+.. versionadded:: 1.3
If you use a class as a view, you can use the
:class:`pyramid.view.view_defaults` class decorator on the class to provide
@@ -952,7 +927,7 @@ for more information about how, and where to set these values.
Influencing HTTP Caching
------------------------
-.. note:: This feature is new in Pyramid 1.1.
+.. versionadded:: 1.1
When a non-``None`` ``http_cache`` argument is passed to a view
configuration, Pyramid will set ``Expires`` and ``Cache-Control`` response
diff --git a/docs/narr/views.rst b/docs/narr/views.rst
index 4f30bb7fa..5a7be15b0 100644
--- a/docs/narr/views.rst
+++ b/docs/narr/views.rst
@@ -176,7 +176,7 @@ exception` objects.
HTTP Exceptions
~~~~~~~~~~~~~~~
-All classes documented in the :mod:`pyramid.httpexceptions` module documented
+All :mod:`pyramid.httpexceptions` classes which are documented
as inheriting from the :class:`pyramid.httpexceptions.HTTPException` are
:term:`http exception` objects. Instances of an HTTP exception object may
either be *returned* or *raised* from within view code. In either case
@@ -227,8 +227,8 @@ equivalent to ``raise HTTPUnauthorized()``. Documentation which maps each
HTTP response code to its purpose and its associated HTTP exception object is
provided within :mod:`pyramid.httpexceptions`.
-.. note:: The :func:`~pyramid.httpexceptions.exception_response` function is
- new as of Pyramid 1.1.
+.. versionadded:: 1.1
+ The :func:`~pyramid.httpexceptions.exception_response` function.
How Pyramid Uses HTTP Exceptions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -236,12 +236,11 @@ How Pyramid Uses HTTP Exceptions
HTTP exceptions are meant to be used directly by application
developers. However, Pyramid itself will raise two HTTP exceptions at
various points during normal operations:
-:exc:`pyramid.httpexceptions.HTTPNotFound` and
-:exc:`pyramid.httpexceptions.HTTPForbidden`. Pyramid will raise the
-:exc:`~pyramid.httpexceptions.HTTPNotFound` exception are raised when it
-cannot find a view to service a request. Pyramid will raise the
-:exc:`~pyramid.httpexceptions.Forbidden` exception or when authorization was
-forbidden by a security policy.
+
+* :exc:`~pyramid.httpexceptions.HTTPNotFound`
+ gets raised when a view to service a request is not found.
+* :exc:`~pyramid.httpexceptions.HTTPForbidden`
+ gets raised when authorization was forbidden by a security policy.
If :exc:`~pyramid.httpexceptions.HTTPNotFound` is raised by Pyramid itself or
within view code, the result of the :term:`Not Found View` will be returned
@@ -265,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``:
@@ -354,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
@@ -525,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`.
@@ -538,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 a8c11acec..63a08adaa 100644
--- a/docs/narr/webob.rst
+++ b/docs/narr/webob.rst
@@ -251,7 +251,7 @@ API documentation for a multidict exists as
Dealing With A JSON-Encoded Request Body
++++++++++++++++++++++++++++++++++++++++
-.. note:: this feature is new as of Pyramid 1.1.
+.. versionadded:: 1.1
:attr:`pyramid.request.Request.json_body` is a property that returns a
:term:`JSON` -decoded representation of the request body. If the request
@@ -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:
@@ -491,7 +490,6 @@ reason for the error. For instance,
:class:`pyramid.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..5499cf4a5 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:
diff --git a/docs/tutorials/bfg/index.rst b/docs/tutorials/bfg/index.rst
index e68e63b0b..a50637279 100644
--- a/docs/tutorials/bfg/index.rst
+++ b/docs/tutorials/bfg/index.rst
@@ -47,7 +47,7 @@ Here's how to convert a :mod:`repoze.bfg` application to a
.. code-block:: bash
- $ bfgenv/bin/python setup.py test
+ $ $VENV/bin/python setup.py test
``bfgenv`` above will be the virtualenv into which you've installed
:mod:`repoze.bfg` 1.3.
@@ -62,7 +62,7 @@ Here's how to convert a :mod:`repoze.bfg` application to a
$ cd ~
$ virtualenv --no-site-packages pyramidenv
$ cd pyramidenv
- $ bin/easy_install pyramid
+ $ $VENV/bin/easy_install pyramid
#. Put a *copy* of your :mod:`repoze.bfg` application into a temporary
location (perhaps by checking a fresh copy of the application out
@@ -186,7 +186,7 @@ Here's how to convert a :mod:`repoze.bfg` application to a
.. code-block:: bash
$ cd /tmp/bfgapp
- $ ~/pyramidenv/bin/python setup.py test
+ $ $VENV/bin/python setup.py test
#. Fix any test failures.
diff --git a/docs/tutorials/modwsgi/index.rst b/docs/tutorials/modwsgi/index.rst
index a22f12610..e0021f8db 100644
--- a/docs/tutorials/modwsgi/index.rst
+++ b/docs/tutorials/modwsgi/index.rst
@@ -53,7 +53,7 @@ specific path information for commands and files.
.. code-block:: text
$ cd ~/modwsgi/env
- $ bin/easy_install pyramid
+ $ $VENV/bin/easy_install pyramid
#. Create and install your :app:`Pyramid` application. For the purposes of
this tutorial, we'll just be using the ``pyramid_starter`` application as
@@ -63,9 +63,9 @@ specific path information for commands and files.
.. code-block:: text
$ cd ~/modwsgi/env
- $ bin/pcreate -s starter myapp
+ $ $VENV/bin/pcreate -s starter myapp
$ cd myapp
- $ ../bin/python setup.py install
+ $ $VENV/bin/python setup.py install
#. Within the virtualenv directory (``~/modwsgi/env``), create a
script named ``pyramid.wsgi``. Give it these contents:
diff --git a/docs/tutorials/wiki/NOTE-relocatable.txt b/docs/tutorials/wiki/NOTE-relocatable.txt
index cec2639f3..e942caba8 100644
--- a/docs/tutorials/wiki/NOTE-relocatable.txt
+++ b/docs/tutorials/wiki/NOTE-relocatable.txt
@@ -1,5 +1,5 @@
We specifically use relative package references where possible so this demo
-works even if the user names their package (in the 'bin/paster create -t
+works even if the user names their package (in the '$VENV/bin/pcreate -s
zodb ...' step) something other than 'tutorial'.
Specifically:
diff --git a/docs/tutorials/wiki/authorization.rst b/docs/tutorials/wiki/authorization.rst
index e90dfe12d..460a852e0 100644
--- a/docs/tutorials/wiki/authorization.rst
+++ b/docs/tutorials/wiki/authorization.rst
@@ -32,9 +32,6 @@ Then we will add the login and logout feature:
* Add a "Logout" link to be shown when logged in and viewing or editing a page
(``view.pt``, ``edit.pt``).
-The source code for this tutorial stage can be browsed at
-`http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki/src/authorization/
-<http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki/src/authorization/>`_.
Access Control
--------------
@@ -58,8 +55,8 @@ returns one of these values:
- If the userid *does not* exist in the system, it will
return ``None``.
-For example, ``groupfinder('editor', request )`` returns ['group:editor'],
-``groupfinder('viewer', request)`` returns [], and ``groupfinder('admin', request)``
+For example, ``groupfinder('editor', request )`` returns ``['group:editor']``,
+``groupfinder('viewer', request)`` returns ``[]``, and ``groupfinder('admin', request)``
returns ``None``. We will use ``groupfinder()`` as an :term:`authentication policy`
"callback" that will provide the :term:`principal` or principals
for a user.
@@ -88,7 +85,7 @@ Add the following lines to the ``Wiki`` class:
:language: python
We import :data:`~pyramid.security.Allow`, an action that
-means that permission is allowed:, and
+means that permission is allowed, and
:data:`~pyramid.security.Everyone`, a special :term:`principal`
that is associated to all requests. Both are used in the
:term:`ACE` entries that make up the ACL.
@@ -96,8 +93,8 @@ that is associated to all requests. Both are used in the
The ACL is a list that needs to be named `__acl__` and be an
attribute of a class. We define an :term:`ACL` with two
:term:`ACE` entries: the first entry allows any user the `view`
-permission. The second entry allows the ``group:editors``
-principal the `edit` permission.
+permission, and the second entry allows the ``group:editors``
+principal the `edit` permission.
The ``Wiki`` class that contains the ACL is the :term:`resource`
constructor for the :term:`root` resource, which is
@@ -107,7 +104,7 @@ the ``context`` attribute.
It's only happenstance that we're assigning this ACL at class scope. An ACL
can be attached to an object *instance* too; this is how "row level security"
-can be achieved in :app:`Pyramid` applications. We actually only need *one*
+can be achieved in :app:`Pyramid` applications. We actually need only *one*
ACL for the entire system, however, because our security requirements are
simple, so this feature is not demonstrated. See
:ref:`assigning_acls` for more information about what an
@@ -147,18 +144,20 @@ machinery represented by this policy: it is required. The ``callback`` is the
Add permission declarations
~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Add a ``permission='edit'`` parameter to the ``@view_config``
-decorator for ``add_page()`` and ``edit_page()``, for example:
+Open ``tutorial/tutorial/views.py``. Add a ``permission='edit'`` parameter
+to the ``@view_config`` decorator for ``add_page()`` and
+``edit_page()``, for example:
.. code-block:: python
:linenos:
- :emphasize-lines: 2
+ :emphasize-lines: 3
- @view_config(route_name='add_page', renderer='templates/edit.pt',
- permission='edit')
+ @view_config(name='add_page', context='.models.Wiki',
+ renderer='templates/edit.pt',
+ permission='edit')
-(Only the highlighted line needs to be added.)
+(Only the highlighted line, along with its preceding comma,
+needs to be added.)
The result is that only users who possess the ``edit``
permission at the time of the request may invoke those two views.
@@ -170,10 +169,11 @@ decorator for ``view_wiki()`` and ``view_page()``, like this:
:linenos:
:emphasize-lines: 2
- @view_config(route_name='view_page', renderer='templates/view.pt',
+ @view_config(context='.models.Page', renderer='templates/view.pt',
permission='view')
-(Only the highlighted line needs to be added.)
+(Only the highlighted line, along with its preceding comma,
+needs to be added.)
This allows anyone to invoke these two views.
@@ -202,7 +202,8 @@ head of ``tutorial/tutorial/views.py``:
:emphasize-lines: 3,6-9,11
:language: python
-(Only the highlighted lines need to be added.)
+(Only the highlighted lines, with other necessary modifications,
+need to be added.)
:meth:`~pyramid.view.forbidden_view_config` will be used
to customize the default 403 Forbidden page.
@@ -217,16 +218,16 @@ Now add the ``login`` and ``logout`` views:
:linenos:
:language: python
-``login()`` is decorated with two decorators:
+``login()`` has two decorators:
- a ``@view_config`` decorator which associates it with the
``login`` route and makes it visible when we visit ``/login``,
- a ``@forbidden_view_config`` decorator which turns it into
- an :term:`forbidden view`. ``login()`` will be invoked
- when a users tries to execute a view callable that
- they are not allowed to. For example, if a user has not logged in
- and tries to add or edit a Wiki page, he will be shown the
- login form before being allowed to continue on.
+ a :term:`forbidden view`. ``login()`` will be invoked
+ when a user tries to execute a view callable for which they lack
+ authorization. For example, if a user has not logged in
+ and tries to add or edit a Wiki page, they will be shown the
+ login form before being allowed to continue.
The order of these two :term:`view configuration` decorators
is unimportant.
@@ -244,8 +245,8 @@ content:
.. literalinclude:: src/authorization/tutorial/templates/login.pt
:language: xml
-The above template is referred to within the login view we just
-added to ``views.py``.
+The above template is referred in the login view that we just added
+in ``views.py``.
Return a logged_in flag to the renderer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -259,7 +260,8 @@ Add the following line to the import at the head of
:emphasize-lines: 4
:language: python
-(Only the highlighted line needs to be added.)
+(Only the highlighted line and a trailing comma on the preceding
+line need to be added.)
Add a ``logged_in`` parameter to the return value of
``view_page()``, ``edit_page()`` and ``add_page()``,
@@ -274,11 +276,12 @@ like this:
edit_url = edit_url,
logged_in = authenticated_userid(request))
-(Only the highlighted line needs to be added.)
+(Only the highlighted line and a trailing comma on the preceding
+line need to be added.)
-:meth:`~pyramid.security.authenticated_userid()` will return None
-if the user is not authenticated, or some user id it the user
-is authenticated.
+:meth:`~pyramid.security.authenticated_userid()` will return ``None``
+if the user is not authenticated, or a user id if the user is
+authenticated.
Add a "Logout" link when logged in
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/tutorials/wiki/background.rst b/docs/tutorials/wiki/background.rst
index ac337abd5..6bbd5026e 100644
--- a/docs/tutorials/wiki/background.rst
+++ b/docs/tutorials/wiki/background.rst
@@ -11,7 +11,7 @@ Python web framework experience.
To code along with this tutorial, the developer will need a UNIX
machine with development tools (Mac OS X with XCode, any Linux or BSD
-variant, etc) *or* a Windows system of any kind.
+variant, etc.) *or* a Windows system of any kind.
.. warning::
diff --git a/docs/tutorials/wiki/basiclayout.rst b/docs/tutorials/wiki/basiclayout.rst
index da381ad7b..f9d4775ad 100644
--- a/docs/tutorials/wiki/basiclayout.rst
+++ b/docs/tutorials/wiki/basiclayout.rst
@@ -4,19 +4,16 @@ Basic Layout
The starter files generated by the ``zodb`` scaffold are basic, but
they provide a good orientation for the high-level patterns common to most
-:term:`traversal` -based :app:`Pyramid` (and :term:`ZODB` based) projects.
+:term:`traversal` -based :app:`Pyramid` (and :term:`ZODB` -based) projects.
-The source code for this tutorial stage can be browsed via
-`http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki/src/basiclayout/
-<http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki/src/basiclayout/>`_.
Application Configuration with ``__init__.py``
------------------------------------------------
A directory on disk can be turned into a Python :term:`package` by containing
an ``__init__.py`` file. Even if empty, this marks a directory as a Python
-package. Our application uses ``__init__.py`` as both a package marker, as
-well as to contain application configuration code.
+package. Our application uses ``__init__.py`` both as a package marker and
+to contain application configuration code.
When you run the application using the ``pserve`` command using the
``development.ini`` generated config file, the application configuration
@@ -31,14 +28,14 @@ point happens to be the ``main`` function within the file named
#. *Lines 1-3*. Perform some dependency imports.
-#. *Lines 6-8* Define a root factory for our Pyramid application.
+#. *Lines 6-8*. Define a root factory for our Pyramid application.
#. *Line 14*. We construct a :term:`Configurator` with a :term:`root
factory` and the settings keywords parsed by :term:`PasteDeploy`. The root
factory is named ``root_factory``.
-#. *Line 15*. Register a 'static view' which answers requests which start
- with URL path ``/static`` using the
+#. *Line 15*. Register a "static view" which answers requests whose URL path
+ start with ``/static`` using the
:meth:`pyramid.config.Configurator.add_static_view method`. This
statement registers a view that will serve up static assets, such as CSS
and image files, for us, in this case, at
@@ -47,16 +44,16 @@ point happens to be the ``main`` function within the file named
will be ``/static``. The second argument of this tag is the "path",
which is a relative :term:`asset specification`, so it finds the resources
it should serve within the ``static`` directory inside the ``tutorial``
- package. The scaffold could have alternately used an *absolute* asset
- specification as the path (``tutorial:static``) but it does not.
+ package. Alternatively the scaffold could have used an *absolute* asset
+ specification as the path (``tutorial:static``).
#. *Line 16*. Perform a :term:`scan`. A scan will find :term:`configuration
- decoration`, such as view configuration decorators (e.g. ``@view_config``)
+ decoration`, such as view configuration decorators (e.g., ``@view_config``)
in the source code of the ``tutorial`` package and will take actions based
on these decorators. We don't pass any arguments to
:meth:`~pyramid.config.Configurator.scan`, which implies that the scan
should take place in the current package (in this case, ``tutorial``).
- The scaffold could have equivalently said ``config.scan('tutorial')`` but
+ The scaffold could have equivalently said ``config.scan('tutorial')``, but
it chose to omit the package name argument.
#. *Line 17*. Use the
@@ -73,7 +70,7 @@ tree represents the site structure, but it *also* represents the
:term:`domain model` of the application, because each resource is a node
stored persistently in a :term:`ZODB` database. The ``models.py`` file is
where the ``zodb`` scaffold put the classes that implement our
-resource objects, each of which happens also to be a domain model object.
+resource objects, each of which also happens to be a domain model object.
Here is the source for ``models.py``:
@@ -82,7 +79,7 @@ Here is the source for ``models.py``:
:language: py
#. *Lines 4-5*. The ``MyModel`` :term:`resource` class is implemented here.
- Instances of this class will be capable of being persisted in :term:`ZODB`
+ Instances of this class are capable of being persisted in :term:`ZODB`
because the class inherits from the
:class:`persistent.mapping.PersistentMapping` class. The ``__parent__``
and ``__name__`` are important parts of the :term:`traversal` protocol.
@@ -140,7 +137,7 @@ Let's try to understand the components in this module:
indeed if you look in the ``templates`` directory of this package, you'll
see a ``mytemplate.pt`` template file, which renders the default home page
of the generated project. This asset specification is *relative* (to the
- view.py's current package). We could have alternately an used the
+ view.py's current package). Alternatively we could have used the
absolute asset specification ``tutorial:templates/mytemplate.pt``, but
chose to use the relative version.
@@ -168,7 +165,7 @@ opposed to the tutorial :term:`package` directory) looks like this:
.. literalinclude:: src/basiclayout/development.ini
:language: ini
-Note the existence of an ``[app:main]`` section which specifies our WSGI
+Note the existence of a ``[app:main]`` section which specifies our WSGI
application. Our ZODB database settings are specified as the
``zodbconn.uri`` setting within this section. This value, and the other
values within this section are passed as ``**settings`` to the ``main``
diff --git a/docs/tutorials/wiki/definingmodels.rst b/docs/tutorials/wiki/definingmodels.rst
index 2cbe691fa..49372179f 100644
--- a/docs/tutorials/wiki/definingmodels.rst
+++ b/docs/tutorials/wiki/definingmodels.rst
@@ -14,9 +14,6 @@ constructors". Both our Page and Wiki constructors will be class objects. A
single instance of the "Wiki" class will serve as a container for "Page"
objects, which will be instances of the "Page" class.
-The source code for this tutorial stage can be browsed via
-`http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki/src/models/
-<http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki/src/models/>`_.
Delete the Database
-------------------
@@ -36,7 +33,7 @@ Edit ``models.py``
.. note::
There is nothing automagically special about the filename ``models.py``. A
- project may have many models throughout its codebase in arbitrarily-named
+ project may have many models throughout its codebase in arbitrarily named
files. Files implementing models often have ``model`` in their filenames,
or they may live in a Python subpackage of your application package named
``models``, but this is only by convention.
@@ -59,7 +56,7 @@ of the root model is also always ``None``.
Then we'll add a ``Page`` class. This class should inherit from the
:class:`persistent.Persistent` class. We'll also give it an ``__init__``
method that accepts a single parameter named ``data``. This parameter will
-contain the :term:`ReStructuredText` body representing the wiki page content.
+contain the :term:`reStructuredText` body representing the wiki page content.
Note that ``Page`` objects don't have an initial ``__name__`` or
``__parent__`` attribute. All objects in a traversal graph must have a
``__name__`` and a ``__parent__`` attribute. We don't specify these here
diff --git a/docs/tutorials/wiki/definingviews.rst b/docs/tutorials/wiki/definingviews.rst
index 27f55da13..23ee142af 100644
--- a/docs/tutorials/wiki/definingviews.rst
+++ b/docs/tutorials/wiki/definingviews.rst
@@ -28,9 +28,6 @@ assumed to return a :term:`response` object.
We're going to define several :term:`view callable` functions, then wire them
into :app:`Pyramid` using some :term:`view configuration`.
-The source code for this tutorial stage can be browsed via
-`http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki/src/views/
-<http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki/src/views/>`_.
Declaring Dependencies in Our ``setup.py`` File
===============================================
@@ -74,6 +71,13 @@ and a final view named ``edit_page`` will allow a page to be edited.
The ``view_wiki`` view function
-------------------------------
+Here is the code for the ``view_wiki`` view function and its decorator, which
+will be added to ``views.py``:
+
+.. literalinclude:: src/views/tutorial/views.py
+ :lines: 12-14
+ :language: python
+
The ``view_wiki`` function will be configured to respond as the default view
callable for a Wiki resource. We'll provide it with a ``@view_config``
decorator which names the class ``tutorial.models.Wiki`` as its context.
@@ -87,16 +91,22 @@ The ``view_wiki`` view callable always redirects to the URL of a Page
resource named "FrontPage". To do so, it returns an instance of the
:class:`pyramid.httpexceptions.HTTPFound` class (instances of which implement
the :class:`pyramid.interfaces.IResponse` interface like
-:class:`pyramid.response.Response` does). The
-:meth:`pyramid.request.Request.resource_url` API.
+:class:`pyramid.response.Response` does).
:meth:`pyramid.request.Request.resource_url` constructs a URL to the
-``FrontPage`` page resource (e.g. ``http://localhost:6543/FrontPage``), and
+``FrontPage`` page resource (i.e., ``http://localhost:6543/FrontPage``), and
uses it as the "location" of the HTTPFound response, forming an HTTP
redirect.
The ``view_page`` view function
-------------------------------
+Here is the code for the ``view_page`` view function and its decorator, which
+will be added to ``views.py``:
+
+.. literalinclude:: src/views/tutorial/views.py
+ :lines: 16-33
+ :language: python
+
The ``view_page`` function will be configured to respond as the default view
of a Page resource. We'll provide it with a ``@view_config`` decorator which
names the class ``tutorial.models.Page`` as its context. This means that
@@ -104,7 +114,7 @@ when a Page resource is the context, and no :term:`view name` exists in the
request, this view will be used. We inform :app:`Pyramid` this view will use
the ``templates/view.pt`` template file as a ``renderer``.
-The ``view_page`` function generates the :term:`ReStructuredText` body of a
+The ``view_page`` function generates the :term:`reStructuredText` body of a
page (stored as the ``data`` attribute of the context passed to the view; the
context will be a Page resource) as HTML. Then it substitutes an HTML anchor
for each *WikiWord* reference in the rendered HTML using a compiled regular
@@ -143,6 +153,13 @@ callable. In the ``view_wiki`` view callable, we unconditionally return a
The ``add_page`` view function
------------------------------
+Here is the code for the ``add_page`` view function and its decorator, which
+will be added to ``views.py``:
+
+.. literalinclude:: src/views/tutorial/views.py
+ :lines: 35-50
+ :language: python
+
The ``add_page`` function will be configured to respond when the context
resource is a Wiki and the :term:`view name` is ``add_page``. We'll provide
it with a ``@view_config`` decorator which names the string ``add_page`` as
@@ -174,7 +191,7 @@ we're trying to add.
If the view rendering is *not* a result of a form submission (if the
expression ``'form.submitted' in request.params`` is ``False``), the view
renders a template. To do so, it generates a "save url" which the template
-use as the form post URL during rendering. We're lazy here, so we're trying
+uses as the form post URL during rendering. We're lazy here, so we're trying
to use the same template (``templates/edit.pt``) for the add view as well as
the page edit view. To do so, we create a dummy Page resource object in
order to satisfy the edit form's desire to have *some* page object exposed as
@@ -190,6 +207,13 @@ the page body, and save it into "our context" (the Wiki) using the
The ``edit_page`` view function
-------------------------------
+Here is the code for the ``edit_page`` view function and its decorator, which
+will be added to ``views.py``:
+
+.. literalinclude:: src/views/tutorial/views.py
+ :lines: 52-60
+ :language: python
+
The ``edit_page`` function will be configured to respond when the context is
a Page resource and the :term:`view name` is ``edit_page``. We'll provide it
with a ``@view_config`` decorator which names the string ``edit_page`` as its
@@ -293,7 +317,7 @@ Our templates name a single static asset named ``pylons.css``. We don't need
to create this file within our package's ``static`` directory because it was
provided at the time we created the project. This file is a little too long to
replicate within the body of this guide, however it is available `online
-<http://github.com/Pylons/pyramid/blob/master/docs/tutorials/wiki/src/views/tutorial/static/pylons.css>`_.
+<https://github.com/Pylons/pyramid/blob/master/docs/tutorials/wiki/src/views/tutorial/static/pylons.css>`_.
This CSS file will be accessed via
e.g. ``/static/pylons.css`` by virtue of the call to
diff --git a/docs/tutorials/wiki/design.rst b/docs/tutorials/wiki/design.rst
index b44ccb10e..eb785dd1c 100644
--- a/docs/tutorials/wiki/design.rst
+++ b/docs/tutorials/wiki/design.rst
@@ -4,7 +4,7 @@ Design
Following is a quick overview of our wiki application, to help
us understand the changes that we will be doing next in our
-default files generated by the ``zodb`` scafffold.
+default files generated by the ``zodb`` scaffold.
Overall
-------
@@ -37,8 +37,8 @@ Views
-----
There will be three views to handle the normal operations of adding,
-editing and viewing wiki pages, plus one view for the wiki front page.
-Two templates will be used, one for viewing, and one for both for adding
+editing, and viewing wiki pages, plus one view for the wiki front page.
+Two templates will be used, one for viewing, and one for both adding
and editing wiki pages.
The default templating systems in :app:`Pyramid` are
@@ -57,7 +57,7 @@ use to do this are below.
corresponding passwords.
- GROUPS, a dictionary mapping usernames to a
- list of groups they belong to.
+ list of groups to which they belong to.
- ``groupfinder``, an *authorization callback* that looks up
USERS and GROUPS. It will be provided in a new
diff --git a/docs/tutorials/wiki/distributing.rst b/docs/tutorials/wiki/distributing.rst
index ed0af222f..9c63cf0bd 100644
--- a/docs/tutorials/wiki/distributing.rst
+++ b/docs/tutorials/wiki/distributing.rst
@@ -12,13 +12,13 @@ On UNIX:
.. code-block:: text
- $ ../bin/python setup.py sdist
+ $ $VENV/bin/python setup.py sdist
On Windows:
.. code-block:: text
- c:\pyramidtut> ..\Scripts\python setup.py sdist
+ c:\pyramidtut> %VENV%\Scripts\python setup.py sdist
The output of such a command will be something like:
diff --git a/docs/tutorials/wiki/index.rst b/docs/tutorials/wiki/index.rst
index c918f8765..981d135c7 100644
--- a/docs/tutorials/wiki/index.rst
+++ b/docs/tutorials/wiki/index.rst
@@ -10,8 +10,9 @@ tutorial, the developer will have created a basic Wiki application with
authentication.
For cut and paste purposes, the source code for all stages of this
-tutorial can be browsed at `https://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki/src
-<https://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki/src>`_.
+tutorial can be browsed on GitHub at `docs/tutorials/wiki/src
+<https://github.com/Pylons/pyramid/tree/master/docs/tutorials/wiki/src>`_,
+which corresponds to the same location if you have Pyramid sources.
.. toctree::
:maxdepth: 2
diff --git a/docs/tutorials/wiki/installation.rst b/docs/tutorials/wiki/installation.rst
index 488ab1883..b51254b92 100644
--- a/docs/tutorials/wiki/installation.rst
+++ b/docs/tutorials/wiki/installation.rst
@@ -22,7 +22,7 @@ Preparation, UNIX
.. code-block:: text
- $ bin/easy_install docutils pyramid_tm pyramid_zodbconn \
+ $ $VENV/bin/easy_install docutils pyramid_tm pyramid_zodbconn \
pyramid_debugtoolbar nose coverage
Preparation, Windows
@@ -39,7 +39,7 @@ Preparation, Windows
.. code-block:: text
- c:\pyramidtut> Scripts\easy_install docutils pyramid_tm \
+ c:\pyramidtut> %VENV%\Scripts\easy_install docutils pyramid_tm \
pyramid_zodbconn pyramid_debugtoolbar nose coverage
.. _making_a_project:
@@ -59,13 +59,13 @@ On UNIX:
.. code-block:: text
- $ bin/pcreate -s zodb tutorial
+ $ $VENV/bin/pcreate -s zodb tutorial
On Windows:
.. code-block:: text
- c:\pyramidtut> Scripts\pcreate -s zodb tutorial
+ c:\pyramidtut> %VENV%\Scripts\pcreate -s zodb tutorial
.. note:: You don't have to call it `tutorial` -- the code uses
relative paths for imports and finding templates and static
@@ -91,14 +91,14 @@ On UNIX:
.. code-block:: text
$ cd tutorial
- $ ../bin/python setup.py develop
+ $ $VENV/bin/python setup.py develop
On Windows:
.. code-block:: text
C:\pyramidtut> cd tutorial
- C:\pyramidtut\tutorial> ..\Scripts\python setup.py develop
+ C:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py develop
.. _running_tests:
@@ -112,13 +112,13 @@ On UNIX:
.. code-block:: text
- $ ../bin/python setup.py test -q
+ $ $VENV/bin/python setup.py test -q
On Windows:
.. code-block:: text
- c:\pyramidtut\tutorial> ..\Scripts\python setup.py test -q
+ c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py test -q
Expose Test Coverage Information
================================
@@ -133,13 +133,13 @@ On UNIX:
.. code-block:: text
- $ ../bin/nosetests --cover-package=tutorial --cover-erase --with-coverage
+ $ $VENV/bin/nosetests --cover-package=tutorial --cover-erase --with-coverage
On Windows:
.. code-block:: text
- c:\pyramidtut\tutorial> ..\Scripts\nosetests --cover-package=tutorial ^
+ c:\pyramidtut\tutorial> %VENV%\Scripts\nosetests --cover-package=tutorial ^
--cover-erase --with-coverage
Looks like the code in the ``zodb`` scaffold for ZODB projects is
@@ -157,13 +157,13 @@ On UNIX:
.. code-block:: text
- $ ../bin/pserve development.ini --reload
+ $ $VENV/bin/pserve development.ini --reload
On Windows:
.. code-block:: text
- c:\pyramidtut\tutorial> ..\Scripts\pserve development.ini --reload
+ c:\pyramidtut\tutorial> %VENV%\Scripts\pserve development.ini --reload
.. note::
@@ -193,8 +193,7 @@ assumptions:
.. note::
- :app:`Pyramid` supports any persistent storage mechanism (e.g. a SQL
- database or filesystem files, etc). :app:`Pyramid` also supports an
- additional mechanism to map URLs to code (:term:`URL dispatch`). However,
- for the purposes of this tutorial, we'll only be using traversal and ZODB.
-
+ :app:`Pyramid` supports any persistent storage mechanism (e.g., a SQL
+ database or filesystem files). :app:`Pyramid` also supports an additional
+ mechanism to map URLs to code (:term:`URL dispatch`). However, for the
+ purposes of this tutorial, we'll only be using traversal and ZODB.
diff --git a/docs/tutorials/wiki/src/authorization/setup.py b/docs/tutorials/wiki/src/authorization/setup.py
index 3164fd724..5d87fedbf 100644
--- a/docs/tutorials/wiki/src/authorization/setup.py
+++ b/docs/tutorials/wiki/src/authorization/setup.py
@@ -3,8 +3,10 @@ import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, 'README.txt')).read()
-CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = [
'pyramid',
diff --git a/docs/tutorials/wiki/src/basiclayout/setup.py b/docs/tutorials/wiki/src/basiclayout/setup.py
index 4998be902..75ba02611 100644
--- a/docs/tutorials/wiki/src/basiclayout/setup.py
+++ b/docs/tutorials/wiki/src/basiclayout/setup.py
@@ -3,8 +3,10 @@ import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, 'README.txt')).read()
-CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = [
'pyramid',
diff --git a/docs/tutorials/wiki/src/models/setup.py b/docs/tutorials/wiki/src/models/setup.py
index 4998be902..75ba02611 100644
--- a/docs/tutorials/wiki/src/models/setup.py
+++ b/docs/tutorials/wiki/src/models/setup.py
@@ -3,8 +3,10 @@ import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, 'README.txt')).read()
-CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = [
'pyramid',
diff --git a/docs/tutorials/wiki/src/tests/setup.py b/docs/tutorials/wiki/src/tests/setup.py
index 702d34c4c..5ff7b545c 100644
--- a/docs/tutorials/wiki/src/tests/setup.py
+++ b/docs/tutorials/wiki/src/tests/setup.py
@@ -3,8 +3,10 @@ import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, 'README.txt')).read()
-CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = [
'pyramid',
diff --git a/docs/tutorials/wiki/src/views/setup.py b/docs/tutorials/wiki/src/views/setup.py
index 3164fd724..5d87fedbf 100644
--- a/docs/tutorials/wiki/src/views/setup.py
+++ b/docs/tutorials/wiki/src/views/setup.py
@@ -3,8 +3,10 @@ import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, 'README.txt')).read()
-CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = [
'pyramid',
diff --git a/docs/tutorials/wiki/tests.rst b/docs/tutorials/wiki/tests.rst
index 7a019dd04..e40dc286b 100644
--- a/docs/tutorials/wiki/tests.rst
+++ b/docs/tutorials/wiki/tests.rst
@@ -6,9 +6,6 @@ We will now add tests for the models and the views and a few functional
tests in the ``tests.py``. Tests ensure that an application works, and
that it continues to work after some changes are made in the future.
-The source code for this tutorial stage can be browsed via
-`http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki/src/tests/
-<http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki/src/tests/>`_.
Test the Models
===============
@@ -62,7 +59,7 @@ Change the ``requires`` list in ``setup.py`` to include ``WebTest``.
.. literalinclude:: src/tests/setup.py
:linenos:
:language: python
- :lines: 9-19
+ :lines: 11-21
:emphasize-lines: 10
After we've added a dependency on WebTest in ``setup.py``, we need to rerun
@@ -74,13 +71,13 @@ On UNIX:
.. code-block:: text
- $ ../bin/python setup.py develop
+ $ $VENV/bin/python setup.py develop
On Windows:
.. code-block:: text
- c:\pyramidtut\tutorial> ..\Scripts\python setup.py develop
+ c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py develop
Once that command has completed successfully, we can run the tests
themselves:
@@ -89,13 +86,13 @@ On UNIX:
.. code-block:: text
- $ ../bin/python setup.py test -q
+ $ $VENV/bin/python setup.py test -q
On Windows:
.. code-block:: text
- c:\pyramidtut\tutorial> ..\Scripts\python setup.py test -q
+ c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py test -q
The expected result looks something like:
diff --git a/docs/tutorials/wiki2/authorization.rst b/docs/tutorials/wiki2/authorization.rst
index 321f1f9c4..5ede26920 100644
--- a/docs/tutorials/wiki2/authorization.rst
+++ b/docs/tutorials/wiki2/authorization.rst
@@ -36,9 +36,6 @@ Then we will add the login and logout feature:
* Add a "Logout" link to be shown when logged in and viewing or editing a page
(``view.pt``, ``edit.pt``).
-The source code for this tutorial stage can be browsed at
-`http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src/authorization/
-<http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src/authorization/>`_.
Access Control
--------------
diff --git a/docs/tutorials/wiki2/basiclayout.rst b/docs/tutorials/wiki2/basiclayout.rst
index e8874784c..6d6287126 100644
--- a/docs/tutorials/wiki2/basiclayout.rst
+++ b/docs/tutorials/wiki2/basiclayout.rst
@@ -6,9 +6,6 @@ The starter files generated by the ``alchemy`` scaffold are very basic, but
they provide a good orientation for the high-level patterns common to most
:term:`url dispatch` -based :app:`Pyramid` projects.
-The source code for this tutorial stage can be browsed at
-`http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src/basiclayout/
-<http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src/basiclayout/>`_.
Application Configuration with ``__init__.py``
----------------------------------------------
@@ -46,9 +43,9 @@ above is executed. It accepts some settings and returns a :term:`WSGI`
application. (See :ref:`startup_chapter` for more about ``pserve``.)
The main function first creates a :term:`SQLAlchemy` database engine using
-``engine_from_config`` from the ``sqlalchemy.`` prefixed settings in the
-``development.ini`` file's ``[app:main]`` section. This will be a URI
-(something like ``sqlite://``):
+:func:`sqlalchemy.engine_from_config` from the ``sqlalchemy.`` prefixed
+settings in the ``development.ini`` file's ``[app:main]`` section.
+This will be a URI (something like ``sqlite://``):
.. literalinclude:: src/basiclayout/tutorial/__init__.py
:lines: 13
@@ -135,11 +132,11 @@ Finally, ``main`` is finished configuring things, so it uses the
View Declarations via ``views.py``
----------------------------------
-Mapping a :term:`route` to code that will be executed when a match for
-the route's pattern occurs is done by registering a :term:`view
-configuration`. Our application uses the
-:meth:`pyramid.view.view_config` decorator to map view callables to
-each route, thereby mapping URL patterns to code.
+Arguably, the main function of a web framework is mapping each URL
+patterns, see :term:`route`, to code, see :term:`view callable`, that is
+executed when the requested URL matches the corresponding :term:`route`. Our
+application uses the :meth:`pyramid.view.view_config` decorator to perform
+this mapping.
Open ``tutorial/tutorial/views.py``. It should already contain the following:
@@ -229,13 +226,12 @@ To give a simple example of a model class, we define one named ``MyModel``:
:linenos:
:language: py
-Our example model has an ``__init__`` method that takes a two arguments
+Our example model has an ``__init__`` method that takes two arguments
(``name``, and ``value``). It stores these values as ``self.name`` and
-``self.value``
-within the ``__init__`` function itself. The ``MyModel`` class also has a
-``__tablename__`` attribute. This informs SQLAlchemy which table to use to
-store the data representing instances of this class.
+``self.value`` within the ``__init__`` function itself. The ``MyModel`` class
+also has a ``__tablename__`` attribute. This informs SQLAlchemy which table
+to use to store the data representing instances of this class.
-That's about all there is to it to models, views, and initialization code in
+That's about all there is to it with models, views, and initialization code in
our stock application.
diff --git a/docs/tutorials/wiki2/definingmodels.rst b/docs/tutorials/wiki2/definingmodels.rst
index dca6238dd..60427a911 100644
--- a/docs/tutorials/wiki2/definingmodels.rst
+++ b/docs/tutorials/wiki2/definingmodels.rst
@@ -6,9 +6,6 @@ The first change we'll make to our stock ``pcreate``-generated application will
be to define a :term:`domain model` constructor representing a wiki page.
We'll do this inside our ``models.py`` file.
-The source code for this tutorial stage can be browsed at
-`http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src/models/
-<http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src/models/>`_.
Making Edits to ``models.py``
-----------------------------
@@ -37,7 +34,7 @@ sample and we're not going to use it.
Then, we added a ``Page`` class. Because this is a SQLAlchemy application,
this class inherits from an instance of
-:class:`sqlalchemy.ext.declarative.declarative_base`.
+:func:`sqlalchemy.ext.declarative.declarative_base`.
.. literalinclude:: src/models/tutorial/models.py
:pyobject: Page
@@ -48,9 +45,10 @@ As you can see, our ``Page`` class has a class level attribute
``__tablename__`` which equals the string ``'pages'``. This means that
SQLAlchemy will store our wiki data in a SQL table named ``pages``. Our
``Page`` class will also have class-level attributes named ``id``, ``name`` and
-``data`` (all instances of :class:`sqlalchemy.Column`). These will map to
-columns in the ``pages`` table. The ``id`` attribute will be the primary key
-in the table. The ``name`` attribute will be a text attribute, each value of
+``data`` (all instances of :class:`sqlalchemy.schema.Column`).
+These will map to columns in the ``pages`` table.
+The ``id`` attribute will be the primary key in the table.
+The ``name`` attribute will be a text attribute, each value of
which needs to be unique within the column. The ``data`` attribute is a text
attribute that will hold the body of each page.
@@ -80,8 +78,6 @@ following:
Installing the Project and re-initializing the Database
-------------------------------------------------------
-Redo the steps in :ref:`installing_project_in_dev_mode`.
-
Because our model has changed, in order to reinitialize the database, we need
to rerun the ``initialize_tutorial_db`` command to pick up the changes you've made
to both the models.py file and to the initializedb.py file.
diff --git a/docs/tutorials/wiki2/definingviews.rst b/docs/tutorials/wiki2/definingviews.rst
index 8714927c3..9894bcb08 100644
--- a/docs/tutorials/wiki2/definingviews.rst
+++ b/docs/tutorials/wiki2/definingviews.rst
@@ -6,19 +6,13 @@ A :term:`view callable` in a :app:`Pyramid` application is typically a simple
Python function that accepts a single parameter named :term:`request`. A
view callable is assumed to return a :term:`response` object.
-The request object passed to every view that is called as the result of a
-route match has an attribute named ``matchdict`` that contains the elements
-placed into the URL by the ``pattern`` of a ``route`` statement. For
-instance, if a call to :meth:`pyramid.config.Configurator.add_route` in
-``__init__.py`` had the pattern ``{one}/{two}``, and the URL at
-``http://example.com/foo/bar`` was invoked, matching this pattern, the
-``matchdict`` dictionary attached to the request passed to the view would
-have a ``'one'`` key with the value ``'foo'`` and a ``'two'`` key with the
-value ``'bar'``.
-
-The source code for this tutorial stage can be browsed at
-`http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src/views/
-<http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src/views/>`_.
+The request object has a dictionary as an attribute named ``matchdict``.
+A ``matchdict`` maps the placeholders in the matching URL ``pattern`` to the substrings
+of the :term:`request` ed URL. For instance, if a call to
+:meth:`pyramid.config.Configurator.add_route` has the pattern
+``{one}/{two}``, and a user visits ``http://example.com/foo/bar``, our pattern would be
+matched and the ``matchdict`` would look like: ``{'one':'foo', 'two':'bar'}``
+
Declaring Dependencies in Our ``setup.py`` File
===============================================
@@ -36,7 +30,7 @@ Open ``tutorial/setup.py`` and edit it to look like the following:
.. literalinclude:: src/views/setup.py
:linenos:
:language: python
- :emphasize-lines: 17
+ :emphasize-lines: 19
(Only the highlighted line needs to be added.)
@@ -55,14 +49,14 @@ On UNIX:
.. code-block:: text
$ cd tutorial
- $ ../bin/python setup.py develop
+ $ $VENV/bin/python setup.py develop
On Windows:
.. code-block:: text
c:\pyramidtut> cd tutorial
- c:\pyramidtut\tutorial> ..\Scripts\python setup.py develop
+ c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py develop
Success executing this command will end with a line to the console something
like::
@@ -129,7 +123,7 @@ The ``view_page`` view function
-------------------------------
``view_page()`` is used to display a single page of our
-wiki. It renders the :term:`ReStructuredText` body of a page (stored as
+wiki. It renders the :term:`reStructuredText` body of a page (stored as
the ``data`` attribute of a ``Page`` model object) as HTML. Then it substitutes an
HTML anchor for each *WikiWord* reference in the rendered HTML using a
compiled regular expression.
@@ -155,10 +149,9 @@ We then generate an edit URL (because it's easier to do here than in the
template), and we return a dictionary with a number of arguments. The fact
that ``view_page()`` returns a dictionary (as opposed to a :term:`response`
object) is a cue to :app:`Pyramid` that it should try to use a :term:`renderer`
-associated with the view configuration to render a template. In our case,
-the template which will be rendered will be the ``templates/view.pt``
-template, as indicated in the ``@view_config`` decorator that is applied to
-``view_page()``.
+associated with the view configuration to render a response. In our case,
+the renderer used will be the ``templates/view.pt`` template, as indicated in
+the ``@view_config`` decorator that is applied to ``view_page()``.
The ``add_page`` view function
------------------------------
@@ -290,7 +283,7 @@ Our templates name a single static asset named ``pylons.css``. We don't need
to create this file within our package's ``static`` directory because it was
provided at the time we created the project. This file is a little too long
to replicate within the body of this guide, however it is available `online
-<http://github.com/Pylons/pyramid/blob/master/docs/tutorials/wiki2/src/views/tutorial/static/pylons.css>`_.
+<https://github.com/Pylons/pyramid/blob/master/docs/tutorials/wiki2/src/views/tutorial/static/pylons.css>`_.
This CSS file will be accessed via
e.g. ``http://localhost:6543/static/pylons.css`` by virtue of the call to
diff --git a/docs/tutorials/wiki2/distributing.rst b/docs/tutorials/wiki2/distributing.rst
index 96293603c..3b048a141 100644
--- a/docs/tutorials/wiki2/distributing.rst
+++ b/docs/tutorials/wiki2/distributing.rst
@@ -12,13 +12,13 @@ On UNIX:
.. code-block:: text
- $ ../bin/python setup.py sdist
+ $ $VENV/bin/python setup.py sdist
On Windows:
.. code-block:: text
- c:\pyramidtut> ..\Scripts\python setup.py sdist
+ c:\pyramidtut> %VENV%\Scripts\python setup.py sdist
The output of such a command will be something like:
diff --git a/docs/tutorials/wiki2/index.rst b/docs/tutorials/wiki2/index.rst
index bbc2fb96e..0a614cb23 100644
--- a/docs/tutorials/wiki2/index.rst
+++ b/docs/tutorials/wiki2/index.rst
@@ -9,9 +9,9 @@ tutorial is finished, the developer will have created a basic Wiki
application with authentication.
For cut and paste purposes, the source code for all stages of this
-tutorial can be browsed at
-`https://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src
-<https://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src>`_.
+tutorial can be browsed on GitHub at `docs/tutorials/wiki2/src
+<https://github.com/Pylons/pyramid/tree/master/docs/tutorials/wiki2/src>`_,
+which corresponds to the same location if you have Pyramid sources.
.. toctree::
:maxdepth: 2
diff --git a/docs/tutorials/wiki2/installation.rst b/docs/tutorials/wiki2/installation.rst
index 9fa01d513..9590e4abe 100644
--- a/docs/tutorials/wiki2/installation.rst
+++ b/docs/tutorials/wiki2/installation.rst
@@ -2,63 +2,138 @@
Installation
============
-Preparation
-===========
+Before You Begin
+================
+
+This tutorial assumes that you have already followed the steps in
+:ref:`installing_chapter`, thereby satisfying the following
+requirements.
+
+* Python interpreter is installed on your operating system
+* :term:`setuptools` or :term:`distribute` is installed
+* :term:`virtualenv` is installed
+
+Create and Use a Virtual Python Environment
+-------------------------------------------
+
+Next let's create a `virtualenv` workspace for our project. We will
+use the `VENV` environment variable instead of absolute path of the
+virtual environment.
+
+**On UNIX:**
+
+.. code-block:: text
+
+ $ export VENV=~/pyramidtut
+ $ virtualenv --no-site-packages $VENV
+ New python executable in /home/foo/env/bin/python
+ Installing setuptools.............done.
+
+**On Windows**:
-Follow the steps in :ref:`installing_chapter`, but name the virtualenv
-directory ``pyramidtut``.
+Set the `VENV` environment variable.
-Preparation, UNIX
------------------
+.. code-block:: text
+
+ c:\> set VENV=c:\pyramidtut
+
+Versions of Python use different paths, so you will need to adjust the
+path to the command for your Python version.
+
+Python 2.7:
+
+.. code-block:: text
-#. Install SQLite3 and its development packages if you don't already
- have them installed. Usually this is via your system's package
- manager. On a Debian system, this would be:
+ c:\> c:\Python27\Scripts\virtualenv --no-site-packages %VENV%
- .. code-block:: text
+Python 3.2:
- $ sudo apt-get install libsqlite3-dev
+.. code-block:: text
-#. Switch to the ``pyramidtut`` directory:
+ c:\> c:\Python32\Scripts\virtualenv --no-site-packages %VENV%
- .. code-block:: text
+Install Pyramid Into the Virtual Python Environment
+---------------------------------------------------
- $ cd pyramidtut
+**On UNIX:**
+.. code-block:: text
-Preparation, Windows
---------------------
+ $ $VENV/bin/easy_install pyramid
-#. Switch to the ``pyramidtut`` directory:
+**On Windows**:
+
+.. code-block:: text
- .. code-block:: text
+ c:\env> %VENV%\Scripts\easy_install pyramid
- c:\> cd pyramidtut
+Install SQLite3 and Its Development Packages
+--------------------------------------------
+
+If you used a package manager to install your Python or if you compiled
+your Python from source, then you must install SQLite3 and its
+development packages. If you downloaded your Python as an installer
+from python.org, then you already have it installed and can proceed to
+the next section :ref:`sql_making_a_project`..
+
+If you need to install the SQLite3 packages, then, for example, using
+the Debian system and apt-get, the command would be the following:
+
+.. code-block:: text
+
+ $ sudo apt-get install libsqlite3-dev
+
+Change Directory to Your Virtual Python Environment
+---------------------------------------------------
+
+Change directory to the ``pyramidtut`` directory.
+
+**On UNIX**:
+
+.. code-block:: text
+
+ $ cd pyramidtut
+
+**On Windows**:
+
+.. code-block:: text
+
+ c:\> cd pyramidtut
.. _sql_making_a_project:
Making a Project
================
-Your next step is to create a project. For this tutorial, we will use the
-:term:`scaffold` named ``alchemy``, which generates an application
-that uses :term:`SQLAlchemy` and :term:`URL dispatch`. :app:`Pyramid`
-supplies a variety of scaffolds to generate sample projects.
+Your next step is to create a project. For this tutorial we will use
+the :term:`scaffold` named ``alchemy`` which generates an application
+that uses :term:`SQLAlchemy` and :term:`URL dispatch`.
+
+:app:`Pyramid` supplies a variety of scaffolds to generate sample
+projects. We will use `pcreate`—a script that comes with Pyramid to
+quickly and easily generate scaffolds usually with a single command—to
+create the scaffold for our project.
+
+By passing in `alchemy` into the `pcreate` command, the script creates
+the files needed to use SQLAlchemy. By passing in our application name
+`tutorial`, the script inserts that application name into all the
+required files. For example, `pcreate` creates the
+``initialize_tutorial_db`` in the ``pyramidtut/bin`` directory.
The below instructions assume your current working directory is the
"virtualenv" named "pyramidtut".
-On UNIX:
+**On UNIX**:
.. code-block:: text
- $ bin/pcreate -s alchemy tutorial
+ $ $VENV/bin/pcreate -s alchemy tutorial
-On Windows:
+**On Windows**:
.. code-block:: text
- c:\pyramidtut> Scripts\pcreate -s alchemy tutorial
+ c:\pyramidtut> %VENV%\pcreate -s alchemy tutorial
.. note:: If you are using Windows, the ``alchemy``
scaffold may not deal gracefully with installation into a
@@ -66,11 +141,10 @@ On Windows:
startup problems, try putting both the virtualenv and the project
into directories that do not contain spaces in their paths.
-
.. _installing_project_in_dev_mode:
-Installing the Project in "Development Mode"
-============================================
+Installing the Project in Development Mode
+==========================================
In order to do development on the project easily, you must "register"
the project as a development egg in your workspace using the
@@ -78,22 +152,23 @@ the project as a development egg in your workspace using the
directory you created in :ref:`sql_making_a_project`, and run the
``setup.py develop`` command using the virtualenv Python interpreter.
-On UNIX:
+**On UNIX**:
.. code-block:: text
$ cd tutorial
- $ ../bin/python setup.py develop
+ $ $VENV/bin/python setup.py develop
-On Windows:
+**On Windows**:
.. code-block:: text
c:\pyramidtut> cd tutorial
- c:\pyramidtut\tutorial> ..\Scripts\python setup.py develop
+ c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py develop
-Success executing this command will end with a line to the console something
-like::
+The console will show `setup.py` checking for packages and installing
+missing packages. Success executing this command will show a line like
+the following::
Finished processing dependencies for tutorial==0.0
@@ -105,17 +180,17 @@ Running the Tests
After you've installed the project in development mode, you may run
the tests for the project.
-On UNIX:
+**On UNIX**:
.. code-block:: text
- $ ../bin/python setup.py test -q
+ $ $VENV/bin/python setup.py test -q
-On Windows:
+**On Windows**:
.. code-block:: text
- c:\pyramidtut\tutorial> ..\Scripts\python setup.py test -q
+ c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py test -q
For a successful test run, you should see output that ends like this::
@@ -137,32 +212,32 @@ tests.
To get this functionality working, we'll need to install the ``nose`` and
``coverage`` packages into our ``virtualenv``:
-On UNIX:
+**On UNIX**:
.. code-block:: text
- $ ../bin/easy_install nose coverage
+ $ $VENV/bin/easy_install nose coverage
-On Windows:
+**On Windows**:
.. code-block:: text
- c:\pyramidtut\tutorial> ..\Scripts\easy_install nose coverage
+ c:\pyramidtut\tutorial> %VENV%\Scripts\easy_install nose coverage
Once ``nose`` and ``coverage`` are installed, we can actually run the
coverage tests.
-On UNIX:
+**On UNIX**:
.. code-block:: text
- $ ../bin/nosetests --cover-package=tutorial --cover-erase --with-coverage
+ $ $VENV/bin/nosetests --cover-package=tutorial --cover-erase --with-coverage
-On Windows:
+**On Windows**:
.. code-block:: text
- c:\pyramidtut\tutorial> ..\Scripts\nosetests --cover-package=tutorial \
+ c:\pyramidtut\tutorial> %VENV%\Scripts\nosetests --cover-package=tutorial \
--cover-erase --with-coverage
If successful, you will see output something like this::
@@ -196,17 +271,17 @@ script` to initialize our database.
Type the following command, make sure you are still in the ``tutorial``
directory (the directory with a ``development.ini`` in it):
-On UNIX:
+**On UNIX**:
.. code-block:: text
- $ ../bin/initialize_tutorial_db development.ini
+ $ $VENV/bin/initialize_tutorial_db development.ini
-On Windows:
+**On Windows**:
.. code-block:: text
- c:\pyramidtut\tutorial> ..\Scripts\initialize_tutorial_db development.ini
+ c:\pyramidtut\tutorial> %VENV%\Scripts\initialize_tutorial_db development.ini
The output to your console should be something like this::
@@ -244,17 +319,17 @@ Starting the Application
Start the application.
-On UNIX:
+**On UNIX**:
.. code-block:: text
- $ ../bin/pserve development.ini --reload
+ $ $VENV/bin/pserve development.ini --reload
-On Windows:
+**On Windows**:
.. code-block:: text
- c:\pyramidtut\tutorial> ..\Scripts\pserve development.ini --reload
+ c:\pyramidtut\tutorial> %VENV%\Scripts\pserve development.ini --reload
If successful, you will see something like this on your console::
@@ -292,4 +367,3 @@ the following assumptions:
mechanism to map URLs to code (:term:`traversal`). However, for the
purposes of this tutorial, we'll only be using url dispatch and
SQLAlchemy.
-
diff --git a/docs/tutorials/wiki2/src/authorization/README.txt b/docs/tutorials/wiki2/src/authorization/README.txt
index 141851285..68f430110 100644
--- a/docs/tutorials/wiki2/src/authorization/README.txt
+++ b/docs/tutorials/wiki2/src/authorization/README.txt
@@ -6,9 +6,9 @@ Getting Started
- cd <directory containing this file>
-- $venv/bin/python setup.py develop
+- $VENV/bin/python setup.py develop
-- $venv/bin/initialize_tutorial_db development.ini
+- $VENV/bin/initialize_tutorial_db development.ini
-- $venv/bin/pserve development.ini
+- $VENV/bin/pserve development.ini
diff --git a/docs/tutorials/wiki2/src/authorization/setup.py b/docs/tutorials/wiki2/src/authorization/setup.py
index 36668dd33..e8fa8f396 100644
--- a/docs/tutorials/wiki2/src/authorization/setup.py
+++ b/docs/tutorials/wiki2/src/authorization/setup.py
@@ -3,8 +3,10 @@ import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, 'README.txt')).read()
-CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = [
'pyramid',
diff --git a/docs/tutorials/wiki2/src/basiclayout/README.txt b/docs/tutorials/wiki2/src/basiclayout/README.txt
index 141851285..68f430110 100644
--- a/docs/tutorials/wiki2/src/basiclayout/README.txt
+++ b/docs/tutorials/wiki2/src/basiclayout/README.txt
@@ -6,9 +6,9 @@ Getting Started
- cd <directory containing this file>
-- $venv/bin/python setup.py develop
+- $VENV/bin/python setup.py develop
-- $venv/bin/initialize_tutorial_db development.ini
+- $VENV/bin/initialize_tutorial_db development.ini
-- $venv/bin/pserve development.ini
+- $VENV/bin/pserve development.ini
diff --git a/docs/tutorials/wiki2/src/basiclayout/setup.py b/docs/tutorials/wiki2/src/basiclayout/setup.py
index a09bf756a..e7d318128 100644
--- a/docs/tutorials/wiki2/src/basiclayout/setup.py
+++ b/docs/tutorials/wiki2/src/basiclayout/setup.py
@@ -3,8 +3,10 @@ import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, 'README.txt')).read()
-CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = [
'pyramid',
diff --git a/docs/tutorials/wiki2/src/models/README.txt b/docs/tutorials/wiki2/src/models/README.txt
index 141851285..68f430110 100644
--- a/docs/tutorials/wiki2/src/models/README.txt
+++ b/docs/tutorials/wiki2/src/models/README.txt
@@ -6,9 +6,9 @@ Getting Started
- cd <directory containing this file>
-- $venv/bin/python setup.py develop
+- $VENV/bin/python setup.py develop
-- $venv/bin/initialize_tutorial_db development.ini
+- $VENV/bin/initialize_tutorial_db development.ini
-- $venv/bin/pserve development.ini
+- $VENV/bin/pserve development.ini
diff --git a/docs/tutorials/wiki2/src/models/setup.py b/docs/tutorials/wiki2/src/models/setup.py
index a09bf756a..e7d318128 100644
--- a/docs/tutorials/wiki2/src/models/setup.py
+++ b/docs/tutorials/wiki2/src/models/setup.py
@@ -3,8 +3,10 @@ import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, 'README.txt')).read()
-CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = [
'pyramid',
diff --git a/docs/tutorials/wiki2/src/tests/README.txt b/docs/tutorials/wiki2/src/tests/README.txt
index 141851285..68f430110 100644
--- a/docs/tutorials/wiki2/src/tests/README.txt
+++ b/docs/tutorials/wiki2/src/tests/README.txt
@@ -6,9 +6,9 @@ Getting Started
- cd <directory containing this file>
-- $venv/bin/python setup.py develop
+- $VENV/bin/python setup.py develop
-- $venv/bin/initialize_tutorial_db development.ini
+- $VENV/bin/initialize_tutorial_db development.ini
-- $venv/bin/pserve development.ini
+- $VENV/bin/pserve development.ini
diff --git a/docs/tutorials/wiki2/src/tests/setup.py b/docs/tutorials/wiki2/src/tests/setup.py
index 3c2961fcc..c3da36b39 100644
--- a/docs/tutorials/wiki2/src/tests/setup.py
+++ b/docs/tutorials/wiki2/src/tests/setup.py
@@ -3,8 +3,10 @@ import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, 'README.txt')).read()
-CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = [
'pyramid',
diff --git a/docs/tutorials/wiki2/src/views/README.txt b/docs/tutorials/wiki2/src/views/README.txt
index 141851285..68f430110 100644
--- a/docs/tutorials/wiki2/src/views/README.txt
+++ b/docs/tutorials/wiki2/src/views/README.txt
@@ -6,9 +6,9 @@ Getting Started
- cd <directory containing this file>
-- $venv/bin/python setup.py develop
+- $VENV/bin/python setup.py develop
-- $venv/bin/initialize_tutorial_db development.ini
+- $VENV/bin/initialize_tutorial_db development.ini
-- $venv/bin/pserve development.ini
+- $VENV/bin/pserve development.ini
diff --git a/docs/tutorials/wiki2/src/views/setup.py b/docs/tutorials/wiki2/src/views/setup.py
index 36668dd33..e8fa8f396 100644
--- a/docs/tutorials/wiki2/src/views/setup.py
+++ b/docs/tutorials/wiki2/src/views/setup.py
@@ -3,8 +3,10 @@ import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, 'README.txt')).read()
-CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = [
'pyramid',
diff --git a/docs/tutorials/wiki2/tests.rst b/docs/tutorials/wiki2/tests.rst
index 6a7cbf62d..33b5d35c1 100644
--- a/docs/tutorials/wiki2/tests.rst
+++ b/docs/tutorials/wiki2/tests.rst
@@ -6,9 +6,6 @@ We will now add tests for the models and the views and a few functional
tests in the ``tests.py``. Tests ensure that an application works, and
that it continues to work after changes are made in the future.
-The source code for this tutorial stage can be browsed at
-`http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src/tests/
-<http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src/tests/>`_.
Testing the Models
@@ -57,7 +54,7 @@ Change the ``requires`` list in ``setup.py`` to include ``WebTest``.
.. literalinclude:: src/tests/setup.py
:linenos:
:language: python
- :lines: 9-20
+ :lines: 11-21
:emphasize-lines: 10
After we've added a dependency on WebTest in ``setup.py``, we need to rerun
@@ -69,13 +66,13 @@ On UNIX:
.. code-block:: text
- $ ../bin/python setup.py develop
+ $ $VENV/bin/python setup.py develop
On Windows:
.. code-block:: text
- c:\pyramidtut\tutorial> ..\Scripts\python setup.py develop
+ c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py develop
Once that command has completed successfully, we can run the tests
themselves:
@@ -84,13 +81,13 @@ On UNIX:
.. code-block:: text
- $ ../bin/python setup.py test -q
+ $ $VENV/bin/python setup.py test -q
On Windows:
.. code-block:: text
- c:\pyramidtut\tutorial> ..\Scripts\python setup.py test -q
+ c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py test -q
The expected result ends something like:
diff --git a/docs/whatsnew-1.0.rst b/docs/whatsnew-1.0.rst
index 66cb9be3a..d1f3046ca 100644
--- a/docs/whatsnew-1.0.rst
+++ b/docs/whatsnew-1.0.rst
@@ -249,7 +249,7 @@ ZCML Externalized
Pyramid core. Loading ZCML is now a feature of the :term:`pyramid_zcml`
package, which can be downloaded from PyPI. Documentation for the package
should be available via
- http://pylonsproject.org/projects/pyramid_zcml/dev/, which describes how to
+ http://docs.pylonsproject.org/projects/pyramid_zcml/en/latest/, which describes how to
add a configuration statement to your ``main`` block to reobtain this
method. You will also need to add an ``install_requires`` dependency upon
the ``pyramid_zcml`` distribution to your ``setup.py`` file.
diff --git a/docs/whatsnew-1.1.rst b/docs/whatsnew-1.1.rst
index 18d0aa0b1..f33fc94ba 100644
--- a/docs/whatsnew-1.1.rst
+++ b/docs/whatsnew-1.1.rst
@@ -395,8 +395,9 @@ Deprecations and Behavior Differences
when porting your application from an older version of Pyramid. Use the
``PYTHONWARNINGS`` environment variable with the value ``all`` in the
shell you use to invoke ``paster serve`` to see these warnings, e.g. on
- UNIX, ``PYTHONWARNINGS=all bin/paster serve development.ini``. Python 2.5
- and 2.6 show deprecation warnings by default, so this is unecessary there.
+ UNIX, ``PYTHONWARNINGS=all $VENV/bin/paster serve development.ini``.
+ Python 2.5 and 2.6 show deprecation warnings by default,
+ so this is unecessary there.
All deprecation warnings are emitted to the console.
- The :class:`pyramid.view.static` class has been deprecated in favor of the
diff --git a/docs/whatsnew-1.3.rst b/docs/whatsnew-1.3.rst
index f32053202..ef0256383 100644
--- a/docs/whatsnew-1.3.rst
+++ b/docs/whatsnew-1.3.rst
@@ -46,12 +46,12 @@ maintain them ourselves. As a result, we've had to make some changes.
Previously (in Pyramid 1.0, 1.1 and 1.2), you created a Pyramid application
using ``paster create``, like so::
- $ myvenv/bin/paster create -t pyramid_starter foo
+ $ $VENV/bin/paster create -t pyramid_starter foo
In 1.3, you're now instead required to create an application using
``pcreate`` like so::
- $ myvenv/bin/pcreate -s starter foo
+ $ $VENV/bin/pcreate -s starter foo
``pcreate`` is required to be used for internal Pyramid scaffolding;
externally distributed scaffolding may allow for both ``pcreate`` and/or
@@ -59,11 +59,11 @@ externally distributed scaffolding may allow for both ``pcreate`` and/or
In previous Pyramid versions, you ran a Pyramid application like so::
- $ myvenv/bin/paster serve development.ini
+ $ $VENV/bin/paster serve development.ini
Instead, you now must use the ``pserve`` command in 1.3::
- $ myvenv/bin/pserve development.ini
+ $ $VENV/bin/pserve development.ini
The ``ini`` configuration file format supported by Pyramid has not changed.
As a result, Python 2-only users can install PasteScript manually and use
@@ -212,7 +212,7 @@ Not Found helpers:
- New API: :meth:`pyramid.config.Configurator.add_notfound_view`. This is a
wrapper for :meth:`pyramid.Config.configurator.add_view` which provides
support for an "append_slash" feature as well as doing the right thing when
- it comes to permissions (a not found view should always be public). It
+ it comes to permissions (a Not Found View should always be public). It
should be preferred over calling ``add_view`` directly with
``context=HTTPNotFound`` as was previously recommended.
@@ -492,7 +492,7 @@ Known Issues
develop`` on Python 3.2, it will quit with an installation error while
trying to install ``Pygments``. If this happens, please just rerun the
``setup.py develop`` command again, and it will complete successfully.
- This is due to a minor bug in SQLAlchemy 0.7.5 under Python 3, and will be
+ This is due to a minor bug in SQLAlchemy 0.7.5 under Python 3, and has been
fixed in a later SQLAlchemy release. Keep an eye on
http://www.sqlalchemy.org/trac/ticket/2421
@@ -524,7 +524,7 @@ Documentation Enhancements
- Removed the "Running Pyramid on Google App Engine" tutorial from the main
docs. It survives on in the Cookbook
- (http://docs.pylonsproject.org/projects/pyramid_cookbook/en/latest/gae.html).
+ (http://docs.pylonsproject.org/projects/pyramid_cookbook/en/latest/deployment/gae.html).
Rationale: it provides the correct info for the Python 2.5 version of GAE
only, and this version of Pyramid does not support Python 2.5.
diff --git a/docs/whatsnew-1.4.rst b/docs/whatsnew-1.4.rst
index 34fda5f37..f725615f3 100644
--- a/docs/whatsnew-1.4.rst
+++ b/docs/whatsnew-1.4.rst
@@ -108,7 +108,7 @@ Minor Feature Additions
- The static view machinery now raises rather than returns
:class:`pyramid.httpexceptions.HTTPNotFound` and
:class:`pyramid.httpexceptions.HTTPMovedPermanently` exceptions, so these can
- be caught by the notfound view (and other exception views).
+ be caught by the Not Found View (and other exception views).
- When there is a predicate mismatch exception (seen when no view matches for
a given request due to predicates not working), the exception now contains
diff --git a/pyramid/authentication.py b/pyramid/authentication.py
index 08d283acc..bc0286ed3 100644
--- a/pyramid/authentication.py
+++ b/pyramid/authentication.py
@@ -450,6 +450,12 @@ class AuthTktAuthenticationPolicy(CallbackAuthenticationPolicy):
Default: ``False``. Make the requesting IP address part of
the authentication data in the cookie. Optional.
+ For IPv6 this option is not recommended. The ``mod_auth_tkt``
+ specification does not specify how to handle IPv6 addresses, so using
+ this option in combination with IPv6 addresses may cause an
+ incompatible cookie. It ties the authentication ticket to that
+ individual's IPv6 address.
+
``timeout``
Default: ``None``. Maximum number of seconds which a newly
@@ -736,9 +742,17 @@ def calculate_digest(ip, timestamp, secret, userid, tokens, user_data,
tokens = bytes_(tokens, 'utf-8')
user_data = bytes_(user_data, 'utf-8')
hash_obj = hashlib.new(hashalg)
- hash_obj.update(
- encode_ip_timestamp(ip, timestamp) + secret + userid + b'\0'
- + tokens + b'\0' + user_data)
+
+ # Check to see if this is an IPv6 address
+ if ':' in ip:
+ ip_timestamp = ip + str(int(timestamp))
+ ip_timestamp = bytes_(ip_timestamp)
+ else:
+ # encode_ip_timestamp not required, left in for backwards compatibility
+ ip_timestamp = encode_ip_timestamp(ip, timestamp)
+
+ hash_obj.update(ip_timestamp + secret + userid + b'\0' +
+ tokens + b'\0' + user_data)
digest = hash_obj.hexdigest()
hash_obj2 = hashlib.new(hashalg)
hash_obj2.update(bytes_(digest) + secret)
@@ -1075,12 +1089,11 @@ class BasicAuthAuthenticationPolicy(CallbackAuthenticationPolicy):
register a view that will send a Basic Auth challenge to the user whenever
there is an attempt to call a view which results in a Forbidden response::
- from pyramid.httpexceptions import HTTPForbidden
from pyramid.httpexceptions import HTTPUnauthorized
from pyramid.security import forget
- from pyramid.view import view_config
+ from pyramid.view import forbidden_view_config
- @view_config(context=HTTPForbidden)
+ @forbidden_view_config()
def basic_challenge(request):
response = HTTPUnauthorized()
response.headers.update(forget(request))
diff --git a/pyramid/authorization.py b/pyramid/authorization.py
index 943f8bd00..1fd05e244 100644
--- a/pyramid/authorization.py
+++ b/pyramid/authorization.py
@@ -80,6 +80,9 @@ class ACLAuthorizationPolicy(object):
except AttributeError:
continue
+ if acl and callable(acl):
+ acl = acl()
+
for ace in acl:
ace_action, ace_principal, ace_permissions = ace
if ace_principal in principals:
diff --git a/pyramid/config/__init__.py b/pyramid/config/__init__.py
index 40c487704..e1320a55f 100644
--- a/pyramid/config/__init__.py
+++ b/pyramid/config/__init__.py
@@ -104,14 +104,7 @@ class Configurator(
A Configurator is used to configure a :app:`Pyramid`
:term:`application registry`.
- The Configurator accepts a number of arguments: ``registry``,
- ``package``, ``settings``, ``root_factory``, ``authentication_policy``,
- ``authorization_policy``, ``renderers``, ``debug_logger``,
- ``locale_negotiator``, ``request_factory``, ``renderer_globals_factory``,
- ``default_permission``, ``session_factory``, ``default_view_mapper``,
- ``autocommit``, ``exceptionresponse_view`` and ``route_prefix``.
-
- If the ``registry`` argument is passed as a non-``None`` value, it must
+ If the ``registry`` argument is not ``None``, it must
be an instance of the :class:`pyramid.registry.Registry` class
representing the registry to configure. If ``registry`` is ``None``, the
configurator will create a :class:`pyramid.registry.Registry` instance
@@ -119,9 +112,9 @@ class Configurator(
otherwise be done. After its construction, the configurator may be used
to add further configuration to the registry.
- .. warning:: If a ``registry`` is passed to the Configurator
- constructor, all other constructor arguments except ``package``
- are ignored.
+ .. warning:: If ``registry`` is assigned the above-mentioned class
+ instance, all other constructor arguments are ignored,
+ with the exception of ``package``.
If the ``package`` argument is passed, it must be a reference to a Python
:term:`package` (e.g. ``sys.modules['thepackage']``) or a :term:`dotted
@@ -154,12 +147,12 @@ class Configurator(
authorization policy is supplied without also supplying an
authentication policy (authorization requires authentication).
- If ``renderers`` is passed, it should be a list of tuples
- representing a set of :term:`renderer` factories which should be
- configured into this application (each tuple representing a set of
+ If ``renderers`` is ``None`` (the default), a default set of
+ :term:`renderer` factories is used. Else, it should be a list of
+ tuples representing a set of renderer factories which should be
+ configured into this application, and each tuple representing a set of
positional values that should be passed to
- :meth:`pyramid.config.Configurator.add_renderer`). If
- it is not passed, a default set of renderer factories is used.
+ :meth:`pyramid.config.Configurator.add_renderer`.
If ``debug_logger`` is not passed, a default debug logger that logs to a
logger will be used (the logger name will be the package name of the
@@ -182,10 +175,9 @@ class Configurator(
same. See :ref:`adding_renderer_globals`. By default, it is ``None``,
which means use no renderer globals factory.
- .. warning::
-
- as of Pyramid 1.1, ``renderer_globals_factory`` is deprecated. Instead,
- use a BeforeRender event subscriber as per :ref:`beforerender_event`.
+ .. deprecated:: 1.1
+ Use a BeforeRender event subscriber as per :ref:`beforerender_event`
+ in place of ``renderer_globals_factory``.
If ``default_permission`` is passed, it should be a
:term:`permission` string to be used as the default permission for
@@ -218,15 +210,15 @@ class Configurator(
:meth:`pyramid.config.Configurator.commit` is called. When
:meth:`pyramid.config.Configurator.commit` is called, the actions implied
by the called methods will be checked for configuration conflicts unless
- ``autocommit`` is ``True``. If a conflict is detected a
+ ``autocommit`` is ``True``. If a conflict is detected, a
``ConfigurationConflictError`` will be raised. Calling
:meth:`pyramid.config.Configurator.make_wsgi_app` always implies a final
commit.
If ``default_view_mapper`` is passed, it will be used as the default
:term:`view mapper` factory for view configurations that don't otherwise
- specify one (see :class:`pyramid.interfaces.IViewMapperFactory`). If a
- default_view_mapper is not passed, a superdefault view mapper will be
+ specify one (see :class:`pyramid.interfaces.IViewMapperFactory`). If
+ ``default_view_mapper`` is not passed, a superdefault view mapper will be
used.
If ``exceptionresponse_view`` is passed, it must be a :term:`view
@@ -236,18 +228,26 @@ class Configurator(
be registered, and all raised exception responses will be bubbled up to
Pyramid's caller. By
default, the ``pyramid.httpexceptions.default_exceptionresponse_view``
- function is used as the ``exceptionresponse_view``. This argument is new
- in Pyramid 1.1.
+ function is used as the ``exceptionresponse_view``.
If ``route_prefix`` is passed, all routes added with
:meth:`pyramid.config.Configurator.add_route` will have the specified path
- prepended to their pattern. This parameter is new in Pyramid 1.2.
+ prepended to their pattern.
If ``introspection`` is passed, it must be a boolean value. If it's
``True``, introspection values during actions will be kept for use
for tools like the debug toolbar. If it's ``False``, introspection
values provided by registrations will be ignored. By default, it is
- ``True``. This parameter is new as of Pyramid 1.3.
+ ``True``.
+
+ .. versionadded:: 1.1
+ The ``exceptionresponse_view`` argument.
+
+ .. versionadded:: 1.2
+ The ``route_prefix`` argument.
+
+ .. versionadded:: 1.3
+ The ``introspection`` argument.
"""
manager = manager # for testing injection
venusian = venusian # for testing injection
@@ -631,7 +631,7 @@ class Configurator(
self.action_state = ActionState() # old actions have been processed
def include(self, callable, route_prefix=None):
- """Include a configuration callables, to support imperative
+ """Include a configuration callable, to support imperative
application extensibility.
.. warning:: In versions of :app:`Pyramid` prior to 1.2, this
@@ -640,8 +640,8 @@ class Configurator(
A configuration callable should be a callable that accepts a single
argument named ``config``, which will be an instance of a
- :term:`Configurator` (be warned that it will not be the same
- configurator instance on which you call this method, however). The
+ :term:`Configurator`. However, be warned that it will not be the same
+ configurator instance on which you call this method. The
code which runs as the result of calling the callable should invoke
methods on the configurator passed to it which add configuration
state. The return value of a callable will be ignored.
@@ -668,7 +668,7 @@ class Configurator(
def includeme(config):
config.add_view(my_view)
- You might cause it be included within your Pyramid application like
+ You might cause it to be included within your Pyramid application like
so:
.. code-block:: python
@@ -701,7 +701,7 @@ class Configurator(
to :meth:`pyramid.config.Configurator.add_route` within the included
callable will have their pattern prefixed with the value of
``route_prefix``. This can be used to help mount a set of routes at a
- different location than the included callable's author intended while
+ different location than the included callable's author intended, while
still maintaining the same route names. For example:
.. code-block:: python
@@ -721,7 +721,9 @@ class Configurator(
because the ``route_prefix`` argument will be prepended to the
pattern.
- The ``route_prefix`` parameter is new as of Pyramid 1.2.
+ .. versionadded:: 1.2
+ The ``route_prefix`` parameter.
+
"""
# """ <-- emacs
@@ -819,10 +821,8 @@ class Configurator(
def with_package(self, package):
""" Return a new Configurator instance with the same registry
- as this configurator using the package supplied as the
- ``package`` argument to the new configurator. ``package`` may
- be an actual Python package object or a :term:`dotted Python name`
- representing a package."""
+ as this configurator. ``package`` may be an actual Python package
+ object or a :term:`dotted Python name` representing a package."""
configurator = self.__class__(
registry=self.registry,
package=package,
@@ -919,8 +919,6 @@ class Configurator(
and scanned. See the :term:`Venusian` documentation for more
information about the ``ignore`` argument.
- .. note:: the ``ignore`` argument is new in Pyramid 1.3.
-
To perform a ``scan``, Pyramid creates a Venusian ``Scanner`` object.
The ``kw`` argument represents a set of keyword arguments to pass to
the Venusian ``Scanner`` object's constructor. See the
@@ -932,7 +930,12 @@ class Configurator(
may require additional arguments. Providing this argument is not
often necessary; it's an advanced usage.
- .. note:: the ``**kw`` argument is new in Pyramid 1.1
+ .. versionadded:: 1.1
+ The ``**kw`` argument.
+
+ .. versionadded:: 1.3
+ The ``ignore`` argument.
+
"""
package = self.maybe_dotted(package)
if package is None: # pragma: no cover
diff --git a/pyramid/config/adapters.py b/pyramid/config/adapters.py
index dad60660a..319beab67 100644
--- a/pyramid/config/adapters.py
+++ b/pyramid/config/adapters.py
@@ -38,9 +38,8 @@ class AdaptersConfiguratorMixin(object):
:meth:`pyramid.config.Configurator.add_subscriber_predicate` before it
can be used. See :ref:`subscriber_predicates` for more information.
- .. note::
-
- THe ``**predicates`` argument is new as of Pyramid 1.4.
+ .. versionadded:: 1.4
+ The ``**predicates`` argument.
"""
dotted = self.maybe_dotted
subscriber, iface = dotted(subscriber), dotted(iface)
@@ -137,6 +136,8 @@ class AdaptersConfiguratorMixin(object):
def add_subscriber_predicate(self, name, factory, weighs_more_than=None,
weighs_less_than=None):
"""
+ .. versionadded:: 1.4
+
Adds a subscriber predicate factory. The associated subscriber
predicate can later be named as a keyword argument to
:meth:`pyramid.config.Configurator.add_subscriber` in the
@@ -150,9 +151,6 @@ class AdaptersConfiguratorMixin(object):
See :ref:`subscriber_predicates` for more information.
- .. note::
-
- This method is new as of Pyramid 1.4.
"""
self._add_predicate(
'subscriber',
@@ -274,6 +272,8 @@ class AdaptersConfiguratorMixin(object):
@action_method
def add_resource_url_adapter(self, adapter, resource_iface=None):
"""
+ .. versionadded:: 1.3
+
When you add a traverser as described in
:ref:`changing_the_traverser`, it's convenient to continue to use the
:meth:`pyramid.request.Request.resource_url` API. However, since the
@@ -299,10 +299,6 @@ class AdaptersConfiguratorMixin(object):
``None``, the url adapter will be used for every type of resource.
See :ref:`changing_resource_url` for more information.
-
- .. note::
-
- This API is new in Pyramid 1.3.
"""
adapter = self.maybe_dotted(adapter)
resource_iface = self.maybe_dotted(resource_iface)
diff --git a/pyramid/config/factories.py b/pyramid/config/factories.py
index ef7975d92..d30df3b74 100644
--- a/pyramid/config/factories.py
+++ b/pyramid/config/factories.py
@@ -182,9 +182,7 @@ class FactoriesConfiguratorMixin(object):
def set_request_property(self, callable, name=None, reify=False):
""" Add a property to the request object.
- .. warning::
-
- This method has been docs-deprecated as of Pyramid 1.4.
+ .. deprecated:: 1.4
:meth:`pyramid.config.Configurator.add_request_method` should be
used instead.
diff --git a/pyramid/config/rendering.py b/pyramid/config/rendering.py
index 4f33b23d9..356bf033e 100644
--- a/pyramid/config/rendering.py
+++ b/pyramid/config/rendering.py
@@ -73,11 +73,9 @@ class RenderingConfiguratorMixin(object):
dictionary, and therefore will be made available to the code
which uses the renderer.
- .. warning::
-
- This method is deprecated as of Pyramid 1.1. Use a BeforeRender
- event subscriber as documented in the :ref:`hooks_chapter` chapter
- instead.
+ .. deprecated:: 1.1
+ Use a BeforeRender event subscriber as documented in the
+ :ref:`hooks_chapter` chapter instead.
.. note::
diff --git a/pyramid/config/routes.py b/pyramid/config/routes.py
index e06d0fecd..7a7bbae1a 100644
--- a/pyramid/config/routes.py
+++ b/pyramid/config/routes.py
@@ -142,7 +142,7 @@ class RoutesConfiguratorMixin(object):
request; it will only be useful for URL generation. By default,
``static`` is ``False``. See :ref:`static_route_narr`.
- .. note:: New in :app:`Pyramid` 1.1.
+ .. versionadded:: 1.1
Predicate Arguments
@@ -180,9 +180,9 @@ class RoutesConfiguratorMixin(object):
will match if the request has *any* request method. If this
predicate returns ``False``, route matching continues.
- .. note:: The ability to pass a tuple of items as
- ``request_method`` is new as of Pyramid 1.2. Previous
- versions allowed only a string.
+ .. versionchanged:: 1.2
+ The ability to pass a tuple of items as ``request_method``.
+ Previous versions allowed only a string.
path_info
@@ -276,8 +276,10 @@ class RoutesConfiguratorMixin(object):
:meth:`pyramid.config.Configurator.add_view_predicate`. More than
one key/value pair can be used at the same time. See
:ref:`view_and_route_predicates` for more information about
- third-party predicates. This argument is new as of Pyramid 1.4.
-
+ third-party predicates.
+
+ .. versionadded:: 1.4
+
View-Related Arguments
.. warning::
@@ -291,7 +293,7 @@ class RoutesConfiguratorMixin(object):
view
- .. warning:: Deprecated as of :app:`Pyramid` 1.1.
+ .. deprecated:: 1.1
A Python object or :term:`dotted Python name` to the same
object that will be used as a view callable when this route
@@ -299,7 +301,7 @@ class RoutesConfiguratorMixin(object):
view_context
- .. warning:: Deprecated as of :app:`Pyramid` 1.1.
+ .. deprecated:: 1.1
A class or an :term:`interface` or :term:`dotted Python
name` to the same object which the :term:`context` of the
@@ -315,7 +317,7 @@ class RoutesConfiguratorMixin(object):
view_permission
- .. warning:: Deprecated as of :app:`Pyramid` 1.1.
+ .. deprecated:: 1.1
The permission name required to invoke the view associated
with this route. e.g. ``edit``. (see
@@ -329,7 +331,7 @@ class RoutesConfiguratorMixin(object):
view_renderer
- .. warning:: Deprecated as of :app:`Pyramid` 1.1.
+ .. deprecated:: 1.1
This is either a single string term (e.g. ``json``) or a
string implying a path or :term:`asset specification`
@@ -353,7 +355,7 @@ class RoutesConfiguratorMixin(object):
view_attr
- .. warning:: Deprecated as of :app:`Pyramid` 1.1.
+ .. deprecated:: 1.1
The view machinery defaults to using the ``__call__`` method
of the view callable (or the function itself, if the view
@@ -491,9 +493,7 @@ class RoutesConfiguratorMixin(object):
See :ref:`view_and_route_predicates` for more information.
- .. note::
-
- This method is new as of Pyramid 1.4.
+ .. versionadded:: 1.4
"""
self._add_predicate(
'route',
diff --git a/pyramid/config/testing.py b/pyramid/config/testing.py
index 7141a5049..2ab85b1f5 100644
--- a/pyramid/config/testing.py
+++ b/pyramid/config/testing.py
@@ -37,19 +37,11 @@ class TestingConfiguratorMixin(object):
not provided (or it is provided, and is ``None``), the default value
``[]`` (the empty list) will be returned by ``remember``.
- .. note::
-
- ``remember_result`` is new as of Pyramid 1.4.
-
``forget_result``, if provided, should be the result returned by
the ``forget`` method of the faux authentication policy. If it is
not provided (or it is provided, and is ``None``), the default value
``[]`` (the empty list) will be returned by ``forget``.
- .. note::
-
- ``forget_result`` is new as of Pyramid 1.4.
-
The behavior of the registered :term:`authentication policy`
depends on the values provided for the ``userid`` and
``groupids`` argument. The authentication policy will return
@@ -64,6 +56,12 @@ class TestingConfiguratorMixin(object):
:func:`pyramid.security.authenticated_userid`,
:func:`pyramid.security.effective_principals`, and
:func:`pyramid.security.principals_allowed_by_permission`.
+
+ .. versionadded:: 1.4
+ The ``remember_result`` argument.
+
+ .. versionadded:: 1.4
+ The ``forget_result`` argument.
"""
from pyramid.testing import DummySecurityPolicy
policy = DummySecurityPolicy(
diff --git a/pyramid/config/tweens.py b/pyramid/config/tweens.py
index 1bc6dc95c..cd14c9ff6 100644
--- a/pyramid/config/tweens.py
+++ b/pyramid/config/tweens.py
@@ -24,7 +24,7 @@ from pyramid.config.util import (
class TweensConfiguratorMixin(object):
def add_tween(self, tween_factory, under=None, over=None):
"""
- .. note:: This feature is new as of Pyramid 1.2.
+ .. versionadded:: 1.2
Add a 'tween factory'. A :term:`tween` (a contraction of 'between')
is a bit of code that sits between the Pyramid router's main request
diff --git a/pyramid/config/views.py b/pyramid/config/views.py
index e4217f2f3..1c7620e67 100644
--- a/pyramid/config/views.py
+++ b/pyramid/config/views.py
@@ -710,7 +710,7 @@ class ViewsConfiguratorMixin(object):
http_cache
- .. note:: This feature is new as of Pyramid 1.1.
+ .. versionadded:: 1.1
When you supply an ``http_cache`` value to a view configuration,
the ``Expires`` and ``Cache-Control`` headers of a response
@@ -822,7 +822,8 @@ class ViewsConfiguratorMixin(object):
think about preserving function attributes such as ``__name__`` and
``__module__`` within decorator logic).
- Passing an iterable is only supported as of :app:`Pyramid` 1.4a4.
+ .. versionchanged:: 1.4a4
+ Passing an iterable.
mapper
@@ -877,9 +878,9 @@ class ViewsConfiguratorMixin(object):
supplied value. Note that use of ``GET`` also implies that the
view will respond to ``HEAD`` as of Pyramid 1.4.
- .. note:: The ability to pass a tuple of items as
- ``request_method`` is new as of Pyramid 1.2. Previous
- versions allowed only a string.
+ .. versionchanged:: 1.2
+ The ability to pass a tuple of items as ``request_method``.
+ Previous versions allowed only a string.
request_param
@@ -897,7 +898,7 @@ class ViewsConfiguratorMixin(object):
match_param
- .. note:: This feature is new as of :app:`Pyramid` 1.2.
+ .. versionadded:: 1.2
This value can be a string of the format "key=value" or a tuple
containing one or more of these strings.
@@ -1354,7 +1355,10 @@ class ViewsConfiguratorMixin(object):
@action_method
def add_view_predicate(self, name, factory, weighs_more_than=None,
weighs_less_than=None):
- """ Adds a view predicate factory. The associated view predicate can
+ """
+ .. versionadded:: 1.4
+
+ Adds a view predicate factory. The associated view predicate can
later be named as a keyword argument to
:meth:`pyramid.config.Configurator.add_view` in the
``predicates`` anonyous keyword argument dictionary.
@@ -1366,10 +1370,6 @@ class ViewsConfiguratorMixin(object):
``factory`` should be a :term:`predicate factory`.
See :ref:`view_and_route_predicates` for more information.
-
- .. note::
-
- This method is new as of Pyramid 1.4.
"""
self._add_predicate(
'view',
@@ -1557,9 +1557,7 @@ class ViewsConfiguratorMixin(object):
``for_``, or ``http_cache`` keyword arguments. These argument values
make no sense in the context of a forbidden view.
- .. note::
-
- This method is new as of Pyramid 1.3.
+ .. versionadded:: 1.3
"""
for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):
if arg in predicates:
@@ -1617,9 +1615,9 @@ class ViewsConfiguratorMixin(object):
append_slash=False,
**predicates
):
- """ Add a default notfound view to the current configuration state.
+ """ Add a default Not Found View to the current configuration state.
The view will be called when Pyramid or application code raises an
- :exc:`pyramid.httpexceptions.HTTPForbidden` exception (e.g. when a
+ :exc:`pyramid.httpexceptions.HTTPNotFound` exception (e.g. when a
view cannot be found for the request). The simplest example is:
.. code-block:: python
@@ -1636,9 +1634,9 @@ class ViewsConfiguratorMixin(object):
:meth:`pyramid.config.Configurator.add_view`, this method will raise
an exception if passed ``name``, ``permission``, ``context``,
``for_``, or ``http_cache`` keyword arguments. These argument values
- make no sense in the context of a notfound view.
+ make no sense in the context of a Not Found View.
- If ``append_slash`` is ``True``, when this notfound view is invoked,
+ If ``append_slash`` is ``True``, when this Not Found View is invoked,
and the current path info does not end in a slash, the notfound logic
will attempt to find a :term:`route` that matches the request's path
info suffixed with a slash. If such a route exists, Pyramid will
@@ -1646,9 +1644,7 @@ class ViewsConfiguratorMixin(object):
Pyramid will return the result of the view callable provided as
``view``, as normal.
- .. note::
-
- This method is new as of Pyramid 1.3.
+ .. versionadded:: 1.3
"""
for arg in ('name', 'permission', 'context', 'for_', 'http_cache'):
if arg in predicates:
@@ -1797,6 +1793,10 @@ class ViewsConfiguratorMixin(object):
qualified URL (e.g. starts with ``http://`` or similar). In this
mode, the ``name`` is used as the prefix of the full URL when
generating a URL using :meth:`pyramid.request.Request.static_url`.
+ Furthermore, if a protocol-relative URL (e.g. ``//example.com/images``)
+ is used as the ``name`` argument, the generated URL will use the
+ protocol of the request (http or https, respectively).
+
For example, if ``add_static_view`` is called like so:
.. code-block:: python
@@ -1805,20 +1805,14 @@ class ViewsConfiguratorMixin(object):
Subsequently, the URLs generated by
:meth:`pyramid.request.Request.static_url` for that static view will
- be prefixed with ``http://example.com/images``:
+ be prefixed with ``http://example.com/images`` (the external webserver
+ listening on ``example.com`` must be itself configured to respond
+ properly to such a request.):
.. code-block:: python
static_url('mypackage:images/logo.png', request)
- When ``add_static_view`` is called with a ``name`` argument that is
- the URL ``http://example.com/images``, subsequent calls to
- :meth:`pyramid.request.Request.static_url` with paths that start with
- the ``path`` argument passed to ``add_static_view`` will generate a
- URL something like ``http://example.com/logo.png``. The external
- webserver listening on ``example.com`` must be itself configured to
- respond properly to such a request.
-
See :ref:`static_assets_section` for more information.
"""
spec = self._make_spec(path)
@@ -1862,6 +1856,12 @@ class StaticURLInfo(object):
kw['subpath'] = subpath
return request.route_url(route_name, **kw)
else:
+ parsed = url_parse(url)
+ if not parsed.scheme:
+ # parsed.scheme is readonly, so we have to parse again
+ # to change the scheme, sigh.
+ url = urlparse.urlunparse(url_parse(
+ url, scheme=request.environ['wsgi.url_scheme']))
subpath = url_quote(subpath)
return urljoin(url, subpath)
@@ -1890,7 +1890,7 @@ class StaticURLInfo(object):
# make sure it ends with a slash
name = name + '/'
- if url_parse(name)[0]:
+ if url_parse(name).netloc:
# it's a URL
# url, spec, route_name
url = name
diff --git a/pyramid/exceptions.py b/pyramid/exceptions.py
index 1c8f99f62..a8fca1d84 100644
--- a/pyramid/exceptions.py
+++ b/pyramid/exceptions.py
@@ -10,18 +10,36 @@ CR = '\n'
class PredicateMismatch(HTTPNotFound):
"""
- Internal exception (not an API) raised by multiviews when no
- view matches. This exception subclasses the ``NotFound``
- exception only one reason: if it reaches the main exception
- handler, it should be treated like a ``NotFound`` by any exception
- view registrations.
+ This exception is raised by multiviews when no view matches
+ all given predicates.
+
+ This exception subclasses the :class:`HTTPNotFound` exception for a
+ specific reason: if it reaches the main exception handler, it should
+ be treated as :class:`HTTPNotFound`` by any exception view
+ registrations. Thus, typically, this exception will not be seen
+ publicly.
+
+ However, this exception will be raised if the predicates of all
+ views configured to handle another exception context cannot be
+ successfully matched. For instance, if a view is configured to
+ handle a context of ``HTTPForbidden`` and the configured with
+ additional predicates, then :class:`PredicateMismatch` will be
+ raised if:
+
+ * An original view callable has raised :class:`HTTPForbidden` (thus
+ invoking an exception view); and
+ * The given request fails to match all predicates for said
+ exception view associated with :class:`HTTPForbidden`.
+
+ The same applies to any type of exception being handled by an
+ exception view.
"""
class URLDecodeError(UnicodeDecodeError):
"""
This exception is raised when :app:`Pyramid` cannot
successfully decode a URL or a URL path segment. This exception
- it behaves just like the Python builtin
+ behaves just like the Python builtin
:exc:`UnicodeDecodeError`. It is a subclass of the builtin
:exc:`UnicodeDecodeError` exception only for identity purposes,
mostly so an exception view can be registered when a URL cannot be
diff --git a/pyramid/httpexceptions.py b/pyramid/httpexceptions.py
index 64afc346a..c21a717f8 100644
--- a/pyramid/httpexceptions.py
+++ b/pyramid/httpexceptions.py
@@ -7,9 +7,9 @@ single HTTP status code. Each class is a subclass of the
:class:`~HTTPException`. Each exception class is also a :term:`response`
object.
-Each exception class has a status code according to `RFC 2068
-<http://www.ietf.org/rfc/rfc2068.txt>`_: codes with 100-300 are not really
-errors; 400s are client errors, and 500s are server errors.
+Each exception class has a status code according to :rfc:`2068`:
+codes with 100-300 are not really errors; 400s are client errors,
+and 500s are server errors.
Exception
HTTPException
@@ -647,8 +647,8 @@ class HTTPNotFound(HTTPClientError):
code: 404, title: Not Found
Raise this exception within :term:`view` code to immediately
- return the :term:`Not Found view` to the invoking user. Usually
- this is a basic ``404`` page, but the Not Found view can be
+ return the :term:`Not Found View` to the invoking user. Usually
+ this is a basic ``404`` page, but the Not Found View can be
customized as necessary. See :ref:`changing_the_notfound_view`.
This exception's constructor accepts a ``detail`` argument
diff --git a/pyramid/interfaces.py b/pyramid/interfaces.py
index b176d49fb..4fb4d615c 100644
--- a/pyramid/interfaces.py
+++ b/pyramid/interfaces.py
@@ -57,9 +57,9 @@ class IApplicationCreated(Interface):
IWSGIApplicationCreatedEvent = IApplicationCreated # b /c
class IResponse(Interface):
- """ Represents a WSGI response using the WebOb response interface. Some
- attribute and method documentation of this interface references `RFC 2616
- <http://www.w3.org/Protocols/rfc2616/>`_.
+ """ Represents a WSGI response using the WebOb response interface.
+ Some attribute and method documentation of this interface references
+ :rfc:`2616`.
This interface is most famously implemented by
:class:`pyramid.response.Response` and the HTTP exception classes in
@@ -460,7 +460,7 @@ class IAuthorizationPolicy(Interface):
class IMultiDict(IDict): # docs-only interface
"""
An ordered dictionary that can have multiple values for each key. A
- multidict adds the methods ``getall``, ``getone``, ``mixed``, ``extend``
+ multidict adds the methods ``getall``, ``getone``, ``mixed``, ``extend``,
``add``, and ``dict_of_lists`` to the normal dictionary interface. A
multidict data structure is used as ``request.POST``, ``request.GET``,
and ``request.params`` within an :app:`Pyramid` application.
@@ -744,10 +744,8 @@ class IResourceURL(Interface):
class IContextURL(IResourceURL):
""" An adapter which deals with URLs related to a context.
- ..warning::
-
- This interface is deprecated as of Pyramid 1.3 with the introduction of
- IResourceURL.
+ .. deprecated:: 1.3
+ use IResourceURL instead.
"""
# this class subclasses IResourceURL because request.resource_url looks
# for IResourceURL via queryAdapter. queryAdapter will find a deprecated
@@ -792,7 +790,7 @@ deprecated(
'scheduled to be removed. Use the '
'"pyramid.config.Configurator.add_resource_url_adapter" method to register '
'a class that implements "pyramid.interfaces.IResourceURL" instead. '
- 'See the "What\'s new In Pyramid 1.3" document for a further description.'
+ 'See the "What\'s new In Pyramid 1.3" document for more details.'
)
class IPackageOverrides(Interface):
diff --git a/pyramid/paster.py b/pyramid/paster.py
index ce07d1fe0..967543849 100644
--- a/pyramid/paster.py
+++ b/pyramid/paster.py
@@ -23,26 +23,34 @@ def get_app(config_uri, name=None, options=None, loadapp=loadapp):
path, section = _getpathsec(config_uri, name)
config_name = 'config:%s' % path
here_dir = os.getcwd()
- if options:
- kw = {'global_conf': options}
- else:
- kw = {}
- app = loadapp(config_name, name=section, relative_to=here_dir, **kw)
+ app = loadapp(
+ config_name,
+ name=section,
+ relative_to=here_dir,
+ global_conf=options)
return app
-def get_appsettings(config_uri, name=None, appconfig=appconfig):
+def get_appsettings(config_uri, name=None, options=None, appconfig=appconfig):
""" Return a dictionary representing the key/value pairs in an ``app``
section within the file represented by ``config_uri``.
+ ``options``, if passed, should be a dictionary used as variable assignments
+ like ``{'http_port': 8080}``. This is useful if e.g. ``%(http_port)s`` is
+ used in the config file.
+
If the ``name`` is None, this will attempt to parse the name from
the ``config_uri`` string expecting the format ``inifile#name``.
If no name is found, the name will default to "main"."""
path, section = _getpathsec(config_uri, name)
config_name = 'config:%s' % path
here_dir = os.getcwd()
- return appconfig(config_name, name=section, relative_to=here_dir)
+ return appconfig(
+ config_name,
+ name=section,
+ relative_to=here_dir,
+ global_conf=options)
def setup_logging(config_uri, fileConfig=fileConfig,
configparser=configparser):
diff --git a/pyramid/path.py b/pyramid/path.py
index e9c63a365..57eccdb19 100644
--- a/pyramid/path.py
+++ b/pyramid/path.py
@@ -114,7 +114,7 @@ class AssetResolver(Resolver):
""" A class used to resolve an :term:`asset specification` to an
:term:`asset descriptor`.
- .. note:: This API is new as of Pyramid 1.3.
+ .. versionadded:: 1.3
The constructor accepts a single argument named ``package`` which may be
any of:
@@ -133,20 +133,19 @@ class AssetResolver(Resolver):
to the :meth:`~pyramid.path.AssetResolver.resolve` method. An asset
specification without a colon in it is treated as relative.
- If the value ``None`` is supplied as the ``package``, the resolver will
+ If ``package`` is ``None``, the resolver will
only be able to resolve fully qualified (not relative) asset
specifications. Any attempt to resolve a relative asset specification
- when the ``package`` is ``None`` will result in an :exc:`ValueError`
- exception.
+ will result in an :exc:`ValueError` exception.
- If the value :attr:`pyramid.path.CALLER_PACKAGE` is supplied as the
- ``package``, the resolver will treat relative asset specifications as
+ If ``package`` is :attr:`pyramid.path.CALLER_PACKAGE`,
+ the resolver will treat relative asset specifications as
relative to the caller of the :meth:`~pyramid.path.AssetResolver.resolve`
method.
- If a *module* or *module name* (as opposed to a package or package name)
- is supplied as ``package``, its containing package is computed and this
- package used to derive the package name (all names are resolved relative
+ If ``package`` is a *module* or *module name* (as opposed to a package or
+ package name), its containing package is computed and this
+ package is used to derive the package name (all names are resolved relative
to packages, never to modules). For example, if the ``package`` argument
to this type was passed the string ``xml.dom.expatbuilder``, and
``template.pt`` is supplied to the
@@ -154,8 +153,8 @@ class AssetResolver(Resolver):
asset spec would be ``xml.minidom:template.pt``, because
``xml.dom.expatbuilder`` is a module object, not a package object.
- If a *package* or *package name* (as opposed to a module or module name)
- is supplied as ``package``, this package will be used to compute relative
+ If ``package`` is a *package* or *package name* (as opposed to a module or
+ module name), this package will be used to compute relative
asset specifications. For example, if the ``package`` argument to this
type was passed the string ``xml.dom``, and ``template.pt`` is supplied
to the :meth:`~pyramid.path.AssetResolver.resolve` method, the resulting
@@ -209,7 +208,7 @@ class DottedNameResolver(Resolver):
""" A class used to resolve a :term:`dotted Python name` to a package or
module object.
- .. note:: This API is new as of Pyramid 1.3.
+ .. versionadded:: 1.3
The constructor accepts a single argument named ``package`` which may be
any of:
@@ -229,18 +228,17 @@ class DottedNameResolver(Resolver):
which has a ``.`` (dot) or ``:`` (colon) as its first character is
treated as relative.
- If the value ``None`` is supplied as the ``package``, the resolver will
- only be able to resolve fully qualified (not relative) names. Any
- attempt to resolve a relative name when the ``package`` is ``None`` will
- result in an :exc:`ValueError` exception.
+ If ``package`` is ``None``, the resolver will only be able to resolve
+ fully qualified (not relative) names. Any attempt to resolve a
+ relative name will result in an :exc:`ValueError` exception.
- If the value :attr:`pyramid.path.CALLER_PACKAGE` is supplied as the
- ``package``, the resolver will treat relative dotted names as relative to
+ If ``package`` is :attr:`pyramid.path.CALLER_PACKAGE`,
+ the resolver will treat relative dotted names as relative to
the caller of the :meth:`~pyramid.path.DottedNameResolver.resolve`
method.
- If a *module* or *module name* (as opposed to a package or package name)
- is supplied as ``package``, its containing package is computed and this
+ If ``package`` is a *module* or *module name* (as opposed to a package or
+ package name), its containing package is computed and this
package used to derive the package name (all names are resolved relative
to packages, never to modules). For example, if the ``package`` argument
to this type was passed the string ``xml.dom.expatbuilder``, and
@@ -249,8 +247,8 @@ class DottedNameResolver(Resolver):
import would be for ``xml.minidom``, because ``xml.dom.expatbuilder`` is
a module object, not a package object.
- If a *package* or *package name* (as opposed to a module or module name)
- is supplied as ``package``, this package will be used to relative compute
+ If ``package`` is a *package* or *package name* (as opposed to a module or
+ module name), this package will be used to relative compute
dotted names. For example, if the ``package`` argument to this type was
passed the string ``xml.dom``, and ``.minidom`` is supplied to the
:meth:`~pyramid.path.DottedNameResolver.resolve` method, the resulting
diff --git a/pyramid/renderers.py b/pyramid/renderers.py
index 6839d72f5..64951a6ba 100644
--- a/pyramid/renderers.py
+++ b/pyramid/renderers.py
@@ -43,23 +43,23 @@ from pyramid.threadlocal import get_current_registry
# API
def render(renderer_name, value, request=None, package=None):
- """ Using the renderer specified as ``renderer_name`` (a template
- or a static renderer) render the value (or set of values) present
+ """ Using the renderer ``renderer_name`` (a template
+ or a static renderer), render the value (or set of values) present
in ``value``. Return the result of the renderer's ``__call__``
method (usually a string or Unicode).
- If the renderer name refers to a file on disk (such as when the
- renderer is a template), it's usually best to supply the name as a
+ If the ``renderer_name`` refers to a file on disk, such as when the
+ renderer is a template, it's usually best to supply the name as an
:term:`asset specification`
(e.g. ``packagename:path/to/template.pt``).
You may supply a relative asset spec as ``renderer_name``. If
the ``package`` argument is supplied, a relative renderer path
will be converted to an absolute asset specification by
- combining the package supplied as ``package`` with the relative
- asset specification supplied as ``renderer_name``. If you do
- not supply a ``package`` (or ``package`` is ``None``) the package
- name of the *caller* of this function will be used as the package.
+ combining the package ``package`` with the relative
+ asset specification ``renderer_name``. If ``package``
+ is ``None`` (the default), the package name of the *caller* of
+ this function will be used as the package.
The ``value`` provided will be supplied as the input to the
renderer. Usually, for template renderings, this should be a
@@ -70,7 +70,7 @@ def render(renderer_name, value, request=None, package=None):
top-level system names, such as ``request``, ``context``,
``renderer_name``, and ``view``. See :ref:`renderer_system_values` for
the full list. If :term:`renderer globals` have been specified, these
- will also be used to agument the value.
+ will also be used to augment the value.
Supply a ``request`` parameter in order to provide the renderer
with the most correct 'system' values (``request`` and ``context``
@@ -88,8 +88,8 @@ def render(renderer_name, value, request=None, package=None):
return helper.render(value, None, request=request)
def render_to_response(renderer_name, value, request=None, package=None):
- """ Using the renderer specified as ``renderer_name`` (a template
- or a static renderer) render the value (or set of values) using
+ """ Using the renderer ``renderer_name`` (a template
+ or a static renderer), render the value (or set of values) using
the result of the renderer's ``__call__`` method (usually a string
or Unicode) as the response body.
@@ -100,8 +100,8 @@ def render_to_response(renderer_name, value, request=None, package=None):
You may supply a relative asset spec as ``renderer_name``. If
the ``package`` argument is supplied, a relative renderer name
will be converted to an absolute asset specification by
- combining the package supplied as ``package`` with the relative
- asset specification supplied as ``renderer_name``. If you do
+ combining the package ``package`` with the relative
+ asset specification ``renderer_name``. If you do
not supply a ``package`` (or ``package`` is ``None``) the package
name of the *caller* of this function will be used as the package.
@@ -134,16 +134,15 @@ def render_to_response(renderer_name, value, request=None, package=None):
return helper.render_to_response(value, None, request=request)
def get_renderer(renderer_name, package=None):
- """ Return the renderer object for the renderer named as
- ``renderer_name``.
+ """ Return the renderer object for the renderer ``renderer_name``.
You may supply a relative asset spec as ``renderer_name``. If
the ``package`` argument is supplied, a relative renderer name
will be converted to an absolute asset specification by
- combining the package supplied as ``package`` with the relative
- asset specification supplied as ``renderer_name``. If you do
- not supply a ``package`` (or ``package`` is ``None``) the package
- name of the *caller* of this function will be used as the package.
+ combining the package ``package`` with the relative
+ asset specification ``renderer_name``. If ``package`` is ``None``
+ (the default), the package name of the *caller* of this function
+ will be used as the package.
"""
if package is None:
package = caller_package()
@@ -204,11 +203,9 @@ class JSON(object):
``default``, and any extra ``kw`` keyword argments passed during
renderer construction.
- .. note::
-
- This feature is new in Pyramid 1.4. Prior to 1.4 there was
- no public API for supplying options to the underlying
- serializer without defining a custom renderer.
+ .. versionadded:: 1.4
+ Prior to this version, there was no public API for supplying options
+ to the underlying serializer without defining a custom renderer.
"""
def __init__(self, serializer=json.dumps, adapters=(), **kw):
@@ -303,8 +300,8 @@ class JSONP(JSON):
config = Configurator()
config.add_renderer('jsonp', JSONP(param_name='callback', indent=4))
- .. note:: The ability of this class to accept a ``**kw`` in its
- constructor is new as of Pyramid 1.4.
+ .. versionchanged:: 1.4
+ The ability of this class to accept a ``**kw`` in its constructor.
The arguments passed to this class' constructor mean the same thing as
the arguments passed to :class:`pyramid.renderers.JSON` (including
@@ -332,7 +329,7 @@ class JSONP(JSON):
- If there is no callback parameter in the request's query string, the
renderer will return a 'plain' JSON response.
- .. note:: This feature is new in Pyramid 1.1.
+ .. versionadded:: 1.1
See also: :ref:`jsonp_renderer`.
"""
diff --git a/pyramid/request.py b/pyramid/request.py
index 27ab337de..f9aa253ac 100644
--- a/pyramid/request.py
+++ b/pyramid/request.py
@@ -321,7 +321,7 @@ class Request(BaseRequest, DeprecatedRequestMethodsMixin, URLMethodsMixin,
version number from which this documentation is autogenerated, but
it will be the 'prevailing WebOb version' at the time of the
release of this :app:`Pyramid` version. See
- http://pythonpaste.org/webob/ for further information.
+ http://webob.org/ for further information.
"""
exception = None
exc_info = None
diff --git a/pyramid/response.py b/pyramid/response.py
index 1dccb7ae8..0f61af472 100644
--- a/pyramid/response.py
+++ b/pyramid/response.py
@@ -35,20 +35,20 @@ class FileResponse(Response):
``path`` is a file path on disk.
- ``request`` must be a Pyramid :term:`request` object if passed. Note
+ ``request`` must be a Pyramid :term:`request` object. Note
that a request *must* be passed if the response is meant to attempt to
use the ``wsgi.file_wrapper`` feature of the web server that you're using
to serve your Pyramid application.
- ``cache_max_age`` if passed, is the number of seconds that should be used
+ ``cache_max_age`` is the number of seconds that should be used
to HTTP cache this response.
- ``content_type``, if passed, is the content_type of the response.
+ ``content_type`` is the content_type of the response.
- ``content_encoding``, if passed is the content_encoding of the response.
+ ``content_encoding`` is the content_encoding of the response.
It's generally safe to leave this set to ``None`` if you're serving a
- binary file. This argument will be ignored if you don't also pass
- ``content-type``.
+ binary file. This argument will be ignored if you also leave
+ ``content-type`` as ``None``.
"""
def __init__(self, path, request=None, cache_max_age=None,
content_type=None, content_encoding=None):
diff --git a/pyramid/router.py b/pyramid/router.py
index 9b6138ea9..63c12a1af 100644
--- a/pyramid/router.py
+++ b/pyramid/router.py
@@ -1,4 +1,5 @@
from zope.interface import (
+ Interface,
implementer,
providedBy,
)
@@ -24,6 +25,7 @@ from pyramid.events import (
NewResponse,
)
+from pyramid.exceptions import PredicateMismatch
from pyramid.httpexceptions import HTTPNotFound
from pyramid.request import Request
from pyramid.threadlocal import manager
@@ -158,8 +160,23 @@ class Router(object):
msg = request.path_info
raise HTTPNotFound(msg)
else:
- response = view_callable(context, request)
-
+ try:
+ response = view_callable(context, request)
+ except PredicateMismatch:
+ # look for other views that meet the predicate
+ # criteria
+ for iface in context_iface.flattened():
+ view_callable = adapters.lookup(
+ (IViewClassifier, request.request_iface, iface),
+ IView, name=view_name, default=None)
+ if view_callable is not None:
+ try:
+ response = view_callable(context, request)
+ break
+ except PredicateMismatch:
+ pass
+ else:
+ raise
return response
def invoke_subrequest(self, request, use_tweens=False):
diff --git a/pyramid/scaffolds/alchemy/+package+/scripts/initializedb.py b/pyramid/scaffolds/alchemy/+package+/scripts/initializedb.py
index 66feb3008..7dfdece15 100644
--- a/pyramid/scaffolds/alchemy/+package+/scripts/initializedb.py
+++ b/pyramid/scaffolds/alchemy/+package+/scripts/initializedb.py
@@ -9,6 +9,8 @@ from pyramid.paster import (
setup_logging,
)
+from pyramid.scripts.common import parse_vars
+
from ..models import (
DBSession,
MyModel,
@@ -18,17 +20,18 @@ from ..models import (
def usage(argv):
cmd = os.path.basename(argv[0])
- print('usage: %s <config_uri>\n'
+ print('usage: %s <config_uri> [var=value]\n'
'(example: "%s development.ini")' % (cmd, cmd))
sys.exit(1)
def main(argv=sys.argv):
- if len(argv) != 2:
+ if len(argv) < 2:
usage(argv)
config_uri = argv[1]
+ options = parse_vars(argv[2:])
setup_logging(config_uri)
- settings = get_appsettings(config_uri)
+ settings = get_appsettings(config_uri, options=options)
engine = engine_from_config(settings, 'sqlalchemy.')
DBSession.configure(bind=engine)
Base.metadata.create_all(engine)
diff --git a/pyramid/scaffolds/alchemy/README.txt_tmpl b/pyramid/scaffolds/alchemy/README.txt_tmpl
index 9e4aa1125..a05c0e174 100644
--- a/pyramid/scaffolds/alchemy/README.txt_tmpl
+++ b/pyramid/scaffolds/alchemy/README.txt_tmpl
@@ -6,9 +6,9 @@ Getting Started
- cd <directory containing this file>
-- $venv/bin/python setup.py develop
+- $VENV/bin/python setup.py develop
-- $venv/bin/initialize_{{project}}_db development.ini
+- $VENV/bin/initialize_{{project}}_db development.ini
-- $venv/bin/pserve development.ini
+- $VENV/bin/pserve development.ini
diff --git a/pyramid/scaffolds/alchemy/setup.py_tmpl b/pyramid/scaffolds/alchemy/setup.py_tmpl
index b8c4c6ef1..69b5faea9 100644
--- a/pyramid/scaffolds/alchemy/setup.py_tmpl
+++ b/pyramid/scaffolds/alchemy/setup.py_tmpl
@@ -3,8 +3,10 @@ import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, 'README.txt')).read()
-CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = [
'pyramid',
diff --git a/pyramid/scaffolds/starter/setup.py_tmpl b/pyramid/scaffolds/starter/setup.py_tmpl
index db00ed2e6..c0908d96f 100644
--- a/pyramid/scaffolds/starter/setup.py_tmpl
+++ b/pyramid/scaffolds/starter/setup.py_tmpl
@@ -3,8 +3,10 @@ import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, 'README.txt')).read()
-CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = [
'pyramid',
diff --git a/pyramid/scaffolds/zodb/setup.py_tmpl b/pyramid/scaffolds/zodb/setup.py_tmpl
index b8610d004..02789657d 100644
--- a/pyramid/scaffolds/zodb/setup.py_tmpl
+++ b/pyramid/scaffolds/zodb/setup.py_tmpl
@@ -3,8 +3,10 @@ import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, 'README.txt')).read()
-CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = [
'pyramid',
diff --git a/pyramid/session.py b/pyramid/session.py
index a5e6a8d3a..7db8c8e0e 100644
--- a/pyramid/session.py
+++ b/pyramid/session.py
@@ -140,30 +140,30 @@ def UnencryptedCookieSessionFactoryConfig(
A number of seconds of inactivity before a session times out.
``cookie_name``
- The name of the cookie used for sessioning. Default: ``session``.
+ The name of the cookie used for sessioning.
``cookie_max_age``
The maximum age of the cookie used for sessioning (in seconds).
Default: ``None`` (browser scope).
``cookie_path``
- The path used for the session cookie. Default: ``/``.
+ The path used for the session cookie.
``cookie_domain``
The domain used for the session cookie. Default: ``None`` (no domain).
``cookie_secure``
- The 'secure' flag of the session cookie. Default: ``False``.
+ The 'secure' flag of the session cookie.
``cookie_httponly``
- The 'httpOnly' flag of the session cookie. Default: ``False``.
+ The 'httpOnly' flag of the session cookie.
``cookie_on_exception``
If ``True``, set a session cookie even if an exception occurs
- while rendering a view. Default: ``True``.
+ while rendering a view.
``signed_serialize``
- A callable which takes more or less arbitrary python data structure and
+ A callable which takes more or less arbitrary Python data structure and
a secret and returns a signed serialization in bytes.
Default: ``signed_serialize`` (using pickle).
diff --git a/pyramid/tests/fixtures/dummy.ini b/pyramid/tests/fixtures/dummy.ini
new file mode 100644
index 000000000..bc2281168
--- /dev/null
+++ b/pyramid/tests/fixtures/dummy.ini
@@ -0,0 +1,4 @@
+[app:myapp]
+use = call:pyramid.tests.test_paster:make_dummyapp
+
+foo = %(bar)s
diff --git a/pyramid/tests/fixtures/static/héhé.html b/pyramid/tests/fixtures/static/héhé.html
deleted file mode 100644
index fe5e9af50..000000000
--- a/pyramid/tests/fixtures/static/héhé.html
+++ /dev/null
@@ -1 +0,0 @@
-<html>hehe file</html>
diff --git a/pyramid/tests/fixtures/static/héhé/index.html b/pyramid/tests/fixtures/static/héhé/index.html
deleted file mode 100644
index 67623d866..000000000
--- a/pyramid/tests/fixtures/static/héhé/index.html
+++ /dev/null
@@ -1 +0,0 @@
-<html>hehe</html>
diff --git a/pyramid/tests/test_authentication.py b/pyramid/tests/test_authentication.py
index 123e4f9f5..cfabf9a9d 100644
--- a/pyramid/tests/test_authentication.py
+++ b/pyramid/tests/test_authentication.py
@@ -561,9 +561,13 @@ class TestAuthTktCookieHelper(unittest.TestCase):
helper.BadTicket = auth_tkt.BadTicket
return helper
- def _makeRequest(self, cookie=None):
+ def _makeRequest(self, cookie=None, ipv6=False):
environ = {'wsgi.version': (1,0)}
- environ['REMOTE_ADDR'] = '1.1.1.1'
+
+ if ipv6 is False:
+ environ['REMOTE_ADDR'] = '1.1.1.1'
+ else:
+ environ['REMOTE_ADDR'] = '::1'
environ['SERVER_NAME'] = 'localhost'
return DummyRequest(environ, cookie=cookie)
@@ -612,6 +616,23 @@ class TestAuthTktCookieHelper(unittest.TestCase):
self.assertEqual(environ['REMOTE_USER_DATA'],'')
self.assertEqual(environ['AUTH_TYPE'],'cookie')
+ def test_identify_good_cookie_include_ipv6(self):
+ helper = self._makeOne('secret', include_ip=True)
+ request = self._makeRequest('ticket', ipv6=True)
+ result = helper.identify(request)
+ self.assertEqual(len(result), 4)
+ self.assertEqual(result['tokens'], ())
+ self.assertEqual(result['userid'], 'userid')
+ self.assertEqual(result['userdata'], '')
+ self.assertEqual(result['timestamp'], 0)
+ self.assertEqual(helper.auth_tkt.value, 'ticket')
+ self.assertEqual(helper.auth_tkt.remote_addr, '::1')
+ self.assertEqual(helper.auth_tkt.secret, 'secret')
+ environ = request.environ
+ self.assertEqual(environ['REMOTE_USER_TOKENS'], ())
+ self.assertEqual(environ['REMOTE_USER_DATA'],'')
+ self.assertEqual(environ['AUTH_TYPE'],'cookie')
+
def test_identify_good_cookie_dont_include_ip(self):
helper = self._makeOne('secret', include_ip=False)
request = self._makeRequest('ticket')
@@ -1098,6 +1119,20 @@ class TestAuthTicket(unittest.TestCase):
self.assertEqual(result,
'66f9cc3e423dc57c91df696cf3d1f0d80000000auserid!a,b!')
+ def test_ipv4(self):
+ ticket = self._makeOne('secret', 'userid', '198.51.100.1',
+ time=10, hashalg='sha256')
+ result = ticket.cookie_value()
+ self.assertEqual(result, 'b3e7156db4f8abde4439c4a6499a0668f9e7ffd7fa27b'\
+ '798400ecdade8d76c530000000auserid!')
+
+ def test_ipv6(self):
+ ticket = self._makeOne('secret', 'userid', '2001:db8::1',
+ time=10, hashalg='sha256')
+ result = ticket.cookie_value()
+ self.assertEqual(result, 'd025b601a0f12ca6d008aa35ff3a22b7d8f3d1c1456c8'\
+ '5becf8760cd7a2fa4910000000auserid!')
+
class TestBadTicket(unittest.TestCase):
def _makeOne(self, msg, expected=None):
from pyramid.authentication import BadTicket
@@ -1141,6 +1176,19 @@ class Test_parse_ticket(unittest.TestCase):
result = self._callFUT('secret', ticket, '0.0.0.0', 'sha512')
self.assertEqual(result, (10, 'userid', ['a', 'b'], ''))
+ def test_ipv4(self):
+ ticket = 'b3e7156db4f8abde4439c4a6499a0668f9e7ffd7fa27b798400ecdade8d7'\
+ '6c530000000auserid!'
+ result = self._callFUT('secret', ticket, '198.51.100.1', 'sha256')
+ self.assertEqual(result, (10, 'userid', [''], ''))
+
+ def test_ipv6(self):
+ ticket = 'd025b601a0f12ca6d008aa35ff3a22b7d8f3d1c1456c85becf8760cd7a2f'\
+ 'a4910000000auserid!'
+ result = self._callFUT('secret', ticket, '2001:db8::1', 'sha256')
+ self.assertEqual(result, (10, 'userid', [''], ''))
+ pass
+
class TestSessionAuthenticationPolicy(unittest.TestCase):
def _getTargetClass(self):
from pyramid.authentication import SessionAuthenticationPolicy
diff --git a/pyramid/tests/test_authorization.py b/pyramid/tests/test_authorization.py
index 27f2a18b4..60b1b0c8d 100644
--- a/pyramid/tests/test_authorization.py
+++ b/pyramid/tests/test_authorization.py
@@ -215,6 +215,15 @@ class TestACLAuthorizationPolicy(unittest.TestCase):
result = sorted(
policy.principals_allowed_by_permission(context, 'read'))
self.assertEqual(result, [])
+
+ def test_callable_acl(self):
+ from pyramid.security import Allow
+ context = DummyContext()
+ fn = lambda self: [(Allow, 'bob', 'read')]
+ context.__acl__ = fn.__get__(context, context.__class__)
+ policy = self._makeOne()
+ result = policy.permits(context, ['bob'], 'read')
+ self.assertTrue(result)
class DummyContext:
diff --git a/pyramid/tests/test_config/test_views.py b/pyramid/tests/test_config/test_views.py
index 4cebdce8a..5388001f6 100644
--- a/pyramid/tests/test_config/test_views.py
+++ b/pyramid/tests/test_config/test_views.py
@@ -3737,6 +3737,13 @@ class TestStaticURLInfo(unittest.TestCase):
expected = [('http://example.com/', 'anotherpackage:path/', None)]
self._assertRegistrations(config, expected)
+ def test_add_url_noscheme(self):
+ inst = self._makeOne()
+ config = self._makeConfig()
+ inst.add(config, '//example.com', 'anotherpackage:path')
+ expected = [('//example.com/', 'anotherpackage:path/', None)]
+ self._assertRegistrations(config, expected)
+
def test_add_viewname(self):
from pyramid.security import NO_PERMISSION_REQUIRED
from pyramid.static import static_view
diff --git a/pyramid/tests/test_integration.py b/pyramid/tests/test_integration.py
index bf3960b2d..c8418c61d 100644
--- a/pyramid/tests/test_integration.py
+++ b/pyramid/tests/test_integration.py
@@ -3,7 +3,6 @@
import datetime
import locale
import os
-import platform
import unittest
from pyramid.wsgi import wsgiapp
@@ -82,27 +81,40 @@ class TestStaticAppBase(IntegrationBase):
res = self.testapp.get('/static/.hiddenfile', status=200)
_assertBody(res.body, os.path.join(here, 'fixtures/static/.hiddenfile'))
- if defaultlocale is not None and platform.system() == 'Linux':
+ if defaultlocale is not None:
# These tests are expected to fail on LANG=C systems due to decode
# errors and on non-Linux systems due to git highchar handling
# vagaries
def test_highchars_in_pathelement(self):
- url = url_quote('/static/héhé/index.html')
- res = self.testapp.get(url, status=200)
- _assertBody(
- res.body,
- os.path.join(here,
- text_('fixtures/static/héhé/index.html', 'utf-8'))
- )
+ path = os.path.join(
+ here,
+ text_('fixtures/static/héhé/index.html', 'utf-8'))
+ pathdir = os.path.dirname(path)
+ body = b'<html>hehe</html>\n'
+ try:
+ os.makedirs(pathdir)
+ with open(path, 'wb') as fp:
+ fp.write(body)
+ url = url_quote('/static/héhé/index.html')
+ res = self.testapp.get(url, status=200)
+ self.assertEqual(res.body, body)
+ finally:
+ os.unlink(path)
+ os.rmdir(pathdir)
def test_highchars_in_filename(self):
- url = url_quote('/static/héhé.html')
- res = self.testapp.get(url, status=200)
- _assertBody(
- res.body,
- os.path.join(here,
- text_('fixtures/static/héhé.html', 'utf-8'))
- )
+ path = os.path.join(
+ here,
+ text_('fixtures/static/héhé.html', 'utf-8'))
+ body = b'<html>hehe file</html>\n'
+ with open(path, 'wb') as fp:
+ fp.write(body)
+ try:
+ url = url_quote('/static/héhé.html')
+ res = self.testapp.get(url, status=200)
+ self.assertEqual(res.body, body)
+ finally:
+ os.unlink(path)
def test_not_modified(self):
self.testapp.extra_environ = {
@@ -634,6 +646,32 @@ class RendererScanAppTest(IntegrationBase, unittest.TestCase):
res = testapp.get('/two', status=200)
self.assertTrue(b'Two!' in res.body)
+class AcceptContentTypeTest(unittest.TestCase):
+ def setUp(self):
+ def hello_view(request):
+ return {'message': 'Hello!'}
+ from pyramid.config import Configurator
+ config = Configurator()
+ config.add_route('hello', '/hello')
+ config.add_view(hello_view, route_name='hello', accept='text/plain', renderer='string')
+ config.add_view(hello_view, route_name='hello', accept='application/json', renderer='json')
+ app = config.make_wsgi_app()
+ from webtest import TestApp
+ self.testapp = TestApp(app)
+
+ def test_ordering(self):
+ res = self.testapp.get('/hello', headers={'Accept': 'application/json; q=1.0, text/plain; q=0.9'}, status=200)
+ self.assertEqual(res.content_type, 'application/json')
+ res = self.testapp.get('/hello', headers={'Accept': 'text/plain; q=0.9, application/json; q=1.0'}, status=200)
+ self.assertEqual(res.content_type, 'application/json')
+
+ def test_wildcards(self):
+ res = self.testapp.get('/hello', headers={'Accept': 'application/*'}, status=200)
+ self.assertEqual(res.content_type, 'application/json')
+ res = self.testapp.get('/hello', headers={'Accept': 'text/*'}, status=200)
+ self.assertEqual(res.content_type, 'text/plain')
+
+
class DummyContext(object):
pass
@@ -663,4 +701,3 @@ def _assertBody(body, filename):
data = data.replace(b'\r', b'')
data = data.replace(b'\n', b'')
assert(body == data)
-
diff --git a/pyramid/tests/test_paster.py b/pyramid/tests/test_paster.py
index b72e0e6b6..5e341172c 100644
--- a/pyramid/tests/test_paster.py
+++ b/pyramid/tests/test_paster.py
@@ -1,12 +1,12 @@
import os
import unittest
+here = os.path.dirname(__file__)
+
class Test_get_app(unittest.TestCase):
- def _callFUT(self, config_file, section_name, options=None, loadapp=None):
+ def _callFUT(self, config_file, section_name, **kw):
from pyramid.paster import get_app
- return get_app(
- config_file, section_name, options=options, loadapp=loadapp
- )
+ return get_app(config_file, section_name, **kw)
def test_it(self):
app = DummyApp()
@@ -55,15 +55,23 @@ class Test_get_app(unittest.TestCase):
self.assertEqual(loadapp.kw, {'global_conf':options})
self.assertEqual(result, app)
+ def test_it_with_dummyapp_requiring_options(self):
+ options = {'bar': 'baz'}
+ app = self._callFUT(
+ os.path.join(here, 'fixtures', 'dummy.ini'),
+ 'myapp', options=options)
+ self.assertEqual(app.settings['foo'], 'baz')
+
class Test_get_appsettings(unittest.TestCase):
- def _callFUT(self, config_file, section_name, appconfig):
+ def _callFUT(self, config_file, section_name, **kw):
from pyramid.paster import get_appsettings
- return get_appsettings(config_file, section_name, appconfig)
+ return get_appsettings(config_file, section_name, **kw)
def test_it(self):
values = {'a':1}
appconfig = DummyLoadWSGI(values)
- result = self._callFUT('/foo/bar/myapp.ini', 'myapp', appconfig)
+ result = self._callFUT('/foo/bar/myapp.ini', 'myapp',
+ appconfig=appconfig)
self.assertEqual(appconfig.config_name, 'config:/foo/bar/myapp.ini')
self.assertEqual(appconfig.section_name, 'myapp')
self.assertEqual(appconfig.relative_to, os.getcwd())
@@ -72,7 +80,8 @@ class Test_get_appsettings(unittest.TestCase):
def test_it_with_hash(self):
values = {'a':1}
appconfig = DummyLoadWSGI(values)
- result = self._callFUT('/foo/bar/myapp.ini#myapp', None, appconfig)
+ result = self._callFUT('/foo/bar/myapp.ini#myapp', None,
+ appconfig=appconfig)
self.assertEqual(appconfig.config_name, 'config:/foo/bar/myapp.ini')
self.assertEqual(appconfig.section_name, 'myapp')
self.assertEqual(appconfig.relative_to, os.getcwd())
@@ -81,12 +90,20 @@ class Test_get_appsettings(unittest.TestCase):
def test_it_with_hash_and_name_override(self):
values = {'a':1}
appconfig = DummyLoadWSGI(values)
- result = self._callFUT('/foo/bar/myapp.ini#myapp', 'yourapp', appconfig)
+ result = self._callFUT('/foo/bar/myapp.ini#myapp', 'yourapp',
+ appconfig=appconfig)
self.assertEqual(appconfig.config_name, 'config:/foo/bar/myapp.ini')
self.assertEqual(appconfig.section_name, 'yourapp')
self.assertEqual(appconfig.relative_to, os.getcwd())
self.assertEqual(result, values)
+ def test_it_with_dummyapp_requiring_options(self):
+ options = {'bar': 'baz'}
+ result = self._callFUT(
+ os.path.join(here, 'fixtures', 'dummy.ini'),
+ 'myapp', options=options)
+ self.assertEqual(result['foo'], 'baz')
+
class Test_setup_logging(unittest.TestCase):
def _callFUT(self, config_file):
from pyramid.paster import setup_logging
@@ -165,6 +182,12 @@ class DummyApp:
def __init__(self):
self.registry = dummy_registry
+def make_dummyapp(global_conf, **settings):
+ app = DummyApp()
+ app.settings = settings
+ app.global_conf = global_conf
+ return app
+
class DummyRequest:
application_url = 'http://example.com:5432'
script_name = ''
@@ -181,6 +204,3 @@ class DummyConfigParser(object):
class DummyConfigParserModule(object):
ConfigParser = DummyConfigParser
-
-
-
diff --git a/pyramid/tests/test_router.py b/pyramid/tests/test_router.py
index 65152ca05..432959147 100644
--- a/pyramid/tests/test_router.py
+++ b/pyramid/tests/test_router.py
@@ -1164,6 +1164,104 @@ class TestRouter(unittest.TestCase):
start_response = DummyStartResponse()
self.assertRaises(RuntimeError, router, environ, start_response)
+ def test_call_view_raises_predicate_mismatch(self):
+ from pyramid.exceptions import PredicateMismatch
+ from pyramid.interfaces import IViewClassifier
+ from pyramid.interfaces import IRequest
+ view = DummyView(DummyResponse(), raise_exception=PredicateMismatch)
+ self._registerView(view, '', IViewClassifier, IRequest, None)
+ environ = self._makeEnviron()
+ router = self._makeOne()
+ start_response = DummyStartResponse()
+ self.assertRaises(PredicateMismatch, router, environ, start_response)
+
+ def test_call_view_predicate_mismatch_doesnt_hide_views(self):
+ from pyramid.exceptions import PredicateMismatch
+ from pyramid.interfaces import IViewClassifier
+ from pyramid.interfaces import IRequest, IResponse
+ from pyramid.response import Response
+ from zope.interface import Interface, implementer
+ class IContext(Interface):
+ pass
+ @implementer(IContext)
+ class DummyContext:
+ pass
+ context = DummyContext()
+ self._registerTraverserFactory(context)
+ view = DummyView(DummyResponse(), raise_exception=PredicateMismatch)
+ self._registerView(view, '', IViewClassifier, IRequest,
+ DummyContext)
+ good_view = DummyView('abc')
+ self._registerView(self.config.derive_view(good_view),
+ '', IViewClassifier, IRequest, IContext)
+ router = self._makeOne()
+ def make_response(s):
+ return Response(s)
+ router.registry.registerAdapter(make_response, (str,), IResponse)
+ environ = self._makeEnviron()
+ start_response = DummyStartResponse()
+ app_iter = router(environ, start_response)
+ self.assertEqual(app_iter, [b'abc'])
+
+ def test_call_view_multiple_predicate_mismatches_dont_hide_views(self):
+ from pyramid.exceptions import PredicateMismatch
+ from pyramid.interfaces import IViewClassifier
+ from pyramid.interfaces import IRequest, IResponse
+ from pyramid.response import Response
+ from zope.interface import Interface, implementer
+ class IBaseContext(Interface):
+ pass
+ class IContext(IBaseContext):
+ pass
+ @implementer(IContext)
+ class DummyContext:
+ pass
+ context = DummyContext()
+ self._registerTraverserFactory(context)
+ view1 = DummyView(DummyResponse(), raise_exception=PredicateMismatch)
+ self._registerView(view1, '', IViewClassifier, IRequest,
+ DummyContext)
+ view2 = DummyView(DummyResponse(), raise_exception=PredicateMismatch)
+ self._registerView(view2, '', IViewClassifier, IRequest,
+ IContext)
+ good_view = DummyView('abc')
+ self._registerView(self.config.derive_view(good_view),
+ '', IViewClassifier, IRequest, IBaseContext)
+ router = self._makeOne()
+ def make_response(s):
+ return Response(s)
+ router.registry.registerAdapter(make_response, (str,), IResponse)
+ environ = self._makeEnviron()
+ start_response = DummyStartResponse()
+ app_iter = router(environ, start_response)
+ self.assertEqual(app_iter, [b'abc'])
+
+ def test_call_view_predicate_mismatch_doesnt_find_unrelated_views(self):
+ from pyramid.exceptions import PredicateMismatch
+ from pyramid.interfaces import IViewClassifier
+ from pyramid.interfaces import IRequest
+ from zope.interface import Interface, implementer
+ class IContext(Interface):
+ pass
+ class IOtherContext(Interface):
+ pass
+ @implementer(IContext)
+ class DummyContext:
+ pass
+ context = DummyContext()
+ self._registerTraverserFactory(context)
+ view = DummyView(DummyResponse(), raise_exception=PredicateMismatch)
+ self._registerView(view, '', IViewClassifier, IRequest,
+ DummyContext)
+ please_dont_call_me_view = DummyView('abc')
+ self._registerView(self.config.derive_view(please_dont_call_me_view),
+ '', IViewClassifier, IRequest, IOtherContext)
+ router = self._makeOne()
+ environ = self._makeEnviron()
+ router = self._makeOne()
+ start_response = DummyStartResponse()
+ self.assertRaises(PredicateMismatch, router, environ, start_response)
+
class DummyPredicate(object):
def __call__(self, info, request):
return True
diff --git a/pyramid/tests/test_scaffolds/fixture_scaffold/setup.py_tmpl b/pyramid/tests/test_scaffolds/fixture_scaffold/setup.py_tmpl
index e63579d50..ee9fd5fda 100644
--- a/pyramid/tests/test_scaffolds/fixture_scaffold/setup.py_tmpl
+++ b/pyramid/tests/test_scaffolds/fixture_scaffold/setup.py_tmpl
@@ -3,8 +3,10 @@ import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, 'README.txt')).read()
-CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = ['pyramid', 'pyramid_debugtoolbar']
diff --git a/pyramid/tests/test_url.py b/pyramid/tests/test_url.py
index a7a565356..e33eeebfd 100644
--- a/pyramid/tests/test_url.py
+++ b/pyramid/tests/test_url.py
@@ -583,6 +583,21 @@ class TestURLMethodsMixin(unittest.TestCase):
self.assertEqual(result,
'http://example.com:5432/absstatic/test_url.py')
+ def test_static_url_noscheme_uses_scheme_from_request(self):
+ import os
+ from pyramid.interfaces import IStaticURLInfo
+ from pyramid.config.views import StaticURLInfo
+ info = StaticURLInfo()
+ here = os.path.abspath(os.path.dirname(__file__))
+ info.add(self.config, '//subdomain.example.com/static', here)
+ request = self._makeOne({'wsgi.url_scheme': 'https'})
+ registry = request.registry
+ registry.registerUtility(info, IStaticURLInfo)
+ abspath = os.path.join(here, 'test_url.py')
+ result = request.static_url(abspath)
+ self.assertEqual(result,
+ 'https://subdomain.example.com/static/test_url.py')
+
def test_static_path_abspath(self):
from pyramid.interfaces import IStaticURLInfo
request = self._makeOne()
diff --git a/pyramid/threadlocal.py b/pyramid/threadlocal.py
index d99b0b734..638f7b7b0 100644
--- a/pyramid/threadlocal.py
+++ b/pyramid/threadlocal.py
@@ -40,7 +40,7 @@ def get_current_request():
is currently active.
This function should be used *extremely sparingly*, usually only
- in unit testing code. it's almost always usually a mistake to use
+ in unit testing code. It's almost always usually a mistake to use
``get_current_request`` outside a testing context because its
usage makes it possible to write code that can be neither easily
tested nor scripted.
@@ -52,7 +52,7 @@ def get_current_registry(context=None): # context required by getSiteManager API
global application registry if no request is currently active.
This function should be used *extremely sparingly*, usually only
- in unit testing code. it's almost always usually a mistake to use
+ in unit testing code. It's almost always usually a mistake to use
``get_current_registry`` outside a testing context because its
usage makes it possible to write code that can be neither easily
tested nor scripted.
diff --git a/pyramid/url.py b/pyramid/url.py
index 8fb5e49ab..84b58ac45 100644
--- a/pyramid/url.py
+++ b/pyramid/url.py
@@ -390,9 +390,8 @@ class URLMethodsMixin(object):
pass ``app_url=''`. Passing ``app_url=''` when the resource path is
``/baz/bar`` will return ``/baz/bar``.
- .. note::
-
- ``app_url`` is new as of Pyramid 1.3.
+ .. versionadded:: 1.3
+ ``app_url``
If ``app_url`` is passed and any of ``scheme``, ``port``, or ``host``
are also passed, ``app_url`` will take precedence and the values
diff --git a/pyramid/view.py b/pyramid/view.py
index e1e03bd93..76752ce8f 100644
--- a/pyramid/view.py
+++ b/pyramid/view.py
@@ -29,9 +29,11 @@ _marker = object()
class static(static_view):
""" Backwards compatibility alias for
:class:`pyramid.static.static_view`; it overrides that class' constructor
- to pass ``use_subpath=True`` by default. This class is deprecated as of
- :app:`Pyramid` 1.1. Use :class:`pyramid.static.static_view` instead
- (probably with a ``use_subpath=True`` argument).
+ to pass ``use_subpath=True`` by default.
+
+ .. deprecated:: 1.1
+ use :class:`pyramid.static.static_view` instead
+ (probably with a ``use_subpath=True`` argument)
"""
def __init__(self, root_dir, cache_max_age=3600, package_name=None):
if package_name is None:
@@ -160,14 +162,14 @@ class view_config(object):
import views
from resources import MyResource
config.add_view(views.my_view, context=MyResource, name='my_view',
- permission='read', 'route_name='site1')
+ permission='read', route_name='site1')
.. note: :class:`pyramid.view.view_config` is also importable, for
backwards compatibility purposes, as the name
:class:`pyramid.view.bfg_view`.
- The following keyword arguments are supported to
- :class:`pyramid.view.view_config`: ``context``, ``permission``, ``name``,
+ :class:`pyramid.view.view_config` supports the following keyword
+ arguments: ``context``, ``permission``, ``name``,
``request_type``, ``route_name``, ``request_method``, ``request_param``,
``containment``, ``xhr``, ``accept``, ``header``, ``path_info``,
``custom_predicates``, ``decorator``, ``mapper``, ``http_cache``,
@@ -312,11 +314,12 @@ See also :ref:`changing_the_notfound_view`.
class notfound_view_config(object):
"""
+ .. versionadded:: 1.3
An analogue of :class:`pyramid.view.view_config` which registers a
- :term:`not found view`.
+ :term:`Not Found View`.
- The notfound_view_config constructor accepts most of the same arguments
+ The ``notfound_view_config`` constructor accepts most of the same arguments
as the constructor of :class:`pyramid.view.view_config`. It can be used
in the same places, and behaves in largely the same way, except it always
registers a not found exception view instead of a 'normal' view.
@@ -337,7 +340,7 @@ class notfound_view_config(object):
argument restricts the set of circumstances under which this notfound
view will be invoked.
- If ``append_slash`` is ``True``, when the notfound view is invoked, and
+ If ``append_slash`` is ``True``, when the Not Found View is invoked, and
the current path info does not end in a slash, the notfound logic will
attempt to find a :term:`route` that matches the request's path info
suffixed with a slash. If such a route exists, Pyramid will issue a
@@ -346,9 +349,6 @@ class notfound_view_config(object):
See :ref:`changing_the_notfound_view` for detailed usage information.
- .. note::
-
- This class is new as of Pyramid 1.3.
"""
venusian = venusian
@@ -377,6 +377,7 @@ class notfound_view_config(object):
class forbidden_view_config(object):
"""
+ .. versionadded:: 1.3
An analogue of :class:`pyramid.view.view_config` which registers a
:term:`forbidden view`.
@@ -394,7 +395,7 @@ class forbidden_view_config(object):
from pyramid.response import Response
@forbidden_view_config()
- def notfound(request):
+ def forbidden(request):
return Response('You are not allowed', status='401 Unauthorized')
All arguments passed to this function have the same meaning as
@@ -403,9 +404,6 @@ class forbidden_view_config(object):
See :ref:`changing_the_forbidden_view` for detailed usage information.
- .. note::
-
- This class is new as of Pyramid 1.3.
"""
venusian = venusian
@@ -436,11 +434,8 @@ def is_response(ob):
""" Return ``True`` if ``ob`` implements the interface implied by
:ref:`the_response`. ``False`` if not.
- .. warning::
-
- This function is deprecated as of :app:`Pyramid` 1.1. New
- code should not use it. Instead, new code should use the
- :func:`pyramid.request.Request.is_response` method."""
+ .. deprecated:: 1.1
+ use :func:`pyramid.request.Request.is_response` instead"""
if ( hasattr(ob, 'app_iter') and hasattr(ob, 'headerlist') and
hasattr(ob, 'status') ):
return True
diff --git a/setup.py b/setup.py
index 66c6aa5fa..4a3cecd98 100644
--- a/setup.py
+++ b/setup.py
@@ -1,6 +1,6 @@
##############################################################################
#
-# Copyright (c) 2008-2011 Agendaless Consulting and Contributors.
+# Copyright (c) 2008-2013 Agendaless Consulting and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the BSD-like license at
@@ -30,8 +30,10 @@ else:
here = os.path.abspath(os.path.dirname(__file__))
try:
- README = open(os.path.join(here, 'README.rst')).read()
- CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+ with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+ with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
except IOError:
README = CHANGES = ''