summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@plope.com>2011-04-22 13:42:19 -0400
committerChris McDonough <chrism@plope.com>2011-04-22 13:42:19 -0400
commited7ffe0e2065100f551793b3774656d8bdde0fb0 (patch)
tree53637b76d148774c5a7c3b9e103373e33e6c2f9e
parentc150d77248653172b487326a1059b8c0bc5056e4 (diff)
downloadpyramid-ed7ffe0e2065100f551793b3774656d8bdde0fb0.tar.gz
pyramid-ed7ffe0e2065100f551793b3774656d8bdde0fb0.tar.bz2
pyramid-ed7ffe0e2065100f551793b3774656d8bdde0fb0.zip
- Make sure deprecation warnings aren't raised when tests are run.
- Modify documentation for cross-referencing. - Use add_view(viewname) syntax rather than add_view(view=viewname) syntax for normalization. - Use warnings.warn rather than zope.deprecated in order to make testing easier. - Move tests which test deprecated methods of configurator to a separate test case.
-rw-r--r--CHANGES.txt24
-rw-r--r--docs/narr/advconfig.rst12
-rw-r--r--docs/narr/hybrid.rst39
-rw-r--r--docs/narr/urldispatch.rst117
-rw-r--r--docs/narr/viewconfig.rst4
-rw-r--r--docs/tutorials/wiki2/basiclayout.rst19
-rw-r--r--docs/tutorials/wiki2/definingviews.rst6
-rw-r--r--docs/tutorials/wiki2/src/authorization/tutorial/__init__.py10
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/__init__.py2
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/__init__.py2
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/__init__.py8
-rw-r--r--pyramid/config.py67
-rw-r--r--pyramid/paster_templates/routesalchemy/+package+/__init__.py_tmpl4
-rw-r--r--pyramid/tests/ccbugapp/__init__.py11
-rw-r--r--pyramid/tests/exceptionviewapp/__init__.py26
-rw-r--r--pyramid/tests/hybridapp/__init__.py3
-rw-r--r--pyramid/tests/restbugapp/__init__.py23
-rw-r--r--pyramid/tests/test_config.py367
18 files changed, 427 insertions, 317 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index c0108ff3a..9e967e5c5 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -162,6 +162,30 @@ Deprecations
``request.response_content_type = 'abc'`` should be changed to
``request.response.content_type = 'abc'``).
+- Passing view-related parameters to
+ ``pyramid.config.Configurator.add_route`` is now deprecated. Previously, a
+ view was permitted to be connected to a route using a set of ``view*``
+ parameters passed to the ``add_route`` method of the Configurator. This
+ was a shorthand which replaced the need to perform a subsequent call to
+ ``add_view``. For example, it was valid (and often recommended) to do::
+
+ config.add_route('home', '/', view='mypackage.views.myview',
+ view_renderer='some/renderer.pt')
+
+ Passing ``view*`` arguments to ``add_route`` is now deprecated in favor of
+ connecting a view to a predefined route via ``Configurator.add_view`` using
+ the route's ``route_name`` parameter. As a result, the above example
+ should now be spelled::
+
+ config.add_route('home', '/')
+ config.add_view('mypackage.views.myview', route_name='home')
+ renderer='some/renderer.pt')
+
+ This deprecation was done to reduce confusion observed in IRC, as well as
+ to (eventually) reduce documentation burden. A deprecation warning is now
+ issued when any view-related parameter is passed to
+ ``Configurator.add_route``.
+
Behavior Changes
----------------
diff --git a/docs/narr/advconfig.rst b/docs/narr/advconfig.rst
index 7ae80155b..5ee554284 100644
--- a/docs/narr/advconfig.rst
+++ b/docs/narr/advconfig.rst
@@ -295,15 +295,9 @@ These are the methods of the configurator which provide conflict detection:
:meth:`~pyramid.config.Configurator.set_locale_negotiator` and
:meth:`~pyramid.config.Configurator.set_default_permission`.
-Some other methods of the configurator also indirectly provide conflict
-detection, because they're implemented in terms of conflict-aware methods:
-
-- :meth:`~pyramid.config.Configurator.add_route` does a second type of
- conflict detection when a ``view`` parameter is passed (it calls
- ``add_view``). This behavior has been deprecated in :app:`Pyramid` 1.1.
-
-- :meth:`~pyramid.config.Configurator.static_view`, a frontend for
- ``add_route`` and ``add_view``.
+:meth:`~pyramid.config.Configurator.add_static_view` also indirectly
+provides conflict detection, because it's implemented in terms of the
+conflict-aware ``add_route`` and ``add_view`` methods.
.. _including_configuration:
diff --git a/docs/narr/hybrid.rst b/docs/narr/hybrid.rst
index d66ad59df..f8ed743fb 100644
--- a/docs/narr/hybrid.rst
+++ b/docs/narr/hybrid.rst
@@ -33,7 +33,7 @@ URL Dispatch Only
~~~~~~~~~~~~~~~~~
An application that uses :term:`url dispatch` exclusively to map URLs to code
-will often have statements like this within your application startup
+will often have statements like this within application startup
configuration:
.. code-block:: python
@@ -47,9 +47,14 @@ configuration:
config.add_view('myproject.views.foobar', route_name='foobar')
config.add_view('myproject.views.bazbuz', route_name='bazbuz')
-Each :term:`route` corresponds to one or more view callables,
-and when that route is matched during a request, :term:`view lookup` is used
-to match the request to one of the view callables.
+Each :term:`route` corresponds to one or more view callables. Each view
+callable is associated with a route by passing a ``route_name`` parameter
+that matches its name during a call to
+:meth:`~pyramid.config.Configurator.add_view`. When a route is matched
+during a request, :term:`view lookup` is used to match the request to its
+associated view callable. The presence of calls to
+:meth:`~pyramid.config.Configurator.add_route` signify that an application is
+using URL dispatch.
Traversal Only
~~~~~~~~~~~~~~
@@ -423,13 +428,11 @@ attribute.
Using ``*subpath`` in a Route Pattern
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-There are certain extremely rare cases when you'd like to influence
-the traversal :term:`subpath` when a route matches without actually
-performing traversal. For instance, the
-:func:`pyramid.wsgi.wsgiapp2` decorator and the
-:class:`pyramid.view.static` helper attempt to compute
-``PATH_INFO`` from the request's subpath, so it's useful to be able to
-influence this value.
+There are certain extremely rare cases when you'd like to influence the
+traversal :term:`subpath` when a route matches without actually performing
+traversal. For instance, the :func:`pyramid.wsgi.wsgiapp2` decorator and the
+:class:`pyramid.view.static` helper attempt to compute ``PATH_INFO`` from the
+request's subpath, so it's useful to be able to influence this value.
When ``*subpath`` exists in a pattern, no path is actually traversed,
but the traversal algorithm will return a :term:`subpath` list implied
@@ -455,14 +458,16 @@ application. We'll detail them here.
Registering a Default View for a Route That Has a ``view`` Attribute
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.. note:: As of :app:`Pyramid` 1.1 this issue is deprecated along with
- the ability to add views directly to the :term:`route configuration`.
+.. warning:: As of :app:`Pyramid` 1.1 this section is slated to be removed in
+ a later documentation release because the the ability to add views
+ directly to the :term:`route configuration` by passing a ``view`` argument
+ to ``add_route`` has been deprecated.
It is an error to provide *both* a ``view`` argument to a :term:`route
configuration` *and* a :term:`view configuration` which names a
``route_name`` that has no ``name`` value or the empty ``name`` value. For
-example, this pair of declarations will generate a "conflict" error at
-startup time.
+example, this pair of declarations will generate a conflict error at startup
+time.
.. code-block:: python
:linenos:
@@ -490,8 +495,8 @@ Can also be spelled like so:
config.add_route('home', '{foo}/{bar}/*traverse')
config.add_view('myproject.views.home', route_name='home')
-The two spellings are logically equivalent. In fact, the former is
-just a syntactical shortcut for the latter.
+The two spellings are logically equivalent. In fact, the former is just a
+syntactical shortcut for the latter.
Binding Extra Views Against a Route Configuration that Doesn't Have a ``*traverse`` Element In Its Pattern
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst
index 2a8052861..4923fd19f 100644
--- a/docs/narr/urldispatch.rst
+++ b/docs/narr/urldispatch.rst
@@ -54,13 +54,13 @@ Route Configuration
-------------------
:term:`Route configuration` is the act of adding a new :term:`route` to an
-application. A route has a *pattern*, representing a pattern meant to match
+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``),
-and a *route name*, which is used by developers within a :app:`Pyramid`
-application to uniquely identify a particular route when generating a URL.
-It also optionally has a ``factory``, a set of :term:`route predicate`
-parameters, and a set of view callables.
+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.
.. index::
single: add_route
@@ -89,22 +89,49 @@ example:
example ``/prefix/:one/:two``. This style is now deprecated
in favor of ``{}`` usage which allows for additional functionality.
-.. versionchanged:: 1.1
- Prior to 1.1, views were typically connected to routes using a set of
- view parameters on :meth:`pyramid.config.Configurator.add_route`. That
- behavior is now deprecated in favor of connecting views to routes using
- :meth:`pyramid.config.Configurator.add_view` with the ``route_name``
- parameter.
-
.. index::
single: route configuration; view callable
+.. _add_route_view_config:
+
Route Configuration That Names a View Callable
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. warning:: This section describes a feature which has been deprecated in
- Pyramid 1.1. The recommended way to connect view callables to routes
- is via :ref:`config-add-route`.
+ Pyramid 1.1 and higher. In order to reduce confusion and documentation
+ burden, passing view-related parameters to
+ :meth:`~pyramid.config.Configurator.add_route` is deprecated.
+
+ In versions earlier than 1.1, a view was permitted to be connected to a
+ route using a set of ``view*`` parameters passed to the
+ :meth:`~pyramid.config.Configurator.add_route`. This was a shorthand
+ which replaced the need to perform a subsequent call to
+ :meth:`~pyramid.config.Configurator.add_view` as described in
+ :ref:`config-add-route`. For example, it was valid (and often recommended)
+ to do:
+
+ .. code-block:: python
+
+ config.add_route('home', '/', view='mypackage.views.myview',
+ view_renderer='some/renderer.pt')
+
+ Instead of the equivalent:
+
+ .. code-block:: python
+
+ config.add_route('home', '/')
+ config.add_view('mypackage.views.myview', route_name='home')
+ renderer='some/renderer.pt')
+
+ Passing ``view*`` arguments to ``add_route`` as shown in the first
+ example above is now deprecated in favor of connecting a view to a
+ predefined route via :meth:`~pyramid.config.Configurator.add_view` using
+ the route's ``route_name`` parameter, as shown in the second example
+ above.
+
+ A deprecation warning is now issued when any view-related parameter is
+ passed to ``Configurator.add_route``. The recommended way to associate a
+ view with a route is documented in :ref:`config-add-route`.
When a route configuration declaration names a ``view`` attribute, the value
of the attribute will reference a :term:`view callable`. This view callable
@@ -139,6 +166,9 @@ When a route configuration names a ``view`` attribute, the :term:`view
callable` named as that ``view`` attribute will always be found and invoked
when the associated route pattern matches during a request.
+See :ref:`add_route_view_related_api` for a description of view-related
+arguments to ``add_route``.
+
.. index::
single: route path pattern syntax
@@ -377,7 +407,8 @@ resource of the view callable ultimately found via :term:`view lookup`.
.. code-block:: python
:linenos:
- config.add_route('abc', '/abc', factory='myproject.resources.root_factory')
+ config.add_route('abc', '/abc',
+ factory='myproject.resources.root_factory')
config.add_view('myproject.views.theview', route_name='abc')
The factory can either be a Python object or a :term:`dotted Python name` (a
@@ -410,7 +441,7 @@ process. Examples of route predicate arguments are ``pattern``, ``xhr``, and
Other arguments are view configuration related arguments. These only have an
effect when the route configuration names a ``view``. These arguments have
-been deprecated as of :app:`Pyramid` 1.1.
+been deprecated as of :app:`Pyramid` 1.1 (see :ref:`add_route_view_config`).
Other arguments are ``name`` and ``factory``. These arguments represent
neither predicates nor view configuration information.
@@ -562,8 +593,8 @@ If any route matches, the route matching process stops. The :term:`request`
is decorated with a special :term:`interface` which describes it as a "route
request", the :term:`context` resource is generated, and the context and the
resulting request are handed off to :term:`view lookup`. During view lookup,
-if any ``view`` was provided within the matched route configuration, the
-:term:`view callable` it points to is called.
+if a :term:`view callable` associated with the matched route is found, that
+view is called.
When a route configuration is declared, it may contain :term:`route
predicate` arguments. All route predicates associated with a route
@@ -754,34 +785,6 @@ request in its ``__init__``. For example:
In a more complicated application, this root factory might be a class
representing a :term:`SQLAlchemy` model.
-Example 4
-~~~~~~~~~
-
-It is possible to create a route declaration without a ``view`` attribute,
-but associate the route with a :term:`view callable` using a ``view``
-declaration.
-
-.. code-block:: python
- :linenos:
-
- config.add_route('idea', 'site/{id}')
- config.add_view(route_name='idea', view='mypackage.views.site_view')
-
-This set of configuration parameters creates a configuration completely
-equivalent to this example provided in :ref:`urldispatch_example1`:
-
-.. code-block:: python
- :linenos:
-
- config.add_route('idea', 'site/{id}', view='mypackage.views.site_view')
-
-In fact, the spelling which names a ``view`` attribute is just syntactic
-sugar for the more verbose spelling which contains separate view and route
-registrations.
-
-More uses for this style of associating views with routes are explored in
-:ref:`hybrid_chapter`.
-
.. index::
single: matching the root URL
single: root url (matching)
@@ -884,8 +887,8 @@ the application's startup configuration, adding the following stanza:
.. code-block:: python
:linenos:
- config.add_view(context='pyramid.exceptions.NotFound',
- view='pyramid.view.append_slash_notfound_view')
+ config.add_view('pyramid.view.append_slash_notfound_view',
+ context='pyramid.exceptions.NotFound')
See :ref:`view_module` and :ref:`changing_the_notfound_view` for more
information about the slash-appending not found view and for a more general
@@ -1083,25 +1086,25 @@ is executed.
Route View Callable Registration and Lookup Details
---------------------------------------------------
-When a request enters the system which matches the pattern of the route,
-the result is simple: the view callable associated with the route is invoked
-with the request that caused the invocation.
+When a request enters the system which matches the pattern of the route, the
+usual result is simple: the view callable associated with the route is
+invoked with the request that caused the invocation.
For most usage, you needn't understand more than this; how it works is an
implementation detail. In the interest of completeness, however, we'll
explain how it *does* work in the this section. You can skip it if you're
uninterested.
-When a ``view`` is attached to a route configuration, :app:`Pyramid` ensures
-that a :term:`view configuration` is registered that will always be found when
-the route pattern is matched during a request. To do so:
+When a view is associated with a route configuration, :app:`Pyramid` ensures
+that a :term:`view configuration` is registered that will always be found
+when the route pattern is matched during a request. To do so:
- A special route-specific :term:`interface` is created at startup time for
each route configuration declaration.
-- When a route configuration declaration mentions a ``view`` attribute, a
+- When an ``add_view`` statement mentions a ``route name`` attribute, a
:term:`view configuration` is registered at startup time. This view
- configuration uses the route-specific interface as a :term:`request` type.
+ configuration uses a route-specific interface as a :term:`request` type.
- At runtime, when a request causes any route to match, the :term:`request`
object is decorated with the route-specific interface.
diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst
index 7ee8e3fe5..743cc016e 100644
--- a/docs/narr/viewconfig.rst
+++ b/docs/narr/viewconfig.rst
@@ -59,8 +59,8 @@ View configuration is performed in one of these ways:
- By specifying a view within a :term:`route configuration`. View
configuration via a route configuration is performed by using the
:meth:`pyramid.config.Configurator.add_route` method, passing a ``view``
- argument specifying a view callable. This method is deprecated as of
- :app:`Pyramid` 1.1.
+ argument specifying a view callable. This pattern of view configuration is
+ deprecated as of :app:`Pyramid` 1.1.
.. note:: A package named ``pyramid_handlers`` (available from PyPI) provides
an analogue of :term:`Pylons` -style "controllers", which are a special
diff --git a/docs/tutorials/wiki2/basiclayout.rst b/docs/tutorials/wiki2/basiclayout.rst
index bb39a686d..82e112c64 100644
--- a/docs/tutorials/wiki2/basiclayout.rst
+++ b/docs/tutorials/wiki2/basiclayout.rst
@@ -85,9 +85,9 @@ used when the URL is ``/``:
:language: py
Since this route has a ``pattern`` equalling ``/`` it is the route that will
-be called when the URL ``/`` is visted, e.g. ``http://localhost:6543/``.
+be matched when the URL ``/`` is visted, e.g. ``http://localhost:6543/``.
-Mapping the ``home`` route to code is done by registering a ``view``. You will
+Mapping the ``home`` route to code is done by registering a view. You will
use :meth:`pyramid.config.Configurator.add_view` in :term:`URL dispatch` to
register views for the routes, mapping your patterns to code:
@@ -95,13 +95,14 @@ register views for the routes, mapping your patterns to code:
:lines: 14
:language: py
-The ``view`` argument of ``tutorial.views.my_view`` is the dotted name to a
-*function* we write (generated by the ``pyramid_routesalchemy`` scaffold) that
-is given a ``request`` object and which returns a response or a dictionary.
-This view also names a ``renderer``, which is a template which lives in the
-``templates`` subdirectory of the package. When the ``tutorial.views.my_view``
-view returns a dictionary, a :term:`renderer` will use this template to create
-a response.
+The first positional ``add_view`` argument ``tutorial.views.my_view`` is the
+dotted name to a *function* we write (generated by the
+``pyramid_routesalchemy`` scaffold) that is given a ``request`` object and
+which returns a response or a dictionary. This view also names a
+``renderer``, which is a template which lives in the ``templates``
+subdirectory of the package. When the ``tutorial.views.my_view`` view
+returns a dictionary, a :term:`renderer` will use this template to create a
+response. This
Finally, we use the :meth:`pyramid.config.Configurator.make_wsgi_app`
method to return a :term:`WSGI` application:
diff --git a/docs/tutorials/wiki2/definingviews.rst b/docs/tutorials/wiki2/definingviews.rst
index f59f75702..832f90b92 100644
--- a/docs/tutorials/wiki2/definingviews.rst
+++ b/docs/tutorials/wiki2/definingviews.rst
@@ -282,8 +282,7 @@ these declarations is very important. ``route`` declarations are matched in
the order they're found in the ``__init__.py`` file.
#. Add a declaration which maps the pattern ``/`` (signifying the root URL)
- to the route named ``view_wiki``. This is the :term:`default view` for the
- wiki.
+ to the route named ``view_wiki``.
#. Add a declaration which maps the pattern ``/{pagename}`` to the route named
``view_page``. This is the regular view for a page.
@@ -299,7 +298,8 @@ to handle the processing and rendering that needs to happen when each route is
requested.
#. Add a declaration which maps the ``view_wiki`` route to the view named
- ``view_wiki`` in our ``views.py`` file.
+ ``view_wiki`` in our ``views.py`` file. This is the :term:`default view`
+ for the wiki.
#. Add a declaration which maps the ``view_page`` route to the view named
``view_page`` in our ``views.py`` file.
diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/__init__.py b/docs/tutorials/wiki2/src/authorization/tutorial/__init__.py
index 7da99775c..e8baa568c 100644
--- a/docs/tutorials/wiki2/src/authorization/tutorial/__init__.py
+++ b/docs/tutorials/wiki2/src/authorization/tutorial/__init__.py
@@ -29,14 +29,14 @@ def main(global_config, **settings):
config.add_route('edit_page', '/{pagename}/edit_page')
config.add_route('view_wiki', '/')
- config.add_view(route_name='login', view='tutorial.login.login',
+ config.add_view('tutorial.login.login', route_name='login',
renderer='tutorial:templates/login.pt')
- config.add_view(route_name='logout', view='tutorial.login.logout')
- config.add_view(route_name='view_page', view='tutorial.views.view_page',
+ config.add_view('tutorial.login.logout', route_name='logout')
+ config.add_view('tutorial.views.view_page', route_name='view_page',
renderer='tutorial:templates/view.pt')
- config.add_view(route_name='add_page', view='tutorial.views.add_page',
+ config.add_view('tutorial.views.add_page', route_name='add_page',
renderer='tutorial:templates/edit.pt', permission='edit')
- config.add_view(route_name='edit_page', view='tutorial.views.edit_page',
+ config.add_view('tutorial.views.edit_page', route_name='edit_page',
renderer='tutorial:templates/edit.pt', permission='edit')
config.add_view('tutorial.login.login',
context='pyramid.exceptions.Forbidden',
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/__init__.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/__init__.py
index 43fd7f0fe..c74f07652 100644
--- a/docs/tutorials/wiki2/src/basiclayout/tutorial/__init__.py
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/__init__.py
@@ -11,7 +11,7 @@ def main(global_config, **settings):
config = Configurator(settings=settings)
config.add_static_view('static', 'tutorial:static')
config.add_route('home', '/')
- config.add_view(route_name='home', view='tutorial.views.my_view',
+ config.add_view('tutorial.views.my_view', route_name='home',
renderer='templates/mytemplate.pt')
return config.make_wsgi_app()
diff --git a/docs/tutorials/wiki2/src/models/tutorial/__init__.py b/docs/tutorials/wiki2/src/models/tutorial/__init__.py
index ff46bbf8f..ecc41ca9f 100644
--- a/docs/tutorials/wiki2/src/models/tutorial/__init__.py
+++ b/docs/tutorials/wiki2/src/models/tutorial/__init__.py
@@ -11,6 +11,6 @@ def main(global_config, **settings):
config = Configurator(settings=settings)
config.add_static_view('static', 'tutorial:static')
config.add_route('home', '/')
- config.add_view(route_name='home', view='tutorial.views.my_view',
+ config.add_view('tutorial.views.my_view', route_name='home',
renderer='templates/mytemplate.pt')
return config.make_wsgi_app()
diff --git a/docs/tutorials/wiki2/src/views/tutorial/__init__.py b/docs/tutorials/wiki2/src/views/tutorial/__init__.py
index 93abf83e7..ad89c124e 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/__init__.py
+++ b/docs/tutorials/wiki2/src/views/tutorial/__init__.py
@@ -14,12 +14,12 @@ def main(global_config, **settings):
config.add_route('view_page', '/{pagename}')
config.add_route('add_page', '/add_page/{pagename}')
config.add_route('edit_page', '/{pagename}/edit_page')
- config.add_view(route_name='view_wiki', view='tutorial.views.view_wiki')
- config.add_view(route_name='view_page', view='tutorial.views.view_page',
+ config.add_view('tutorial.views.view_wiki', route_name='view_wiki')
+ config.add_view('tutorial.views.view_page', route_name='view_page',
renderer='tutorial:templates/view.pt')
- config.add_view(route_name='add_page', view='tutorial.views.add_page',
+ config.add_view('tutorial.views.add_page', route_name='add_page',
renderer='tutorial:templates/edit.pt')
- config.add_view(route_name='edit_page', view='tutorial.views.edit_page',
+ config.add_view('tutorial.views.edit_page', route_name='edit_page',
renderer='tutorial:templates/edit.pt')
return config.make_wsgi_app()
diff --git a/pyramid/config.py b/pyramid/config.py
index 334e00201..eedb6ad9f 100644
--- a/pyramid/config.py
+++ b/pyramid/config.py
@@ -4,6 +4,7 @@ import re
import sys
import types
import traceback
+import warnings
import venusian
@@ -13,8 +14,6 @@ from zope.configuration.config import GroupingContextDecorator
from zope.configuration.config import ConfigurationMachine
from zope.configuration.xmlconfig import registerCommonDirectives
-from zope.deprecation import deprecated
-
from zope.interface import Interface
from zope.interface import implementedBy
from zope.interface.interfaces import IInterface
@@ -1380,7 +1379,6 @@ class Configurator(object):
discriminator = tuple(discriminator)
self.action(discriminator, register)
- @action_method
def _add_view_from_route(self,
route_name,
view,
@@ -1418,9 +1416,14 @@ class Configurator(object):
raise ConfigurationError(
'view_renderer argument not permitted without '
'view argument')
- _add_view_from_route = deprecated(
- _add_view_from_route, 'Use add_view() to add views for a route. No '
- 'longer supported directly from add_route() in pyramid 1.1')
+
+ warnings.warn(
+ 'Passing view-related arguments to add_route() is deprecated as of '
+ 'Pyramid 1.1. Use add_view() to associate a view with a route '
+ 'instead. See "Deprecations" in "What\'s New in Pyramid 1.1" '
+ 'within the general Pyramid documentation for further details.',
+ DeprecationWarning,
+ 4)
@action_method
def add_route(self,
@@ -1457,13 +1460,6 @@ class Configurator(object):
narrow the circumstances in which a route will be match a
request; non-predicate arguments are informational.
- .. warning:: View-related arguments have been deprecated in
- :app:`Pyramid` 1.1. *Do not use it for new development;
- it should only be used to support older code bases which
- depend upon it.* Use
- :meth:`pyramid.config.Configurator.add_view` to add views
- to a route.
-
Non-Predicate Arguments
name
@@ -1535,6 +1531,14 @@ class Configurator(object):
by applications, it is meant to be hooked by frameworks
that use :app:`Pyramid` as a base.
+ use_global_views
+
+ When a request matches this route, and view lookup cannot
+ find a view which has a ``route_name`` predicate argument
+ that matches the route, try to fall back to using a view
+ that otherwise matches the context, request, and view name
+ (but which does not match the route_name predicate).
+
Predicate Arguments
pattern
@@ -1641,12 +1645,21 @@ class Configurator(object):
:ref:`custom_route_predicates` for more information about
``info``.
+ .. _add_route_view_related_api:
+
View-Related Arguments
+ .. warning:: The arguments described below have been deprecated as of
+ :app:`Pyramid` 1.1. *Do not use these for new development; they
+ should only be used to support older code bases which depend upon
+ them.* Use a separate call to
+ :meth:`pyramid.config.Configurator.add_view` to associate a view
+ with a route.
+
view
- .. warning:: Deprecated in favor of
- :meth:`pyramid.config.Configurator.add_view`.
+ .. warning:: Deprecated as of :app:`Pyramid` 1.1; see
+ :ref:`add_route_view_related_api`.
A Python object or :term:`dotted Python name` to the same
object that will be used as a view callable when this route
@@ -1654,8 +1667,8 @@ class Configurator(object):
view_context
- .. warning:: Deprecated in favor of
- :meth:`pyramid.config.Configurator.add_view`.
+ .. warning:: Deprecated as of :app:`Pyramid` 1.1; see
+ :ref:`add_route_view_related_api`.
A class or an :term:`interface` or :term:`dotted Python
name` to the same object which the :term:`context` of the
@@ -1671,8 +1684,8 @@ class Configurator(object):
view_permission
- .. warning:: Deprecated in favor of
- :meth:`pyramid.config.Configurator.add_view`.
+ .. warning:: Deprecated as of :app:`Pyramid` 1.1; see
+ :ref:`add_route_view_related_api`.
The permission name required to invoke the view associated
with this route. e.g. ``edit``. (see
@@ -1686,8 +1699,8 @@ class Configurator(object):
view_renderer
- .. warning:: Deprecated in favor of
- :meth:`pyramid.config.Configurator.add_view`.
+ .. warning:: Deprecated as of :app:`Pyramid` 1.1; see
+ :ref:`add_route_view_related_api`.
This is either a single string term (e.g. ``json``) or a
string implying a path or :term:`asset specification`
@@ -1711,8 +1724,8 @@ class Configurator(object):
view_attr
- .. warning:: Deprecated in favor of
- :meth:`pyramid.config.Configurator.add_view`.
+ .. warning:: Deprecated as of :app:`Pyramid` 1.1; see
+ :ref:`add_route_view_related_api`.
The view machinery defaults to using the ``__call__`` method
of the view callable (or the function itself, if the view
@@ -1728,14 +1741,6 @@ class Configurator(object):
If the ``view`` argument is not provided, this argument has no
effect.
- use_global_views
-
- When a request matches this route, and view lookup cannot
- find a view which has a ``route_name`` predicate argument
- that matches the route, try to fall back to using a view
- that otherwise matches the context, request, and view name
- (but which does not match the route_name predicate).
-
"""
# these are route predicates; if they do not match, the next route
# in the routelist will be tried
diff --git a/pyramid/paster_templates/routesalchemy/+package+/__init__.py_tmpl b/pyramid/paster_templates/routesalchemy/+package+/__init__.py_tmpl
index aea2393d6..f5e3a0630 100644
--- a/pyramid/paster_templates/routesalchemy/+package+/__init__.py_tmpl
+++ b/pyramid/paster_templates/routesalchemy/+package+/__init__.py_tmpl
@@ -11,8 +11,8 @@ def main(global_config, **settings):
config = Configurator(settings=settings)
config.add_static_view('static', '{{package}}:static')
config.add_route('home', '/')
- config.add_view(route_name='home',
- view='{{package}}.views.my_view',
+ config.add_view('{{package}}.views.my_view',
+ route_name='home',
renderer='templates/mytemplate.pt')
return config.make_wsgi_app()
diff --git a/pyramid/tests/ccbugapp/__init__.py b/pyramid/tests/ccbugapp/__init__.py
index 6c2eb6ecf..ad6387a75 100644
--- a/pyramid/tests/ccbugapp/__init__.py
+++ b/pyramid/tests/ccbugapp/__init__.py
@@ -1,7 +1,8 @@
def includeme(config):
- config.add_route('rdf',
- 'licenses/:license_code/:license_version/rdf',
- '.views.rdf_view')
+ config.add_route('rdf', 'licenses/:license_code/:license_version/rdf')
config.add_route('juri',
- 'licenses/:license_code/:license_version/:jurisdiction',
- '.views.juri_view')
+ 'licenses/:license_code/:license_version/:jurisdiction')
+ config.add_view('.views.rdf_view', route_name='rdf')
+ config.add_view('.views.juri_view', route_name='juri')
+
+
diff --git a/pyramid/tests/exceptionviewapp/__init__.py b/pyramid/tests/exceptionviewapp/__init__.py
index cf69227cd..f169e0cd5 100644
--- a/pyramid/tests/exceptionviewapp/__init__.py
+++ b/pyramid/tests/exceptionviewapp/__init__.py
@@ -1,21 +1,23 @@
def includeme(config):
+ config.add_route('route_raise_exception', 'route_raise_exception')
+ config.add_route('route_raise_exception2', 'route_raise_exception2',
+ factory='.models.route_factory')
+ config.add_route('route_raise_exception3', 'route_raise_exception3',
+ factory='.models.route_factory2')
+ config.add_route('route_raise_exception4', 'route_raise_exception4')
config.add_view('.views.maybe')
config.add_view('.views.no', context='.models.NotAnException')
config.add_view('.views.yes', context=".models.AnException")
config.add_view('.views.raise_exception', name='raise_exception')
- config.add_route('route_raise_exception', 'route_raise_exception',
- view='.views.raise_exception')
- config.add_route('route_raise_exception2',
- 'route_raise_exception2',
- view='.views.raise_exception',
- factory='.models.route_factory')
- config.add_route('route_raise_exception3',
- 'route_raise_exception3',
- view='.views.raise_exception',
- factory='.models.route_factory2')
+ config.add_view('.views.raise_exception',
+ route_name='route_raise_exception')
+ config.add_view('.views.raise_exception',
+ route_name='route_raise_exception2')
+ config.add_view('.views.raise_exception',
+ route_name='route_raise_exception3')
config.add_view('.views.whoa', context='.models.AnException',
route_name='route_raise_exception3')
- config.add_route('route_raise_exception4', 'route_raise_exception4',
- view='.views.raise_exception')
+ config.add_view('.views.raise_exception',
+ route_name='route_raise_exception4')
config.add_view('.views.whoa', context='.models.AnException',
route_name='route_raise_exception4')
diff --git a/pyramid/tests/hybridapp/__init__.py b/pyramid/tests/hybridapp/__init__.py
index 5b51e3d1e..1cc2dde83 100644
--- a/pyramid/tests/hybridapp/__init__.py
+++ b/pyramid/tests/hybridapp/__init__.py
@@ -1,6 +1,7 @@
def includeme(config):
# <!-- we want this view to "win" -->
- config.add_route('route', 'abc', view='.views.route_view')
+ config.add_route('route', 'abc')
+ config.add_view('.views.route_view', route_name='route')
# <!-- .. even though this one has a more specific context -->
config.add_view('.views.global_view',
context='pyramid.traversal.DefaultRootFactory')
diff --git a/pyramid/tests/restbugapp/__init__.py b/pyramid/tests/restbugapp/__init__.py
index 461fcce92..9ad79e32e 100644
--- a/pyramid/tests/restbugapp/__init__.py
+++ b/pyramid/tests/restbugapp/__init__.py
@@ -1,14 +1,15 @@
def includeme(config):
config.add_route('gameactions_pet_get_pets', '/pet',
- view='.views.PetRESTView',
- view_attr='GET',
- request_method='GET',
- permission='view',
- renderer='json')
+ request_method='GET')
config.add_route('gameactions_pet_care_for_pet', '/pet',
- view='.views.PetRESTView',
- view_attr='POST',
- request_method='POST',
- permission='view',
- renderer='json')
-
+ request_method='POST')
+ config.add_view('.views.PetRESTView',
+ route_name='gameactions_pet_get_pets',
+ attr='GET',
+ permission='view',
+ renderer='json')
+ config.add_view('.views.PetRESTView',
+ route_name='gameactions_pet_care_for_pet',
+ attr='POST',
+ permission='view',
+ renderer='json')
diff --git a/pyramid/tests/test_config.py b/pyramid/tests/test_config.py
index 5818f248b..578965702 100644
--- a/pyramid/tests/test_config.py
+++ b/pyramid/tests/test_config.py
@@ -68,6 +68,12 @@ class ConfiguratorTests(unittest.TestCase):
request.registry = config.registry
return request
+ def _conflictFunctions(self, e):
+ conflicts = e._conflicts.values()
+ for conflict in conflicts:
+ for confinst in conflict:
+ yield confinst[2]
+
def test_ctor_no_registry(self):
import sys
from pyramid.interfaces import ISettings
@@ -1979,129 +1985,6 @@ class ConfiguratorTests(unittest.TestCase):
request.accept = ['text/html']
self.assertEqual(predicate(None, request), False)
- def test_add_route_with_view(self):
- config = self._makeOne(autocommit=True)
- view = lambda *arg: 'OK'
- config.add_route('name', 'path', view=view)
- request_type = self._getRouteRequestIface(config, 'name')
- wrapper = self._getViewCallable(config, None, request_type)
- self.assertEqual(wrapper(None, None), 'OK')
- self._assertRoute(config, 'name', 'path')
-
- def test_add_route_with_view_context(self):
- config = self._makeOne(autocommit=True)
- view = lambda *arg: 'OK'
- config.add_route('name', 'path', view=view, view_context=IDummy)
- request_type = self._getRouteRequestIface(config, 'name')
- wrapper = self._getViewCallable(config, IDummy, request_type)
- self.assertEqual(wrapper(None, None), 'OK')
- self._assertRoute(config, 'name', 'path')
- wrapper = self._getViewCallable(config, IOther, request_type)
- self.assertEqual(wrapper, None)
-
- def test_add_route_with_view_exception(self):
- from zope.interface import implementedBy
- config = self._makeOne(autocommit=True)
- view = lambda *arg: 'OK'
- config.add_route('name', 'path', view=view, view_context=RuntimeError)
- request_type = self._getRouteRequestIface(config, 'name')
- wrapper = self._getViewCallable(
- config, ctx_iface=implementedBy(RuntimeError),
- request_iface=request_type, exception_view=True)
- self.assertEqual(wrapper(None, None), 'OK')
- self._assertRoute(config, 'name', 'path')
- wrapper = self._getViewCallable(
- config, ctx_iface=IOther,
- request_iface=request_type, exception_view=True)
- self.assertEqual(wrapper, None)
-
- def test_add_route_with_view_for(self):
- config = self._makeOne(autocommit=True)
- view = lambda *arg: 'OK'
- config.add_route('name', 'path', view=view, view_for=IDummy)
- request_type = self._getRouteRequestIface(config, 'name')
- wrapper = self._getViewCallable(config, IDummy, request_type)
- self.assertEqual(wrapper(None, None), 'OK')
- self._assertRoute(config, 'name', 'path')
- wrapper = self._getViewCallable(config, IOther, request_type)
- self.assertEqual(wrapper, None)
-
- def test_add_route_with_for_(self):
- config = self._makeOne(autocommit=True)
- view = lambda *arg: 'OK'
- config.add_route('name', 'path', view=view, for_=IDummy)
- request_type = self._getRouteRequestIface(config, 'name')
- wrapper = self._getViewCallable(config, IDummy, request_type)
- self.assertEqual(wrapper(None, None), 'OK')
- self._assertRoute(config, 'name', 'path')
- wrapper = self._getViewCallable(config, IOther, request_type)
- self.assertEqual(wrapper, None)
-
- def test_add_route_with_view_renderer(self):
- config = self._makeOne(autocommit=True)
- self._registerRenderer(config)
- view = lambda *arg: 'OK'
- config.add_route('name', 'path', view=view,
- view_renderer='fixtures/minimal.txt')
- request_type = self._getRouteRequestIface(config, 'name')
- wrapper = self._getViewCallable(config, None, request_type)
- self._assertRoute(config, 'name', 'path')
- self.assertEqual(wrapper(None, None).body, 'Hello!')
-
- def test_add_route_with_view_attr(self):
- config = self._makeOne(autocommit=True)
- self._registerRenderer(config)
- class View(object):
- def __init__(self, context, request):
- pass
- def alt(self):
- return 'OK'
- config.add_route('name', 'path', view=View, view_attr='alt')
- request_type = self._getRouteRequestIface(config, 'name')
- wrapper = self._getViewCallable(config, None, request_type)
- self._assertRoute(config, 'name', 'path')
- request = self._makeRequest(config)
- self.assertEqual(wrapper(None, request), 'OK')
-
- def test_add_route_with_view_renderer_alias(self):
- config = self._makeOne(autocommit=True)
- self._registerRenderer(config)
- view = lambda *arg: 'OK'
- config.add_route('name', 'path', view=view,
- renderer='fixtures/minimal.txt')
- request_type = self._getRouteRequestIface(config, 'name')
- wrapper = self._getViewCallable(config, None, request_type)
- self._assertRoute(config, 'name', 'path')
- self.assertEqual(wrapper(None, None).body, 'Hello!')
-
- def test_add_route_with_view_permission(self):
- from pyramid.interfaces import IAuthenticationPolicy
- from pyramid.interfaces import IAuthorizationPolicy
- config = self._makeOne(autocommit=True)
- policy = lambda *arg: None
- config.registry.registerUtility(policy, IAuthenticationPolicy)
- config.registry.registerUtility(policy, IAuthorizationPolicy)
- view = lambda *arg: 'OK'
- config.add_route('name', 'path', view=view, view_permission='edit')
- request_type = self._getRouteRequestIface(config, 'name')
- wrapper = self._getViewCallable(config, None, request_type)
- self._assertRoute(config, 'name', 'path')
- self.assertTrue(hasattr(wrapper, '__call_permissive__'))
-
- def test_add_route_with_view_permission_alias(self):
- from pyramid.interfaces import IAuthenticationPolicy
- from pyramid.interfaces import IAuthorizationPolicy
- config = self._makeOne(autocommit=True)
- policy = lambda *arg: None
- config.registry.registerUtility(policy, IAuthenticationPolicy)
- config.registry.registerUtility(policy, IAuthorizationPolicy)
- view = lambda *arg: 'OK'
- config.add_route('name', 'path', view=view, permission='edit')
- request_type = self._getRouteRequestIface(config, 'name')
- wrapper = self._getViewCallable(config, None, request_type)
- self._assertRoute(config, 'name', 'path')
- self.assertTrue(hasattr(wrapper, '__call_permissive__'))
-
def test_add_route_no_pattern_with_path(self):
config = self._makeOne(autocommit=True)
route = config.add_route('name', path='path')
@@ -3035,24 +2918,6 @@ class ConfiguratorTests(unittest.TestCase):
registeredview = self._getViewCallable(config)
self.assertEqual(registeredview.__name__, 'view3')
- def test_conflict_route_with_view(self):
- from zope.configuration.config import ConfigurationConflictError
- config = self._makeOne()
- def view1(request): pass
- def view2(request): pass
- config.add_route('a', '/a', view=view1)
- config.add_route('a', '/a', view=view2)
- try:
- config.commit()
- except ConfigurationConflictError, why:
- c1, c2, c3, c4 = self._conflictFunctions(why)
- self.assertEqual(c1, 'test_conflict_route_with_view')
- self.assertEqual(c2, 'test_conflict_route_with_view')
- self.assertEqual(c3, 'test_conflict_route_with_view')
- self.assertEqual(c4, 'test_conflict_route_with_view')
- else: # pragma: no cover
- raise AssertionError
-
def test_conflict_set_notfound_view(self):
from zope.configuration.config import ConfigurationConflictError
config = self._makeOne()
@@ -3106,12 +2971,6 @@ class ConfiguratorTests(unittest.TestCase):
self.assertTrue("@view_config(name='two', renderer='string')" in
which)
- def _conflictFunctions(self, e):
- conflicts = e._conflicts.values()
- for conflict in conflicts:
- for confinst in conflict:
- yield confinst[2]
-
def test___getattr__missing_when_directives_exist(self):
config = self._makeOne()
directives = {}
@@ -3138,6 +2997,220 @@ class ConfiguratorTests(unittest.TestCase):
foo_meth = config.foo
self.assertTrue(foo_meth.im_func is foo)
+class TestConfiguratorDeprecatedFeatures(unittest.TestCase):
+ def setUp(self):
+ import warnings
+ warnings.filterwarnings('ignore')
+
+ def tearDown(self):
+ import warnings
+ warnings.resetwarnings()
+
+ def _makeOne(self, *arg, **kw):
+ from pyramid.config import Configurator
+ return Configurator(*arg, **kw)
+
+ def _getRouteRequestIface(self, config, name):
+ from pyramid.interfaces import IRouteRequest
+ iface = config.registry.getUtility(IRouteRequest, name)
+ return iface
+
+ def _getViewCallable(self, config, ctx_iface=None, request_iface=None,
+ name='', exception_view=False):
+ from zope.interface import Interface
+ from pyramid.interfaces import IRequest
+ from pyramid.interfaces import IView
+ from pyramid.interfaces import IViewClassifier
+ from pyramid.interfaces import IExceptionViewClassifier
+ if exception_view:
+ classifier = IExceptionViewClassifier
+ else:
+ classifier = IViewClassifier
+ if ctx_iface is None:
+ ctx_iface = Interface
+ if request_iface is None:
+ request_iface = IRequest
+ return config.registry.adapters.lookup(
+ (classifier, request_iface, ctx_iface), IView, name=name,
+ default=None)
+
+ def _registerRenderer(self, config, name='.txt'):
+ from pyramid.interfaces import IRendererFactory
+ from pyramid.interfaces import ITemplateRenderer
+ from zope.interface import implements
+ class Renderer:
+ implements(ITemplateRenderer)
+ def __init__(self, info):
+ self.__class__.info = info
+ def __call__(self, *arg):
+ return 'Hello!'
+ config.registry.registerUtility(Renderer, IRendererFactory, name=name)
+ return Renderer
+
+ def _assertRoute(self, config, name, path, num_predicates=0):
+ from pyramid.interfaces import IRoutesMapper
+ mapper = config.registry.getUtility(IRoutesMapper)
+ routes = mapper.get_routes()
+ route = routes[0]
+ self.assertEqual(len(routes), 1)
+ self.assertEqual(route.name, name)
+ self.assertEqual(route.path, path)
+ self.assertEqual(len(routes[0].predicates), num_predicates)
+ return route
+
+ def _makeRequest(self, config):
+ request = DummyRequest()
+ request.registry = config.registry
+ return request
+
+ def _conflictFunctions(self, e):
+ conflicts = e._conflicts.values()
+ for conflict in conflicts:
+ for confinst in conflict:
+ yield confinst[2]
+
+ def test_add_route_with_view(self):
+ config = self._makeOne(autocommit=True)
+ view = lambda *arg: 'OK'
+ config.add_route('name', 'path', view=view)
+ request_type = self._getRouteRequestIface(config, 'name')
+ wrapper = self._getViewCallable(config, None, request_type)
+ self.assertEqual(wrapper(None, None), 'OK')
+ self._assertRoute(config, 'name', 'path')
+
+ def test_add_route_with_view_context(self):
+ config = self._makeOne(autocommit=True)
+ view = lambda *arg: 'OK'
+ config.add_route('name', 'path', view=view, view_context=IDummy)
+ request_type = self._getRouteRequestIface(config, 'name')
+ wrapper = self._getViewCallable(config, IDummy, request_type)
+ self.assertEqual(wrapper(None, None), 'OK')
+ self._assertRoute(config, 'name', 'path')
+ wrapper = self._getViewCallable(config, IOther, request_type)
+ self.assertEqual(wrapper, None)
+
+ def test_add_route_with_view_exception(self):
+ from zope.interface import implementedBy
+ config = self._makeOne(autocommit=True)
+ view = lambda *arg: 'OK'
+ config.add_route('name', 'path', view=view, view_context=RuntimeError)
+ request_type = self._getRouteRequestIface(config, 'name')
+ wrapper = self._getViewCallable(
+ config, ctx_iface=implementedBy(RuntimeError),
+ request_iface=request_type, exception_view=True)
+ self.assertEqual(wrapper(None, None), 'OK')
+ self._assertRoute(config, 'name', 'path')
+ wrapper = self._getViewCallable(
+ config, ctx_iface=IOther,
+ request_iface=request_type, exception_view=True)
+ self.assertEqual(wrapper, None)
+
+ def test_add_route_with_view_for(self):
+ config = self._makeOne(autocommit=True)
+ view = lambda *arg: 'OK'
+ config.add_route('name', 'path', view=view, view_for=IDummy)
+ request_type = self._getRouteRequestIface(config, 'name')
+ wrapper = self._getViewCallable(config, IDummy, request_type)
+ self.assertEqual(wrapper(None, None), 'OK')
+ self._assertRoute(config, 'name', 'path')
+ wrapper = self._getViewCallable(config, IOther, request_type)
+ self.assertEqual(wrapper, None)
+
+ def test_add_route_with_for_(self):
+ config = self._makeOne(autocommit=True)
+ view = lambda *arg: 'OK'
+ config.add_route('name', 'path', view=view, for_=IDummy)
+ request_type = self._getRouteRequestIface(config, 'name')
+ wrapper = self._getViewCallable(config, IDummy, request_type)
+ self.assertEqual(wrapper(None, None), 'OK')
+ self._assertRoute(config, 'name', 'path')
+ wrapper = self._getViewCallable(config, IOther, request_type)
+ self.assertEqual(wrapper, None)
+
+ def test_add_route_with_view_renderer(self):
+ config = self._makeOne(autocommit=True)
+ self._registerRenderer(config)
+ view = lambda *arg: 'OK'
+ config.add_route('name', 'path', view=view,
+ view_renderer='fixtures/minimal.txt')
+ request_type = self._getRouteRequestIface(config, 'name')
+ wrapper = self._getViewCallable(config, None, request_type)
+ self._assertRoute(config, 'name', 'path')
+ self.assertEqual(wrapper(None, None).body, 'Hello!')
+
+ def test_add_route_with_view_attr(self):
+ config = self._makeOne(autocommit=True)
+ self._registerRenderer(config)
+ class View(object):
+ def __init__(self, context, request):
+ pass
+ def alt(self):
+ return 'OK'
+ config.add_route('name', 'path', view=View, view_attr='alt')
+ request_type = self._getRouteRequestIface(config, 'name')
+ wrapper = self._getViewCallable(config, None, request_type)
+ self._assertRoute(config, 'name', 'path')
+ request = self._makeRequest(config)
+ self.assertEqual(wrapper(None, request), 'OK')
+
+ def test_add_route_with_view_renderer_alias(self):
+ config = self._makeOne(autocommit=True)
+ self._registerRenderer(config)
+ view = lambda *arg: 'OK'
+ config.add_route('name', 'path', view=view,
+ renderer='fixtures/minimal.txt')
+ request_type = self._getRouteRequestIface(config, 'name')
+ wrapper = self._getViewCallable(config, None, request_type)
+ self._assertRoute(config, 'name', 'path')
+ self.assertEqual(wrapper(None, None).body, 'Hello!')
+
+ def test_add_route_with_view_permission(self):
+ from pyramid.interfaces import IAuthenticationPolicy
+ from pyramid.interfaces import IAuthorizationPolicy
+ config = self._makeOne(autocommit=True)
+ policy = lambda *arg: None
+ config.registry.registerUtility(policy, IAuthenticationPolicy)
+ config.registry.registerUtility(policy, IAuthorizationPolicy)
+ view = lambda *arg: 'OK'
+ config.add_route('name', 'path', view=view, view_permission='edit')
+ request_type = self._getRouteRequestIface(config, 'name')
+ wrapper = self._getViewCallable(config, None, request_type)
+ self._assertRoute(config, 'name', 'path')
+ self.assertTrue(hasattr(wrapper, '__call_permissive__'))
+
+ def test_add_route_with_view_permission_alias(self):
+ from pyramid.interfaces import IAuthenticationPolicy
+ from pyramid.interfaces import IAuthorizationPolicy
+ config = self._makeOne(autocommit=True)
+ policy = lambda *arg: None
+ config.registry.registerUtility(policy, IAuthenticationPolicy)
+ config.registry.registerUtility(policy, IAuthorizationPolicy)
+ view = lambda *arg: 'OK'
+ config.add_route('name', 'path', view=view, permission='edit')
+ request_type = self._getRouteRequestIface(config, 'name')
+ wrapper = self._getViewCallable(config, None, request_type)
+ self._assertRoute(config, 'name', 'path')
+ self.assertTrue(hasattr(wrapper, '__call_permissive__'))
+
+ def test_conflict_route_with_view(self):
+ from zope.configuration.config import ConfigurationConflictError
+ config = self._makeOne()
+ def view1(request): pass
+ def view2(request): pass
+ config.add_route('a', '/a', view=view1)
+ config.add_route('a', '/a', view=view2)
+ try:
+ config.commit()
+ except ConfigurationConflictError, why:
+ c1, c2, c3, c4 = self._conflictFunctions(why)
+ self.assertEqual(c1, 'test_conflict_route_with_view')
+ self.assertEqual(c2, 'test_conflict_route_with_view')
+ self.assertEqual(c3, 'test_conflict_route_with_view')
+ self.assertEqual(c4, 'test_conflict_route_with_view')
+ else: # pragma: no cover
+ raise AssertionError
+
+
class TestConfigurator_add_directive(unittest.TestCase):
def setUp(self):