sean.upton@uniontrib.com wrote:
A follow-up: After upgrading to 2.3.2, and further investigation, I have found I have a problem, and I have found a workaround. However, what I have discovered is that the problem is not one of acquisition; rather, it is an issue of ZCatalog not cooperating with my DTML methods, residing on disk as part of my Python product.
So, in a slightly different light, here is my problem: if I use one of these DTML methods as an index, it has problems evaluating code because it (the Catalog) runs the method, but it will not successfully obtain the namespace of either the object I am trying to catalog / add, or the namespace of the acquisition parent of the newly created - just about to be indexed - object. The implication of this, is that while evaluating the DTML, there is a NameError raised for ANY call to a method within an object of the class you are trying to index; I did not try accessing properties, but I assume that they would suffer the same fate: evaluation of the DTML, being run by the Catalog as an agent, would fail to resolve the namespace of the object for which it is trying to index, and this would mean that any calls to methods/properties of the object from within the DTML would fail with a NameError, raising an exception that breaks any Catalog Aware object attempting to use a DTML method as a text index.
Actually it is worse than this. The problem here lies in the calling API of DTML Methods. The client context must be passed explicitly as the first parameter of the DTML Method in order for it to know the object it is being called for, even if it is an instance method of a ZClass. When the index calls your method, no parameters are passed, and the DTML Method is too dumb to resolve its parent through self. Workaround: Do not index against DTML Methods. Use Python Scripts, as they can through their container binding act like true instance methods when called blind.
My iterateText method resides as a python method BOTH in the class for the object I just added, and the parent folder (a custom class subclassed from OFS.Folder) I am adding the object to. My searchTextWeighted (the method I am indexing) was a DTML method on disk, referenced with searchTextWeighted = Globals.HTMLFile('dtml/searchTextWeighted', globals())
...I changed this to a python method within the class, and this fixed the problem, but not in the way I necessarily want. What I am hoping to be able to do is create templates that get indexed, so that modifying an existing indexed 'field' does not require directly modifying the class itself, only the DTML methods to which the class refers to.
Solution: write a wrapper method in your class that looks for a DTML method to index against. If it finds one then call it or a default DTML method passing self as the client like so: defaultSearchTextWeighted = Globals.HTMLFile('dtml/searchTextWeighted', globals()) def searchText(self): """Look for a DTML Method to call""" if hasattr(self, 'searchTextWeighted'): stw = self.searchTextWeighted else: stw = self.defaultSearchTextWeighted return stw(self)
Why won't ZCatalog use the namespace of the object it is attempting to index to run these methods, which belong to the class of those objects? It seems like if it did, there would be no problem doing what I originally set out to do. Is this a bug, or am I going about doing this the wrong way?
Any thoughts would be greatly appreciated. For now, I can live with my workaround...
Sean
hth, -- | Casey Duncan | Kaivo, Inc. | cduncan@kaivo.com `------------------>