diff options
| author | Chris McDonough <chrism@agendaless.com> | 2009-01-12 00:30:12 +0000 |
|---|---|---|
| committer | Chris McDonough <chrism@agendaless.com> | 2009-01-12 00:30:12 +0000 |
| commit | ec2941b96a8f961438f9a341c936dfa660439a95 (patch) | |
| tree | 648aa834b6c661a93a0947f6968024e89fd1c9fd | |
| parent | 74f67dcdc4c672b3e85d674c5eaebb8d435564a3 (diff) | |
| download | pyramid-ec2941b96a8f961438f9a341c936dfa660439a95.tar.gz pyramid-ec2941b96a8f961438f9a341c936dfa660439a95.tar.bz2 pyramid-ec2941b96a8f961438f9a341c936dfa660439a95.zip | |
- Make the (internal) thread local registry manager maintain a stack
of registries in order to make it possible to call one BFG
application from inside another.
| -rw-r--r-- | CHANGES.txt | 4 | ||||
| -rw-r--r-- | repoze/bfg/registry.py | 25 | ||||
| -rw-r--r-- | repoze/bfg/router.py | 117 | ||||
| -rw-r--r-- | repoze/bfg/tests/test_registry.py | 27 | ||||
| -rw-r--r-- | repoze/bfg/tests/test_router.py | 13 |
5 files changed, 111 insertions, 75 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 46a8cf542..5bda29b6d 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -36,6 +36,10 @@ Features - Projects generated by the paster templates now use the ``DummyTemplateRenderer.assert_`` method in their view tests. +- Make the (internal) thread local registry manager maintain a stack + of registries in order to make it possible to call one BFG + application from inside another. + Bug Fixes --------- diff --git a/repoze/bfg/registry.py b/repoze/bfg/registry.py index f2f47a889..179fbd3dd 100644 --- a/repoze/bfg/registry.py +++ b/repoze/bfg/registry.py @@ -25,15 +25,26 @@ deprecated( ) class ThreadLocalRegistryManager(threading.local): - registry = getGlobalSiteManager() - def set(self, registry): - self.registry = registry + def __init__(self): + self.stack = [] + + def push(self, registry): + self.stack.append(registry) + + set = push # backwards compatibility + + def pop(self): + if self.stack: + return self.stack.pop() def get(self): - return self.registry + try: + return self.stack[-1] + except IndexError: + return getGlobalSiteManager() def clear(self): - self.registry = getGlobalSiteManager() + self.stack[:] = [] registry_manager = ThreadLocalRegistryManager() @@ -62,7 +73,7 @@ def makeRegistry(filename, package, lock=threading.Lock()): lock.acquire() try: registry = Components(package.__name__) - registry_manager.set(registry) + registry_manager.push(registry) original_getSiteManager.sethook(getSiteManager) zope.component.getGlobalSiteManager = registry_manager.get zcml_configure(filename, package=package) @@ -70,7 +81,7 @@ def makeRegistry(filename, package, lock=threading.Lock()): finally: zope.component.getGlobalSiteManager = getGlobalSiteManager lock.release() - registry_manager.clear() + registry_manager.pop() def getSiteManager(context=None): if context is None: diff --git a/repoze/bfg/router.py b/repoze/bfg/router.py index 622a8870b..ffbd853dc 100644 --- a/repoze/bfg/router.py +++ b/repoze/bfg/router.py @@ -48,62 +48,69 @@ class Router(object): 'view' code based on registrations within the application registry; call ``start_response`` and return an iterable. """ - registry_manager.set(self.registry) - request = Request(environ) - directlyProvides(request, IRequest) - dispatch(NewRequest(request)) - - root_factory = getUtility(IRootFactory) - root = root_factory(environ) - traverser = getAdapter(root, ITraverserFactory) - context, view_name, subpath = traverser(environ) - - request.root = root - request.context = context - request.view_name = view_name - request.subpath = subpath - - permitted = view_execution_permitted(context, request, view_name) - - settings = queryUtility(ISettings) - debug_authorization = settings and settings.debug_authorization - - if debug_authorization: - logger = queryUtility(ILogger, 'repoze.bfg.debug') - logger and logger.debug( - 'debug_authorization of url %s (view name %r against context ' - '%r): %s' % (request.url, view_name, context, permitted.msg) - ) - if not permitted: + registry_manager.push(self.registry) + + try: + request = Request(environ) + directlyProvides(request, IRequest) + dispatch(NewRequest(request)) + + root_factory = getUtility(IRootFactory) + root = root_factory(environ) + traverser = getAdapter(root, ITraverserFactory) + context, view_name, subpath = traverser(environ) + + request.root = root + request.context = context + request.view_name = view_name + request.subpath = subpath + + permitted = view_execution_permitted(context, request, view_name) + + settings = queryUtility(ISettings) + debug_authorization = settings and settings.debug_authorization + if debug_authorization: - msg = permitted.msg - else: - msg = 'Unauthorized: failed security policy check' - app = HTTPUnauthorized(escape(msg)) - return app(environ, start_response) - - response = render_view_to_response(context, request, view_name, - secure=False) - - if response is None: - debug_notfound = settings and settings.debug_notfound - if debug_notfound: logger = queryUtility(ILogger, 'repoze.bfg.debug') - msg = ( - 'debug_notfound of url %s; path_info: %r, context: %r, ' - 'view_name: %r, subpath: %r' % ( - request.url, request.path_info, context, view_name, subpath) + logger and logger.debug( + 'debug_authorization of url %s (view name %r against ' + 'context %r): %s' % ( + request.url, view_name, context, permitted.msg) ) - logger and logger.debug(msg) - else: - msg = request.url - app = HTTPNotFound(escape(msg)) - return app(environ, start_response) - - dispatch(NewResponse(response)) - - start_response(response.status, response.headerlist) - return response.app_iter + if not permitted: + if debug_authorization: + msg = permitted.msg + else: + msg = 'Unauthorized: failed security policy check' + app = HTTPUnauthorized(escape(msg)) + return app(environ, start_response) + + response = render_view_to_response(context, request, view_name, + secure=False) + + if response is None: + debug_notfound = settings and settings.debug_notfound + if debug_notfound: + logger = queryUtility(ILogger, 'repoze.bfg.debug') + msg = ( + 'debug_notfound of url %s; path_info: %r, context: %r, ' + 'view_name: %r, subpath: %r' % ( + request.url, request.path_info, context, view_name, + subpath) + ) + logger and logger.debug(msg) + else: + msg = request.url + app = HTTPNotFound(escape(msg)) + return app(environ, start_response) + + dispatch(NewResponse(response)) + + start_response(response.status, response.headerlist) + return response.app_iter + + finally: + registry_manager.pop() def make_app(root_factory, package=None, filename='configure.zcml', options=None): @@ -130,10 +137,10 @@ def make_app(root_factory, package=None, filename='configure.zcml', app = Router(registry) try: - registry_manager.set(registry) + registry_manager.push(registry) dispatch(WSGIApplicationCreatedEvent(app)) finally: - registry_manager.clear() + registry_manager.pop() return app diff --git a/repoze/bfg/tests/test_registry.py b/repoze/bfg/tests/test_registry.py index 0d051c131..51883b196 100644 --- a/repoze/bfg/tests/test_registry.py +++ b/repoze/bfg/tests/test_registry.py @@ -49,16 +49,28 @@ class TestThreadLocalRegistryManager(unittest.TestCase, PlacelessSetup): def test_init(self): local = self._makeOne() from zope.component import getGlobalSiteManager - self.assertEqual(local.registry, getGlobalSiteManager()) + self.assertEqual(local.stack, []) + self.assertEqual(local.get(), getGlobalSiteManager()) + + def test_push_and_pop(self): + local = self._makeOne() + from zope.component import getGlobalSiteManager + local.push(True) + self.assertEqual(local.get(), True) + self.assertEqual(local.pop(), True) + self.assertEqual(local.pop(), None) + self.assertEqual(local.get(), getGlobalSiteManager()) def test_set_get_and_clear(self): local = self._makeOne() from zope.component import getGlobalSiteManager local.set(None) - self.failIfEqual(local.registry, getGlobalSiteManager()) + self.assertEqual(local.stack, [None]) self.assertEqual(local.get(), None) local.clear() - self.assertEqual(local.registry, getGlobalSiteManager()) + self.assertEqual(local.get(), getGlobalSiteManager()) + local.clear() + self.assertEqual(local.get(), getGlobalSiteManager()) class GetSiteManagerTests(unittest.TestCase): def _getFUT(self): @@ -76,16 +88,15 @@ class GetSiteManagerTests(unittest.TestCase): self.assertRaises(ComponentLookupError, gsm, object) class DummyRegistrationManager: - registry = None - def set(self, registry): + def push(self, registry): self.registry = registry + def pop(self): + self.popped = True + def get(self): return self.registry - def clear(self): - self.cleared = True - class DummyLock: def acquire(self): self.acquired = True diff --git a/repoze/bfg/tests/test_router.py b/repoze/bfg/tests/test_router.py index 3f52bd9cd..35ab21f9c 100644 --- a/repoze/bfg/tests/test_router.py +++ b/repoze/bfg/tests/test_router.py @@ -483,7 +483,8 @@ class MakeAppTests(unittest.TestCase, PlacelessSetup): 'debug_authorization':True} import repoze.bfg.router old_registry_manager = repoze.bfg.router.registry_manager - repoze.bfg.router.registry_manager = DummyRegistryManager() + dummy_registry_manager = DummyRegistryManager() + repoze.bfg.router.registry_manager = dummy_registry_manager try: from repoze.bfg.tests import fixtureapp rootpolicy = make_rootfactory(None) @@ -498,15 +499,17 @@ class MakeAppTests(unittest.TestCase, PlacelessSetup): self.assertEqual(settings.reload_templates, True) self.assertEqual(settings.debug_authorization, True) self.assertEqual(rootfactory, rootpolicy) + self.assertEqual(dummy_registry_manager.pushed, True) + self.assertEqual(dummy_registry_manager.popped, True) finally: repoze.bfg.router.registry_manager = old_registry_manager class DummyRegistryManager: - def set(self, registry): - pass + def push(self, registry): + self.pushed = True - def clear(self): - pass + def pop(self): + self.popped = True class DummyContext: pass |
