From bd39b16939147d667e9c483e341c0e0a14284eec Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Mon, 23 Nov 2009 08:07:16 +0000 Subject: - The internal ILogger utility named ``repoze.bfg.debug`` is now just an IDebugLogger unnamed utility. A named utility with the old name is registered for b/w compat. --- CHANGES.txt | 4 + repoze/bfg/configuration.py | 249 ++++++++++++++++----------- repoze/bfg/interfaces.py | 4 +- repoze/bfg/log.py | 2 +- repoze/bfg/router.py | 62 +------ repoze/bfg/tests/test_configuration.py | 298 +++++++++++++++++++-------------- repoze/bfg/tests/test_router.py | 42 +---- repoze/bfg/zcml.py | 4 +- 8 files changed, 338 insertions(+), 327 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 3ad281f6d..cabb15d6c 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -90,6 +90,10 @@ Internals ``repoze.bfg.threadlocal.get_current_registry`` API to obtain the registry. +- The internal ILogger utility named ``repoze.bfg.debug`` is now just + an IDebugLogger unnamed utility. A named utility with the old name + is registered for b/w compat. + Backwards Incompatibilites -------------------------- diff --git a/repoze/bfg/configuration.py b/repoze/bfg/configuration.py index 3a3a0d893..2175fdf4e 100644 --- a/repoze/bfg/configuration.py +++ b/repoze/bfg/configuration.py @@ -23,7 +23,7 @@ from repoze.bfg.interfaces import IAuthenticationPolicy from repoze.bfg.interfaces import IAuthorizationPolicy from repoze.bfg.interfaces import IDefaultRootFactory from repoze.bfg.interfaces import IForbiddenView -from repoze.bfg.interfaces import ILogger +from repoze.bfg.interfaces import IDebugLogger from repoze.bfg.interfaces import IMultiView from repoze.bfg.interfaces import INotFoundView from repoze.bfg.interfaces import IPackageOverrides @@ -41,6 +41,7 @@ from repoze.bfg.interfaces import IView from repoze.bfg import chameleon_zpt from repoze.bfg import chameleon_text from repoze.bfg import renderers +from repoze.bfg.authorization import ACLAuthorizationPolicy from repoze.bfg.compat import all from repoze.bfg.events import WSGIApplicationCreatedEvent from repoze.bfg.exceptions import Forbidden @@ -63,6 +64,13 @@ from repoze.bfg.view import static import martian +DEFAULT_RENDERERS = ( + ('.pt', chameleon_zpt.renderer_factory), + ('.txt', chameleon_text.renderer_factory), + ('json', renderers.json_renderer_factory), + ('string', renderers.string_renderer_factory), + ) + class Configurator(object): """ A Configurator is used to configure a :mod:`repoze.bfg` @@ -86,22 +94,76 @@ class Configurator(object): default), the package is assumed to be the Python package in which the *caller* of the ``Configurator`` constructor lives. """ - def __init__(self, registry=None, package=None, settings=None): + def __init__(self, registry=None, package=None, settings=None, + root_factory=None, debug_logger=None, zcml_file=None, + authentication_policy=None, authorization_policy=None, + renderers=DEFAULT_RENDERERS): self.package = package or caller_package() self.registry = registry if registry is None: registry = Registry(self.package.__name__) self.registry = registry - self._default_configuration() + self.settings(settings) + self.root_factory(root_factory) + if debug_logger is None: + debug_logger = make_stream_logger('repoze.bfg.debug', + sys.stderr) + registry.registerUtility(debug_logger, IDebugLogger) + registry.registerUtility(debug_logger, IDebugLogger, + 'repoze.bfg.debug') # b /c + if authentication_policy or authorization_policy: + self.security_policies(authentication_policy, + authorization_policy) + for name, renderer in renderers: + self.renderer(renderer, name) + if zcml_file is not None: + self.load_zcml(zcml_file) + + def settings(self, mapping): + settings = Settings(mapping or {}) + self.registry.registerUtility(settings, ISettings) + + def make_spec(self, path_or_spec): + package, filename = resolve_resource_spec(path_or_spec, + self.package.__name__) + if package is None: + return filename # absolute filename + return '%s:%s' % (package, filename) + + def split_spec(self, path_or_spec): + return resolve_resource_spec(path_or_spec, self.package.__name__) + + def renderer_from_name(self, path_or_spec): + if path_or_spec is None: + # check for global default renderer + factory = self.registry.queryUtility(IRendererFactory) + if factory is not None: + return factory(path_or_spec) + return None + + if '.' in path_or_spec: + name = os.path.splitext(path_or_spec)[1] + spec = self.make_spec(path_or_spec) + else: + name = path_or_spec + spec = path_or_spec + + factory = self.registry.queryUtility(IRendererFactory, name=name) + if factory is None: + raise ValueError('No renderer for renderer name %r' % name) + return factory(spec) + + def authentication_policy(self, policy, _info=u''): + """ Add a :mod:`repoze.bfg` :term:`authentication policy` to + the current configuration.""" + self.registry.registerUtility(policy, IAuthenticationPolicy, info=_info) + + def authorization_policy(self, policy, _info=u''): + """ Add a :mod:`repoze.bfg` :term:`authorization policy` to + the current configuration state.""" + self.registry.registerUtility(policy, IAuthorizationPolicy, info=_info) - def _default_configuration(self): - self.renderer(chameleon_zpt.renderer_factory, '.pt') - self.renderer(chameleon_text.renderer_factory, '.txt') - self.renderer(renderers.json_renderer_factory, 'json') - self.renderer(renderers.string_renderer_factory, 'string') - self.root_factory(DefaultRootFactory) - self.settings({}) - self.debug_logger(None) + # API def make_wsgi_app(self, manager=manager, getSiteManager=getSiteManager): """ Returns a :mod:`repoze.bfg` WSGI application representing @@ -122,36 +184,6 @@ class Configurator(object): manager.pop() return app - def declarative(self, root_factory, spec='configure.zcml', - settings=None, debug_logger=None, os=os, - lock=threading.Lock()): - self._default_configuration() - - # debug_logger, os and lock *only* for unittests - if settings is None: - settings = {} - - if not 'configure_zcml' in settings: - settings['configure_zcml'] = spec - - settings = Settings(settings) - spec = settings['configure_zcml'] - - self.settings(settings) - self.debug_logger(debug_logger) - self.root_factory(root_factory or DefaultRootFactory) - self.load_zcml(spec, lock=lock) - - def make_spec(self, path_or_spec): - package, filename = resolve_resource_spec(path_or_spec, - self.package.__name__) - if package is None: - return filename # absolute filename - return '%s:%s' % (package, filename) - - def split_spec(self, path_or_spec): - return resolve_resource_spec(path_or_spec, self.package.__name__) - def load_zcml(self, spec='configure.zcml', lock=threading.Lock()): """ Load configuration from a :term:`ZCML` file into the current configuration state. The ``spec`` argument is an @@ -194,6 +226,23 @@ class Configurator(object): getSiteManager.reset() return self.registry + def security_policies(self, authentication, authorization=None): + """ Register security policies safely. The ``authentication`` + argument represents a :term:`authentication policy`. The + ``authorization`` argument represents a :term:`authorization + policy`. If the ``authorization`` argument is ``None``, a + default ``repoze.bfg.authorization.ACLAuthorizationPolicy`` + will be registered as the authorization policy.""" + if authorization is None: + authorization = ACLAuthorizationPolicy() # default + if authorization and not authentication: + raise ConfigurationError( + 'If the "authorization" is passed a vallue, ' + 'the "authentication" argument musty also be ' + 'passed a value; authorization requires authentication.') + self.authentication_policy(authentication) + self.authorization_policy(authorization) + def view(self, view=None, name="", for_=None, permission=None, request_type=None, route_name=None, request_method=None, request_param=None, containment=None, attr=None, @@ -232,8 +281,8 @@ class Configurator(object): request_param=request_param, header=header, accept=accept, containment=containment) - derived_view = self.derive_view(view, permission, predicates, attr, - renderer, wrapper, name) + derived_view = self._derive_view(view, permission, predicates, attr, + renderer, wrapper, name) r_for_ = for_ r_request_type = request_type if r_for_ is None: @@ -270,14 +319,14 @@ class Configurator(object): self.registry.registerAdapter(multiview, (for_, request_type), IMultiView, name, info=_info) - def derive_view(self, view, permission=None, predicates=(), - attr=None, renderer_name=None, wrapper_viewname=None, - viewname=None): + def _derive_view(self, view, permission=None, predicates=(), + attr=None, renderer_name=None, wrapper_viewname=None, + viewname=None): renderer = self.renderer_from_name(renderer_name) authn_policy = self.registry.queryUtility(IAuthenticationPolicy) authz_policy = self.registry.queryUtility(IAuthorizationPolicy) settings = self.registry.queryUtility(ISettings) - logger = self.registry.queryUtility(ILogger, 'repoze.bfg.debug') + logger = self.registry.queryUtility(IDebugLogger) mapped_view = _map_view(view, attr, renderer, renderer_name) owrapped_view = _owrap_view(mapped_view, viewname, wrapper_viewname) secured_view = _secure_view(owrapped_view, permission, @@ -288,26 +337,6 @@ class Configurator(object): derived_view = _predicate_wrap(debug_view, predicates) return derived_view - def renderer_from_name(self, path_or_spec): - if path_or_spec is None: - # check for global default renderer - factory = self.registry.queryUtility(IRendererFactory) - if factory is not None: - return factory(path_or_spec) - return None - - if '.' in path_or_spec: - name = os.path.splitext(path_or_spec)[1] - spec = self.make_spec(path_or_spec) - else: - name = path_or_spec - spec = path_or_spec - - factory = self.registry.queryUtility(IRendererFactory, name=name) - if factory is None: - raise ValueError('No renderer for renderer name %r' % name) - return factory(spec) - def route(self, name, path, view=None, view_for=None, permission=None, factory=None, for_=None, header=None, xhr=False, accept=None, path_info=None, @@ -376,16 +405,6 @@ class Configurator(object): _info=_info, _configurator=self, exclude_filter=lambda name: name.startswith('.')) - def authentication_policy(self, policy, _info=u''): - """ Add a :mod:`repoze.bfg` :term:`authentication policy` to - the current configuration.""" - self.registry.registerUtility(policy, IAuthenticationPolicy, info=_info) - - def authorization_policy(self, policy, _info=u''): - """ Add a :mod:`repoze.bfg` :term:`authorization policy` to - the current configuration state.""" - self.registry.registerUtility(policy, IAuthorizationPolicy, info=_info) - def renderer(self, factory, name, _info=u''): """ Add a :mod:`repoze.bfg` :term:`renderer` to the current configuration state.""" @@ -449,14 +468,14 @@ class Configurator(object): """ Add a default forbidden view to the current configuration state.""" - return self.system_view(IForbiddenView, *arg, **kw) + return self._system_view(IForbiddenView, *arg, **kw) def notfound(self, *arg, **kw): """ Add a default not found view to the current configuration state.""" - return self.system_view(INotFoundView, *arg, **kw) + return self._system_view(INotFoundView, *arg, **kw) - def system_view(self, iface, view=None, attr=None, renderer=None, + def _system_view(self, iface, view=None, attr=None, renderer=None, wrapper=None, _info=u''): if not view: if renderer: @@ -467,9 +486,9 @@ class Configurator(object): 'specified and no renderer ' 'specified') - derived_view = self.derive_view(view, attr=attr, - renderer_name=renderer, - wrapper_viewname=wrapper) + derived_view = self._derive_view(view, attr=attr, + renderer_name=renderer, + wrapper_viewname=wrapper) self.registry.registerUtility(derived_view, iface, '', info=_info) def static(self, name, path, cache_max_age=3600, _info=u''): @@ -480,21 +499,12 @@ class Configurator(object): view_for=StaticRootFactory, factory=StaticRootFactory(spec), _info=_info) - def settings(self, settings): - """ Register the value passed in as ``settings`` as the basis - of the value returned by the - ``repoze.bfg.settings.get_settings`` API.""" - settings = Settings(settings) - self.registry.registerUtility(settings, ISettings) - - def debug_logger(self, logger): - if logger is None: - logger = make_stream_logger('repoze.bfg.debug', sys.stderr) - self.registry.registerUtility(logger, ILogger, 'repoze.bfg.debug') - def root_factory(self, factory): """ Add a :term:`root factory` to the current configuration - state.""" + state. If the ``factory`` argument is ``None`` a default root + factory will be registered.""" + if factory is None: + factory = DefaultRootFactory self.registry.registerUtility(factory, IRootFactory) self.registry.registerUtility(factory, IDefaultRootFactory) # b/c @@ -919,3 +929,50 @@ def _authdebug_view(view, permission, authn_policy, authz_policy, settings, return wrapped_view +# note that ``options`` is a b/w compat alias for ``settings`` and +# ``Configurator`` is a testing dep inj +def make_app(root_factory, package=None, filename='configure.zcml', + settings=None, options=None, Configurator=Configurator): + """ Return a Router object, representing a fully configured + ``repoze.bfg`` WSGI application. + + ``root_factory`` must be a callable that accepts a :term:`request` + object and which returns a traversal root object. The traversal + root returned by the root factory is the *default* traversal root; + it can be overridden on a per-view basis. ``root_factory`` may be + ``None``, in which case a 'default default' traversal root is + used. + + ``package`` is a Python module representing the application's + package. It is optional, defaulting to ``None``. ``package`` may + be ``None``. If ``package`` is ``None``, the ``filename`` passed + or the value in the ``options`` dictionary named + ``configure_zcml`` must be a) absolute pathname to a ZCML file + that represents the application's configuration *or* b) a + 'specification' in the form + ``dotted.package.name:relative/file/path.zcml``. + + ``filename`` is the filesystem path to a ZCML file (optionally + relative to the package path) that should be parsed to create the + application registry. It defaults to ``configure.zcml``. It can + also be a 'specification' in the form + ``dotted_package_name:relatve/file/path.zcml``. Note that if any + value for ``configure_zcml`` is passed within the ``options`` + dictionary, the value passed as ``filename`` will be ignored, + replaced with the ``configure_zcml`` value. + + ``settings``, if used, should be a dictionary containing runtime + settings (e.g. the key/value pairs in an app section of a + PasteDeploy file), with each key representing the option and the + key's value representing the specific option value, + e.g. ``{'reload_templates':True}``. Note that the keyword + parameter ``options`` is a backwards compatibility alias for the + ``settings`` keyword parameter. + """ + settings = settings or options or {} + zcml_file = settings.get('configure_zcml', filename) + config = Configurator(package=package, settings=settings, + root_factory=root_factory, zcml_file=zcml_file) + app = config.make_wsgi_app() + return app + diff --git a/repoze/bfg/interfaces.py b/repoze/bfg/interfaces.py index d7963ef22..0f2d6ce45 100644 --- a/repoze/bfg/interfaces.py +++ b/repoze/bfg/interfaces.py @@ -151,9 +151,11 @@ class ILocation(Interface): __parent__ = Attribute("The parent in the location hierarchy") __name__ = Attribute("The name within the parent") -class ILogger(Interface): +class IDebugLogger(Interface): """ Interface representing a PEP 282 logger """ +ILogger = IDebugLogger # b/c + class IRoutesMapper(Interface): """ Interface representing a Routes ``Mapper`` object """ diff --git a/repoze/bfg/log.py b/repoze/bfg/log.py index ac2145a47..a9957e550 100644 --- a/repoze/bfg/log.py +++ b/repoze/bfg/log.py @@ -3,7 +3,7 @@ import logging def make_stream_logger(name, stream, levelname='DEBUG', fmt='%(asctime)s %(message)s'): """ Return an object which implements - ``repoze.bfg.interfaces.ILogger`` (ie. a Python PEP 282 logger + ``repoze.bfg.interfaces.IDebugLogger`` (ie. a Python PEP 282 logger instance) with the name ``name`` using the stream (or open filehandle) ``stream``, logging at ``levelname`` log level or above with format ``fmt``. """ diff --git a/repoze/bfg/router.py b/repoze/bfg/router.py index ccf3d1a76..872b5a134 100644 --- a/repoze/bfg/router.py +++ b/repoze/bfg/router.py @@ -3,7 +3,7 @@ from zope.interface import providedBy from zope.interface import alsoProvides from repoze.bfg.interfaces import IForbiddenView -from repoze.bfg.interfaces import ILogger +from repoze.bfg.interfaces import IDebugLogger from repoze.bfg.interfaces import INotFoundView from repoze.bfg.interfaces import IRootFactory from repoze.bfg.interfaces import IRouter @@ -13,12 +13,12 @@ from repoze.bfg.interfaces import ISettings from repoze.bfg.interfaces import ITraverser from repoze.bfg.interfaces import IView +from repoze.bfg.configuration import make_app # b/c import from repoze.bfg.events import AfterTraversal from repoze.bfg.events import NewRequest from repoze.bfg.events import NewResponse from repoze.bfg.exceptions import Forbidden from repoze.bfg.exceptions import NotFound -from repoze.bfg.resource import resolve_resource_spec from repoze.bfg.request import Request from repoze.bfg.threadlocal import manager from repoze.bfg.traversal import DefaultRootFactory @@ -26,6 +26,8 @@ from repoze.bfg.traversal import ModelGraphTraverser from repoze.bfg.view import default_forbidden_view from repoze.bfg.view import default_notfound_view +make_app = make_app # prevent pyflakes from complaining + class Router(object): """ The main repoze.bfg WSGI application. """ implements(IRouter) @@ -35,7 +37,7 @@ class Router(object): def __init__(self, registry): q = registry.queryUtility - self.logger = q(ILogger, 'repoze.bfg.debug') + self.logger = q(IDebugLogger) self.notfound_view = q(INotFoundView, default=default_notfound_view) self.forbidden_view = q(IForbiddenView, default=default_forbidden_view) self.root_factory = q(IRootFactory, default=DefaultRootFactory) @@ -150,57 +152,3 @@ class Router(object): finally: manager.pop() -# note that ``options`` is a b/w compat alias for ``settings`` and -# ``Configurator`` is a testing dep inj -def make_app(root_factory, package=None, filename='configure.zcml', - settings=None, options=None, Configurator=None): - """ Return a Router object, representing a fully configured - ``repoze.bfg`` WSGI application. - - ``root_factory`` must be a callable that accepts a :term:`request` - object and which returns a traversal root object. The traversal - root returned by the root factory is the *default* traversal root; - it can be overridden on a per-view basis. ``root_factory`` may be - ``None``, in which case a 'default default' traversal root is - used. - - ``package`` is a Python module representing the application's - package. It is optional, defaulting to ``None``. ``package`` may - be ``None``. If ``package`` is ``None``, the ``filename`` passed - or the value in the ``options`` dictionary named - ``configure_zcml`` must be a) absolute pathname to a ZCML file - that represents the application's configuration *or* b) a - 'specification' in the form - ``dotted_package_name:relative/file/path.zcml``. - - ``filename`` is the filesystem path to a ZCML file (optionally - relative to the package path) that should be parsed to create the - application registry. It defaults to ``configure.zcml``. It can - also be a 'specification' in the form - ``dotted_package_name:relatve/file/path.zcml``. Note that if any - value for ``configure_zcml`` is passed within the ``options`` - dictionary, the value passed as ``filename`` will be ignored, - replaced with the ``configure_zcml`` value. - - ``settings``, if used, should be a dictionary containing runtime - settings (e.g. the key/value pairs in an app section of a - PasteDeploy file), with each key representing the option and the - key's value representing the specific option value, - e.g. ``{'reload_templates':True}``. Note that the keyword - parameter ``options`` is a backwards compatibility alias for the - ``settings`` keyword parameter. - """ - if Configurator is None: - from repoze.bfg.configuration import Configurator # pragma: no cover - settings = settings or options - config = Configurator() - package_name = package and package.__name__ or None - package_name, filename = resolve_resource_spec(filename, package_name) - if package_name is not None: - spec = '%s:%s' % (package_name, filename) - else: - spec = filename - config.declarative(root_factory, spec, settings=settings) - app = config.make_wsgi_app() - return app - diff --git a/repoze/bfg/tests/test_configuration.py b/repoze/bfg/tests/test_configuration.py index 0fdf1922a..624e90c05 100644 --- a/repoze/bfg/tests/test_configuration.py +++ b/repoze/bfg/tests/test_configuration.py @@ -3,12 +3,9 @@ import unittest from repoze.bfg import testing class ConfiguratorTests(unittest.TestCase): - def _makeOne(self, registry=None, package=None): - from repoze.bfg.registry import Registry + def _makeOne(self, *arg, **kw): from repoze.bfg.configuration import Configurator - if registry is None: - registry = Registry() - return Configurator(registry, package) + return Configurator(*arg, **kw) def _registerRenderer(self, config, name='.txt'): from repoze.bfg.interfaces import IRendererFactory @@ -36,11 +33,6 @@ class ConfiguratorTests(unittest.TestCase): (ctx_iface, request_iface), IView, name=name, default=None) - def _callDeclarative(self, *arg, **kw): - inst = self._makeOne() - inst.declarative(*arg, **kw) - return inst.registry - def _getRouteRequestIface(self, config, name): from repoze.bfg.interfaces import IRouteRequest iface = config.registry.getUtility(IRouteRequest, name) @@ -69,9 +61,9 @@ class ConfiguratorTests(unittest.TestCase): return L def _registerLogger(self, config): - from repoze.bfg.interfaces import ILogger + from repoze.bfg.interfaces import IDebugLogger logger = DummyLogger() - config.registry.registerUtility(logger, ILogger, 'repoze.bfg.debug') + config.registry.registerUtility(logger, IDebugLogger) return logger def _makeRequest(self, config): @@ -94,10 +86,12 @@ class ConfiguratorTests(unittest.TestCase): import sys from repoze.bfg.interfaces import ISettings from repoze.bfg.configuration import Configurator + from repoze.bfg.interfaces import IRendererFactory config = Configurator() this_pkg = sys.modules['repoze.bfg.tests'] self.failUnless(config.registry.getUtility(ISettings)) self.assertEqual(config.package, this_pkg) + self.failUnless(config.registry.getUtility(IRendererFactory, 'json')) def test_ctor_with_package_registry(self): import sys @@ -106,14 +100,63 @@ class ConfiguratorTests(unittest.TestCase): config = Configurator(package=bfg_pkg) self.assertEqual(config.package, bfg_pkg) - def test__default_configuration(self): + def test_ctor_noreg_zcml_file(self): + config = self._makeOne( + registry=None, + zcml_file='repoze.bfg.tests.fixtureapp:configure.zcml') + registry = config.registry + from repoze.bfg.tests.fixtureapp.models import IFixture + self.failUnless(registry.queryUtility(IFixture)) # only in c.zcml + + def test_ctor_noreg_zcml_file_routes_in_config(self): from repoze.bfg.interfaces import ISettings - from repoze.bfg.registry import Registry - registry = Registry() - config = self._makeOne(registry) - config._default_configuration() - self.assertEqual(config.registry, registry) - self.failIf(config.registry.getUtility(ISettings) is None) + from repoze.bfg.interfaces import IRootFactory + from repoze.bfg.interfaces import IRoutesMapper + config = self._makeOne( + zcml_file='repoze.bfg.tests.routesapp:configure.zcml') + self.failUnless(config.registry.getUtility(IRoutesMapper)) + + def test_ctor_noreg_custom_settings(self): + from repoze.bfg.interfaces import ISettings + settings = {'reload_templates':True, + 'mysetting':True} + config = self._makeOne(settings=settings) + settings = config.registry.getUtility(ISettings) + self.assertEqual(settings['reload_templates'], True) + self.assertEqual(settings['debug_authorization'], False) + self.assertEqual(settings['mysetting'], True) + + def test_ctor_noreg_debug_logger_None_default(self): + from repoze.bfg.interfaces import IDebugLogger + config = self._makeOne() + logger = config.registry.getUtility(IDebugLogger) + self.assertEqual(logger.name, 'repoze.bfg.debug') + + def test_ctor_noreg_debug_logger_non_None(self): + from repoze.bfg.interfaces import IDebugLogger + logger = object() + config = self._makeOne(debug_logger=logger) + result = config.registry.getUtility(IDebugLogger) + self.assertEqual(logger, result) + + def test_ctor_authentication_policy(self): + from repoze.bfg.interfaces import IAuthenticationPolicy + policy = object() + config = self._makeOne(authentication_policy=policy) + result = config.registry.getUtility(IAuthenticationPolicy) + self.assertEqual(policy, result) + + def test_ctor_no_root_factory(self): + from repoze.bfg.interfaces import IRootFactory + config = self._makeOne() + self.failUnless(config.registry.getUtility(IRootFactory)) + + def test_ctor_alternate_renderers(self): + from repoze.bfg.interfaces import IRendererFactory + renderer = object() + config = self._makeOne(renderers=[('yeah', renderer)]) + self.assertEqual(config.registry.getUtility(IRendererFactory, 'yeah'), + renderer) def test_make_wsgi_app(self): from repoze.bfg.threadlocal import get_current_registry @@ -171,75 +214,13 @@ class ConfiguratorTests(unittest.TestCase): from repoze.bfg.tests.fixtureapp.models import IFixture self.failUnless(registry.queryUtility(IFixture)) # only in c.zcml - def test_declarative_fixtureapp_default_filename_withpackage(self): - rootfactory = DummyRootFactory(None) - registry = self._callDeclarative( - rootfactory, - 'repoze.bfg.tests.fixtureapp:configure.zcml') - from repoze.bfg.tests.fixtureapp.models import IFixture - self.failUnless(registry.queryUtility(IFixture)) # only in c.zcml - - def test_declarative_fixtureapp_explicit_specification_in_settings(self): - rootfactory = DummyRootFactory(None) - zcmlfile = 'repoze.bfg.tests.fixtureapp.subpackage:yetanother.zcml' - registry = self._callDeclarative( - rootfactory, 'repoze.bfg.tests.fixtureapp:configure.zcml', - settings={'configure_zcml':zcmlfile}) - from repoze.bfg.tests.fixtureapp.models import IFixture - self.failIf(registry.queryUtility(IFixture)) # only in c.zcml - - def test_declarative_custom_settings(self): - settings = {'mysetting':True} - rootfactory = DummyRootFactory(None) - registry = self._callDeclarative( - rootfactory, 'repoze.bfg.tests.fixtureapp:configure.zcml', - settings=settings) - from repoze.bfg.interfaces import ISettings - settings = registry.getUtility(ISettings) - self.assertEqual(settings.reload_templates, False) - self.assertEqual(settings.debug_authorization, False) - self.assertEqual(settings.mysetting, True) - - def test_declarative_registrations(self): - settings = {'reload_templates':True, - 'debug_authorization':True} - rootfactory = DummyRootFactory(None) - registry = self._callDeclarative( - rootfactory, 'repoze.bfg.tests.fixtureapp:configure.zcml', - settings=settings) - from repoze.bfg.interfaces import ISettings - from repoze.bfg.interfaces import ILogger - from repoze.bfg.interfaces import IRootFactory - settings = registry.getUtility(ISettings) - logger = registry.getUtility(ILogger, name='repoze.bfg.debug') - rootfactory = registry.getUtility(IRootFactory) - self.assertEqual(logger.name, 'repoze.bfg.debug') - self.assertEqual(settings.reload_templates, True) - self.assertEqual(settings.debug_authorization, True) - self.assertEqual(rootfactory, rootfactory) - - def test_declarative_routes_in_config(self): - from repoze.bfg.interfaces import ISettings - from repoze.bfg.interfaces import ILogger - from repoze.bfg.interfaces import IRootFactory - from repoze.bfg.interfaces import IRoutesMapper - settings = {'reload_templates':True, - 'debug_authorization':True} - rootfactory = DummyRootFactory(None) - registry = self._callDeclarative( - rootfactory, 'repoze.bfg.tests.routesapp:configure.zcml', - settings=settings) - settings = registry.getUtility(ISettings) - logger = registry.getUtility(ILogger, name='repoze.bfg.debug') - self.assertEqual(registry.getUtility(IRootFactory), rootfactory) - self.failUnless(registry.getUtility(IRoutesMapper)) - - def test_declarative_lock_and_unlock(self): - rootfactory = DummyRootFactory(None) + def test_load_zcml_lock_and_unlock(self): + config = self._makeOne() dummylock = DummyLock() - registry = self._callDeclarative( - rootfactory, 'repoze.bfg.tests.fixtureapp:configure.zcml', + registry = config.load_zcml( + 'repoze.bfg.tests.fixtureapp:configure.zcml', lock=dummylock) + from repoze.bfg.tests.fixtureapp.models import IFixture self.assertEqual(dummylock.acquired, True) self.assertEqual(dummylock.released, True) @@ -1061,35 +1042,35 @@ class ConfiguratorTests(unittest.TestCase): request = self._makeRequest(config) self.assertEqual(wrapped(None, request).__class__, StaticURLParser) - def test_system_view_no_view_no_renderer(self): + def test__system_view_no_view_no_renderer(self): from zope.configuration.exceptions import ConfigurationError config = self._makeOne() - self.assertRaises(ConfigurationError, config.system_view, IDummy) + self.assertRaises(ConfigurationError, config._system_view, IDummy) - def test_system_view_no_view_with_renderer(self): + def test__system_view_no_view_with_renderer(self): config = self._makeOne() self._registerRenderer(config, name='.pt') - config.system_view(IDummy, + config._system_view(IDummy, renderer='repoze.bfg.tests:fixtures/minimal.pt') request = self._makeRequest(config) view = config.registry.getUtility(IDummy) result = view(None, request) self.assertEqual(result.body, 'Hello!') - def test_system_view_with_attr(self): + def test__system_view_with_attr(self): config = self._makeOne() class view(object): def __init__(self, context, request): pass def index(self): return 'OK' - config.system_view(IDummy, view=view, attr='index') + config._system_view(IDummy, view=view, attr='index') view = config.registry.getUtility(IDummy) request = self._makeRequest(config) result = view(None, request) self.assertEqual(result, 'OK') - def test_system_view_with_wrapper(self): + def test__system_view_with_wrapper(self): from zope.interface import Interface from zope.interface import directlyProvides from repoze.bfg.interfaces import IRequest @@ -1099,7 +1080,7 @@ class ConfiguratorTests(unittest.TestCase): wrapper = lambda *arg: 'OK2' config.registry.registerAdapter(wrapper, (Interface, Interface), IView, name='wrapper') - config.system_view(IDummy, view=view, wrapper='wrapper') + config._system_view(IDummy, view=view, wrapper='wrapper') view = config.registry.getUtility(IDummy) request = self._makeRequest(config) directlyProvides(request, IRequest) @@ -1144,20 +1125,20 @@ class ConfiguratorTests(unittest.TestCase): self.assertEqual( config.registry.getUtility(IAuthorizationPolicy), policy) - def test_derive_view_as_function_context_and_request(self): + def test__derive_view_as_function_context_and_request(self): def view(context, request): return 'OK' config = self._makeOne() - result = config.derive_view(view) + result = config._derive_view(view) self.failUnless(result is view) self.failIf(hasattr(result, '__call_permissive__')) self.assertEqual(view(None, None), 'OK') - def test_derive_view_as_function_requestonly(self): + def test__derive_view_as_function_requestonly(self): def view(request): return 'OK' config = self._makeOne() - result = config.derive_view(view) + result = config._derive_view(view) self.failIf(result is view) self.assertEqual(view.__module__, result.__module__) self.assertEqual(view.__doc__, result.__doc__) @@ -1165,14 +1146,14 @@ class ConfiguratorTests(unittest.TestCase): self.failIf(hasattr(result, '__call_permissive__')) self.assertEqual(result(None, None), 'OK') - def test_derive_view_as_newstyle_class_context_and_request(self): + def test__derive_view_as_newstyle_class_context_and_request(self): class view(object): def __init__(self, context, request): pass def __call__(self): return 'OK' config = self._makeOne() - result = config.derive_view(view) + result = config._derive_view(view) self.failIf(result is view) self.assertEqual(view.__module__, result.__module__) self.assertEqual(view.__doc__, result.__doc__) @@ -1180,14 +1161,14 @@ class ConfiguratorTests(unittest.TestCase): self.failIf(hasattr(result, '__call_permissive__')) self.assertEqual(result(None, None), 'OK') - def test_derive_view_as_newstyle_class_requestonly(self): + def test__derive_view_as_newstyle_class_requestonly(self): class view(object): def __init__(self, context, request): pass def __call__(self): return 'OK' config = self._makeOne() - result = config.derive_view(view) + result = config._derive_view(view) self.failIf(result is view) self.assertEqual(view.__module__, result.__module__) self.assertEqual(view.__doc__, result.__doc__) @@ -1195,14 +1176,14 @@ class ConfiguratorTests(unittest.TestCase): self.failIf(hasattr(result, '__call_permissive__')) self.assertEqual(result(None, None), 'OK') - def test_derive_view_as_oldstyle_class_context_and_request(self): + def test__derive_view_as_oldstyle_class_context_and_request(self): class view: def __init__(self, context, request): pass def __call__(self): return 'OK' config = self._makeOne() - result = config.derive_view(view) + result = config._derive_view(view) self.failIf(result is view) self.assertEqual(view.__module__, result.__module__) self.assertEqual(view.__doc__, result.__doc__) @@ -1210,14 +1191,14 @@ class ConfiguratorTests(unittest.TestCase): self.failIf(hasattr(result, '__call_permissive__')) self.assertEqual(result(None, None), 'OK') - def test_derive_view_as_oldstyle_class_requestonly(self): + def test__derive_view_as_oldstyle_class_requestonly(self): class view: def __init__(self, context, request): pass def __call__(self): return 'OK' config = self._makeOne() - result = config.derive_view(view) + result = config._derive_view(view) self.failIf(result is view) self.assertEqual(view.__module__, result.__module__) self.assertEqual(view.__doc__, result.__doc__) @@ -1225,24 +1206,24 @@ class ConfiguratorTests(unittest.TestCase): self.failIf(hasattr(result, '__call_permissive__')) self.assertEqual(result(None, None), 'OK') - def test_derive_view_as_instance_context_and_request(self): + def test__derive_view_as_instance_context_and_request(self): class View: def __call__(self, context, request): return 'OK' view = View() config = self._makeOne() - result = config.derive_view(view) + result = config._derive_view(view) self.failUnless(result is view) self.failIf(hasattr(result, '__call_permissive__')) self.assertEqual(result(None, None), 'OK') - def test_derive_view_as_instance_requestonly(self): + def test__derive_view_as_instance_requestonly(self): class View: def __call__(self, request): return 'OK' view = View() config = self._makeOne() - result = config.derive_view(view) + result = config._derive_view(view) self.failIf(result is view) self.assertEqual(view.__module__, result.__module__) self.assertEqual(view.__doc__, result.__doc__) @@ -1250,13 +1231,13 @@ class ConfiguratorTests(unittest.TestCase): self.failIf(hasattr(result, '__call_permissive__')) self.assertEqual(result(None, None), 'OK') - def test_derive_view_with_debug_authorization_no_authpol(self): + def test__derive_view_with_debug_authorization_no_authpol(self): view = lambda *arg: 'OK' config = self._makeOne() self._registerSettings(config, debug_authorization=True, reload_templates=True) logger = self._registerLogger(config) - result = config.derive_view(view, permission='view') + result = config._derive_view(view, permission='view') self.assertEqual(view.__module__, result.__module__) self.assertEqual(view.__doc__, result.__doc__) self.assertEqual(view.__name__, result.__name__) @@ -1271,14 +1252,14 @@ class ConfiguratorTests(unittest.TestCase): "'view_name' against context None): Allowed " "(no authorization policy in use)") - def test_derive_view_with_debug_authorization_no_permission(self): + def test__derive_view_with_debug_authorization_no_permission(self): view = lambda *arg: 'OK' config = self._makeOne() self._registerSettings(config, debug_authorization=True, reload_templates=True) self._registerSecurityPolicy(config, True) logger = self._registerLogger(config) - result = config.derive_view(view) + result = config._derive_view(view) self.assertEqual(view.__module__, result.__module__) self.assertEqual(view.__doc__, result.__doc__) self.assertEqual(view.__name__, result.__name__) @@ -1293,14 +1274,14 @@ class ConfiguratorTests(unittest.TestCase): "'view_name' against context None): Allowed (" "no permission registered)") - def test_derive_view_debug_authorization_permission_authpol_permitted(self): + def test__derive_view_debug_authorization_permission_authpol_permitted(self): view = lambda *arg: 'OK' config = self._makeOne() self._registerSettings(config, debug_authorization=True, reload_templates=True) logger = self._registerLogger(config) self._registerSecurityPolicy(config, True) - result = config.derive_view(view, permission='view') + result = config._derive_view(view, permission='view') self.assertEqual(view.__module__, result.__module__) self.assertEqual(view.__doc__, result.__doc__) self.assertEqual(view.__name__, result.__name__) @@ -1314,7 +1295,7 @@ class ConfiguratorTests(unittest.TestCase): "debug_authorization of url url (view name " "'view_name' against context None): True") - def test_derive_view_debug_authorization_permission_authpol_denied(self): + def test__derive_view_debug_authorization_permission_authpol_denied(self): from repoze.bfg.exceptions import Forbidden view = lambda *arg: 'OK' config = self._makeOne() @@ -1322,7 +1303,7 @@ class ConfiguratorTests(unittest.TestCase): debug_authorization=True, reload_templates=True) logger = self._registerLogger(config) self._registerSecurityPolicy(config, False) - result = config.derive_view(view, permission='view') + result = config._derive_view(view, permission='view') self.assertEqual(view.__module__, result.__module__) self.assertEqual(view.__doc__, result.__doc__) self.assertEqual(view.__name__, result.__name__) @@ -1336,14 +1317,14 @@ class ConfiguratorTests(unittest.TestCase): "debug_authorization of url url (view name " "'view_name' against context None): False") - def test_derive_view_debug_authorization_permission_authpol_denied2(self): + def test__derive_view_debug_authorization_permission_authpol_denied2(self): view = lambda *arg: 'OK' config = self._makeOne() self._registerSettings(config, debug_authorization=True, reload_templates=True) logger = self._registerLogger(config) self._registerSecurityPolicy(config, False) - result = config.derive_view(view, permission='view') + result = config._derive_view(view, permission='view') self.assertEqual(view.__module__, result.__module__) self.assertEqual(view.__doc__, result.__doc__) self.assertEqual(view.__name__, result.__name__) @@ -1353,7 +1334,7 @@ class ConfiguratorTests(unittest.TestCase): permitted = result.__permitted__(None, None) self.assertEqual(permitted, False) - def test_derive_view_with_predicates_all(self): + def test__derive_view_with_predicates_all(self): view = lambda *arg: 'OK' predicates = [] def predicate1(context, request): @@ -1363,14 +1344,14 @@ class ConfiguratorTests(unittest.TestCase): predicates.append(True) return True config = self._makeOne() - result = config.derive_view(view, predicates=[predicate1, predicate2]) + result = config._derive_view(view, predicates=[predicate1, predicate2]) request = self._makeRequest(config) request.method = 'POST' next = result(None, None) self.assertEqual(next, 'OK') self.assertEqual(predicates, [True, True]) - def test_derive_view_with_predicates_checker(self): + def test__derive_view_with_predicates_checker(self): view = lambda *arg: 'OK' predicates = [] def predicate1(context, request): @@ -1380,14 +1361,14 @@ class ConfiguratorTests(unittest.TestCase): predicates.append(True) return True config = self._makeOne() - result = config.derive_view(view, predicates=[predicate1, predicate2]) + result = config._derive_view(view, predicates=[predicate1, predicate2]) request = self._makeRequest(config) request.method = 'POST' next = result.__predicated__(None, None) self.assertEqual(next, True) self.assertEqual(predicates, [True, True]) - def test_derive_view_with_predicates_notall(self): + def test__derive_view_with_predicates_notall(self): from repoze.bfg.exceptions import NotFound view = lambda *arg: 'OK' predicates = [] @@ -1398,13 +1379,13 @@ class ConfiguratorTests(unittest.TestCase): predicates.append(True) return False config = self._makeOne() - result = config.derive_view(view, predicates=[predicate1, predicate2]) + result = config._derive_view(view, predicates=[predicate1, predicate2]) request = self._makeRequest(config) request.method = 'POST' self.assertRaises(NotFound, result, None, None) self.assertEqual(predicates, [True, True]) - def test_derive_view_with_wrapper_viewname(self): + def test__derive_view_with_wrapper_viewname(self): from webob import Response from repoze.bfg.interfaces import IView inner_response = Response('OK') @@ -1418,7 +1399,7 @@ class ConfiguratorTests(unittest.TestCase): config = self._makeOne() config.registry.registerAdapter( outer_view, (None, None), IView, 'owrap') - result = config.derive_view(inner_view, viewname='inner', + result = config._derive_view(inner_view, viewname='inner', wrapper_viewname='owrap') self.failIf(result is inner_view) self.assertEqual(inner_view.__module__, result.__module__) @@ -1428,7 +1409,7 @@ class ConfiguratorTests(unittest.TestCase): response = result(None, request) self.assertEqual(response.body, 'outer OK') - def test_derive_view_with_wrapper_viewname_notfound(self): + def test__derive_view_with_wrapper_viewname_notfound(self): from webob import Response inner_response = Response('OK') def inner_view(context, request): @@ -1436,7 +1417,7 @@ class ConfiguratorTests(unittest.TestCase): config = self._makeOne() request = self._makeRequest(config) request.registry = config.registry - wrapped = config.derive_view( + wrapped = config._derive_view( inner_view, viewname='inner', wrapper_viewname='owrap') result = self.assertRaises(ValueError, wrapped, None, request) @@ -2274,6 +2255,50 @@ class TestRequestOnly(unittest.TestCase): foo = Foo() self.assertFalse(self._callFUT(foo)) +class TestMakeApp(unittest.TestCase): + def setUp(self): + testing.setUp() + + def tearDown(self): + testing.tearDown() + + def _callFUT(self, *arg, **kw): + from repoze.bfg.configuration import make_app + return make_app(*arg, **kw) + + def test_it(self): + settings = {'a':1} + rootfactory = object() + app = self._callFUT(rootfactory, settings=settings, + Configurator=DummyConfigurator) + self.assertEqual(app.root_factory, rootfactory) + self.assertEqual(app.settings, settings) + self.assertEqual(app.zcml_file, 'configure.zcml') + + def test_it_options_means_settings(self): + settings = {'a':1} + rootfactory = object() + app = self._callFUT(rootfactory, options=settings, + Configurator=DummyConfigurator) + self.assertEqual(app.root_factory, rootfactory) + self.assertEqual(app.settings, settings) + self.assertEqual(app.zcml_file, 'configure.zcml') + + def test_it_with_package(self): + package = object() + rootfactory = object() + app = self._callFUT(rootfactory, package=package, + Configurator=DummyConfigurator) + self.assertEqual(app.package, package) + + def test_it_with_custom_configure_zcml(self): + rootfactory = object() + settings = {'configure_zcml':'2.zcml'} + app = self._callFUT(rootfactory, filename='1.zcml', settings=settings, + Configurator=DummyConfigurator) + self.assertEqual(app.zcml_file, '2.zcml') + + class DummyRequest: subpath = () def __init__(self): @@ -2347,3 +2372,16 @@ class DummySecurityPolicy: def permits(self, context, principals, permission): return self.permitted + +class DummyConfigurator(object): + def __init__(self, registry=None, package=None, + root_factory=None, zcml_file=None, + settings=None): + self.root_factory = root_factory + self.package = package + self.zcml_file = zcml_file + self.settings = settings + + def make_wsgi_app(self): + return self + diff --git a/repoze/bfg/tests/test_router.py b/repoze/bfg/tests/test_router.py index df8d069ea..76c61f1e2 100644 --- a/repoze/bfg/tests/test_router.py +++ b/repoze/bfg/tests/test_router.py @@ -29,9 +29,9 @@ class TestRouter(unittest.TestCase): mapper.connect(path, name, factory) def _registerLogger(self): - from repoze.bfg.interfaces import ILogger + from repoze.bfg.interfaces import IDebugLogger logger = DummyLogger() - self.registry.registerUtility(logger, ILogger, name='repoze.bfg.debug') + self.registry.registerUtility(logger, IDebugLogger) return logger def _registerSettings(self, **kw): @@ -507,35 +507,6 @@ class TestRouter(unittest.TestCase): self.failUnless(req_iface.providedBy(request)) self.failUnless(IFoo.providedBy(request)) -class TestMakeApp(unittest.TestCase): - def setUp(self): - testing.setUp() - - def tearDown(self): - testing.tearDown() - - def _callFUT(self, *arg, **kw): - from repoze.bfg.router import make_app - return make_app(*arg, **kw) - - def test_it(self): - settings = {'a':1} - rootfactory = object() - app = self._callFUT(rootfactory, settings=settings, - Configurator=DummyConfigurator) - self.assertEqual(app.root_factory, rootfactory) - self.assertEqual(app.settings, settings) - self.assertEqual(app.spec, 'configure.zcml') - - def test_it_options_means_settings(self): - settings = {'a':1} - rootfactory = object() - app = self._callFUT(rootfactory, options=settings, - Configurator=DummyConfigurator) - self.assertEqual(app.root_factory, rootfactory) - self.assertEqual(app.settings, settings) - self.assertEqual(app.spec, 'configure.zcml') - class DummyContext: pass @@ -599,12 +570,3 @@ class DummyLogger: warn = info debug = info -class DummyConfigurator(object): - def make_wsgi_app(self): - return self - - def declarative(self, root_factory=None, spec=None, settings=None): - self.root_factory = root_factory - self.spec = spec - self.settings = settings - diff --git a/repoze/bfg/zcml.py b/repoze/bfg/zcml.py index 2359c86dc..9c0f381f1 100644 --- a/repoze/bfg/zcml.py +++ b/repoze/bfg/zcml.py @@ -322,8 +322,8 @@ class SystemViewHandler(object): def register(iface=self.iface): reg = get_current_registry() config = Configurator(reg) - config.system_view(iface, view=view, attr=attr, renderer=renderer, - wrapper=wrapper, _info=_context.info) + config._system_view(iface, view=view, attr=attr, renderer=renderer, + wrapper=wrapper, _info=_context.info) _context.action( discriminator = self.iface, -- cgit v1.2.3