From fe73313da14bae9af47e9e4ccad263bdb086cb93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Fri, 7 Sep 2018 18:59:05 +0200 Subject: [PATCH] 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. --- qubesadmin/events/__init__.py | 8 +++++--- qubesadmin/tests/events.py | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/qubesadmin/events/__init__.py b/qubesadmin/events/__init__.py index da809e3..3c69878 100644 --- a/qubesadmin/events/__init__.py +++ b/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) diff --git a/qubesadmin/tests/events.py b/qubesadmin/tests/events.py index 3d340d1..e2f43e7 100644 --- a/qubesadmin/tests/events.py +++ b/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):