Added "request_selector" predicate
authorThierry Florac <thierry.florac@onf.fr>
Thu, 15 Mar 2018 09:25:02 +0100
changeset 152 98ded173ec22
parent 151 a24a40d4f0c7
child 153 417296f4bfab
Added "request_selector" predicate
src/pyams_utils/include.py
src/pyams_utils/request.py
--- a/src/pyams_utils/include.py	Thu Mar 15 09:24:20 2018 +0100
+++ b/src/pyams_utils/include.py	Thu Mar 15 09:25:02 2018 +0100
@@ -23,7 +23,7 @@
 # import packages
 from chameleon import PageTemplateFile
 from pyams_utils.context import ContextSelector
-from pyams_utils.request import get_annotations, get_debug
+from pyams_utils.request import get_annotations, get_debug, RequestSelector
 from pyams_utils.site import site_factory
 from pyams_utils.tales import ExtensionExpr
 from pyams_utils.traversing import NamespaceTraverser
@@ -50,6 +50,7 @@
 
     # add custom subscriber predicate to filter events via supported interface(s)
     config.add_subscriber_predicate('context_selector', ContextSelector)
+    config.add_subscriber_predicate('request_selector', RequestSelector)
 
     # load registry components
     config.registry.registerAdapter(AttributeAnnotations, (IAttributeAnnotatable, ), IAnnotations)
--- a/src/pyams_utils/request.py	Thu Mar 15 09:24:20 2018 +0100
+++ b/src/pyams_utils/request.py	Thu Mar 15 09:25:02 2018 +0100
@@ -31,6 +31,42 @@
 _marker = object()
 
 
+class RequestSelector(object):
+    """Interface based request selector
+
+    This selector can be used as a subscriber predicate to define
+    an interface that the event's 'request' attribute must support for the event to be applied::
+
+    .. code-block:: python
+
+        from pyams_utils.interfaces.site import ISiteRoot
+
+        @subscriber(IBeforeTraverseEvent, request_selector=IPyAMSLayer)
+        def before_traverse_event(event):
+            '''This is an event handler for an IPyAMSRequest modification event'''
+    """
+
+    def __init__(self, ifaces, config):
+        if not isinstance(ifaces, (list, tuple, set)):
+            ifaces = (ifaces,)
+        self.interfaces = ifaces
+
+    def text(self):
+        return 'request_selector = %s' % str(self.interfaces)
+
+    phash = text
+
+    def __call__(self, event):
+        for intf in self.interfaces:
+            try:
+                if intf.providedBy(event.request):
+                    return True
+            except (AttributeError, TypeError):
+                if isinstance(event.request, intf):
+                    return True
+        return False
+
+
 def request_property(key=None, prefix=None):
     """Define a method decorator used to store result into current request's annotations