Kaynağa Gözat

events: merge fire_event and fire_event_pre functions

Those functions really do very similar things - lets merge them and add
simple parameter.
Marek Marczykowski-Górecki 7 yıl önce
ebeveyn
işleme
6238254f49

+ 4 - 4
doc/qubes-events.rst

@@ -22,10 +22,10 @@ parent class and then for it's child. For each class, first are called handlers
 defined in it's source, then handlers from extensions and last the callers added
 manually.
 
-There is second method, :py:meth:`qubes.events.Emitter.fire_event_pre`, which
-fires events in reverse order. It is suitable for events fired before some
-action is performed. You may at your own responsibility raise exceptions from
-such events to try to prevent such action.
+The :py:meth:`qubes.events.Emitter.fire_event` method have keyword argument
+`pre_event`, which fires events in reverse order. It is suitable for events
+fired before some action is performed. You may at your own responsibility raise
+exceptions from such events to try to prevent such action.
 
 Events handlers may yield values. Those values are aggregated and returned
 to the caller as a list of those values. See below for details.

+ 8 - 4
qubes/__init__.py

@@ -250,10 +250,12 @@ class property(object):  # pylint: disable=redefined-builtin,invalid-name
             value = self.type(value)
 
         if has_oldvalue:
-            instance.fire_event_pre('property-pre-set:' + self.__name__,
+            instance.fire_event('property-pre-set:' + self.__name__,
+                pre_event=True,
                 name=self.__name__, newvalue=value, oldvalue=oldvalue)
         else:
-            instance.fire_event_pre('property-pre-set:' + self.__name__,
+            instance.fire_event('property-pre-set:' + self.__name__,
+                pre_event=True,
                 name=self.__name__, newvalue=value)
 
         instance._property_init(self, value) # pylint: disable=protected-access
@@ -276,14 +278,16 @@ class property(object):  # pylint: disable=redefined-builtin,invalid-name
             has_oldvalue = False
 
         if has_oldvalue:
-            instance.fire_event_pre('property-pre-del:' + self.__name__,
+            instance.fire_event('property-pre-del:' + self.__name__,
+                pre_event=True,
                 name=self.__name__, oldvalue=oldvalue)
             delattr(instance, self._attr_name)
             instance.fire_event('property-del:' + self.__name__,
                 name=self.__name__, oldvalue=oldvalue)
 
         else:
-            instance.fire_event_pre('property-pre-del:' + self.__name__,
+            instance.fire_event('property-pre-del:' + self.__name__,
+                pre_event=True,
                 name=self.__name__)
             instance.fire_event('property-del:' + self.__name__,
                 name=self.__name__)

+ 2 - 2
qubes/api/__init__.py

@@ -181,8 +181,8 @@ class AbstractQubesAPI(object):
 
     def fire_event_for_permission(self, **kwargs):
         '''Fire an event on the source qube to check for permission'''
-        return self.src.fire_event_pre('mgmt-permission:' + self.method,
-            dest=self.dest, arg=self.arg, **kwargs)
+        return self.src.fire_event('mgmt-permission:' + self.method,
+            pre_event=True, dest=self.dest, arg=self.arg, **kwargs)
 
     def fire_event_for_filter(self, iterable, **kwargs):
         '''Fire an event on the source qube to filter for permission'''

+ 1 - 1
qubes/app.py

@@ -476,7 +476,7 @@ class VMCollection(object):
         vm = self[key]
         if not vm.is_halted():
             raise qubes.exc.QubesVMNotHaltedError(vm)
-        self.app.fire_event_pre('domain-pre-delete', vm=vm)
+        self.app.fire_event('domain-pre-delete', pre_event=True, vm=vm)
         try:
             vm.libvirt_domain.undefine()
         except libvirt.libvirtError as e:

+ 3 - 2
qubes/devices.py

@@ -180,7 +180,7 @@ class DeviceCollection(object):
             raise DeviceAlreadyAttached(
                 'device {!s} of class {} already attached to {!s}'.format(
                     device, self._bus, self._vm))
-        self._vm.fire_event_pre('device-pre-attach:'+self._bus,
+        self._vm.fire_event('device-pre-attach:'+self._bus, pre_event=True,
             device=device, options=device_assignment.options)
         if device_assignment.persistent:
             self._set.add(device_assignment)
@@ -208,7 +208,8 @@ class DeviceCollection(object):
                     device_assignment.ident, self._bus, self._vm))
 
         device = device_assignment.device
-        self._vm.fire_event_pre('device-pre-detach:'+self._bus, device=device)
+        self._vm.fire_event('device-pre-detach:' + self._bus,
+            pre_event=True, device=device)
         if device in self._set:
             device_assignment.persistent = True
             self._set.discard(device_assignment)

+ 10 - 32
qubes/events.py

@@ -134,16 +134,19 @@ class Emitter(object, metaclass=EmitterMeta):
         # pylint: disable=no-member
         self.__handlers__[event].remove(func)
 
-    def _fire_event_in_order(self, order, event, kwargs):
+    def _fire_event(self, event, kwargs, pre_event=False):
         '''Fire event for classes in given order.
 
-        Do not use this method. Use :py:meth:`fire_event` or
-        :py:meth:`fire_event_pre`.
+        Do not use this method. Use :py:meth:`fire_event`.
         '''
 
         if not self.events_enabled:
             return []
 
+        order = itertools.chain((self,), self.__class__.__mro__)
+        if not pre_event:
+            order = reversed(list(order))
+
         effects = []
         for i in order:
             try:
@@ -161,46 +164,21 @@ class Emitter(object, metaclass=EmitterMeta):
                     effects.extend(effect)
         return effects
 
-    def fire_event(self, event, **kwargs):
+    def fire_event(self, event, pre_event=False, **kwargs):
         '''Call all handlers for an event.
 
         Handlers are called for class and all parent classes, in **reversed**
+        or **true** (depending on *pre_event* parameter)
         method resolution order. For each class first are called bound handlers
         (specified in class definition), then handlers from extensions. Aside
         from above, remaining order is undefined.
 
-        .. seealso::
-            :py:meth:`fire_event_pre`
-
-        :param str event: event identifier
-        :returns: list of effects
-
-        All *kwargs* are passed verbatim. They are different for different
-        events.
-        '''
-
-        return self._fire_event_in_order(
-            itertools.chain(reversed(self.__class__.__mro__), (self,)),
-            event, kwargs)
-
-
-    def fire_event_pre(self, event, **kwargs):
-        '''Call all handlers for an event.
-
-        Handlers are called for class and all parent classes, in **true**
-        method resolution order. This is intended for ``-pre-`` events, where
-        order of invocation should be reversed.
-
-        .. seealso::
-            :py:meth:`fire_event`
-
         :param str event: event identifier
+        :param pre_event: is this -pre- event? reverse handlers calling order
         :returns: list of effects
 
         All *kwargs* are passed verbatim. They are different for different
         events.
         '''
 
-        return self._fire_event_in_order(
-            itertools.chain((self,), self.__class__.__mro__),
-            event, kwargs)
+        return self._fire_event(event, kwargs, pre_event=pre_event)

+ 0 - 11
qubes/tests/__init__.py

@@ -159,17 +159,6 @@ class TestEmitter(qubes.events.Emitter):
         self.fired_events[(event, ev_kwargs)] += 1
         return effects
 
-    def fire_event_pre(self, event, **kwargs):
-        effects = super(TestEmitter, self).fire_event_pre(event, **kwargs)
-        ev_kwargs = frozenset(
-            (key,
-                frozenset(value.items()) if isinstance(value, dict)
-                else tuple(value) if isinstance(value, list)
-                else value)
-            for key, value in kwargs.items()
-        )
-        self.fired_events[(event, ev_kwargs)] += 1
-        return effects
 
 def expectedFailureIfTemplate(templates):
     """

+ 0 - 3
qubes/tests/api_admin.py

@@ -76,7 +76,6 @@ class AdminAPITestCase(qubes.tests.QubesTestCase):
 
         self.emitter = qubes.tests.TestEmitter()
         self.app.domains[0].fire_event = self.emitter.fire_event
-        self.app.domains[0].fire_event_pre = self.emitter.fire_event_pre
 
     def tearDown(self):
         self.base_dir_patch2.stop()
@@ -1793,8 +1792,6 @@ class TC_00_VMs(AdminAPITestCase):
     def test_590_firewall_reload(self):
         self.vm.firewall.save = unittest.mock.Mock()
         self.app.domains['test-vm1'].fire_event = self.emitter.fire_event
-        self.app.domains['test-vm1'].fire_event_pre = \
-            self.emitter.fire_event_pre
         value = self.call_mgmt_func(b'admin.vm.firewall.Reload',
                 b'test-vm1', b'')
         self.assertIsNone(value)

+ 2 - 3
qubes/tests/events.py

@@ -73,7 +73,6 @@ class TC_00_Emitter(qubes.tests.QubesTestCase):
 
         emitter = TestEmitter()
         emitter.events_enabled = True
-        emitter.fire_event('testevent')
 
         effect = emitter.fire_event('testevent')
 
@@ -129,8 +128,8 @@ class TC_00_Emitter(qubes.tests.QubesTestCase):
                 ['testevent_1'])
 
         with self.subTest('fire_event_pre'):
-            effect = emitter.fire_event_pre('testevent')
-            effect2 = emitter2.fire_event_pre('testevent')
+            effect = emitter.fire_event('testevent', pre_event=True)
+            effect2 = emitter2.fire_event('testevent', pre_event=True)
             self.assertEqual(list(effect),
                 ['testevent_2', 'testevent_1'])
             self.assertEqual(list(effect2),

+ 4 - 3
qubes/vm/qubesvm.py

@@ -847,7 +847,8 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
 
             self.log.info('Starting {}'.format(self.name))
 
-            self.fire_event_pre('domain-pre-start',
+            self.fire_event('domain-pre-start',
+                pre_event=True,
                 start_guid=start_guid, mem_required=mem_required)
 
             yield from self.storage.verify()
@@ -935,7 +936,7 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
         if self.is_halted():
             raise qubes.exc.QubesVMNotStartedError(self)
 
-        self.fire_event_pre('domain-pre-shutdown', force=force)
+        self.fire_event('domain-pre-shutdown', pre_event=True, force=force)
 
         self.libvirt_domain.shutdown()
 
@@ -1071,7 +1072,7 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
             raise qubes.exc.QubesVMError(
                 self, 'Domain {!r}: qrexec not connected'.format(self.name))
 
-        self.fire_event_pre('domain-cmd-pre-run', start_guid=gui)
+        self.fire_event('domain-cmd-pre-run', pre_event=True, start_guid=gui)
 
         return (yield from asyncio.create_subprocess_exec(
             qubes.config.system_path['qrexec_client_path'],