فهرست منبع

Improved handling of positional and keyword args for events

Nuwan Goonasekera 7 سال پیش
والد
کامیت
5fb32f6297
5فایلهای تغییر یافته به همراه189 افزوده شده و 105 حذف شده
  1. 14 13
      cloudbridge/cloud/base/events.py
  2. 8 10
      cloudbridge/cloud/base/services.py
  3. 69 16
      cloudbridge/cloud/interfaces/events.py
  4. 76 52
      test/test_event_system.py
  5. 22 14
      test/test_middleware_system.py

+ 14 - 13
cloudbridge/cloud/base/events.py

@@ -51,12 +51,12 @@ class InterceptingEventHandler(EventHandler):
     def dispatcher(self, value):
         self.__dispatcher = value
 
-    def invoke(self, **kwargs):
-        kwargs.pop('next_handler', None)
-        next_handler = self._get_next_handler(kwargs.get('event', None))
+    def invoke(self, event_args, *args, **kwargs):
+        next_handler = self._get_next_handler(event_args.get('event'))
+        event_args['next_handler'] = next_handler
         # callback is responsible for invoking the next_handler and
         # controlling the result value
-        return self.callback(next_handler=next_handler, **kwargs)
+        return self.callback(event_args, *args, **kwargs)
 
     def unsubscribe(self):
         if self.dispatcher:
@@ -69,14 +69,15 @@ class ObservingEventHandler(InterceptingEventHandler):
         super(ObservingEventHandler, self).__init__(event_pattern, priority,
                                                     callback)
 
-    def invoke(self, **kwargs):
+    def invoke(self, event_args, *args, **kwargs):
+        # Observers shouldn't pass a next_handler
+        event_args.pop('next_handler', None)
+        next_handler = self._get_next_handler(event_args.get('event'))
         # Notify listener. Ignore result from observable handler
-        kwargs.pop('next_handler', None)
-        self.callback(**kwargs)
-        # Kick off the handler chain
-        next_handler = self._get_next_handler(kwargs.get('event', None))
+        self.callback(event_args, *args, **kwargs)
+        # Kick off the remaining handler chain
         if next_handler:
-            return next_handler.invoke(**kwargs)
+            return next_handler.invoke(event_args, *args, **kwargs)
         else:
             return None
 
@@ -154,13 +155,13 @@ class SimpleEventDispatcher(EventDispatcher):
         self.subscribe(handler)
         return handler
 
-    def emit(self, sender, event, **kwargs):
+    def emit(self, sender, event, *args, **kwargs):
         handlers = self.get_handlers_for_event(event)
 
         if handlers:
             # only kick off first handler in chain
-            return handlers[0].invoke(sender=sender, event=event,
-                                      **kwargs)
+            event_args = {'event': event, 'sender': sender}
+            return handlers[0].invoke(event_args, *args, **kwargs)
         else:
             message = "Event '{}' has no subscribed handlers.".\
                 format(event)

+ 8 - 10
cloudbridge/cloud/base/services.py

@@ -4,6 +4,7 @@ Base implementation for services available through a provider
 import logging
 
 import cloudbridge.cloud.base.helpers as cb_helpers
+from cloudbridge.cloud.base.middleware import observe
 from cloudbridge.cloud.base.resources import BaseBucket
 from cloudbridge.cloud.base.resources import BaseNetwork
 from cloudbridge.cloud.base.resources import BaseRouter
