diff options
| -rw-r--r-- | CHANGES.txt | 12 | ||||
| -rw-r--r-- | repoze/bfg/router.py | 29 | ||||
| -rw-r--r-- | repoze/bfg/settings.py | 3 | ||||
| -rw-r--r-- | repoze/bfg/tests/fixtureapp/another.zcml | 2 | ||||
| -rw-r--r-- | repoze/bfg/tests/fixtureapp/configure.zcml | 5 | ||||
| -rw-r--r-- | repoze/bfg/tests/fixtureapp/models.py | 3 | ||||
| -rw-r--r-- | repoze/bfg/tests/test_router.py | 147 | ||||
| -rw-r--r-- | repoze/bfg/tests/test_settings.py | 11 |
8 files changed, 149 insertions, 63 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index d87c2749e..d601f3199 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,15 @@ +Next release +============ + +Features +-------- + +- Allow a Paste config file (``configure_zcml``) value or an + environment variable (``BFG_CONFIGURE_ZCML``) to name a ZCML file + that will be used to bootstrap the application. Previously, the + integrator could not influence which ZCML file was used to do the + boostrapping (only the original application developer). + 1.0a9 (2009-07-01) ================== diff --git a/repoze/bfg/router.py b/repoze/bfg/router.py index 4eb0fed81..3b9b12cb7 100644 --- a/repoze/bfg/router.py +++ b/repoze/bfg/router.py @@ -210,8 +210,9 @@ def default_notfound_view(context, request): def make_app(root_factory, package=None, filename='configure.zcml', authentication_policy=None, authorization_policy=None, - options=None, registry=None, debug_logger=None): - # registry and debug_logger *only* for unittests + options=None, registry=None, debug_logger=None, + manager=manager): + # registry, debug_logger and manager *only* for unittests """ Return a Router object, representing a fully configured ``repoze.bfg`` WSGI application. @@ -223,13 +224,18 @@ def make_app(root_factory, package=None, filename='configure.zcml', used. ``package`` is a Python module representing the application's - package. It is optional, defaulting to ``None``. If ``package`` - is ``None``, the ``filename`` passed must be an absolute pathname - to a ZCML file that represents the application's configuration. + package. It is optional, defaulting to ``None``. ``package`` may + be ``None``. If ``package`` is ``None``, either the ``filename`` + passed or the value in the ``options`` dictionary named + ``configure_zcml`` must be an absolute pathname to a ZCML file + that represents the application's configuration. ``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``. + application registry. It defaults to ``configure.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. ``authentication_policy`` should be an object that implements the ``repoze.bfg.interfaces.IAuthenticationPolicy`` interface (e.g. @@ -265,19 +271,24 @@ def make_app(root_factory, package=None, filename='configure.zcml', if options is None: options = {} + if not 'configure_zcml' in options: + options['configure_zcml'] = filename + + settings = Settings(get_options(options)) + filename = settings['configure_zcml'] + if registry is None: regname = filename if package: regname = package.__name__ registry = Registry(regname) + registry.registerUtility(settings, ISettings) + if debug_logger is None: debug_logger = make_stream_logger('repoze.bfg.debug', sys.stderr) registry.registerUtility(debug_logger, ILogger, 'repoze.bfg.debug') - settings = Settings(get_options(options)) - registry.registerUtility(settings, ISettings) - if root_factory is None: root_factory = DefaultRootFactory diff --git a/repoze/bfg/settings.py b/repoze/bfg/settings.py index 08607f756..57295fcdc 100644 --- a/repoze/bfg/settings.py +++ b/repoze/bfg/settings.py @@ -55,11 +55,14 @@ def get_options(kw, environ=os.environ): config_reload_resources = kw.get('reload_resources', '') effective_reload_resources = asbool(eget('BFG_RELOAD_RESOURCES', config_reload_resources)) + configure_zcml = kw.get('configure_zcml', '') + effective_configure_zcml = eget('BFG_CONFIGURE_ZCML', configure_zcml) update = { 'debug_authorization': effective_debug_all or effective_debug_auth, 'debug_notfound': effective_debug_all or effective_debug_notfound, 'reload_templates': effective_reload_all or effective_reload_templates, 'reload_resources':effective_reload_all or effective_reload_resources, + 'configure_zcml':effective_configure_zcml, } kw.update(update) diff --git a/repoze/bfg/tests/fixtureapp/another.zcml b/repoze/bfg/tests/fixtureapp/another.zcml index c01245656..0ed8cff1b 100644 --- a/repoze/bfg/tests/fixtureapp/another.zcml +++ b/repoze/bfg/tests/fixtureapp/another.zcml @@ -1,5 +1,7 @@ <configure xmlns="http://namespaces.repoze.org/bfg"> + <include package="repoze.bfg.includes" /> + <view view=".views.fixture_view" for="*" diff --git a/repoze/bfg/tests/fixtureapp/configure.zcml b/repoze/bfg/tests/fixtureapp/configure.zcml index 29d7a7329..4a36d891a 100644 --- a/repoze/bfg/tests/fixtureapp/configure.zcml +++ b/repoze/bfg/tests/fixtureapp/configure.zcml @@ -16,6 +16,11 @@ request_type=".views.IDummy" /> + <utility + component=".models.fixture" + provides=".models.IFixture" + /> + <include file="another.zcml"/> </configure> diff --git a/repoze/bfg/tests/fixtureapp/models.py b/repoze/bfg/tests/fixtureapp/models.py index a57b06308..d80d14bb3 100644 --- a/repoze/bfg/tests/fixtureapp/models.py +++ b/repoze/bfg/tests/fixtureapp/models.py @@ -3,3 +3,6 @@ from zope.interface import Interface class IFixture(Interface): pass +def fixture(): + """ """ + diff --git a/repoze/bfg/tests/test_router.py b/repoze/bfg/tests/test_router.py index b0f75d899..cd88f8971 100644 --- a/repoze/bfg/tests/test_router.py +++ b/repoze/bfg/tests/test_router.py @@ -97,7 +97,7 @@ class RouterTests(unittest.TestCase): return L def _registerRootFactory(self, val): - rootfactory = make_rootfactory(val) + rootfactory = DummyRootFactory(val) from repoze.bfg.interfaces import IRootFactory self.registry.registerUtility(rootfactory, IRootFactory) return rootfactory @@ -221,7 +221,7 @@ class RouterTests(unittest.TestCase): context = DummyContext() self._registerTraverserFactory(context) environ = self._makeEnviron() - view = make_view('abc') + view = DummyView('abc') self._registerView(view, '', None, None) router = self._makeOne() start_response = DummyStartResponse() @@ -251,7 +251,7 @@ class RouterTests(unittest.TestCase): self._registerTraverserFactory(context) self._registerAuthenticationPolicy() response = DummyResponse() - view = make_view(response) + view = DummyView(response) from repoze.bfg.security import ACLDenied denied = ACLDenied('ace', 'acl', 'permission', ['principals'], context) environ = self._makeEnviron() @@ -269,7 +269,7 @@ class RouterTests(unittest.TestCase): self._registerTraverserFactory(context) response = DummyResponse() response.app_iter = ['Hello world'] - view = make_view(response) + view = DummyView(response) environ = self._makeEnviron() self._registerView(view, '', None, None) rootfactory = self._registerRootFactory(context) @@ -289,7 +289,7 @@ class RouterTests(unittest.TestCase): self._registerTraverserFactory(context, _deprecation_warning='abc') response = DummyResponse() response.app_iter = ['Hello world'] - view = make_view(response) + view = DummyView(response) environ = self._makeEnviron() self._registerView(view, '', None, None) router = self._makeOne() @@ -308,7 +308,7 @@ class RouterTests(unittest.TestCase): rootfactory = self._registerRootFactory(context) response = DummyResponse() response.app_iter = ['Hello world'] - view = make_view(response) + view = DummyView(response) environ = self._makeEnviron() self._registerView(view, 'foo', None, None) router = self._makeOne() @@ -334,7 +334,7 @@ class RouterTests(unittest.TestCase): rootfactory = self._registerRootFactory(context) response = DummyResponse() response.app_iter = ['Hello world'] - view = make_view(response) + view = DummyView(response) environ = self._makeEnviron() self._registerView(view, '', IContext, IRequest) router = self._makeOne() @@ -360,7 +360,7 @@ class RouterTests(unittest.TestCase): directlyProvides(context, INotContext) self._registerTraverserFactory(context, subpath=['']) response = DummyResponse() - view = make_view(response) + view = DummyView(response) environ = self._makeEnviron() self._registerView(view, '', IContext, IRequest) router = self._makeOne() @@ -379,7 +379,7 @@ class RouterTests(unittest.TestCase): directlyProvides(context, IContext) self._registerTraverserFactory(context, subpath=['']) response = DummyResponse() - view = make_view(response) + view = DummyView(response) environ = self._makeEnviron() self._registerView(view, '', IContext, IRequest) router = self._makeOne() @@ -398,7 +398,7 @@ class RouterTests(unittest.TestCase): directlyProvides(context, IContext) self._registerTraverserFactory(context, subpath=['']) response = DummyResponse() - view = make_view(response) + view = DummyView(response) environ = self._makeEnviron() self._registerView(view, '', IContext, IRequest) router = self._makeOne() @@ -421,7 +421,7 @@ class RouterTests(unittest.TestCase): directlyProvides(context, IContext) self._registerTraverserFactory(context, subpath=['']) response = DummyResponse() - view = make_view(response) + view = DummyView(response) environ = self._makeEnviron() self._registerView(view, '', IContext, IRequest) router = self._makeOne() @@ -444,7 +444,7 @@ class RouterTests(unittest.TestCase): directlyProvides(context, IContext) self._registerTraverserFactory(context, subpath=['']) response = DummyResponse() - view = make_view(response) + view = DummyView(response) environ = self._makeEnviron() self._registerView(view, '', IContext, IRequest) router = self._makeOne() @@ -465,7 +465,7 @@ class RouterTests(unittest.TestCase): self._registerTraverserFactory(context, subpath=['']) self._registerAuthenticationPolicy() response = DummyResponse() - view = make_view(response) + view = DummyView(response) environ = self._makeEnviron() self._registerView(view, '', IContext, IRequest) checker = self._registerViewPermission('', True) @@ -486,7 +486,7 @@ class RouterTests(unittest.TestCase): self._registerTraverserFactory(context, subpath=['']) self._registerAuthenticationPolicy() response = DummyResponse() - view = make_view(response) + view = DummyView(response) from repoze.bfg.security import ACLDenied denied = ACLDenied('ace', 'acl', 'permission', ['principals'], context) environ = self._makeEnviron() @@ -511,7 +511,7 @@ class RouterTests(unittest.TestCase): self._registerTraverserFactory(context, subpath=['']) self._registerAuthenticationPolicy() response = DummyResponse() - view = make_view(response) + view = DummyView(response) from repoze.bfg.security import ACLDenied denied = ACLDenied('ace', 'acl', 'permission', ['principals'], context) environ = self._makeEnviron() @@ -537,7 +537,7 @@ class RouterTests(unittest.TestCase): self._registerAuthenticationPolicy() self._registerTraverserFactory(context, subpath=['']) response = DummyResponse() - view = make_view(response) + view = DummyView(response) from repoze.bfg.security import ACLDenied environ = self._makeEnviron() self._registerView(view, '', IContext, IRequest) @@ -571,7 +571,7 @@ class RouterTests(unittest.TestCase): self._registerTraverserFactory(context) response = DummyResponse() response.app_iter = ['Hello world'] - view = make_view(response) + view = DummyView(response) environ = self._makeEnviron() self._registerView(view, '', None, None) from repoze.bfg.interfaces import INewRequest @@ -591,7 +591,7 @@ class RouterTests(unittest.TestCase): self._registerTraverserFactory(context) response = DummyResponse() response.app_iter = ['Hello world'] - view = make_view(response) + view = DummyView(response) environ = self._makeEnviron() self._registerView(view, '', None, None) router = self._makeOne() @@ -610,7 +610,7 @@ class RouterTests(unittest.TestCase): self._registerTraverserFactory(context) response = DummyResponse() response.app_iter = ['Hello world'] - view = make_view(response) + view = DummyView(response) environ = self._makeEnviron(REQUEST_METHOD='POST') self._registerView(view, '', None, None) router = self._makeOne() @@ -631,7 +631,7 @@ class RouterTests(unittest.TestCase): self._registerTraverserFactory(context) response = DummyResponse() response.app_iter = ['Hello world'] - view = make_view(response) + view = DummyView(response) environ = self._makeEnviron(REQUEST_METHOD='PUT') self._registerView(view, '', None, None) router = self._makeOne() @@ -650,7 +650,7 @@ class RouterTests(unittest.TestCase): self._registerTraverserFactory(context) response = DummyResponse() response.app_iter = ['Hello world'] - view = make_view(response) + view = DummyView(response) environ = self._makeEnviron(REQUEST_METHOD='UNKNOWN') self._registerView(view, '', None, None) router = self._makeOne() @@ -663,27 +663,49 @@ class RouterTests(unittest.TestCase): class MakeAppTests(unittest.TestCase): def setUp(self): cleanUp() - import repoze.bfg.router - self.old_tl_manager = repoze.bfg.router.manager - self.regmgr = DummyRegistryManager() - repoze.bfg.router.manager = self.regmgr def tearDown(self): cleanUp() - import repoze.bfg.router - repoze.bfg.router.threadlocal_manager = self.old_tl_manager def _callFUT(self, *arg, **kw): from repoze.bfg.router import make_app return make_app(*arg, **kw) - def test_fixtureapp(self): + def test_fixtureapp_default_filename_withpackage(self): + manager = DummyRegistryManager() from repoze.bfg.tests import fixtureapp - rootpolicy = make_rootfactory(None) - app = self._callFUT(rootpolicy, fixtureapp) + rootpolicy = DummyRootFactory(None) + app = self._callFUT(rootpolicy, fixtureapp, manager=manager) self.assertEqual(app.registry.__name__, 'repoze.bfg.tests.fixtureapp') + from repoze.bfg.tests.fixtureapp.models import IFixture + self.failUnless(app.registry.queryUtility(IFixture)) # only in c.zcml + def test_fixtureapp_explicit_filename(self): + manager = DummyRegistryManager() + from repoze.bfg.tests import fixtureapp + rootpolicy = DummyRootFactory(None) + app = self._callFUT(rootpolicy, fixtureapp, filename='another.zcml', + manager=manager) + self.assertEqual(app.registry.__name__, 'repoze.bfg.tests.fixtureapp') + from repoze.bfg.tests.fixtureapp.models import IFixture + self.failIf(app.registry.queryUtility(IFixture)) # only in c.zcml + + def test_fixtureapp_explicit_filename_in_options(self): + import os + manager = DummyRegistryManager() + rootpolicy = DummyRootFactory(None) + from repoze.bfg.tests import fixtureapp + zcmlfile = os.path.join(os.path.dirname(fixtureapp.__file__), + 'another.zcml') + app = self._callFUT(rootpolicy, fixtureapp, filename='configure.zcml', + options={'configure_zcml':zcmlfile}, + manager=manager) + self.assertEqual(app.registry.__name__, 'repoze.bfg.tests.fixtureapp') + from repoze.bfg.tests.fixtureapp.models import IFixture + self.failIf(app.registry.queryUtility(IFixture)) # only in c.zcml + def test_event(self): + manager = DummyRegistryManager() def subscriber(event): event.app.created = True from repoze.bfg.interfaces import IWSGIApplicationCreatedEvent @@ -693,15 +715,17 @@ class MakeAppTests(unittest.TestCase): (IWSGIApplicationCreatedEvent,) ) from repoze.bfg.tests import fixtureapp - rootpolicy = make_rootfactory(None) - app = self._callFUT(rootpolicy, fixtureapp) + rootpolicy = DummyRootFactory(None) + app = self._callFUT(rootpolicy, fixtureapp, manager=manager) assert app.created is True def test_custom_settings(self): + manager = DummyRegistryManager() options= {'mysetting':True} from repoze.bfg.tests import fixtureapp - rootpolicy = make_rootfactory(None) - app = self._callFUT(rootpolicy, fixtureapp, options=options) + rootpolicy = DummyRootFactory(None) + app = self._callFUT(rootpolicy, fixtureapp, options=options, + manager=manager) from repoze.bfg.interfaces import ISettings settings = app.registry.getUtility(ISettings) self.assertEqual(settings.reload_templates, False) @@ -709,11 +733,13 @@ class MakeAppTests(unittest.TestCase): self.assertEqual(settings.mysetting, True) def test_registrations(self): + manager = DummyRegistryManager() options= {'reload_templates':True, 'debug_authorization':True} from repoze.bfg.tests import fixtureapp - rootpolicy = make_rootfactory(None) - app = self._callFUT(rootpolicy, fixtureapp, options=options) + rootpolicy = DummyRootFactory(None) + app = self._callFUT(rootpolicy, fixtureapp, options=options, + manager=manager) from repoze.bfg.interfaces import ISettings from repoze.bfg.interfaces import ILogger from repoze.bfg.interfaces import IRootFactory @@ -724,15 +750,17 @@ class MakeAppTests(unittest.TestCase): self.assertEqual(settings.reload_templates, True) self.assertEqual(settings.debug_authorization, True) self.assertEqual(rootfactory, rootpolicy) - self.failUnless(self.regmgr.pushed and self.regmgr.popped) + self.failUnless(manager.pushed and manager.popped) def test_routes_in_config_with_rootpolicy(self): + manager = DummyRegistryManager() options= {'reload_templates':True, 'debug_authorization':True} from repoze.bfg.urldispatch import RoutesRootFactory from repoze.bfg.tests import routesapp - rootpolicy = make_rootfactory(None) - app = self._callFUT(rootpolicy, routesapp, options=options) + rootpolicy = DummyRootFactory(None) + app = self._callFUT(rootpolicy, routesapp, options=options, + manager=manager) from repoze.bfg.interfaces import ISettings from repoze.bfg.interfaces import ILogger from repoze.bfg.interfaces import IRootFactory @@ -744,15 +772,17 @@ class MakeAppTests(unittest.TestCase): self.assertEqual(settings.debug_authorization, True) self.failUnless(isinstance(rootfactory, RoutesRootFactory)) self.assertEqual(rootfactory.default_root_factory, rootpolicy) - self.failUnless(self.regmgr.pushed and self.regmgr.popped) + self.failUnless(manager.pushed and manager.popped) def test_routes_in_config_no_rootpolicy(self): + manager = DummyRegistryManager() options= {'reload_templates':True, 'debug_authorization':True} from repoze.bfg.urldispatch import RoutesRootFactory from repoze.bfg.router import DefaultRootFactory from repoze.bfg.tests import routesapp - app = self._callFUT(None, routesapp, options=options) + app = self._callFUT(None, routesapp, options=options, + manager=manager) from repoze.bfg.interfaces import ISettings from repoze.bfg.interfaces import ILogger from repoze.bfg.interfaces import IRootFactory @@ -764,29 +794,33 @@ class MakeAppTests(unittest.TestCase): self.assertEqual(settings.debug_authorization, True) self.failUnless(isinstance(rootfactory, RoutesRootFactory)) self.assertEqual(rootfactory.default_root_factory, DefaultRootFactory) - self.failUnless(self.regmgr.pushed and self.regmgr.popped) + self.failUnless(manager.pushed and manager.popped) def test_no_routes_in_config_no_rootpolicy(self): + manager = DummyRegistryManager() from repoze.bfg.router import DefaultRootFactory from repoze.bfg.interfaces import IRootFactory options= {'reload_templates':True, 'debug_authorization':True} from repoze.bfg.tests import fixtureapp - app = self._callFUT(None, fixtureapp, options=options) + app = self._callFUT(None, fixtureapp, options=options, + manager=manager) rootfactory = app.registry.getUtility(IRootFactory) self.assertEqual(rootfactory, DefaultRootFactory) def test_authorization_policy_no_authentication_policy(self): + manager = DummyRegistryManager() from repoze.bfg.interfaces import IAuthorizationPolicy authzpolicy = DummyContext() from repoze.bfg.tests import routesapp logger = DummyLogger() app = self._callFUT(None, routesapp, authorization_policy=authzpolicy, - debug_logger=logger) + debug_logger=logger, manager=manager) self.failIf(app.registry.queryUtility(IAuthorizationPolicy)) self.assertEqual(logger.messages, []) def test_authentication_policy_no_authorization_policy(self): + manager = DummyRegistryManager() from repoze.bfg.interfaces import IAuthorizationPolicy from repoze.bfg.interfaces import IAuthenticationPolicy from repoze.bfg.authorization import ACLAuthorizationPolicy @@ -794,7 +828,7 @@ class MakeAppTests(unittest.TestCase): from repoze.bfg.tests import routesapp logger = DummyLogger() app = self._callFUT(None, routesapp, authentication_policy=authnpolicy, - debug_logger=logger) + debug_logger=logger, manager=manager) self.assertEqual(app.registry.getUtility(IAuthenticationPolicy), authnpolicy) self.assertEqual( @@ -803,6 +837,7 @@ class MakeAppTests(unittest.TestCase): self.assertEqual(len(logger.messages), 1) # deprecation warning def test_authentication_policy_and_authorization_policy(self): + manager = DummyRegistryManager() from repoze.bfg.interfaces import IAuthorizationPolicy from repoze.bfg.interfaces import IAuthenticationPolicy authnpolicy = DummyContext() @@ -811,7 +846,7 @@ class MakeAppTests(unittest.TestCase): logger = DummyLogger() app = self._callFUT(None, routesapp, authentication_policy=authnpolicy, authorization_policy = authzpolicy, - debug_logger=logger) + debug_logger=logger, manager=manager) self.assertEqual(app.registry.getUtility(IAuthenticationPolicy), authnpolicy) self.assertEqual(app.registry.getUtility(IAuthorizationPolicy), @@ -866,15 +901,19 @@ class DummyRegistryManager: class DummyContext: pass -def make_view(response): - def view(context, request): - return response - return view +class DummyView: + def __init__(self, response): + self.response = response + + def __call__(self, context, request): + return self.response + +class DummyRootFactory: + def __init__(self, root): + self.root = root -def make_rootfactory(root): - def rootpolicy(environ): - return root - return rootpolicy + def __call__(self, environ): + return self.root class DummyStartResponse: status = () diff --git a/repoze/bfg/tests/test_settings.py b/repoze/bfg/tests/test_settings.py index 8319a302d..bef8297bf 100644 --- a/repoze/bfg/tests/test_settings.py +++ b/repoze/bfg/tests/test_settings.py @@ -148,6 +148,17 @@ class TestGetOptions(unittest.TestCase): self.assertEqual(result['debug_notfound'], True) self.assertEqual(result['debug_authorization'], True) + def test_configure_zcml(self): + result = self._callFUT({}) + self.assertEqual(result['configure_zcml'], '') + result = self._callFUT({'configure_zcml':'abc'}) + self.assertEqual(result['configure_zcml'], 'abc') + result = self._callFUT({}, {'BFG_CONFIGURE_ZCML':'abc'}) + self.assertEqual(result['configure_zcml'], 'abc') + result = self._callFUT({'configure_zcml':'def'}, + {'BFG_CONFIGURE_ZCML':'abc'}) + self.assertEqual(result['configure_zcml'], 'abc') + def test_originals_kept(self): result = self._callFUT({'a':'i am so a'}) self.assertEqual(result['a'], 'i am so a') |
