Creating custom indexes on-the-fly...is it possible?

Thanks, Dieter! I had a feeling it was something related to the parts of Plone that I'm still trying to absorb. :slight_smile:

I'll take your @implementer suggestion and report back.

Hi Dieter, thanks for pushing me forward. Those 'Could not adapt' errors are in my past. :slight_smile: Either "implements" or "@implementer" solve that problem. They seem to need both IAbstractDataObject and IOurDataObject listed, which I don't understand since IOurDataObject extends IAbstractDataObject, but I'm willing to move forward not understanding that!

So, with my class now decorated like this:

@implementer(IAbstractDataObject,IOurDataObject)
class OurItem(Item):

manually adding a new OurItem send lots of info lines to the log, including both "flavors" (attr retrieved in the "try" and attr retrieved in the "except").

Unfortunately, it still fails with this traceback:

  Module ZPublisher.Publish, line 138, in publish
  Module ZPublisher.mapply, line 77, in mapply
  Module ZPublisher.Publish, line 48, in call_object
  Module plone.z3cform.layout, line 63, in __call__
  Module plone.z3cform.layout, line 47, in update
  Module plone.dexterity.browser.add, line 134, in update
  Module plone.z3cform.fieldsets.extensible, line 65, in update
  Module plone.z3cform.patch, line 30, in GroupForm_update
  Module z3c.form.group, line 145, in update
  Module plone.app.z3cform.csrf, line 22, in execute
  Module z3c.form.action, line 98, in execute
  Module z3c.form.button, line 315, in __call__
  Module z3c.form.button, line 170, in __call__
  Module plone.dexterity.browser.add, line 109, in handleAdd
  Module z3c.form.form, line 265, in createAndAdd
  Module plone.dexterity.browser.add, line 84, in add
  Module plone.dexterity.utils, line 184, in addContentToContainer
  Module Products.BTreeFolder2.BTreeFolder2, line 461, in _setObject
  Module zope.event, line 31, in notify
  Module zope.component.event, line 27, in dispatch
  Module zope.component._api, line 139, in subscribers
  Module zope.interface.registry, line 442, in subscribers
  Module zope.interface.adapter, line 607, in subscribers
  Module zope.component.event, line 36, in objectEventNotify
  Module zope.component._api, line 139, in subscribers
  Module zope.interface.registry, line 442, in subscribers
  Module zope.interface.adapter, line 607, in subscribers
  Module Products.CMFUid.UniqueIdAnnotationTool, line 86, in handleUidAnnotationEvent
AttributeError: 'NoneType' object has no attribute 'unregister'

I looked at the code and that line is inside handleUidAnnotationEvent(ob, event) on the uid_handler.unregister(ob) line. Even though it's in a "try", the only "except" is for UniqueIdError, so this AttributeError is not caught. uid_handler apparently was set to None earlier in uid_handler = getToolByName(ob, 'portal_uidhandler', None)

Is that a sign that my OurItem class needs to implement more than __getattr__()???

Thanks for any insight anyone can give. I hate to sound like such a noob but I sense that I'm really close to getting this working.

P.S. I didn't want to confuse things but just in case it provides any helpful information, I have a form for importing files containing data for multiple OurItems (which works when I'm just using the vanilla Dexterity Item) and its call to createContentInContainer results in a slightly different None-related error:

  Module plone.dexterity.utils, line 198, in createContentInContainer
  Module plone.dexterity.utils, line 184, in addContentToContainer
  Module Products.BTreeFolder2.BTreeFolder2, line 461, in _setObject
  Module zope.event, line 31, in notify
  Module zope.component.event, line 27, in dispatch
  Module zope.component._api, line 139, in subscribers
  Module zope.interface.registry, line 442, in subscribers
  Module zope.interface.adapter, line 607, in subscribers
  Module zope.component.event, line 36, in objectEventNotify
  Module zope.component._api, line 139, in subscribers
  Module zope.interface.registry, line 442, in subscribers
  Module zope.interface.adapter, line 607, in subscribers
  Module five.intid.intid, line 105, in addIntIdSubscriber
  Module zope.event, line 31, in notify
  Module zope.component.event, line 27, in dispatch
  Module zope.component._api, line 139, in subscribers
  Module zope.interface.registry, line 442, in subscribers
  Module zope.interface.adapter, line 607, in subscribers
  Module z3c.relationfield.event, line 34, in addRelationsEventOnly
  Module z3c.relationfield.event, line 23, in addRelations
  Module z3c.relationfield.event, line 132, in _setRelation
  Module plone.app.relationfield.monkey, line 24, in set_from_object
TypeError: 'NoneType' object is not callable

This almost certainly is related to IAbstractDataObject having a z3c.relationfield.schema.Relation attribute that is programmatically set when this import form is used, but is not set when the vanilla Add form is used (since its required=False and readonly=True).

I suspect if I solve the first None problem, this one will be solved too.

Thanks again!

In the code snippet from your original post, there was no implements/implementer. If IOurDataObject inherits from IAbstractDataObject, then an implementer(IOurDataObject) should indeed by sufficient.

Look at the code of UniqueIdAnnotationTool and try to find out where the unexpected None comes from. I am using Products.PDBDebugMode for development: it enters the python debugger when an (unhandled) exception is raised - allowing me to directly investigate what led to the exception.

1 Like

Dieter,

  1. You are of course correct that @implementer(IOurDataObject) is all I need. I made that change and everything behaves the same as when IAbstractDataObject was in the implementer().

  2. Thanks for the Products.PDBDebugMode tip! Wow! I already knew how to put import pdb; pdb.set_trace() into my own code, but PDBDebugMode takes it to the next level! It is now a permanent member of my tool kit. :slight_smile:

Now, as far as that None error, when I got into debug mode, I inspected the ob and event parameters to handleUidAnnotationEvent() and they appear to be normal. ob is <OurItem at /the/location/I/added/it> and event is <zope.lifecycleevent.ObjectAddedEvent object at 0x7f3011e023d0>.

Since the offending None comes from the line,

 uid_handler = getToolByName(ob, 'portal_uidhandler', None)

I called that again (setting to a new variable) and that caused my __getattr__ to write the following to be written to the log:

Inside __getattr__ with portal_uidhandler
Inside __getattr__ with __conform__
Except __getattr__ with __conform__
Just got our attr __conform__
Except __getattr__ with portal_uidhandler
Just got our attr portal_uidhandler

So, I think we're getting somewhere. Note that last line. The attempt to get OurItem's 'portal_uidhandler' fails with the super(OurItem, self).__getattr__(key) approach so it tries to find it in our jsonRepr field.

But we of course do not have 'portal_uidhandler' in our jsonRepr field, so that is where the None comes from.

So the question becomes: why is getToolByName(ob, 'portal_uidhandler') not finding the 'portal_uidhandler' in the usual manner?

We're so close I can taste it!

Thanks again for any additional insight.