@@ -147,17 +148,14 @@ class BaseBucketService(
         super(BaseBucketService, self).__init__(provider)
         self._service_event_pattern = "provider.storage.buckets"
 
-    def _init_get(self):
-        def _get_pre_log(bucket_id):
-            log.debug("Getting {} bucket with the id: {}".format(
-                self.provider.name, bucket_id))
+    @observe(event_pattern="provider.storage.buckets.get", priority=2000)
+    def _get_pre_log(self, bucket_id):
+        log.debug("Getting {} bucket with the id: {}".format(
+            self.provider.name, bucket_id))
 
-        def _get_post_log(callback_result, bucket_id):
-            log.debug("Returned bucket object: {}".format(callback_result))
-
-        self.observe("get", 2000, _get_pre_log)
-        self.observe("get", 3000, _get_post_log)
-        self.mark_initialized("get")
+    @observe(event_pattern="provider.storage.buckets.get", priority=3000)
+    def _get_post_log(self, callback_result, bucket_id):
+        log.debug("Returned bucket object: {}".format(callback_result))
 
     def _init_find(self):
         def _find_pre_log(**kwargs):

+ 69 - 16
cloudbridge/cloud/interfaces/events.py

@@ -26,14 +26,24 @@ class EventDispatcher(object):
             priority.
 
         :type callback: function
-        :param callback: The callback function that should be called with
-            the parameters given at when the even is emitted.
+        :param callback: The callback function that should be invoked. The
+            callback must have a signature of the form:
+            `def callback(event_args, *args, **kwargs)`
+            Where the first positional argument is always event_args, which
+            is a dict value containing information about the event.
+            `event_args` includes the following keys:
+            'event': The name of the event
+            'sender': The object which raised the event
+            The event_args dict can also be used to convey additional info to
+            downstream event handlers.
+            The rest of the arguments to the callback can be any combination
+            of positional or keyword arguments as desired.
 
         :rtype: :class:`.EventHandler`
         :return:  An object of class EventHandler. The EventHandler will
-        already be subscribed to the dispatcher, and need not be manually
-        subscribed. The returned event handler can be used to unsubscribe
-        from future events when required.
+            already be subscribed to the dispatcher, and need not be manually
+            subscribed. The returned event handler can be used to unsubscribe
+            from future events when required.
         """
         pass
 
@@ -58,27 +68,47 @@ class EventDispatcher(object):
             priority.
 
         :type callback: function
-        :param callback: The callback function that should be called with
-            the parameters given at when the even is emitted.
+        :param callback: The callback function that should be invoked. The
+            callback must have a signature of the form:
+            `def callback(event_args, *args, **kwargs)`
+            Where the first positional argument is always event_args, which
+            is a dict value containing information about the event.
+            `event_args` includes the following keys:
+            'event': The name of the event
+            'sender': The object which raised the event
+            'event_handler': The next event handler in the chain
+                             (only for intercepting handlers)
+            The event_args dict can also be used to convey additional info to
+            downstream event handlers.
+            The rest of the arguments to the callback can be any combination
+            of positional or keyword arguments as desired.
 
         :rtype: :class:`.EventHandler`
         :return:  An object of class EventHandler. The EventHandler will
-        already be subscribed to the dispatcher, and need not be manually
-        subscribed. The returned event handler can be used to unsubscribe
-        from future events when required.
+            already be subscribed to the dispatcher, and need not be manually
+            subscribed. The returned event handler can be used to unsubscribe
+            from future events when required.
         """
         pass
 
     @abstractmethod
-    def emit(self, sender, event, **kwargs):
+    def emit(self, sender, event, *args, **kwargs):
         """
-        Raises an event while registering a given callback
+        Raises an event, which will trigger all handlers that are registered
+        for this event. The return value of the emit function is the return
+        value of the highest priority handler (i.e. the first handler in the
+        event chain). The first event handlers is responsible for calling the
+        next handler in the event chain, and so on, propagating arguments
+        and return values as desired.
 
         :type event: str
         :param event: The name of the event which is being raised.
 
         :type sender: object
         :param sender: The object which is raising the event
+
+        All additional positional and keyword arguments are passed through
+        to the callback functions for the event as is. Refer to the c
         """
         pass
 
@@ -153,16 +183,39 @@ class EventHandler(object):
     def callback(self):
         """
         The callback that will be triggered when this event handler is invoked.
-        The callback signature must accept **kwargs and pass them through.
-        In general, the callback will always receive the event that
-        triggered this handler as an argument.
+        The callback signature must accept *args and **kwargs and pass them
+        through.
+        The callback must have a signature of the form:
+        `def callback(event_args, *args, **kwargs)`
+        where the first positional argument is always event_args, which
+        is a dict value containing information about the event.
+        `event_args` includes the following keys:
+        'event': The name of the event
+        'sender': The object which raised the event
+        'event_handler': The next event handler in the chain
+                         (only for intercepting handlers)
+        The event_args dict can also be used to convey additional info to
+        downstream event handlers.
+        The rest of the arguments to the callback can be any combination
+        of positional or keyword arguments as desired.
         """
         pass
 
     @abstractmethod
-    def invoke(self, **kwargs):
+    def invoke(self, event_args, *args, **kwargs):
         """
         Executes this event handler's callback
+
+        :type event_args: dict
+        :param event_args: The first positional argument is always event_args,
+           which is a dict value containing information about the event.
+           `event_args` includes the following keys:
+           'event': The name of the event
+           'sender': The object which raised the event
+           'event_handler': The next event handler in the chain
+                            (only for intercepting handlers)
+           The event_args dict can also be used to convey additional info to
+           downstream event handlers.
         """
         pass
 

+ 76 - 52
test/test_event_system.py

@@ -17,10 +17,12 @@ class EventSystemTestCase(unittest.TestCase):
         EVENT_NAME = "event.hello.world"
         callback_tracker = ['']
 
-        def my_callback(**kwargs):
-            self.assertDictEqual(kwargs,
+        def my_callback(event_args, *args, **kwargs):
+            self.assertDictEqual(event_args,
                                  {'sender': self,
                                   'event': EVENT_NAME})
+            self.assertSequenceEqual(args, ['first_pos_arg'])
+            self.assertDictEqual(kwargs, {'a_keyword_arg': 'another_thing'})
             callback_tracker[0] += 'obs'
             return "hello"
 
@@ -28,7 +30,8 @@ class EventSystemTestCase(unittest.TestCase):
         handler = dispatcher.observe(event_pattern=EVENT_NAME, priority=1000,
                                      callback=my_callback)
         self.assertIsInstance(handler, EventHandler)
-        result = dispatcher.emit(self, EVENT_NAME)
+        result = dispatcher.emit(self, EVENT_NAME, 'first_pos_arg',
+                                 a_keyword_arg='another_thing')
         self.assertEqual(
             callback_tracker[0], "obs", "callback should have been invoked"
             "once and contain value `obs` but tracker value is {0}".format(
@@ -40,11 +43,13 @@ class EventSystemTestCase(unittest.TestCase):
         EVENT_NAME = "event.hello.world"
         callback_tracker = ['']
 
-        def my_callback(**kwargs):
-            self.assertDictEqual(kwargs,
+        def my_callback(event_args, *args, **kwargs):
+            self.assertDictEqual(event_args,
                                  {'sender': self,
                                   'event': EVENT_NAME,
                                   'next_handler': None})
+            self.assertSequenceEqual(args, ['first_pos_arg'])
+            self.assertDictEqual(kwargs, {'a_keyword_arg': 'another_thing'})
             callback_tracker[0] += "intcpt"
             return "world"
 
@@ -52,7 +57,8 @@ class EventSystemTestCase(unittest.TestCase):
         handler = dispatcher.intercept(event_pattern=EVENT_NAME, priority=1000,
                                        callback=my_callback)
         self.assertIsInstance(handler, EventHandler)
-        result = dispatcher.emit(self, EVENT_NAME)
+        result = dispatcher.emit(self, EVENT_NAME, 'first_pos_arg',
+                                 a_keyword_arg='another_thing')
         self.assertEqual(
             callback_tracker[0], "intcpt", "callback should have been invoked"
             "once and contain value `intcpt` but tracker value is {0}".format(
@@ -64,25 +70,30 @@ class EventSystemTestCase(unittest.TestCase):
         EVENT_NAME = "event.hello.world"
         callback_tracker = ['']
 
-        def my_callback_obs(**kwargs):
-            self.assertDictEqual(kwargs,
+        def my_callback_obs(event_args, *args, **kwargs):
+            self.assertDictEqual(event_args,
                                  {'sender': self,
                                   'event': EVENT_NAME})
+            self.assertSequenceEqual(args, ['first_pos_arg'])
+            self.assertDictEqual(kwargs, {'a_keyword_arg': 'another_thing'})
             callback_tracker[0] += "obs_"
             return "hello"
 
-        def my_callback_intcpt(**kwargs):
-            self.assertDictEqual(kwargs,
+        def my_callback_intcpt(event_args, *args, **kwargs):
+            self.assertDictEqual(event_args,
                                  {'sender': self,
                                   'event': EVENT_NAME,
                                   'next_handler': None})
+            self.assertSequenceEqual(args, ['first_pos_arg'])
+            self.assertDictEqual(kwargs, {'a_keyword_arg': 'another_thing'})
             callback_tracker[0] += "intcpt_"
             return "world"
 
         dispatcher = SimpleEventDispatcher()
         dispatcher.observe(EVENT_NAME, 1000, my_callback_obs)
         dispatcher.intercept(EVENT_NAME, 1001, my_callback_intcpt)
-        result = dispatcher.emit(self, EVENT_NAME)
+        result = dispatcher.emit(self, EVENT_NAME, 'first_pos_arg',
+                                 a_keyword_arg='another_thing')
         self.assertEqual(
             callback_tracker[0], "obs_intcpt_", "callback was not invoked in "
             "expected order. Should have been obs_intcpt_ but is {0}".format(
@@ -94,24 +105,28 @@ class EventSystemTestCase(unittest.TestCase):
         EVENT_NAME = "event.hello.world"
         callback_tracker = ['']
 
-        def my_callback_intcpt(**kwargs):
-            self.assertEqual(kwargs.get('sender'), self)
-            self.assertEqual(kwargs.get('next_handler').priority, 1001)
-            self.assertEqual(kwargs.get('next_handler').callback.__name__,
+        def my_callback_intcpt(event_args, *args, **kwargs):
+            self.assertSequenceEqual(args, ['first_pos_arg'])
+            self.assertDictEqual(kwargs, {'a_keyword_arg': 'another_thing'})
+            self.assertEqual(event_args.get('sender'), self)
+            self.assertEqual(event_args.get('next_handler').priority, 1001)
+            self.assertEqual(event_args.get('next_handler').callback.__name__,
                              "my_callback_obs")
             callback_tracker[0] += "intcpt_"
             # invoke next handler
-            next_handler = kwargs.get('next_handler')
+            next_handler = event_args.get('next_handler')
             assert next_handler.priority == 1001
             assert next_handler.event_pattern == EVENT_NAME
             assert next_handler.callback == my_callback_obs
-            retval = next_handler.invoke(**kwargs)
+            retval = next_handler.invoke(event_args, *args, **kwargs)
             self.assertIsNone(retval, "Return values of observable handlers"
                               " should not be propagated.")
             return "world"
 
-        def my_callback_obs(**kwargs):
-            self.assertDictEqual(kwargs,
+        def my_callback_obs(event_args, *args, **kwargs):
+            self.assertSequenceEqual(args, ['first_pos_arg'])
+            self.assertDictEqual(kwargs, {'a_keyword_arg': 'another_thing'})
+            self.assertDictEqual(event_args,
                                  {'sender': self,
                                   'event': EVENT_NAME})
             callback_tracker[0] += "obs_"
@@ -121,7 +136,8 @@ class EventSystemTestCase(unittest.TestCase):
         # register priorities out of order to test that too
         dispatcher.observe(EVENT_NAME, 1001, my_callback_obs)
         dispatcher.intercept(EVENT_NAME, 1000, my_callback_intcpt)
-        result = dispatcher.emit(self, EVENT_NAME)
+        result = dispatcher.emit(self, EVENT_NAME, 'first_pos_arg',
+                                 a_keyword_arg='another_thing')
         self.assertEqual(
             callback_tracker[0], "intcpt_obs_", "callback was not invoked in "
             "expected order. Should have been intcpt_obs_ but is {0}".format(
@@ -133,17 +149,18 @@ class EventSystemTestCase(unittest.TestCase):
         EVENT_NAME = "event.hello.world"
         callback_tracker = ['']
 
-        def my_callback_intcpt1(**kwargs):
-            self.assertEqual(kwargs.get('sender'), self)
-            self.assertEqual(kwargs.get('next_handler').priority, 2020)
-            self.assertEqual(kwargs.get('next_handler').callback.__name__,
+        def my_callback_intcpt1(event_args, *args, **kwargs):
+            self.assertEqual(event_args.get('sender'), self)
+            next_handler = event_args.get('next_handler')
+            self.assertEqual(next_handler.priority, 2020)
+            self.assertEqual(next_handler.callback.__name__,
                              "my_callback_intcpt2")
             callback_tracker[0] += "intcpt1_"
             # invoke next handler but ignore return value
-            return "hello" + kwargs.get('next_handler').invoke(**kwargs)
+            return "hello" + next_handler.invoke(event_args, *args, **kwargs)
 
-        def my_callback_intcpt2(**kwargs):
-            self.assertDictEqual(kwargs,
+        def my_callback_intcpt2(event_args, *args, **kwargs):
+            self.assertDictEqual(event_args,
                                  {'sender': self,
                                   'event': EVENT_NAME,
                                   'next_handler': None})
@@ -163,7 +180,7 @@ class EventSystemTestCase(unittest.TestCase):
 
     def test_subscribe_event_duplicate_priority(self):
 
-        def my_callback(**kwargs):
+        def my_callback(event_args, *args, **kwargs):
             pass
 
         dispatcher = SimpleEventDispatcher()
@@ -174,7 +191,7 @@ class EventSystemTestCase(unittest.TestCase):
 
     def test_subscribe_event_duplicate_wildcard_priority(self):
 
-        def my_callback(**kwargs):
+        def my_callback(event_args, *args, **kwargs):
             pass
 
         dispatcher = SimpleEventDispatcher()
@@ -185,7 +202,7 @@ class EventSystemTestCase(unittest.TestCase):
 
     def test_subscribe_event_duplicate_wildcard_priority_allowed(self):
         # duplicate priorities for different wildcard namespaces allowed
-        def my_callback(**kwargs):
+        def my_callback(event_args, *args, **kwargs):
             pass
 
         dispatcher = SimpleEventDispatcher()
@@ -198,21 +215,21 @@ class EventSystemTestCase(unittest.TestCase):
         EVENT_NAME = "event.hello.world"
         callback_tracker = ['']
 
-        def my_callback1(**kwargs):
-            self.assertDictEqual(kwargs, {'sender': self,
-                                          'event': EVENT_NAME})
+        def my_callback1(event_args, *args, **kwargs):
+            self.assertDictEqual(event_args, {'sender': self,
+                                              'event': EVENT_NAME})
             callback_tracker[0] += "event1_"
             return "hello"
 
-        def my_callback2(**kwargs):
-            self.assertDictEqual(kwargs,
+        def my_callback2(event_args, *args, **kwargs):
+            self.assertDictEqual(event_args,
                                  {'sender': self,
                                   'event': "event.hello.anotherworld"})
             callback_tracker[0] += "event2_"
             return "another"
 
-        def my_callback3(**kwargs):
-            self.assertDictEqual(kwargs,
+        def my_callback3(event_args, *args, **kwargs):
+            self.assertDictEqual(event_args,
                                  {'sender': self,
                                   'event': "event.hello.anotherworld",
                                   'next_handler': None})
@@ -243,19 +260,22 @@ class EventSystemTestCase(unittest.TestCase):
     def test_subscribe_wildcard(self):
         callback_tracker = ['']
 
-        def my_callback1(**kwargs):
+        def my_callback1(event_args, *args, **kwargs):
             callback_tracker[0] += "event1_"
-            return "hello" + kwargs.get('next_handler').invoke(**kwargs)
+            next_handler = event_args.get('next_handler')
+            return "hello" + next_handler.invoke(event_args, *args, **kwargs)
 
-        def my_callback2(**kwargs):
+        def my_callback2(event_args, *args, **kwargs):
             callback_tracker[0] += "event2_"
-            return "some" + kwargs.get('next_handler').invoke(**kwargs)
+            next_handler = event_args.get('next_handler')
+            return "some" + next_handler.invoke(event_args, *args, **kwargs)
 
-        def my_callback3(**kwargs):
+        def my_callback3(event_args, *args, **kwargs):
             callback_tracker[0] += "event3_"
-            return "other" + kwargs.get('next_handler').invoke(**kwargs)
+            next_handler = event_args.get('next_handler')
+            return "other" + next_handler.invoke(event_args, *args, **kwargs)
 
-        def my_callback4(**kwargs):
+        def my_callback4(*args, **kwargs):
             callback_tracker[0] += "event4_"
             return "world"
 
@@ -287,14 +307,16 @@ class EventSystemTestCase(unittest.TestCase):
     def test_subscribe_after_emit(self):
         callback_tracker = ['']
 
-        def my_callback1(**kwargs):
+        def my_callback1(event_args, *args, **kwargs):
             callback_tracker[0] += "event1_"
-            if kwargs.get('next_handler'):
-                return "hello" + kwargs.get('next_handler').invoke(**kwargs)
+            next_handler = event_args.get('next_handler')
+            if next_handler:
+                return "hello" + next_handler.invoke(
+                    event_args, *args, **kwargs)
             else:
                 return "hello"
 
-        def my_callback2(**kwargs):
+        def my_callback2(*args, **kwargs):
             callback_tracker[0] += "event2_"
             return "some"
 
@@ -314,14 +336,16 @@ class EventSystemTestCase(unittest.TestCase):
         EVENT_NAME = "event.hello.world"
         callback_tracker = ['']
 
-        def my_callback1(**kwargs):
+        def my_callback1(event_args, *args, **kwargs):
             callback_tracker[0] += "event1_"
-            if kwargs.get('next_handler'):
-                return "hello" + kwargs.get('next_handler').invoke(**kwargs)
+            next_handler = event_args.get('next_handler')
+            if next_handler:
+                return "hello" + next_handler.invoke(
+                    event_args, *args, **kwargs)
             else:
                 return "hello"
 
-        def my_callback2(**kwargs):
+        def my_callback2(*args, **kwargs):
             callback_tracker[0] += "event2_"
             return "some"
 

+ 22 - 14
test/test_middleware_system.py

@@ -45,19 +45,25 @@ class MiddlewareSystemTestCase(unittest.TestCase):
                 self.invocation_order = ""
 
             @observe(event_pattern="some.event.*", priority=1000)
-            def my_callback_obs(self, **kwargs):
+            def my_callback_obs(self, *args, **kwargs):
                 self.invocation_order += "observe"
+                assert 'first_pos_arg' in args
+                assert kwargs.get('a_keyword_arg') == "something"
 
             @intercept(event_pattern="some.event.*", priority=900)
-            def my_callback_intcpt(self, **kwargs):
+            def my_callback_intcpt(self, event_args, *args, **kwargs):
                 self.invocation_order += "intercept_"
-                return kwargs.get('next_handler').invoke(**kwargs)
+                assert 'first_pos_arg' in args
+                assert kwargs.get('a_keyword_arg') == "something"
+                next_handler = event_args.get('next_handler')
+                return next_handler.invoke(event_args, *args, **kwargs)
 
         dispatcher = SimpleEventDispatcher()
         manager = SimpleMiddlewareManager(dispatcher)
         middleware = DummyMiddleWare()
         manager.add(middleware)
-        dispatcher.emit(self, EVENT_NAME)
+        dispatcher.emit(self, EVENT_NAME, 'first_pos_arg',
+                        a_keyword_arg='something')
 
         self.assertEqual(middleware.invocation_order, "intercept_observe")
         self.assertListEqual(
@@ -75,22 +81,24 @@ class MiddlewareSystemTestCase(unittest.TestCase):
         class DummyMiddleWare1(BaseMiddleware):
 
             @observe(event_pattern="some.really.*", priority=1000)
-            def my_callback_obs1(self, **kwargs):
+            def my_callback_obs1(self, *args, **kwargs):
                 pass
 
             @intercept(event_pattern="some.*", priority=900)
-            def my_callback_intcpt2(self, **kwargs):
-                return kwargs.get('next_handler').invoke(**kwargs)
+            def my_callback_intcpt2(self, event_args, *args, **kwargs):
+                next_handler = event_args.get('next_handler')
+                return next_handler.invoke(event_args, *args, **kwargs)
 
         class DummyMiddleWare2(BaseMiddleware):
 
             @observe(event_pattern="some.really.*", priority=1050)
-            def my_callback_obs3(self, **kwargs):
+            def my_callback_obs3(self, *args, **kwargs):
                 pass
 
             @intercept(event_pattern="*", priority=950)
-            def my_callback_intcpt4(self, **kwargs):
-                return kwargs.get('next_handler').invoke(**kwargs)
+            def my_callback_intcpt4(self, event_args, *args, **kwargs):
+                next_handler = event_args.get('next_handler')
+                return next_handler.invoke(event_args, *args, **kwargs)
 
         dispatcher = SimpleEventDispatcher()
         manager = SimpleMiddlewareManager(dispatcher)
@@ -131,18 +139,18 @@ class MiddlewareSystemTestCase(unittest.TestCase):
         class SomeDummyClass(object):
 
             @observe(event_pattern="another.really.*", priority=1000)
-            def not_a_match(self, **kwargs):
+            def not_a_match(self, *args, **kwargs):
                 pass
 
             @intercept(event_pattern="another.*", priority=900)
-            def my_callback_intcpt2(self, **kwargs):
+            def my_callback_intcpt2(self, *args, **kwargs):
                 pass
 
-            def not_an_event_handler(self, **kwargs):
+            def not_an_event_handler(self, *args, **kwargs):
                 pass
 
             @observe(event_pattern="another.interesting.*", priority=1000)
-            def my_callback_obs1(self, **kwargs):
+            def my_callback_obs1(self, *args, **kwargs):
                 pass
 
         dispatcher = SimpleEventDispatcher()