Shane Hathaway wrote: > Chris McDonough wrote: >> repoze.bfg 1.2b1 has been released. It is available via: >> >> easy_install -i http://dist.repoze.org/bfg/1.2/simple repoze.bfg >> >> Or via PyPI. >> >> The docs at http://docs.repoze.org/bfg/1.2 have been updated. > > Yay! :-) > > I've been following BFG 1.2 releases for a project. BFG 1.2 is shaping > up to be a solid release. > > Since you're working in this area, I wonder if you could clarify > something for me. In my application, I registered a utility using a BFG > ZCML directive, but when I tried to use the utility, I found that no > utilities were registered at all. I solved the problem by adding a call > to hook_zca() in my run.py, mimicking some code I found in BFG. So the > end of my run.app() now looks like this: > > config = Configurator(settings=settings, root_factory=root_factory) > config.hook_zca() > config.begin() > config.load_zcml(zcml_file) > config.end() > return config.make_wsgi_app() > > Is this a sensible solution?
I think so. The way it works is this: - At startup, the component registry associated with the Configurator is populated. Each BFG app uses its own component registry. If a registry is not passed to the configurator constructor, one is created. - During a request, the application component registry is "made current". This means calls to "r.b.threadlocal.get_current_registry()" in the thread handling the request will return the component registry. - BFG itself always uses "get_current_registry()" in places that it doesn't "naturally" have access to the registry. - App developers can use get_current_registry() to get the registry and thus get access to utilities and such, e.g. get_current_registry().getUtility(...) So far I haven't mentioned anything about the "ZCA global" APIs like getSiteManager, getUtility, etc. Using the ZCA global API to get at data in a BFG registry is actually not documented within the BFG documentation. It's sort of a hidden feature that doing so is even possible. Without special treatment, the ZCA global APIs will always return the global ZCA registry (the one in z.component.globalregistry.base). To make them start returning the "current" BFG registry, as you found, calling config.hook_zca() is required. config.hook_zca() does this under the hood: from zope.component import getSiteManager from repoze.bfg.threadlocal import get_current_registry getSiteManager.sethook(get_current_registry) This causes the ZCA global API to start using the BFG application registry in threads which are running a BFG request. There are three other options: - You can disuse the ZCA global API and use get_current_registry() instead. - You disuse both the ZCA global API and get_current_registry() and rely on getting to the registry via "request.registry" (in view code). - You can tell your BFG app to use the ZCA global registry at startup time: from zope.component import getGlobalSiteManager config = Configurator(registry=getGlobalSiteManager(), settings=settings, root_factory=root_factory) config.setup_registry() config.begin() config.load_zcml(zcml_file) config.end() return config.make_wsgi_app() The last option means that the configurator will populate and use the ZCA global registry rather than creating a new application-specific registry; since by default the ZCA global API will use this registry, things will work as you might expect a Zope app to when you use the global ZCA API. - C _______________________________________________ Repoze-dev mailing list Repozefirstname.lastname@example.org http://lists.repoze.org/listinfo/repoze-dev