Skip to content

Robustness in content_export for CMFEditions versions, lock_info #194

@seanupton

Description

@seanupton

These are two distinct issues — both with ContentExport (Plone 5.1, Python 2.7.18, collective.exportimport == 1.7, plone.restapi==7.8.0,) — but I'm using a common monkey patch to work around them, so I figured I would make an issue, if for nothing else, to get this discussion somewhere outside just my own head:

  1. A content item with CMFEditions history containing an item ID rename will not export, because Next/Previous serialization of plone.restapi attempts to get a position (both next, and previous) in container for an id that is no longer there, which fails with something like ValueError: 'OLD_ID_IS_HERE_BUT_CONTAINER_DOES_NOT_GET_IT' is not in list.
  2. If a content item's creator is no longer an existing Plone user, plone.restapi locking serialization fails with AttributeError: 'NoneType' object has no attribute 'getProperty'.

I ended up monkey patching in my export runscript to work around these two things:

from plone.app.dexterity.behaviors.nextprevious import NextPreviousBase

import plone.restapi


# monkey patch plone.app.dexterity.behaviors.nextprevious to handle
# CMFEditions revision objects that have had an id rename, robustly
# for collective.exportimport use case:
orig_get_next = NextPreviousBase.getNextItem
orig_get_prev = NextPreviousBase.getPreviousItem
orig_creator_name = plone.restapi.services.locking.creator_name


def forgiving_call(orig):
    def _inner(*args):
        try:
            return orig(*args)
        except (ValueError, AttributeError):
            # for next/previous serializing:
            #   the object isn't in the parent, probably because its id was
            #   renamed, and plone.restapi.serializer.nextprev.NextPrevious
            #   is trying to serialize a fetched historic CMFEditions
            #   revision of the object to serialize, and that historic
            #   version has the old ID no longer in the parent container
            # for creator_name for locking:
            #   need to be robust around a creator who is no longer in system
            #   as a plone user
            return None
    return _inner


NextPreviousBase.getNextItem = forgiving_call(orig_get_next)
NextPreviousBase.getPreviousItem = forgiving_call(orig_get_prev)
plone.restapi.services.locking.creator_name = forgiving_call(orig_creator_name)

I am unsure about how to address these in a "safe for use outside my limited-purpose runscript" because monkey patching these is a change in behavior for multiple places in plone.restapi, and my use-case is limited to making my export work without omitting content. But content will not export reliably in either condition described above for me without doing this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions