Plone 5.2 integration tests - TypeError: Object has default comparison

I've started testing on my packages in a py3/Plone 5.2 environment and seem to consistently be getting this error on any code that tries to index.

Error in test test_append_match (ims.entrez.tests.test_mass_edit.TestMassEdit)
    Traceback (most recent call last):
      File "/usr/lib64/python3.6/unittest/case.py", line 60, in testPartExecutor
        yield
      File "/usr/lib64/python3.6/unittest/case.py", line 622, in run
        testMethod()
      File "/sprj/btp_zope_plone5/buildouts/hawking/src/ims.entrez/ims/entrez/tests/test_mass_edit.py", line 67, in test_append_match
        mass.process_modify(data)
      File "/sprj/btp_zope_plone5/buildouts/hawking/src/ims.entrez/ims/entrez/browser/mass.py", line 33, in process_modify
        for brain in cat(UID=data['uids']):
      File "/sprj/btp_zope_plone5/buildouts/hawking/eggs/Products.CMFPlone-5.2.0-py3.6.egg/Products/CMFPlone/CatalogTool.py", line 429, in searchResults
        processQueue()
      File "/sprj/btp_zope_plone5/buildouts/hawking/eggs/Products.CMFCore-2.4.0-py3.6.egg/Products/CMFCore/indexing.py", line 95, in processQueue
        processed = queue.process()
      File "/sprj/btp_zope_plone5/buildouts/hawking/eggs/Products.CMFCore-2.4.0-py3.6.egg/Products/CMFCore/indexing.py", line 222, in process
        util.reindex(obj, attributes, update_metadata=metadata)
      File "/sprj/btp_zope_plone5/buildouts/hawking/eggs/Products.CMFCore-2.4.0-py3.6.egg/Products/CMFCore/indexing.py", line 50, in reindex
        update_metadata=update_metadata)
      File "/sprj/btp_zope_plone5/buildouts/hawking/eggs/Products.CMFCore-2.4.0-py3.6.egg/Products/CMFCore/CatalogTool.py", line 367, in _reindexObject
        self.catalog_object(object, uid, idxs, update_metadata)
      File "/sprj/btp_zope_plone5/buildouts/hawking/eggs/Products.CMFPlone-5.2.0-py3.6.egg/Products/CMFPlone/CatalogTool.py", line 351, in catalog_object
        update_metadata, pghandler=pghandler)
      File "/sprj/btp_zope_plone5/buildouts/hawking/eggs/Products.ZCatalog-5.0.1-py3.6.egg/Products/ZCatalog/ZCatalog.py", line 499, in catalog_object
        update_metadata=update_metadata)
      File "/sprj/btp_zope_plone5/buildouts/hawking/eggs/Products.ZCatalog-5.0.1-py3.6.egg/Products/ZCatalog/Catalog.py", line 369, in catalogObject
        blah = x.index_object(index, object, threshold)
      File "/sprj/btp_zope_plone5/buildouts/hawking/eggs/Products.ZCatalog-5.0.1-py3.6.egg/Products/PluginIndexes/unindex.py", line 240, in index_object
        res += self._index_object(documentId, obj, threshold, attr)
      File "/sprj/btp_zope_plone5/buildouts/hawking/eggs/Products.ZCatalog-5.0.1-py3.6.egg/Products/PluginIndexes/unindex.py", line 284, in _index_object
        self.insertForwardIndexEntry(datum, documentId)
      File "/sprj/btp_zope_plone5/buildouts/hawking/eggs/Products.ZCatalog-5.0.1-py3.6.egg/Products/PluginIndexes/unindex.py", line 223, in insertForwardIndexEntry
        self._index[entry] = IITreeSet((documentId, ))
    TypeError: Object has default comparison

There's nothing particularly noteworthy about the content type, it's just a Dexterity Item. This seems to be common enough that I don't think it's anything particular to this test, but here it is anyway.

class TestMassEdit(base.IntegrationTestCase):

    def add_journal_publication(self):
        self.folder.invokeFactory('JournalPublication', 'jpub')
        self.pub = self.folder['jpub']
        self.pub.title = 'Test pub'

    def test_append_match(self):
        # a valid match, add foobar to it
        self.add_journal_publication()
        self.assertEqual(self.pub.pubtypelist, ['Journal Article'])
        data = {'uids': [self.pub.UID()],
                'strategy': 'append_match',
                'field_to_change': 'pubtypelist',
                'new_value': u'foobar',
                'match_value': 'Journal Article',
                }
        mass = self.folder.restrictedTraverse('@@mass-edit')
        mass.process_modify(data)
        self.assertEqual(self.pub.pubtypelist, ['Journal Article', 'foobar'])

and

def process_modify(self, data):
        cat = plone.api.portal.get_tool('portal_catalog')

        for brain in cat(UID=data['uids']):
            o = brain.getObject()
            self.process_edit(o, data)
            o.reindexObject()

        plone.api.portal.show_message(
            _(u"Publications modified"), self.request, type="info")
        self.request.response.redirect(self.context.absolute_url())

What types have entry and documentId?

The error message (--> BTrees:objectkeymakros.h) means that what is used as key does not define its own "rich comparison methods" but inherits them from object (which do not fulfill the BTrees requirements).

Note that Python 3 has dropped __cmp__; for comparisons, classes must nor implement "rich comparison" methods (e.g. "lt", "le", etc). BTrees rely on full comparison support for its keys.

Ah, the entry value was the problem, thank you. The value was the title of the pub, because I have an index uses the filter() function on it. In python 2 this would return a str, but in python 3 it is returning a filter object. I should probably just replace this with list comprehension.

You might want to sort your sequences. Otherwise, you index may contain different entries with the same components (just differently sorted).

This is actually meant to be a str, not an arbitrary sequence actually. The gotcha for me was that in python 2 filter would return the data type passed into it, but in python 3 it always returns that iterable filter instance. I just need to join that into a string (or use list comprehension instead, and join that into a str).

Plone Foundation Code of Conduct