summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.txt35
-rw-r--r--README.rst2
-rw-r--r--TODO.txt6
-rw-r--r--docs/conf.py2
-rw-r--r--docs/whatsnew-1.2.rst40
-rw-r--r--pyramid/config/__init__.py32
-rw-r--r--pyramid/config/adapters.py5
-rw-r--r--pyramid/config/assets.py1
-rw-r--r--pyramid/config/factories.py7
-rw-r--r--pyramid/config/rendering.py14
-rw-r--r--pyramid/config/routes.py72
-rw-r--r--pyramid/config/security.py40
-rw-r--r--pyramid/config/tweens.py14
-rw-r--r--pyramid/config/views.py54
-rw-r--r--pyramid/httpexceptions.py2
-rw-r--r--pyramid/interfaces.py10
-rw-r--r--pyramid/tests/ccbugapp/__init__.py16
-rw-r--r--pyramid/tests/ccbugapp/views.py10
-rw-r--r--pyramid/tests/conflictapp/__init__.py23
-rw-r--r--pyramid/tests/conflictapp/included.py6
-rw-r--r--pyramid/tests/test_config/test_init.py179
-rw-r--r--pyramid/tests/test_config/test_security.py84
-rw-r--r--pyramid/tests/test_integration.py65
-rw-r--r--setup.py2
24 files changed, 451 insertions, 270 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index c752f8005..e5340de4c 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,6 +1,14 @@
Next release
============
+- When a ``renderers=`` argument is not specified to the Configurator
+ constructor, eagerly register and commit the default renderer set. This
+ permits the overriding of the default renderers, which was broken in 1.2a1
+ without a commit directly after Configurator construction.
+
+1.2a1 (2011-08-24)
+==================
+
Features
--------
@@ -171,6 +179,33 @@ Backwards Incompatibilities
instead make a separate call to the method for each callable. This change
was introduced to support the ``route_prefix`` feature of include.
+- It may be necessary to more strictly order configuration route and view
+ statements when using an "autocommitting" Configurator. In the past, it
+ was possible to add a view which named a route name before adding a route
+ with that name when you used an autocommitting configurator. For example::
+
+ config = Configurator(autocommit=True)
+ config.add_view('my.pkg.someview', route_name='foo')
+ config.add_route('foo', '/foo')
+
+ The above will raise an exception when the view attempts to add itself.
+ Now you must add the route before adding the view::
+
+ config = Configurator(autocommit=True)
+ config.add_route('foo', '/foo')
+ config.add_view('my.pkg.someview', route_name='foo')
+
+ This won't effect "normal" users, only people who have legacy BFG codebases
+ that used an autommitting configurator and possibly tests that use the
+ configurator API (the configurator returned by ``pyramid.testing.setUp`` is
+ an autocommitting configurator). The right way to get around this is to
+ use a non-autocommitting configurator (the default), which does not have
+ these directive ordering requirements.
+
+- The ``pyramid.config.Configurator.add_route`` directive no longer returns a
+ route object. This change was required to make route vs. view
+ configuration processing work properly.
+
Documentation
-------------
diff --git a/README.rst b/README.rst
index 5534efc4d..895c5bb07 100644
--- a/README.rst
+++ b/README.rst
@@ -8,8 +8,6 @@ deployment more fun, more predictable, and more productive.
Pyramid is the newest web framework produced by the `Pylons Project
<http://pylonsproject.org/>`_.
-Pyramid was previously known as `repoze.bfg <http://bfg.repoze.org>`_.
-
Support and Documentation
-------------------------
diff --git a/TODO.txt b/TODO.txt
index 29869630d..7d5b096e5 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -8,12 +8,12 @@ Should-Have
deploying via proxy:
https://docs.pylonsproject.org/projects/pyramid_cookbook/dev/deployment/nginx.html#step-2-starting-paster
-- Fix conflict behavior for routes and auth policies (define phases and use
- order=).
-
Nice-to-Have
------------
+- Add a default-view-config-params decorator that can be applied to a class
+ which names defaults for method-based view_config decorator options.
+
- Flesh out "paste" chapter.
- Move config-related stuff from "renderers" to config/rendering, and
diff --git a/docs/conf.py b/docs/conf.py
index f021f01a2..23b88b949 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -93,7 +93,7 @@ copyright = '%s, Agendaless Consulting' % datetime.datetime.now().year
# other places throughout the built documents.
#
# The short X.Y version.
-version = '1.2dev'
+version = '1.2a1'
# The full version, including alpha/beta/rc tags.
release = version
diff --git a/docs/whatsnew-1.2.rst b/docs/whatsnew-1.2.rst
index 9718a547c..c5a71e1ce 100644
--- a/docs/whatsnew-1.2.rst
+++ b/docs/whatsnew-1.2.rst
@@ -176,6 +176,46 @@ Backwards Incompatibilities
:meth:`pyramid.config.Configurator.include`, it will break. You now must
now instead make a separate call to the method for each callable.
+- It may be necessary to more strictly order configuration route and view
+ statements when using an "autocommitting" :term:`Configurator`. In the
+ past, it was possible to add a view which named a route name before adding
+ a route with that name when you used an autocommitting configurator. For
+ example:
+
+ .. code-block:: python
+
+ config = Configurator(autocommit=True)
+ config.add_view('my.pkg.someview', route_name='foo')
+ config.add_route('foo', '/foo')
+
+ The above will raise an exception when the view attempts to add itself.
+ Now you must add the route before adding the view:
+
+ .. code-block:: python
+
+ config = Configurator(autocommit=True)
+ config.add_route('foo', '/foo')
+ config.add_view('my.pkg.someview', route_name='foo')
+
+ This won't effect "normal" users, only people who have legacy BFG codebases
+ that used an autommitting configurator and possibly tests that use the
+ configurator API (the configurator returned by
+ :func:`pyramid.testing.setUp` is an autocommitting configurator). The
+ right way to get around this is to use a default non-autocommitting
+ configurator, which does not have these directive ordering requirements:
+
+ .. code-block:: python
+
+ config = Configurator()
+ config.add_view('my.pkg.someview', route_name='foo')
+ config.add_route('foo', '/foo')
+
+ The above will work fine.
+
+- The :meth:`pyramid.config.Configurator.add_route` directive no longer
+ returns a route object. This change was required to make route vs. view
+ configuration processing work properly.
+
Documentation Enhancements
--------------------------
diff --git a/pyramid/config/__init__.py b/pyramid/config/__init__.py
index c7ee8c47f..dc592977b 100644
--- a/pyramid/config/__init__.py
+++ b/pyramid/config/__init__.py
@@ -303,29 +303,33 @@ class Configurator(
self.add_view(exceptionresponse_view, context=IExceptionResponse)
self.add_view(exceptionresponse_view,context=WebobWSGIHTTPException)
- # commit before adding default_view_mapper, as the
- # exceptionresponse_view above requires the superdefault view
- # mapper
+ # commit below because:
+ #
+ # - the default exceptionresponse_view requires the superdefault view
+ # mapper, so we need to configure it before adding default_view_mapper
+ #
+ # - superdefault renderers should be overrideable without requiring
+ # the user to commit before calling config.add_renderer
self.commit()
- if default_view_mapper is not None:
- self.set_view_mapper(default_view_mapper)
- self.commit()
-
- # The following registrations should be treated as if the methods had
- # been called after configurator construction (commit should not be
- # called after this). Rationale: user-supplied implementations
- # should be preferred rather than add-on author implementations (as
- # per automatic conflict resolution).
+ # self.commit() should not be called after this point because the
+ # following registrations should be treated as analogues of methods
+ # called by the user after configurator construction. Rationale:
+ # user-supplied implementations should be preferred rather than
+ # add-on author implementations with the help of automatic conflict
+ # resolution.
if authentication_policy and not authorization_policy:
authorization_policy = ACLAuthorizationPolicy() # default
- if authentication_policy:
- self.set_authentication_policy(authentication_policy)
if authorization_policy:
self.set_authorization_policy(authorization_policy)
+ if authentication_policy:
+ self.set_authentication_policy(authentication_policy)
+
+ if default_view_mapper is not None:
+ self.set_view_mapper(default_view_mapper)
for name, renderer in renderers:
self.add_renderer(name, renderer)
diff --git a/pyramid/config/adapters.py b/pyramid/config/adapters.py
index f022e7f08..6c6ca92b7 100644
--- a/pyramid/config/adapters.py
+++ b/pyramid/config/adapters.py
@@ -1,6 +1,7 @@
from zope.interface import Interface
from pyramid.interfaces import IResponse
+from pyramid.interfaces import PHASE3_CONFIG
from pyramid.config.util import action_method
@@ -27,7 +28,7 @@ class AdaptersConfiguratorMixin(object):
iface = (iface,)
def register():
self.registry.registerHandler(subscriber, iface)
- self.action(None, register)
+ self.action(None, register, order=PHASE3_CONFIG)
return subscriber
@action_method
@@ -52,7 +53,7 @@ class AdaptersConfiguratorMixin(object):
reg.registerSelfAdapter((type_or_iface,), IResponse)
else:
reg.registerAdapter(adapter, (type_or_iface,), IResponse)
- self.action((IResponse, type_or_iface), register)
+ self.action((IResponse, type_or_iface), register, order=PHASE3_CONFIG)
def _register_response_adapters(self):
# cope with WebOb response objects that aren't decorated with IResponse
diff --git a/pyramid/config/assets.py b/pyramid/config/assets.py
index 931ffb74c..1b5254072 100644
--- a/pyramid/config/assets.py
+++ b/pyramid/config/assets.py
@@ -235,6 +235,7 @@ class AssetsConfiguratorMixin(object):
from_package = sys.modules[package]
to_package = sys.modules[override_package]
override(from_package, path, to_package, override_prefix)
+
self.action(None, register)
override_resource = override_asset # bw compat
diff --git a/pyramid/config/factories.py b/pyramid/config/factories.py
index 1421082cd..53db93c64 100644
--- a/pyramid/config/factories.py
+++ b/pyramid/config/factories.py
@@ -4,6 +4,7 @@ from pyramid.interfaces import IDefaultRootFactory
from pyramid.interfaces import IRequestFactory
from pyramid.interfaces import IRootFactory
from pyramid.interfaces import ISessionFactory
+from pyramid.interfaces import PHASE3_CONFIG
from pyramid.traversal import DefaultRootFactory
@@ -24,7 +25,7 @@ class FactoriesConfiguratorMixin(object):
def register():
self.registry.registerUtility(factory, IRootFactory)
self.registry.registerUtility(factory, IDefaultRootFactory) # b/c
- self.action(IRootFactory, register)
+ self.action(IRootFactory, register, order=PHASE3_CONFIG)
_set_root_factory = set_root_factory # bw compat
@@ -41,7 +42,7 @@ class FactoriesConfiguratorMixin(object):
"""
def register():
self.registry.registerUtility(session_factory, ISessionFactory)
- self.action(ISessionFactory, register)
+ self.action(ISessionFactory, register, order=PHASE3_CONFIG)
@action_method
def set_request_factory(self, factory):
@@ -60,5 +61,5 @@ class FactoriesConfiguratorMixin(object):
factory = self.maybe_dotted(factory)
def register():
self.registry.registerUtility(factory, IRequestFactory)
- self.action(IRequestFactory, register)
+ self.action(IRequestFactory, register, order=PHASE3_CONFIG)
diff --git a/pyramid/config/rendering.py b/pyramid/config/rendering.py
index 3096b3d8e..deb1404e7 100644
--- a/pyramid/config/rendering.py
+++ b/pyramid/config/rendering.py
@@ -2,6 +2,8 @@ import warnings
from pyramid.interfaces import IRendererFactory
from pyramid.interfaces import IRendererGlobalsFactory
+from pyramid.interfaces import PHASE1_CONFIG
+from pyramid.interfaces import PHASE3_CONFIG
from pyramid.config.util import action_method
@@ -49,10 +51,11 @@ class RenderingConfiguratorMixin(object):
# as a name
if not name:
name = ''
- # we need to register renderers eagerly because they are used during
- # view configuration
- self.registry.registerUtility(factory, IRendererFactory, name=name)
- self.action((IRendererFactory, name), None)
+ def register():
+ self.registry.registerUtility(factory, IRendererFactory, name=name)
+ # we need to register renderers early (in phase 1) because they are
+ # used during view configuration (which happens in phase 3)
+ self.action((IRendererFactory, name), register, order=PHASE1_CONFIG)
@action_method
def set_renderer_globals_factory(self, factory, warn=True):
@@ -86,5 +89,4 @@ class RenderingConfiguratorMixin(object):
factory = self.maybe_dotted(factory)
def register():
self.registry.registerUtility(factory, IRendererGlobalsFactory)
- self.action(IRendererGlobalsFactory, register)
-
+ self.action(IRendererGlobalsFactory, register, order=PHASE3_CONFIG)
diff --git a/pyramid/config/routes.py b/pyramid/config/routes.py
index 625ef436d..6de9b6e59 100644
--- a/pyramid/config/routes.py
+++ b/pyramid/config/routes.py
@@ -3,6 +3,7 @@ import warnings
from pyramid.interfaces import IRequest
from pyramid.interfaces import IRouteRequest
from pyramid.interfaces import IRoutesMapper
+from pyramid.interfaces import PHASE2_CONFIG
from pyramid.exceptions import ConfigurationError
from pyramid.request import route_request_iface
@@ -344,34 +345,6 @@ class RoutesConfiguratorMixin(object):
custom=custom_predicates
)
- request_iface = self.registry.queryUtility(IRouteRequest, name=name)
- if request_iface is None:
- if use_global_views:
- bases = (IRequest,)
- else:
- bases = ()
- request_iface = route_request_iface(name, bases)
- self.registry.registerUtility(
- request_iface, IRouteRequest, name=name)
- deferred_views = getattr(self.registry, 'deferred_route_views', {})
- view_info = deferred_views.pop(name, ())
- for info in view_info:
- self.add_view(**info)
-
- # deprecated adding views from add_route
- if any([view, view_context, view_permission, view_renderer,
- view_for, for_, permission, renderer, view_attr]):
- self._add_view_from_route(
- route_name=name,
- view=view,
- permission=view_permission or permission,
- context=view_context or view_for or for_,
- renderer=view_renderer or renderer,
- attr=view_attr,
- )
-
- mapper = self.get_routes_mapper()
-
factory = self.maybe_dotted(factory)
if pattern is None:
pattern = path
@@ -381,11 +354,46 @@ class RoutesConfiguratorMixin(object):
if self.route_prefix:
pattern = self.route_prefix.rstrip('/') + '/' + pattern.lstrip('/')
- discriminator = ('route', name)
- self.action(discriminator, None)
+ mapper = self.get_routes_mapper()
- return mapper.connect(name, pattern, factory, predicates=predicates,
- pregenerator=pregenerator, static=static)
+ def register_route_request_iface():
+ request_iface = self.registry.queryUtility(IRouteRequest, name=name)
+ if request_iface is None:
+ if use_global_views:
+ bases = (IRequest,)
+ else:
+ bases = ()
+ request_iface = route_request_iface(name, bases)
+ self.registry.registerUtility(
+ request_iface, IRouteRequest, name=name)
+
+ def register_connect():
+ return mapper.connect(name, pattern, factory, predicates=predicates,
+ pregenerator=pregenerator, static=static)
+
+
+ # We have to connect routes in the order they were provided;
+ # we can't use a phase to do that, because when the actions are
+ # sorted, actions in the same phase lose relative ordering
+ self.action(('route-connect', name), register_connect)
+
+ # But IRouteRequest interfaces must be registered before we begin to
+ # process view registrations (in phase 3)
+ self.action(('route', name), register_route_request_iface,
+ order=PHASE2_CONFIG)
+
+ # deprecated adding views from add_route; must come after
+ # route registration for purposes of autocommit ordering
+ if any([view, view_context, view_permission, view_renderer,
+ view_for, for_, permission, renderer, view_attr]):
+ self._add_view_from_route(
+ route_name=name,
+ view=view,
+ permission=view_permission or permission,
+ context=view_context or view_for or for_,
+ renderer=view_renderer or renderer,
+ attr=view_attr,
+ )
def get_routes_mapper(self):
""" Return the :term:`routes mapper` object associated with
diff --git a/pyramid/config/security.py b/pyramid/config/security.py
index 897d4bbec..bdf9be5e6 100644
--- a/pyramid/config/security.py
+++ b/pyramid/config/security.py
@@ -1,6 +1,9 @@
from pyramid.interfaces import IAuthorizationPolicy
from pyramid.interfaces import IAuthenticationPolicy
from pyramid.interfaces import IDefaultPermission
+from pyramid.interfaces import PHASE1_CONFIG
+from pyramid.interfaces import PHASE2_CONFIG
+from pyramid.interfaces import PHASE3_CONFIG
from pyramid.exceptions import ConfigurationError
from pyramid.config.util import action_method
@@ -18,18 +21,16 @@ class SecurityConfiguratorMixin(object):
can be used to achieve the same purpose.
"""
- self._set_authentication_policy(policy)
- def ensure():
- if self.autocommit:
- return
+ def register():
+ self._set_authentication_policy(policy)
if self.registry.queryUtility(IAuthorizationPolicy) is None:
raise ConfigurationError(
'Cannot configure an authentication policy without '
'also configuring an authorization policy '
- '(see the set_authorization_policy method)')
- self.action(IAuthenticationPolicy, callable=ensure)
+ '(use the set_authorization_policy method)')
+ # authentication policy used by view config (phase 3)
+ self.action(IAuthenticationPolicy, register, order=PHASE2_CONFIG)
- @action_method
def _set_authentication_policy(self, policy):
policy = self.maybe_dotted(policy)
self.registry.registerUtility(policy, IAuthenticationPolicy)
@@ -45,16 +46,22 @@ class SecurityConfiguratorMixin(object):
:class:`pyramid.config.Configurator` constructor
can be used to achieve the same purpose.
"""
- self._set_authorization_policy(policy)
+ def register():
+ self._set_authorization_policy(policy)
def ensure():
+ if self.autocommit:
+ return
if self.registry.queryUtility(IAuthenticationPolicy) is None:
raise ConfigurationError(
- 'Cannot configure an authorization policy without also '
- 'configuring an authentication policy '
- '(see the set_authentication_policy method)')
- self.action(IAuthorizationPolicy, callable=ensure)
+ 'Cannot configure an authorization policy without '
+ 'also configuring an authentication policy '
+ '(use the set_authorization_policy method)')
+
+ # authorization policy used by view config (phase 3) and
+ # authentication policy (phase 2)
+ self.action(IAuthorizationPolicy, register, order=PHASE1_CONFIG)
+ self.action(None, ensure, order=PHASE3_CONFIG)
- @action_method
def _set_authorization_policy(self, policy):
policy = self.maybe_dotted(policy)
self.registry.registerUtility(policy, IAuthorizationPolicy)
@@ -96,8 +103,9 @@ class SecurityConfiguratorMixin(object):
:class:`pyramid.config.Configurator` constructor
can be used to achieve the same purpose.
"""
- # default permission used during view registration
- self.registry.registerUtility(permission, IDefaultPermission)
- self.action(IDefaultPermission, None)
+ # default permission used during view registration (phase 3)
+ def register():
+ self.registry.registerUtility(permission, IDefaultPermission)
+ self.action(IDefaultPermission, register, order=PHASE1_CONFIG)
diff --git a/pyramid/config/tweens.py b/pyramid/config/tweens.py
index be7f3d478..bf127b5df 100644
--- a/pyramid/config/tweens.py
+++ b/pyramid/config/tweens.py
@@ -1,6 +1,7 @@
from zope.interface import implements
from pyramid.interfaces import ITweens
+from pyramid.interfaces import PHASE3_CONFIG
from pyramid.exceptions import ConfigurationError
from pyramid.tweens import excview_tween_factory
@@ -128,17 +129,20 @@ class TweensConfiguratorMixin(object):
raise ConfigurationError('%s cannot be under MAIN' % name)
registry = self.registry
+
tweens = registry.queryUtility(ITweens)
if tweens is None:
tweens = Tweens()
registry.registerUtility(tweens, ITweens)
tweens.add_implicit(EXCVIEW, excview_tween_factory, over=MAIN)
- if explicit:
- tweens.add_explicit(name, tween_factory)
- else:
- tweens.add_implicit(name, tween_factory, under=under, over=over)
- self.action(('tween', name, explicit))
+ def register():
+ if explicit:
+ tweens.add_explicit(name, tween_factory)
+ else:
+ tweens.add_implicit(name, tween_factory, under=under, over=over)
+
+ self.action(('tween', name, explicit), register, order=PHASE3_CONFIG)
class CyclicDependencyError(Exception):
def __init__(self, cycles):
diff --git a/pyramid/config/views.py b/pyramid/config/views.py
index 8c7106736..06d6e901e 100644
--- a/pyramid/config/views.py
+++ b/pyramid/config/views.py
@@ -25,6 +25,8 @@ from pyramid.interfaces import IViewClassifier
from pyramid.interfaces import IRequest
from pyramid.interfaces import IRouteRequest
from pyramid.interfaces import IRendererFactory
+from pyramid.interfaces import PHASE1_CONFIG
+from pyramid.interfaces import PHASE3_CONFIG
from pyramid.exceptions import ConfigurationError
from pyramid.exceptions import PredicateMismatch
@@ -885,31 +887,6 @@ class ViewsConfiguratorMixin(object):
raise ConfigurationError(
'request_type must be an interface, not %s' % request_type)
- request_iface = IRequest
-
- if route_name is not None:
- request_iface = self.registry.queryUtility(IRouteRequest,
- name=route_name)
- if request_iface is None:
- deferred_views = getattr(self.registry,
- 'deferred_route_views', None)
- if deferred_views is None:
- deferred_views = self.registry.deferred_route_views = {}
- info = dict(
- view=view, name=name, for_=for_, permission=permission,
- request_type=request_type, route_name=route_name,
- request_method=request_method, request_param=request_param,
- containment=containment, attr=attr,
- renderer=renderer, wrapper=wrapper, xhr=xhr, accept=accept,
- header=header, path_info=path_info,
- match_param=match_param,
- custom_predicates=custom_predicates, context=context,
- mapper = mapper, http_cache = http_cache,
- )
- view_info = deferred_views.setdefault(route_name, [])
- view_info.append(info)
- return
-
order, predicates, phash = make_predicates(xhr=xhr,
request_method=request_method, path_info=path_info,
request_param=request_param, header=header, accept=accept,
@@ -931,8 +908,19 @@ class ViewsConfiguratorMixin(object):
registry = self.registry)
def register(permission=permission, renderer=renderer):
+ request_iface = IRequest
+ if route_name is not None:
+ request_iface = self.registry.queryUtility(IRouteRequest,
+ name=route_name)
+ if request_iface is None:
+ # route configuration should have already happened in
+ # phase 2
+ raise ConfigurationError(
+ 'No route named %s found for view registration' %
+ route_name)
+
if renderer is None:
- # use default renderer if one exists
+ # use default renderer if one exists (reg'd in phase 1)
if self.registry.queryUtility(IRendererFactory) is not None:
renderer = renderers.RendererHelper(
name=None,
@@ -941,6 +929,7 @@ class ViewsConfiguratorMixin(object):
if permission is None:
# intent: will be None if no default permission is registered
+ # (reg'd in phase 1)
permission = self.registry.queryUtility(IDefaultPermission)
# __no_permission_required__ handled by _secure_view
@@ -1058,11 +1047,11 @@ class ViewsConfiguratorMixin(object):
discriminator = [
'view', context, name, request_type, IView, containment,
- request_param, request_method, match_param, route_name, attr,
- xhr, accept, header, path_info]
+ request_param, request_method, route_name, attr,
+ xhr, accept, header, path_info, match_param]
discriminator.extend(sorted(custom_predicates))
discriminator = tuple(discriminator)
- self.action(discriminator, register)
+ self.action(discriminator, register, order=PHASE3_CONFIG)
def derive_view(self, view, attr=None, renderer=None):
"""
@@ -1281,8 +1270,11 @@ class ViewsConfiguratorMixin(object):
can be used to achieve the same purpose.
"""
mapper = self.maybe_dotted(mapper)
- self.registry.registerUtility(mapper, IViewMapperFactory)
- self.action(IViewMapperFactory, None)
+ def register():
+ self.registry.registerUtility(mapper, IViewMapperFactory)
+ # IViewMapperFactory is looked up as the result of view config
+ # in phase 3
+ self.action(IViewMapperFactory, register, order=PHASE1_CONFIG)
@action_method
def add_static_view(self, name, path, **kw):
diff --git a/pyramid/httpexceptions.py b/pyramid/httpexceptions.py
index 8c49889be..fef4fe47e 100644
--- a/pyramid/httpexceptions.py
+++ b/pyramid/httpexceptions.py
@@ -987,7 +987,7 @@ class HTTPInsufficientStorage(HTTPServerError):
def exception_response(status_code, **kw):
"""Creates an HTTP exception based on a status code. Example::
- raise responsecode(404) # raises an HTTPNotFound exception.
+ raise exception_response(404) # raises an HTTPNotFound exception.
The values passed as ``kw`` are provided to the exception's constructor.
"""
diff --git a/pyramid/interfaces.py b/pyramid/interfaces.py
index 6864e5dfb..408135711 100644
--- a/pyramid/interfaces.py
+++ b/pyramid/interfaces.py
@@ -847,4 +847,12 @@ class IRendererInfo(Interface):
'renderer was created')
settings = Attribute('The deployment settings dictionary related '
'to the current application')
-
+
+
+# configuration phases: a lower phase number means the actions associated
+# with this phase will be executed earlier than those with later phase
+# numbers
+
+PHASE1_CONFIG = -20
+PHASE2_CONFIG = -10
+PHASE3_CONFIG = 0
diff --git a/pyramid/tests/ccbugapp/__init__.py b/pyramid/tests/ccbugapp/__init__.py
index ad6387a75..afe21d4e0 100644
--- a/pyramid/tests/ccbugapp/__init__.py
+++ b/pyramid/tests/ccbugapp/__init__.py
@@ -1,8 +1,16 @@
+from webob import Response
+
+def rdf_view(request):
+ """ """
+ return Response('rdf')
+
+def juri_view(request):
+ """ """
+ return Response('juri')
+
def includeme(config):
config.add_route('rdf', 'licenses/:license_code/:license_version/rdf')
config.add_route('juri',
'licenses/:license_code/:license_version/:jurisdiction')
- config.add_view('.views.rdf_view', route_name='rdf')
- config.add_view('.views.juri_view', route_name='juri')
-
-
+ config.add_view(rdf_view, route_name='rdf')
+ config.add_view(juri_view, route_name='juri')
diff --git a/pyramid/tests/ccbugapp/views.py b/pyramid/tests/ccbugapp/views.py
deleted file mode 100644
index 4a6939ac2..000000000
--- a/pyramid/tests/ccbugapp/views.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from webob import Response
-
-def rdf_view(request):
- """ """
- return Response('rdf')
-
-def juri_view(request):
- """ """
- return Response('juri')
-
diff --git a/pyramid/tests/conflictapp/__init__.py b/pyramid/tests/conflictapp/__init__.py
new file mode 100644
index 000000000..429237973
--- /dev/null
+++ b/pyramid/tests/conflictapp/__init__.py
@@ -0,0 +1,23 @@
+from pyramid.response import Response
+from pyramid.authentication import AuthTktAuthenticationPolicy
+from pyramid.authorization import ACLAuthorizationPolicy
+
+def aview(request):
+ return Response('a view')
+
+def routeview(request):
+ return Response('route view')
+
+def protectedview(request):
+ return Response('protected view')
+
+def includeme(config):
+ # purposely sorta-randomly ordered (route comes after view naming it,
+ # authz comes after views)
+ config.add_view(aview)
+ config.add_view(protectedview, name='protected', permission='view')
+ config.add_view(routeview, route_name='aroute')
+ config.add_route('aroute', '/route')
+ config.set_authentication_policy(AuthTktAuthenticationPolicy('seekri1t'))
+ config.set_authorization_policy(ACLAuthorizationPolicy())
+ config.include('pyramid.tests.conflictapp.included')
diff --git a/pyramid/tests/conflictapp/included.py b/pyramid/tests/conflictapp/included.py
new file mode 100644
index 000000000..0b76fb2bc
--- /dev/null
+++ b/pyramid/tests/conflictapp/included.py
@@ -0,0 +1,6 @@
+from webob import Response
+
+def bview(request): return Response('b view')
+
+def includeme(config):
+ config.add_view(bview)
diff --git a/pyramid/tests/test_config/test_init.py b/pyramid/tests/test_config/test_init.py
index 0f7c7677e..0a787275d 100644
--- a/pyramid/tests/test_config/test_init.py
+++ b/pyramid/tests/test_config/test_init.py
@@ -103,6 +103,7 @@ class ConfiguratorTests(unittest.TestCase):
this_pkg = sys.modules['pyramid.tests.test_config']
self.assertTrue(config.registry.getUtility(ISettings))
self.assertEqual(config.package, this_pkg)
+ config.commit()
self.assertTrue(config.registry.getUtility(IRendererFactory, 'json'))
self.assertTrue(config.registry.getUtility(IRendererFactory, 'string'))
if not __pypy__:
@@ -185,6 +186,7 @@ class ConfiguratorTests(unittest.TestCase):
from pyramid.interfaces import IAuthenticationPolicy
policy = object()
config = self._makeOne(authentication_policy=policy)
+ config.commit()
result = config.registry.getUtility(IAuthenticationPolicy)
self.assertEqual(policy, result)
@@ -205,12 +207,21 @@ class ConfiguratorTests(unittest.TestCase):
from pyramid.interfaces import IRendererFactory
renderer = object()
config = self._makeOne(renderers=[('yeah', renderer)])
+ config.commit()
self.assertEqual(config.registry.getUtility(IRendererFactory, 'yeah'),
renderer)
+ def test_ctor_default_renderers(self):
+ from pyramid.interfaces import IRendererFactory
+ from pyramid.renderers import json_renderer_factory
+ config = self._makeOne()
+ self.assertEqual(config.registry.getUtility(IRendererFactory, 'json'),
+ json_renderer_factory)
+
def test_ctor_default_permission(self):
from pyramid.interfaces import IDefaultPermission
config = self._makeOne(default_permission='view')
+ config.commit()
self.assertEqual(config.registry.getUtility(IDefaultPermission), 'view')
def test_ctor_session_factory(self):
@@ -224,6 +235,7 @@ class ConfiguratorTests(unittest.TestCase):
from pyramid.interfaces import IViewMapperFactory
mapper = object()
config = self._makeOne(default_view_mapper=mapper)
+ config.commit()
self.assertEqual(config.registry.getUtility(IViewMapperFactory),
mapper)
@@ -463,6 +475,7 @@ class ConfiguratorTests(unittest.TestCase):
reg = Registry()
config = self._makeOne(reg)
config.setup_registry(authentication_policy=policy)
+ config.commit()
result = reg.getUtility(IAuthenticationPolicy)
self.assertEqual(policy, result)
@@ -472,6 +485,7 @@ class ConfiguratorTests(unittest.TestCase):
reg = Registry()
config = self._makeOne(reg)
config.setup_registry(authentication_policy='pyramid.tests')
+ config.commit()
result = reg.getUtility(IAuthenticationPolicy)
import pyramid.tests
self.assertEqual(result, pyramid.tests)
@@ -484,6 +498,7 @@ class ConfiguratorTests(unittest.TestCase):
dummy = object()
config.setup_registry(authentication_policy=dummy,
authorization_policy='pyramid.tests')
+ config.commit()
result = reg.getUtility(IAuthorizationPolicy)
import pyramid.tests
self.assertEqual(result, pyramid.tests)
@@ -607,6 +622,7 @@ class ConfiguratorTests(unittest.TestCase):
reg = Registry()
config = self._makeOne(reg)
config.setup_registry(renderers=[('yeah', renderer)])
+ config.commit()
self.assertEqual(reg.getUtility(IRendererFactory, 'yeah'),
renderer)
@@ -616,6 +632,7 @@ class ConfiguratorTests(unittest.TestCase):
reg = Registry()
config = self._makeOne(reg)
config.setup_registry(default_permission='view')
+ config.commit()
self.assertEqual(reg.getUtility(IDefaultPermission), 'view')
def test_setup_registry_includes(self):
@@ -1913,71 +1930,33 @@ pyramid.tests.test_config.dummy_include2""",
def test_add_view_with_route_name(self):
from pyramid.renderers import null_renderer
- from zope.component import ComponentLookupError
view = lambda *arg: 'OK'
config = self._makeOne(autocommit=True)
- config.add_view(view=view, route_name='foo', renderer=null_renderer)
- self.assertEqual(len(config.registry.deferred_route_views), 1)
- infos = config.registry.deferred_route_views['foo']
- self.assertEqual(len(infos), 1)
- info = infos[0]
- self.assertEqual(info['route_name'], 'foo')
- self.assertEqual(info['view'], view)
- self.assertRaises(ComponentLookupError,
- self._getRouteRequestIface, config, 'foo')
- wrapper = self._getViewCallable(config, None)
- self.assertEqual(wrapper, None)
config.add_route('foo', '/a/b')
+ config.add_view(view=view, route_name='foo', renderer=null_renderer)
request_iface = self._getRouteRequestIface(config, 'foo')
self.assertNotEqual(request_iface, None)
wrapper = self._getViewCallable(config, request_iface=request_iface)
self.assertNotEqual(wrapper, None)
self.assertEqual(wrapper(None, None), 'OK')
- def test_add_view_with_route_name_deferred_views_already_exist(self):
- view = lambda *arg: 'OK'
- config = self._makeOne(autocommit=True)
- config.registry.deferred_route_views = {'bar':[]}
- config.add_view(view=view, route_name='foo')
- self.assertEqual(len(config.registry.deferred_route_views), 2)
- self.assertEqual(config.registry.deferred_route_views['bar'], [])
- infos = config.registry.deferred_route_views['foo']
- self.assertEqual(len(infos), 1)
-
- def test_deferred_route_views_retains_custom_predicates(self):
+ def test_add_view_with_nonexistant_route_name(self):
+ from pyramid.renderers import null_renderer
+ from zope.configuration.config import ConfigurationExecutionError
view = lambda *arg: 'OK'
- config = self._makeOne(autocommit=True)
- config.add_view(view=view, route_name='foo', custom_predicates=('123',))
- self.assertEqual(len(config.registry.deferred_route_views), 1)
- infos = config.registry.deferred_route_views['foo']
- self.assertEqual(len(infos), 1)
- info = infos[0]
- self.assertEqual(info['route_name'], 'foo')
- self.assertEqual(info['custom_predicates'], ('123',))
+ config = self._makeOne()
+ config.add_view(view=view, route_name='foo', renderer=null_renderer)
+ self.assertRaises(ConfigurationExecutionError, config.commit)
def test_add_view_with_route_name_exception(self):
from pyramid.renderers import null_renderer
from zope.interface import implementedBy
- from zope.component import ComponentLookupError
view = lambda *arg: 'OK'
config = self._makeOne(autocommit=True)
+ config.add_route('foo', '/a/b')
config.add_view(view=view, route_name='foo', context=RuntimeError,
renderer=null_renderer)
- self.assertEqual(len(config.registry.deferred_route_views), 1)
- infos = config.registry.deferred_route_views['foo']
- self.assertEqual(len(infos), 1)
- info = infos[0]
- self.assertEqual(info['route_name'], 'foo')
- self.assertEqual(info['view'], view)
- self.assertRaises(ComponentLookupError,
- self._getRouteRequestIface, config, 'foo')
- wrapper_exc_view = self._getViewCallable(
- config, ctx_iface=implementedBy(RuntimeError),
- exception_view=True)
- self.assertEqual(wrapper_exc_view, None)
- config.add_route('foo', '/a/b')
request_iface = self._getRouteRequestIface(config, 'foo')
- self.assertNotEqual(request_iface, None)
wrapper_exc_view = self._getViewCallable(
config, ctx_iface=implementedBy(RuntimeError),
request_iface=request_iface, exception_view=True)
@@ -2351,45 +2330,40 @@ pyramid.tests.test_config.dummy_include2""",
def test_add_route_defaults(self):
config = self._makeOne(autocommit=True)
- route = config.add_route('name', 'path')
+ config.add_route('name', 'path')
self._assertRoute(config, 'name', 'path')
- self.assertEqual(route.name, 'name')
def test_add_route_with_route_prefix(self):
config = self._makeOne(autocommit=True)
config.route_prefix = 'root'
- route = config.add_route('name', 'path')
- self.assertEqual(route.name, 'name')
- self.assertEqual(route.pattern, 'root/path')
-
+ config.add_route('name', 'path')
self._assertRoute(config, 'name', 'root/path')
def test_add_route_discriminator(self):
config = self._makeOne()
- route = config.add_route('name', 'path')
- self._assertRoute(config, 'name', 'path')
- self.assertEqual(route.name, 'name')
+ config.add_route('name', 'path')
self.assertEqual(config._ctx.actions[-1][0], ('route', 'name'))
def test_add_route_with_factory(self):
config = self._makeOne(autocommit=True)
factory = object()
- route = config.add_route('name', 'path', factory=factory)
+ config.add_route('name', 'path', factory=factory)
+ route = self._assertRoute(config, 'name', 'path')
self.assertEqual(route.factory, factory)
def test_add_route_with_static(self):
config = self._makeOne(autocommit=True)
- route = config.add_route('name', 'path/{foo}', static=True)
- self.assertEqual(route.name, 'name')
+ config.add_route('name', 'path/{foo}', static=True)
mapper = config.get_routes_mapper()
self.assertEqual(len(mapper.get_routes()), 0)
self.assertEqual(mapper.generate('name', {"foo":"a"}), '/path/a')
def test_add_route_with_factory_dottedname(self):
config = self._makeOne(autocommit=True)
- route = config.add_route(
+ config.add_route(
'name', 'path',
factory='pyramid.tests.test_config.dummyfactory')
+ route = self._assertRoute(config, 'name', 'path')
self.assertEqual(route.factory, dummyfactory)
def test_add_route_with_xhr(self):
@@ -2474,9 +2448,8 @@ pyramid.tests.test_config.dummy_include2""",
def test_add_route_no_pattern_with_path(self):
config = self._makeOne(autocommit=True)
- route = config.add_route('name', path='path')
+ config.add_route('name', path='path')
self._assertRoute(config, 'name', 'path')
- self.assertEqual(route.name, 'name')
def test_add_route_no_path_no_pattern(self):
from pyramid.exceptions import ConfigurationError
@@ -2485,7 +2458,8 @@ pyramid.tests.test_config.dummy_include2""",
def test_add_route_with_pregenerator(self):
config = self._makeOne(autocommit=True)
- route = config.add_route('name', 'pattern', pregenerator='123')
+ config.add_route('name', 'pattern', pregenerator='123')
+ route = self._assertRoute(config, 'name', 'pattern')
self.assertEqual(route.pregenerator, '123')
def test_add_route_no_view_with_view_attr(self):
@@ -2554,6 +2528,7 @@ pyramid.tests.test_config.dummy_include2""",
def __call__(self, *arg, **kw):
return 'moo'
config.add_renderer(None, moo)
+ config.commit()
def view(request):
return 'OK'
result = config.derive_view(view)
@@ -2572,6 +2547,7 @@ pyramid.tests.test_config.dummy_include2""",
config = self._makeOne()
config.add_renderer(None, moo)
config.add_renderer('foo', foo)
+ config.commit()
result = config.derive_view(view, renderer='foo')
self.assertFalse(result is view)
request = self._makeRequest(config)
@@ -2787,81 +2763,6 @@ pyramid.tests.test_config.dummy_include2""",
config.end()
self.assertTrue('div' in result.body)
- def test_set_authentication_policy_no_authz_policy(self):
- from zope.configuration.config import ConfigurationExecutionError
- config = self._makeOne()
- policy = object()
- config.set_authentication_policy(policy)
- self.assertRaises(ConfigurationExecutionError, config.commit)
-
- def test_set_authentication_policy_no_authz_policy_autocommit(self):
- from pyramid.interfaces import IAuthenticationPolicy
- config = self._makeOne(autocommit=True)
- policy = object()
- config.set_authentication_policy(policy)
- self.assertEqual(
- config.registry.getUtility(IAuthenticationPolicy), policy)
-
- def test_set_authentication_policy_with_authz_policy(self):
- from pyramid.interfaces import IAuthenticationPolicy
- from pyramid.interfaces import IAuthorizationPolicy
- config = self._makeOne()
- authn_policy = object()
- authz_policy = object()
- config.registry.registerUtility(authz_policy, IAuthorizationPolicy)
- config.set_authentication_policy(authn_policy)
- config.commit()
- self.assertEqual(
- config.registry.getUtility(IAuthenticationPolicy), authn_policy)
-
- def test_set_authentication_policy_with_authz_policy_autocommit(self):
- from pyramid.interfaces import IAuthenticationPolicy
- from pyramid.interfaces import IAuthorizationPolicy
- config = self._makeOne(autocommit=True)
- authn_policy = object()
- authz_policy = object()
- config.registry.registerUtility(authz_policy, IAuthorizationPolicy)
- config.set_authentication_policy(authn_policy)
- config.commit()
- self.assertEqual(
- config.registry.getUtility(IAuthenticationPolicy), authn_policy)
-
- def test_set_authorization_policy_no_authn_policy(self):
- from zope.configuration.config import ConfigurationExecutionError
- config = self._makeOne()
- policy = object()
- config.set_authorization_policy(policy)
- self.assertRaises(ConfigurationExecutionError, config.commit)
-
- def test_set_authorization_policy_no_authn_policy_autocommit(self):
- from pyramid.exceptions import ConfigurationError
- config = self._makeOne(autocommit=True)
- policy = object()
- self.assertRaises(ConfigurationError,
- config.set_authorization_policy, policy)
-
- def test_set_authorization_policy_with_authn_policy(self):
- from pyramid.interfaces import IAuthorizationPolicy
- from pyramid.interfaces import IAuthenticationPolicy
- config = self._makeOne()
- authn_policy = object()
- authz_policy = object()
- config.registry.registerUtility(authn_policy, IAuthenticationPolicy)
- config.set_authorization_policy(authz_policy)
- self.assertEqual(
- config.registry.getUtility(IAuthorizationPolicy), authz_policy)
-
- def test_set_authorization_policy_with_authn_policy_autocommit(self):
- from pyramid.interfaces import IAuthorizationPolicy
- from pyramid.interfaces import IAuthenticationPolicy
- config = self._makeOne(autocommit=True)
- authn_policy = object()
- authz_policy = object()
- config.registry.registerUtility(authn_policy, IAuthenticationPolicy)
- config.set_authorization_policy(authz_policy)
- self.assertEqual(
- config.registry.getUtility(IAuthorizationPolicy), authz_policy)
-
def test_set_locale_negotiator(self):
from pyramid.interfaces import ILocaleNegotiator
config = self._makeOne(autocommit=True)
@@ -3830,11 +3731,13 @@ class TestConfiguratorDeprecatedFeatures(unittest.TestCase):
try:
config.commit()
except ConfigurationConflictError, why:
- c1, c2, c3, c4 = self._conflictFunctions(why)
+ c1, c2, c3, c4, c5, c6 = 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')
+ self.assertEqual(c5, 'test_conflict_route_with_view')
+ self.assertEqual(c6, 'test_conflict_route_with_view')
else: # pragma: no cover
raise AssertionError
diff --git a/pyramid/tests/test_config/test_security.py b/pyramid/tests/test_config/test_security.py
new file mode 100644
index 000000000..64ba895c6
--- /dev/null
+++ b/pyramid/tests/test_config/test_security.py
@@ -0,0 +1,84 @@
+import unittest
+
+class ConfiguratorSecurityMethodsTests(unittest.TestCase):
+ def _makeOne(self, *arg, **kw):
+ from pyramid.config import Configurator
+ config = Configurator(*arg, **kw)
+ return config
+
+ def test_set_authentication_policy_no_authz_policy(self):
+ from zope.configuration.config import ConfigurationExecutionError
+ config = self._makeOne()
+ policy = object()
+ config.set_authentication_policy(policy)
+ self.assertRaises(ConfigurationExecutionError, config.commit)
+
+ def test_set_authentication_policy_no_authz_policy_autocommit(self):
+ from pyramid.exceptions import ConfigurationError
+ config = self._makeOne(autocommit=True)
+ policy = object()
+ self.assertRaises(ConfigurationError,
+ config.set_authentication_policy, policy)
+
+ def test_set_authentication_policy_with_authz_policy(self):
+ from pyramid.interfaces import IAuthenticationPolicy
+ from pyramid.interfaces import IAuthorizationPolicy
+ config = self._makeOne()
+ authn_policy = object()
+ authz_policy = object()
+ config.registry.registerUtility(authz_policy, IAuthorizationPolicy)
+ config.set_authentication_policy(authn_policy)
+ config.commit()
+ self.assertEqual(
+ config.registry.getUtility(IAuthenticationPolicy), authn_policy)
+
+ def test_set_authentication_policy_with_authz_policy_autocommit(self):
+ from pyramid.interfaces import IAuthenticationPolicy
+ from pyramid.interfaces import IAuthorizationPolicy
+ config = self._makeOne(autocommit=True)
+ authn_policy = object()
+ authz_policy = object()
+ config.registry.registerUtility(authz_policy, IAuthorizationPolicy)
+ config.set_authentication_policy(authn_policy)
+ config.commit()
+ self.assertEqual(
+ config.registry.getUtility(IAuthenticationPolicy), authn_policy)
+
+ def test_set_authorization_policy_no_authn_policy(self):
+ from zope.configuration.config import ConfigurationExecutionError
+ config = self._makeOne()
+ policy = object()
+ config.set_authorization_policy(policy)
+ self.assertRaises(ConfigurationExecutionError, config.commit)
+
+ def test_set_authorization_policy_no_authn_policy_autocommit(self):
+ from pyramid.interfaces import IAuthorizationPolicy
+ config = self._makeOne(autocommit=True)
+ policy = object()
+ config.set_authorization_policy(policy)
+ self.assertEqual(
+ config.registry.getUtility(IAuthorizationPolicy), policy)
+
+ def test_set_authorization_policy_with_authn_policy(self):
+ from pyramid.interfaces import IAuthorizationPolicy
+ from pyramid.interfaces import IAuthenticationPolicy
+ config = self._makeOne()
+ authn_policy = object()
+ authz_policy = object()
+ config.registry.registerUtility(authn_policy, IAuthenticationPolicy)
+ config.set_authorization_policy(authz_policy)
+ config.commit()
+ self.assertEqual(
+ config.registry.getUtility(IAuthorizationPolicy), authz_policy)
+
+ def test_set_authorization_policy_with_authn_policy_autocommit(self):
+ from pyramid.interfaces import IAuthorizationPolicy
+ from pyramid.interfaces import IAuthenticationPolicy
+ config = self._makeOne(autocommit=True)
+ authn_policy = object()
+ authz_policy = object()
+ config.registry.registerUtility(authn_policy, IAuthenticationPolicy)
+ config.set_authorization_policy(authz_policy)
+ self.assertEqual(
+ config.registry.getUtility(IAuthorizationPolicy), authz_policy)
+
diff --git a/pyramid/tests/test_integration.py b/pyramid/tests/test_integration.py
index 1ebf83062..f391e65cb 100644
--- a/pyramid/tests/test_integration.py
+++ b/pyramid/tests/test_integration.py
@@ -344,6 +344,71 @@ class TestExceptionViewsApp(IntegrationBase):
res = self.testapp.get('/route_raise_exception4', status=200)
self.assertTrue('whoa' in res.body)
+class TestConflictApp(unittest.TestCase):
+ package = 'pyramid.tests.conflictapp'
+ def _makeConfig(self):
+ from pyramid.config import Configurator
+ config = Configurator()
+ return config
+
+ def test_autoresolved_view(self):
+ config = self._makeConfig()
+ config.include(self.package)
+ app = config.make_wsgi_app()
+ from webtest import TestApp
+ self.testapp = TestApp(app)
+ res = self.testapp.get('/')
+ self.assertTrue('a view' in res.body)
+ res = self.testapp.get('/route')
+ self.assertTrue('route view' in res.body)
+
+ def test_overridden_autoresolved_view(self):
+ from pyramid.response import Response
+ config = self._makeConfig()
+ config.include(self.package)
+ def thisview(request):
+ return Response('this view')
+ config.add_view(thisview)
+ app = config.make_wsgi_app()
+ from webtest import TestApp
+ self.testapp = TestApp(app)
+ res = self.testapp.get('/')
+ self.assertTrue('this view' in res.body)
+
+ def test_overridden_route_view(self):
+ from pyramid.response import Response
+ config = self._makeConfig()
+ config.include(self.package)
+ def thisview(request):
+ return Response('this view')
+ config.add_view(thisview, route_name='aroute')
+ app = config.make_wsgi_app()
+ from webtest import TestApp
+ self.testapp = TestApp(app)
+ res = self.testapp.get('/route')
+ self.assertTrue('this view' in res.body)
+
+ def test_nonoverridden_authorization_policy(self):
+ config = self._makeConfig()
+ config.include(self.package)
+ app = config.make_wsgi_app()
+ from webtest import TestApp
+ self.testapp = TestApp(app)
+ res = self.testapp.get('/protected', status=403)
+ self.assertTrue('403 Forbidden' in res)
+
+ def test_overridden_authorization_policy(self):
+ config = self._makeConfig()
+ config.include(self.package)
+ from pyramid.testing import DummySecurityPolicy
+ config.set_authorization_policy(DummySecurityPolicy('fred'))
+ config.set_authentication_policy(DummySecurityPolicy(permissive=True))
+ app = config.make_wsgi_app()
+ from webtest import TestApp
+ self.testapp = TestApp(app)
+ res = self.testapp.get('/protected', status=200)
+ self.assertTrue('protected view' in res)
+
class ImperativeIncludeConfigurationTest(unittest.TestCase):
def setUp(self):
from pyramid.config import Configurator
diff --git a/setup.py b/setup.py
index 4c556dbc3..40823384a 100644
--- a/setup.py
+++ b/setup.py
@@ -53,7 +53,7 @@ if sys.version_info[:2] < (2, 6):
install_requires.append('simplejson')
setup(name='pyramid',
- version='1.2dev',
+ version='1.2a1',
description=('The Pyramid web application development framework, a '
'Pylons project'),
long_description=README + '\n\n' + CHANGES,