Parcourir la source

events: add support for wildcard event handlers

Port 5a39e777089d8bde6d0a620830a898c1cf3dd924 ("events: add support for
wildcard event handlers") from qubes-core-admin:

    Support registering handlers for more flexible wildcard events: not only
    '*', but also 'something*'. This allows to register handlers for
    'property-set:*' and such.
Marek Marczykowski-Górecki il y a 6 ans
Parent
commit
fe73313da1
2 fichiers modifiés avec 22 ajouts et 3 suppressions
  1. 5 3
      qubesadmin/events/__init__.py
  2. 17 0
      qubesadmin/tests/events.py

+ 5 - 3
qubesadmin/events/__init__.py

@@ -21,6 +21,7 @@
 '''Event handling implementation, require Python >=3.5.2 for asyncio.'''
 
 import asyncio
+import fnmatch
 import subprocess
 
 import qubesadmin.config
@@ -200,7 +201,8 @@ class EventsDispatcher(object):
             if event in ['domain-add', 'domain-delete']:
                 self.app.domains.clear_cache()
             subject = None
-        for handler in self.handlers.get(event, []):
-            handler(subject, event, **kwargs)
-        for handler in self.handlers.get('*', []):
+        handlers = [h_func for h_name, h_func_set in self.handlers.items()
+            for h_func in h_func_set
+            if fnmatch.fnmatch(event, h_name)]
+        for handler in handlers:
             handler(subject, event, **kwargs)

+ 17 - 0
qubesadmin/tests/events.py

@@ -79,6 +79,23 @@ class TC_00_Events(qubesadmin.tests.QubesTestCase):
         self.dispatcher.handle('', 'some-event', arg1='value1')
         self.assertFalse(handler.called)
 
+    def test_002_handler_glob_partial(self):
+        handler = unittest.mock.Mock()
+        self.dispatcher.add_handler('some-*', handler)
+        self.dispatcher.handle('', 'some-event', arg1='value1')
+        handler.assert_called_once_with(None, 'some-event', arg1='value1')
+        handler.reset_mock()
+        self.dispatcher.handle('test-vm', 'some-event', arg1='value1')
+        handler.assert_called_once_with(
+            self.app.domains.get_blind('test-vm'), 'some-event', arg1='value1')
+        handler.reset_mock()
+        self.dispatcher.handle('', 'other-event', arg1='value1')
+        self.assertFalse(handler.called)
+        handler.reset_mock()
+        self.dispatcher.remove_handler('some-*', handler)
+        self.dispatcher.handle('', 'some-event', arg1='value1')
+        self.assertFalse(handler.called)
+
     @asyncio.coroutine
     def mock_get_events_reader(self, stream, cleanup_func, expected_vm,
             vm=None):