summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-01-12 00:30:12 +0000
committerChris McDonough <chrism@agendaless.com>2009-01-12 00:30:12 +0000
commitec2941b96a8f961438f9a341c936dfa660439a95 (patch)
tree648aa834b6c661a93a0947f6968024e89fd1c9fd
parent74f67dcdc4c672b3e85d674c5eaebb8d435564a3 (diff)
downloadpyramid-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.txt4
-rw-r--r--repoze/bfg/registry.py25
-rw-r--r--repoze/bfg/router.py117
-rw-r--r--repoze/bfg/tests/test_registry.py27
-rw-r--r--repoze/bfg/tests/test_router.py13
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