[Grok-dev] Upgrading catalog utility

Uli Fouquet uli at gnufix.de
Wed Sep 7 09:32:36 EST 2011

Hi Roberto,

Roberto Allende wrote:

> Short version:
> How do i recreate, ie delete an create a new catalog for an existing
> application ?.

As all the gurus seem to be on vacation, I'll try to put in some bits.

I guess what you really want is an updated catalog, right? To do this,
you might perform two steps:

1) update the existing catalog instance to be compatible with your code.

2) update (i.e: reindex) all the contents of the changed catalog.

Step 1) can be done in two ways:

a) remove the old catalog and replace it by a new one.

b) examine the old catalog and modify it to reflect your changes.

For a):

As catalogs are normally stored as local utilities (i.e. they are stored
persistently inside your 'site' or grok.Application instance), you can
unregister them and register a new instance based on your changed code,
roughly like this:

   import grok
   from zope.catalog.interfaces import ICatalog
   from zope.component import getUtility, getGlobalSiteManager
   # get the catalog to replace
   cat = getUtility(ICatalog, name='my_catalog') # your catalog name
   # get a site manager responsible for registering the catalog
   # If you're not 'in a site', for instance on the debug shell, then
   # you can use something like
   #    from zope.component.hooks import setSite
   #    setSite(myapp)
   site = grok.getSite()
   sm = site.getSiteManager()
   # remove old catalog
   sm.unregisterUtility(cat, provided=ICatalog, name='my_catalog')
   # create new catalog as grok would do it at app creation time
   # cf. http://svn.zope.org/grok/trunk/src/grok/meta.py?view=auto
   # On startup Grok looks for Indexes definitions in the code and
   # registers them in the global registry in case you want to
   # create a new site. Then these indexes definitions are looked
   # up (triggered by an grok.IObjectAddedEvent) and installed in
   # a catalog. We do the same here, but manually.
   gsm = getGlobalSiteManager()
   # The indexes setup subscribers are registered as subscription
   # handlers
   handler_regs = gsm.registeredHandlers()
   # Filter out handlers that do not setup indexes
   all_cat_setup_handlers = [
       x.handler for x in handler_regs
       if isinstance(x.handler, grok.meta.IndexesSetupSubscriber)]
   # Filter out handlers not handlings our specific catalog
   # (in case we have several)
   our_cat_setup_handlers = [
       x for x in all_cat_setup_handlers
       if x.catalog_name == 'my_catalog']
   for indexes_setup in our_cat_setup_handlers:
       # Indexes subscribers need a site to cater, the
       # event is not really neccessary here, so we set it to None
       indexes_setup(site, None) # Create new catalog and indexes

This way you will (hopefully) get a 'refreshed' catalog based on your
changed code.

There are, of course, other ways to do this. You could simply fire a
grok.IObjectAdded event for your existing site, but that might be
dangerous because also other local utilities might try to install things
in your already existing site, not checking whether the thing to install
already exists. They might overwrite existing things, etc.

Furthermore, existing catalogs would not be created anew. They would
only be updated and missing indexes would be added. Indexes that were
removed in your code, would not be removed from the real catalog

So much for replacing the old catalog by a new one.

For b):

What, if it is sufficient to update (not replace) an existing catalog?
You could start as above:

   import grok
   from zope.catalog.interfaces import ICatalog
   from zope.component import getUtility, getGlobalSiteManager
   # get the catalog to update
   cat = getUtility(ICatalog, name='my_catalog') # your catalog name

Then, you could simply update this existing catalog to your liking:

   from zope.catalog.field import FieldIndex
   cat['new_atttribute'] = FieldIndex(
       field_name = 'new_attribute',
       interface = MyObject,
       field_callable = False, # see zope.catalog.attribute module

Obviously, you could also remove old indexes and the like, but this way
it is completely up to you to register the correct indexes, i.e. you
have to make sure that the new indexes match with the index
defininitions in your code.

This way you can get a new/updated catalog.

But what about the contents?

2.) Update catalog contents

If you only add a new index and this index indexes same objects
('MyObject' instances in your example) as already existing indexes: no
problem. The new index might be filled automatically after adding it
(don't know exactly), but if not then you can trigger


at any time to reindex everything.

If, however, you add an index that handles a new content type, say
IOtherContent instances, then you first have to find all objects of that
type in your site and register them manually with your catalog,
providing an IntId and all that, but that might not be what you need
right now. So I leave it here and hope that it helps :)

Best regards,


-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Dies ist ein digital signierter Nachrichtenteil
Url : http://mail.zope.org/pipermail/grok-dev/attachments/20110907/67db2d16/attachment.bin 

More information about the Grok-dev mailing list