From 3fd91222c6fb46bc2d5838229d7c54130619d73a Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sun, 13 Jul 2008 10:21:59 +0000 Subject: Use an application-local component registry. --- repoze/bfg/registry.py | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 repoze/bfg/registry.py (limited to 'repoze/bfg/registry.py') diff --git a/repoze/bfg/registry.py b/repoze/bfg/registry.py new file mode 100644 index 000000000..acb5a4abc --- /dev/null +++ b/repoze/bfg/registry.py @@ -0,0 +1,70 @@ +import threading +import zope.component + +from zope.component import getGlobalSiteManager +from zope.component.interfaces import ComponentLookupError +from zope.component.interfaces import IComponentLookup +from zope.component.registry import Components +from zope.component import getSiteManager as original_getSiteManager + +from zope.configuration import xmlconfig + +class ThreadLocalRegistryManager(threading.local): + registry = getGlobalSiteManager() + def set(self, registry): + self.registry = registry + + def get(self): + return self.registry + + def clear(self): + self.registry = getGlobalSiteManager() + +registry_manager = ThreadLocalRegistryManager() + +def setRegistryManager(manager): # for unit tests + global registry_manager + old_registry_manager = registry_manager + registry_manager = manager + return old_registry_manager + +def makeRegistry(filename, package, lock=threading.Lock()): + # This is absurd and probably not worth it. We want to try to + # push our ZCML-defined configuration into an app-local component + # registry in order to allow more than one bfg app to live in the + # same process space without one unnecessarily stomping on the + # other's component registrations (although I suspect directives + # that side effects are going to fail). The only way to do that + # currently is to override zope.component.getGlobalSiteManager for + # the duration of the ZCML includes. We acquire a lock in case + # another make_app runs in a different thread simultaneously, in a + # vain attempt to prevent mixing of registrations. There's not + # much we can do about non-make_app code that tries to use the + # global site manager API directly in a different thread while we + # hold the lock. Those registrations will end up in our + # application's registry. + lock.acquire() + try: + # Do I actually want a globalregistry.BaseGlobalComponents? + registry = Components(package.__name__) + registry_manager.set(registry) + original_getSiteManager.sethook(getSiteManager) + zope.component.getGlobalSiteManager = registry_manager.get + context = xmlconfig.file(filename, package=package) + return context, registry + finally: + lock.release() + zope.component.getGlobalSiteManager = getGlobalSiteManager + registry_manager.clear() + +def getSiteManager(context=None): + if context is None: + return registry_manager.get() + else: + try: + return IComponentLookup(context) + except TypeError, error: + raise ComponentLookupError(*error.args) + +from zope.testing.cleanup import addCleanUp +addCleanUp(original_getSiteManager.reset) -- cgit v1.2.3