Added "parent_selector" predicate for IObjectMoved/IObjectAdded events
authorThierry Florac <thierry.florac@onf.fr>
Thu, 14 Jun 2018 13:57:57 +0200
changeset 195 65b6d930b42b
parent 194 9313b3c435eb
child 196 c0db0561ded3
Added "parent_selector" predicate for IObjectMoved/IObjectAdded events
src/pyams_utils/container.py
src/pyams_utils/include.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
--- a/src/pyams_utils/include.py	Thu Jun 14 08:58:27 2018 +0200
+++ b/src/pyams_utils/include.py	Thu Jun 14 13:57:57 2018 +0200
@@ -22,6 +22,7 @@
 
 # import packages
 from chameleon import PageTemplateFile
+from pyams_utils.container import ParentSelector
 from pyams_utils.context import ContextSelector
 from pyams_utils.request import get_annotations, get_debug, RequestSelector
 from pyams_utils.site import site_factory
@@ -50,6 +51,7 @@
 
     # add custom subscriber predicate to filter events via supported interface(s)
     config.add_subscriber_predicate('context_selector', ContextSelector)
+    config.add_subscriber_predicate('parent_selector', ParentSelector)
     config.add_subscriber_predicate('request_selector', RequestSelector)
 
     # load registry components