qubes/events: fix event handling order
Events are divided into "pre" and "post" events. "Pre" events fire handlers in MRO, "post" fire them in reverse.
This commit is contained in:
parent
41fef46db2
commit
9fa3d60d0b
@ -510,9 +510,9 @@ class property(object):
|
||||
value = self._type(value)
|
||||
|
||||
if has_oldvalue:
|
||||
instance.fire_event('property-pre-set:' + self.__name__, value, oldvalue)
|
||||
instance.fire_event_pre('property-pre-set:' + self.__name__, value, oldvalue)
|
||||
else:
|
||||
instance.fire_event('property-pre-set:' + self.__name__, value)
|
||||
instance.fire_event_pre('property-pre-set:' + self.__name__, value)
|
||||
|
||||
|
||||
instance._init_property(self, value)
|
||||
|
@ -92,24 +92,17 @@ class Emitter(object):
|
||||
cls.__handlers__[event].add(handler)
|
||||
|
||||
|
||||
def fire_event(self, event, *args, **kwargs):
|
||||
'''Call all handlers for an event.
|
||||
def _fire_event_in_order(self, order, event, *args, **kwargs):
|
||||
'''Fire event for classes in given order.
|
||||
|
||||
Handlers are called for class and all parent classess, in 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.
|
||||
|
||||
:param str event: event identificator
|
||||
|
||||
All *args* and *kwargs* are passed verbatim. They are different for
|
||||
different events.
|
||||
Do not use this method. Use :py:meth:`fire_event` or
|
||||
:py:meth:`fire_event_pre`.
|
||||
'''
|
||||
|
||||
if not self.events_enabled:
|
||||
return
|
||||
|
||||
for cls in self.__class__.__mro__:
|
||||
for cls in order:
|
||||
# first fire bound (= our own) handlers, then handlers from extensions
|
||||
if not hasattr(cls, '__handlers__'):
|
||||
continue
|
||||
@ -122,3 +115,42 @@ class Emitter(object):
|
||||
# this is from extension or hand-added, so we see method as
|
||||
# unbound, therefore we need to pass self
|
||||
handler(self, event, *args, **kwargs)
|
||||
|
||||
|
||||
def fire_event(self, event, *args, **kwargs):
|
||||
'''Call all handlers for an event.
|
||||
|
||||
Handlers are called for class and all parent classess, in **reversed**
|
||||
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 identificator
|
||||
|
||||
All *args* and *kwargs* are passed verbatim. They are different for
|
||||
different events.
|
||||
'''
|
||||
|
||||
self._fire_event_in_order(reversed(self.__class__.__mro__), event, *args, **kwargs)
|
||||
|
||||
|
||||
def fire_event_pre(self, event, *args, **kwargs):
|
||||
'''Call all handlers for an event.
|
||||
|
||||
Handlers are called for class and all parent classess, 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 identificator
|
||||
|
||||
All *args* and *kwargs* are passed verbatim. They are different for
|
||||
different events.
|
||||
'''
|
||||
|
||||
self._fire_event_in_order(self.__class__.__mro__, event, *args, **kwargs)
|
||||
|
@ -93,7 +93,7 @@ class DeviceCollection(object):
|
||||
raise KeyError(
|
||||
'device {!r} of class {} already attached to {!r}'.format(
|
||||
device, self._class, self._vm))
|
||||
self._vm.fire_event('device-pre-attached:{}'.format(self._class), device)
|
||||
self._vm.fire_event_pre('device-pre-attached:{}'.format(self._class), device)
|
||||
self._set.add(device)
|
||||
self._vm.fire_event('device-attached:{}'.format(self._class), device)
|
||||
|
||||
@ -108,7 +108,7 @@ class DeviceCollection(object):
|
||||
raise KeyError(
|
||||
'device {!r} of class {} not attached to {!r}'.format(
|
||||
device, self._class, self._vm))
|
||||
self._vm.fire_event('device-pre-detached:{}'.format(self._class), device)
|
||||
self._vm.fire_event_pre('device-pre-detached:{}'.format(self._class), device)
|
||||
self._set.remove(device)
|
||||
self._vm.fire_event('device-detached:{}'.format(self._class), device)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user