collective.exportimport icon indicating copy to clipboard operation
collective.exportimport copied to clipboard

Ignoring some portlets during import

Open mauritsvanrees opened this issue 3 years ago • 0 comments

I have an portlet export that includes a portlet that I no longer want. Currently, the import fails, because the portlet type is not known:

Traceback (innermost last):
  Module ZPublisher.WSGIPublisher, line 167, in transaction_pubevents
  Module ZPublisher.WSGIPublisher, line 376, in publish_module
  Module ZPublisher.WSGIPublisher, line 271, in publish
  Module ZPublisher.mapply, line 85, in mapply
  Module ZPublisher.WSGIPublisher, line 68, in call_object
  Module collective.exportimport.import_other, line 582, in __call__
  Module collective.exportimport.import_other, line 597, in import_portlets
  Module collective.exportimport.import_other, line 618, in register_portlets
  Module zope.component._api, line 165, in getUtility
zope.interface.interfaces.ComponentLookupError:
(<InterfaceClass zope.component.interfaces.IFactory>, 'collective.quickupload.QuickUploadPortlet')

It would be nice if the importer could ignore it. I see two options:

  1. Catch the ComponentLookupError from above, log a warning, and continue with the next portlet.
  2. Have a list of portlet types that must be ignored. Empty by default, but easily monkey patched.

I prefer the first one, as it is a small change and works for everyone. But maybe we prefer that integrators explicitly catch the error. For the second one I now have this monkey patch, from which I could make a PR.

from collective.exportimport import import_other

import logging


logger = logging.getLogger(__name__)
_orig_register_portlets = import_other.register_portlets
IGNORE_PORTLET_TYPES = [
    "collective.quickupload.QuickUploadPortlet",
]


def register_portlets(obj, item):
    """Register portlets for one object.

    CHANGE compared to original: pop unwanted portlets.

    I tried to override the browser view first,
    but then I would have had to copy the template.
    """
    for manager_name, portlets in item.get("portlets", {}).items():
        if not portlets:
            continue
        ignore = []
        for portlet_data in portlets:
            if portlet_data["type"] in IGNORE_PORTLET_TYPES:
                logger.info(
                    "Ignoring portlet type %s at %s",
                    portlet_data["type"],
                    obj.absolute_url(),
                )
                ignore.append(portlet_data)
        for portlet_data in ignore:
            portlets.remove(portlet_data)
    return _orig_register_portlets(obj, item)


import_other.register_portlets = register_portlets
logger.info(
    "Patched collective.exportimport register_portlets to ignore these types: %s",
    IGNORE_PORTLET_TYPES,
)

Do we have a preference?

mauritsvanrees avatar Sep 21 '21 13:09 mauritsvanrees