Upgrading catalog utility

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Upgrading catalog utility

Roberto Allende
Hello

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

Long Version:
I need to upgrate an applcation made with grok to a new version and i
need to add a new index to its catalog. Following the example at Grok
Documentation[1], let's say i've:

class SiteCatalog(grok.Indexes):
    grok.site(Testvalueindex)
    grok.context(MyObject)
    grok.name('my_catalog')

    counter = Value()

An my new catalog has a new attribute, called new_attribute:

class SiteCatalog(grok.Indexes):
    grok.site(Testvalueindex)
    grok.context(MyObject)
    grok.name('my_catalog')

    counter = Value()
    new_attribute = grok.index.Field()

So, the problem is i've to re create SiteCatalog for my application
and "Source code for grok.index"[2] says  "Note that, since index
creation (and thus a call to our :meth:`setup()` method) currently
occurs only during the creation of a new Grok `Application` object in
the Zope Database".

I tried to instantiate the index and they monkey patch, which it
wouldn't be the most elegant solution but it could solve the problem
runing an upgrade method just once and i got an "can only be
instantiated on class level" exception.

So... any suggestion is very appreciated.

Kind Regards
Roberto Allende

1. http://grok.zope.org/documentation/how-to/implementing-search/view
2. http://grok.zope.org/doc/dev/_modules/grok/index.html
_______________________________________________
Grok-dev mailing list
[hidden email]
https://mail.zope.org/mailman/listinfo/grok-dev
Reply | Threaded
Open this post in threaded view
|

Re: Upgrading catalog utility

Uli Fouquet
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
instances.

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

   cat.updateIndexes()

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,

--
Uli


_______________________________________________
Grok-dev mailing list
[hidden email]
https://mail.zope.org/mailman/listinfo/grok-dev

signature.asc (196 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Upgrading catalog utility

Sebastian Ware
Big BIG thanks Uli!!! I have asked many times how to do this but not got any answer. I will be trying this too!

Mvh Sebastian

7 sep 2011 kl. 16.32 skrev Uli Fouquet:

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


_______________________________________________
Grok-dev mailing list
[hidden email]
https://mail.zope.org/mailman/listinfo/grok-dev