[Zope-dev] Stacking zope.component registries

Marius Gedminas marius at gedmin.as
Thu Apr 8 16:36:56 EDT 2010


On Thu, Apr 08, 2010 at 02:37:33PM -0400, Chris McDonough wrote:
> Not sure how a new layer setup and teardown is signaled but assuming you can 
> hook that, do something like this:
> 
> class StackManager(object):
>      def __init__(self, default=None):
>          self.stack = []
>          self.default = default
> 
>      def push(self, info):
>          self.stack.append(info)
> 
>      def pop(self):
>          if self.stack:
>              return self.stack.pop()
> 
>      def get(self):
>          try:
>              return self.stack[-1]
>          except IndexError:
>              return self.default()
> 
>      def clear(self):
>          self.stack[:] = []
> 
> from zope.component import getGlobalSiteManager
> global_registry = getGlobalSiteManager()
> 
> def defaults():
>      return {'registry':global_registry}
> 
> manager = StackManager(default=defaults)
> 
> def get_current_registry(context=None):
>      return manager.get()['registry']
> 
> from zope.component import getSiteManager
> getSiteManager.sethook(get_current_registry)

That seems a bit short-sighted: it would break all tests that rely on
setSite() working.

> 
> Then when a layer is pushed:
> 
>    from zope.comonent.registry import Components
>    manager.push({'registry':Components()})

I suspect Martin wants

     manager.push({'registry': Components(bases=[manager.get()])})

here.

> 
> And popped:
> 
>    manager.pop()
> 
> 
> On 4/8/10 1:26 PM, Martin Aspeli wrote:
> > Hi,
> >
> > I'd like to come up with a way to set up a test fixture that does the
> > component registry equivalent of stackable DemoStorage's: whilst a layer
> > is in effect, calls to provideAdapter() and friends (and ZCML execution)
> > go into a global registry that is stacked on top of the default global one.o

Someone (I'm bad with names, sorry!) recently proposed a change to
zope.configuration that makes ZCML directives use getSiteManager()
instead of getGlobalSiteManager(); with that patch in, Chris's example
should make ZCML configuration register all the components into your
stacked registry.  Although you'd have the other problem of setSite()
having no effect on the site manager, which would break all local
utilities and adapters in your tests.

provideAdapter is harder, since it hardcodes the global registry.  You'd
have to monkey-patch the `base` global, or fix provideAdapter and
friends.

> >
> > On layer tear-down, the registry is popped, leaving the original (or
> > previous) global registry intact.

I like this goal.

> >
> > In zope.component.globalregistry, I see:
> >
> > def provideUtility(component, provides=None, name=u''):
> >       base.registerUtility(component, provides, name, event=False)
> >
> > base is a module-level variable of type BaseGlobalComponents(). I guess
> > there'd be a way to use __bases__ to create this kind of stack, but I'm
> > not clear on the details, and in particular whether this would really
> > work with provideAdapter() and the rest of the (test-oriented) Python API.

I don't see any way around monkey-patching
zope.component.globalregistry.base/globalSiteManager (two names for the
same object for extra fun!).  Also note that the root folder in the
database has a local site manager with __bases__ directly referencing
the global site object, which is pickled by name.  If you replace it,
you'll need to use a different BaseGlobalComponents instance, I think.

Marius Gedminas
-- 
http://pov.lt/ -- Zope 3 consulting and development
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: Digital signature
Url : http://mail.zope.org/pipermail/zope-dev/attachments/20100408/cab814d8/attachment.bin 


More information about the Zope-Dev mailing list