diff -r 9313b3c435eb -r 65b6d930b42b src/pyams_utils/container.py --- a/src/pyams_utils/container.py Thu Jun 14 08:58:27 2018 +0200 +++ b/src/pyams_utils/container.py Thu Jun 14 13:57:57 2018 +0200 @@ -17,6 +17,7 @@ # import interfaces from zope.container.interfaces import IContainer, IContained +from zope.lifecycleevent.interfaces import IObjectMovedEvent from zope.location.interfaces import ISublocations # import packages @@ -38,6 +39,44 @@ self._order = PersistentList() +class ParentSelector(object): + """Interface based parent selector + + This selector can be used as a subscriber predicate on IObjectAddedEvent to define + an interface that the new parent must support for the event to be applied:: + + .. code-block:: python + + from pyams_utils.interfaces.site import ISiteRoot + + @subscriber(IObjectAddedEvent, parent_selector=ISiteRoot) + def siteroot_object_added_event_handler(event): + '''This is an event handler for an ISiteRoot object added event''' + """ + + def __init__(self, ifaces, config): + if not isinstance(ifaces, (list, tuple, set)): + ifaces = (ifaces,) + self.interfaces = ifaces + + def text(self): + return 'parent_selector = %s' % str(self.interfaces) + + phash = text + + def __call__(self, event): + if not IObjectMovedEvent.providedBy(event): + return False + for intf in self.interfaces: + try: + if intf.providedBy(event.newParent): + return True + except (AttributeError, TypeError): + if isinstance(event.newParent, intf): + return True + return False + + @adapter_config(context=IContained, provides=ISublocations) class ContainerSublocationsAdapter(ContextAdapter): """Contained object sub-locations adapter