فهرست منبع

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 سال پیش
والد
کامیت
6238254f49
10فایلهای تغییر یافته به همراه34 افزوده شده و 65 حذف شده
  1. 4 4
      doc/qubes-events.rst
  2. 8 4
      qubes/__init__.py
  3. 2 2
      qubes/api/__init__.py
  4. 1 1
      qubes/app.py
  5. 3 2
      qubes/devices.py
  6. 10 32
      qubes/events.py
  7. 0 11
      qubes/tests/__init__.py
  8. 0 3
      qubes/tests/api_admin.py
  9. 2 3
      qubes/tests/events.py
  10. 4 3
      qubes/vm/qubesvm.py

+ 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
 defined in it's source, then handlers from extensions and last the callers added
 manually.
 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
 Events handlers may yield values. Those values are aggregated and returned
 to the caller as a list of those values. See below for details.
 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)
             value = self.type(value)
 
 
         if has_oldvalue:
         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)
                 name=self.__name__, newvalue=value, oldvalue=oldvalue)
         else:
         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)
                 name=self.__name__, newvalue=value)
 
 
         instance._property_init(self, value) # pylint: disable=protected-access
         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
             has_oldvalue = False
 
 
         if has_oldvalue:
         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)
                 name=self.__name__, oldvalue=oldvalue)
             delattr(instance, self._attr_name)
             delattr(instance, self._attr_name)
             instance.fire_event('property-del:' + self.__name__,
             instance.fire_event('property-del:' + self.__name__,
                 name=self.__name__, oldvalue=oldvalue)
                 name=self.__name__, oldvalue=oldvalue)
 
 
         else:
         else:
-            instance.fire_event_pre('property-pre-del:' + self.__name__,
+            instance.fire_event('property-pre-del:' + self.__name__,
+                pre_event=True,
                 name=self.__name__)
                 name=self.__name__)
             instance.fire_event('property-del:' + self.__name__,
             instance.fire_event('property-del:' + self.__name__,
                 name=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):
     def fire_event_for_permission(self, **kwargs):
         '''Fire an event on the source qube to check for permission'''
         '''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):
     def fire_event_for_filter(self, iterable, **kwargs):
         '''Fire an event on the source qube to filter for permission'''
         '''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]
         vm = self[key]
         if not vm.is_halted():
         if not vm.is_halted():
             raise qubes.exc.QubesVMNotHaltedError(vm)
             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:
         try:
             vm.libvirt_domain.undefine()
             vm.libvirt_domain.undefine()
         except libvirt.libvirtError as e:
         except libvirt.libvirtError as e:

+ 3 - 2
qubes/devices.py

@@ -180,7 +180,7 @@ class DeviceCollection(object):
             raise DeviceAlreadyAttached(
             raise DeviceAlreadyAttached(
                 'device {!s} of class {} already attached to {!s}'.format(
                 'device {!s} of class {} already attached to {!s}'.format(
                     device, self._bus, self._vm))
                     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)
             device=device, options=device_assignment.options)
         if device_assignment.persistent:
         if device_assignment.persistent:
             self._set.add(device_assignment)
             self._set.add(device_assignment)
@@ -208,7 +208,8 @@ class DeviceCollection(object):
                     device_assignment.ident, self._bus, self._vm))
                     device_assignment.ident, self._bus, self._vm))
 
 
         device = device_assignment.device
         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:
         if device in self._set:
             device_assignment.persistent = True
             device_assignment.persistent = True
             self._set.discard(device_assignment)
             self._set.discard(device_assignment)

+ 10 - 32
qubes/events.py

@@ -134,16 +134,19 @@ class Emitter(object, metaclass=EmitterMeta):
         # pylint: disable=no-member
         # pylint: disable=no-member
         self.__handlers__[event].remove(func)
         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.
         '''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:
         if not self.events_enabled:
             return []
             return []
 
 
+        order = itertools.chain((self,), self.__class__.__mro__)
+        if not pre_event:
+            order = reversed(list(order))
+
         effects = []
         effects = []
         for i in order:
         for i in order:
             try:
             try:
@@ -161,46 +164,21 @@ class Emitter(object, metaclass=EmitterMeta):
                     effects.extend(effect)
                     effects.extend(effect)
         return effects
         return effects
 
 
-    def fire_event(self, event, **kwargs):
+    def fire_event(self, event, pre_event=False, **kwargs):
         '''Call all handlers for an event.
         '''Call all handlers for an event.
 
 
         Handlers are called for class and all parent classes, in **reversed**
         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
         method resolution order. For each class first are called bound handlers
         (specified in class definition), then handlers from extensions. Aside
         (specified in class definition), then handlers from extensions. Aside
         from above, remaining order is undefined.
         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 str event: event identifier
+        :param pre_event: is this -pre- event? reverse handlers calling order
         :returns: list of effects
         :returns: list of effects
 
 
         All *kwargs* are passed verbatim. They are different for different
         All *kwargs* are passed verbatim. They are different for different
         events.
         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
         self.fired_events[(event, ev_kwargs)] += 1
         return effects
         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):
 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.emitter = qubes.tests.TestEmitter()
         self.app.domains[0].fire_event = self.emitter.fire_event
         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):
     def tearDown(self):
         self.base_dir_patch2.stop()
         self.base_dir_patch2.stop()
@@ -1793,8 +1792,6 @@ class TC_00_VMs(AdminAPITestCase):
     def test_590_firewall_reload(self):
     def test_590_firewall_reload(self):
         self.vm.firewall.save = unittest.mock.Mock()
         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 = 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',
         value = self.call_mgmt_func(b'admin.vm.firewall.Reload',
                 b'test-vm1', b'')
                 b'test-vm1', b'')
         self.assertIsNone(value)
         self.assertIsNone(value)

+ 2 - 3
qubes/tests/events.py

@@ -73,7 +73,6 @@ class TC_00_Emitter(qubes.tests.QubesTestCase):
 
 
         emitter = TestEmitter()
         emitter = TestEmitter()
         emitter.events_enabled = True
         emitter.events_enabled = True
-        emitter.fire_event('testevent')
 
 
         effect = emitter.fire_event('testevent')
         effect = emitter.fire_event('testevent')
 
 
@@ -129,8 +128,8 @@ class TC_00_Emitter(qubes.tests.QubesTestCase):
                 ['testevent_1'])
                 ['testevent_1'])
 
 
         with self.subTest('fire_event_pre'):
         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),
             self.assertEqual(list(effect),
                 ['testevent_2', 'testevent_1'])
                 ['testevent_2', 'testevent_1'])
             self.assertEqual(list(effect2),
             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.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)
                 start_guid=start_guid, mem_required=mem_required)
 
 
             yield from self.storage.verify()
             yield from self.storage.verify()
@@ -935,7 +936,7 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
         if self.is_halted():
         if self.is_halted():
             raise qubes.exc.QubesVMNotStartedError(self)
             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()
         self.libvirt_domain.shutdown()
 
 
@@ -1071,7 +1072,7 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
             raise qubes.exc.QubesVMError(
             raise qubes.exc.QubesVMError(
                 self, 'Domain {!r}: qrexec not connected'.format(self.name))
                 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(
         return (yield from asyncio.create_subprocess_exec(
             qubes.config.system_path['qrexec_client_path'],
             qubes.config.system_path['qrexec_client_path'],