From eb2fee960c0434a8369e252a930115e9c9356164 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Mon, 22 Aug 2011 21:36:21 -0400 Subject: first cut, tests fail --- pyramid/config/__init__.py | 11 +++++------ pyramid/config/adapters.py | 5 +++-- pyramid/config/assets.py | 1 + pyramid/config/factories.py | 7 ++++--- pyramid/config/rendering.py | 14 ++++++++------ pyramid/config/routes.py | 21 +++++++++++---------- pyramid/config/security.py | 35 ++++++++++++++++------------------- pyramid/config/tweens.py | 14 +++++++++----- pyramid/config/views.py | 37 +++++++++++++++---------------------- pyramid/interfaces.py | 10 +++++++++- 10 files changed, 81 insertions(+), 74 deletions(-) diff --git a/pyramid/config/__init__.py b/pyramid/config/__init__.py index c7ee8c47f..baae824ac 100644 --- a/pyramid/config/__init__.py +++ b/pyramid/config/__init__.py @@ -309,10 +309,6 @@ class Configurator( 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 @@ -322,10 +318,13 @@ class Configurator( 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..b83ca346c 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 @@ -353,10 +354,6 @@ class RoutesConfiguratorMixin(object): 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, @@ -370,8 +367,6 @@ class RoutesConfiguratorMixin(object): attr=view_attr, ) - mapper = self.get_routes_mapper() - factory = self.maybe_dotted(factory) if pattern is None: pattern = path @@ -381,11 +376,17 @@ 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() + + def register(): + return mapper.connect(name, pattern, factory, predicates=predicates, + pregenerator=pregenerator, static=static) + - return mapper.connect(name, pattern, factory, predicates=predicates, - pregenerator=pregenerator, static=static) + # route actions must run before view registration actions; all + # IRouteRequest interfaces must be registered before we begin to + # process view registrations + self.action(('route', name), register, order=PHASE2_CONFIG) 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..96e2c1479 100644 --- a/pyramid/config/security.py +++ b/pyramid/config/security.py @@ -1,6 +1,8 @@ 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.exceptions import ConfigurationError from pyramid.config.util import action_method @@ -18,18 +20,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 +45,12 @@ class SecurityConfiguratorMixin(object): :class:`pyramid.config.Configurator` constructor can be used to achieve the same purpose. """ - self._set_authorization_policy(policy) - def ensure(): - 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) + def register(): + self._set_authorization_policy(policy) + # authorization policy used by view config (phase 3) and + # authentication policy (phase 2) + self.action(IAuthorizationPolicy, register, order=PHASE1_CONFIG) - @action_method def _set_authorization_policy(self, policy): policy = self.maybe_dotted(policy) self.registry.registerUtility(policy, IAuthorizationPolicy) @@ -96,8 +92,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 2d39524ac..633906468 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 @@ -874,24 +876,11 @@ class ViewsConfiguratorMixin(object): 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, - custom_predicates=custom_predicates, context=context, - mapper = mapper, http_cache = http_cache, - ) - view_info = deferred_views.setdefault(route_name, []) - view_info.append(info) - return - + # route configuration should have already happened + raise ConfigurationError( + 'No route named %s found for view registration' % + route_name) + order, predicates, phash = make_predicates(xhr=xhr, request_method=request_method, path_info=path_info, request_param=request_param, header=header, accept=accept, @@ -914,7 +903,7 @@ class ViewsConfiguratorMixin(object): def register(permission=permission, renderer=renderer): 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, @@ -923,6 +912,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 @@ -1044,7 +1034,7 @@ class ViewsConfiguratorMixin(object): xhr, accept, header, path_info] 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): """ @@ -1263,8 +1253,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/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 -- cgit v1.2.3