How to clean up old interfaces on zc.relation catalog?

后端 未结 4 2079
既然无缘
既然无缘 2021-01-22 14:48

I was using plone.directives.form version 1.0 with Plone 4.2.5 and after upgrading to 4.2.6 I started seeing the following traceback and I guess its due to plone.

相关标签:
4条回答
  • 2021-01-22 15:07

    In case someone runs into this type of problem and cannot bring the old package back, here's another approach:

    import transaction
    
    from AccessControl.SecurityManagement import newSecurityManager
    from AccessControl.User import system
    
    from Testing.makerequest import makerequest
    
    from zope.component.hooks import setSite
    from zope.globalrequest import setRequest
    
    from zc.relation.interfaces import ICatalog
    from z3c.relationfield.event import _relations
    from z3c.relationfield.event import _setRelation
    from zope.component import getUtility
    
    app = makerequest(app)
    newSecurityManager(None, system)
    portal = app.Plone
    setSite(portal)
    portal.REQUEST['PARENTS'] = [portal]
    portal.REQUEST.setVirtualRoot('/')
    setRequest(portal.REQUEST)
    
    THRESHOLD = 100
    
    relations_catalog = getUtility(ICatalog)
    
    paths = ['/'.join(r.from_object.getPhysicalPath())
             for r in relations_catalog.findRelations() if r.from_object]
    
    relations_catalog.clear()
    
    counter = 0
    for path in paths:
        obj = app.unrestrictedTraverse(path)
        for name, relation in _relations(obj):
            _setRelation(obj, name, relation)
        counter += 1
        if counter % THRESHOLD == 0:
            transaction.savepoint()
    transaction.commit()
    
    0 讨论(0)
  • 2021-01-22 15:17

    One more option, I developed a package called collective.diversion that is designed to ease the pain of pickling errors when moving a class. Neither of the above scripts worked for me, however using collective.diversion did.

    Adding the package to the buildout and including the following ZCML caused the items to be loaded, and they'll be persisted back in the correct place on write, so reindexing the catalogue should be sufficient.

    <configure
      xmlns="http://namespaces.zope.org/zope"
      xmlns:diversion="http://namespaces.plone.org/diversion">
    
      <diversion:class
          old="plone.directives.form.schema.Schema"
          new="plone.supermodel.model.Schema"
          />
    
    </configure>
    
    0 讨论(0)
  • 2021-01-22 15:19

    Just for reference that's how I fixed it:

    While still on plone.directives.form 1.0 update your objects so that they do no longer provide the plone.directives.form.schema.Schema interface.

    Then re-create the relations:

    from z3c.relationfield import RelationValue
    from zc.relation.interfaces import ICatalog
    from zope.app.intid.interfaces import IIntIds
    from zope.component import getUtility
    from zope.event import notify
    from zope.lifecycleevent import ObjectModifiedEvent
    
    logger = logging.getLogger(LOGGER)
    relations_catalog = getUtility(ICatalog)
    intids = getUtility(IIntIds)
    
    relations = [rel for rel in relations_catalog.findRelations()]
    len_relations = len(relations)
    logger.info('Relations needed to update: {0}'.format(len_relations))
    
    for relation in relations:
        # get the object link and the object linked
        object_with_link = relation.from_object
        object_linked_to = relation.to_object
    
        # remove the broken relation
        object_with_link.reference = None
    
        # let the catalog remove the old relation
        notify(ObjectModifiedEvent(object_with_link))
    
        # create a new relation
        object_linked_to_intid = intids.getId(object_linked_to)
        new_relation = RelationValue(object_linked_to_intid)
        object_with_link.reference = new_relation
    
        # let the catalog know about this new relation
        notify(ObjectModifiedEvent(object_with_link))
    

    After this, stop the instance, run buildout again to update plone.directives.form to version 1.1 and voilà!

    0 讨论(0)
  • 2021-01-22 15:20

    The Schema class is now in plone.supermodel.model, not plone.directives.form.schema.

    However, the real problem you should try to fix is that the code is for some reason trying to store a schema in the ZODB. Pickling/unpickling Zope interfaces is not supported.

    0 讨论(0)
提交回复
热议问题