Catalog column metadata same as object id

I have a catalog metadata name of "coa" which was causing a KeyError: "standard_view" in some cases such as a catalog rebuild. This was alarming because actually calling the view page of something is not something I want to index and is surely going to make indexing take a long time. The culprit turns out to be Acquisition: there was a folder with id "coa" and when its parent was indexed, It would try to use the callable value of this folder as its coa attribute.

A couple relevant code snippets, here's ZCatalog.Catalog.Catalog.recordify:

def recordify(self, object):
    """ turns an object into a record tuple """
    record = []
    # the unique id is always the first element
    for x in self.names:
        attr = getattr(object, x, MV)
        if (attr is not MV and safe_callable(attr)):
            attr = attr()
    return tuple(record)

def __call__(self):
        Resolve and return the selected view template applied to the object.
        This should not consider the default page.
        template = self.unrestrictedTraverse(self.getLayout())
        return template()

I think I can use plone.indexer for all zope.interface.Interface and have it return Missing.Value if 'coa' is in obj.objectIds(), but that only solves this specific case - I could still have the same problem with any other attribute. For my purposes I basically never want to get attributes from Acquisition when indexing. I also don't think it's practical to insist that every catalog column metadata becomes a reserved id that content cannot use.

I'm thinking of monkey patching recordify to either return MV if the attribute name is in obj.objectIds() or maybe have it only do that if it raises a KeyError (so in normal TTP operations it would in fact index the folder's view page, but it wouldn't flat out break when trying to programmatically rebuild). Anyone else run into this?

You can add coa = None or coa = Missing.Value to the body of the class. Then you would always have an attribute, so aq doesn't kick in.

What kind of objects are we talking about? afaik DX implements __getattr__, which should return the default value if specified.

We - by the looks of it- do check for catalog indexes and metadata. Not sure in which version this is added.

I would create a small migration script that renames all content objects which have an ID that is either a catalog index or column.

Interesting, looks like check_id was added in 5.1.5 but that aspect of it must be 5.2. The thing I don't like about that approach is it doesn't handle the case where you add a metadata column and have content with that id already.

What kind of objects are we talking about? afaik DX implements __getattr__, which should return the default value if specified.

Plone's default Folder content type. I am exclusively using DX for my custom content so a general DX solution would be fine. Maybe there's a future solution in Plone? I should have specified, our current production is on 5.0.5 and we are in development to soon upgrade to 5.1.5. And then 5.2 by the end of the year for py3 support. A short term stop gap would be fine if there are things like that updated check_id in the future.

I'd verify that the new checkid thingy does catch this.
If so then patch it into your current setup and rename the existing coa objects, which should end up als coa-1 I guess.

Whenever I add a content type specific index with indexer, I also register a such indexer for Interface that only raises AttributeError. At least that used to be the fastest way to skip an index.

Good call @datakurre. That worked, whereas simply returning MV did not.