Shane Hathaway wrote:
> Chris McDonough wrote:
>> repoze.bfg 1.2b1 has been released.  It is available via:
>>    easy_install -i repoze.bfg
>> Or via PyPI.
>> The docs at 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, mimicking some code I found in BFG.  So the 
> end of my 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.

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

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()

- 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,
   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

Reply via email to