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)
|
value = self._type(value)
|
||||||
|
|
||||||
if has_oldvalue:
|
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:
|
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)
|
instance._init_property(self, value)
|
||||||
|
@ -92,24 +92,17 @@ class Emitter(object):
|
|||||||
cls.__handlers__[event].add(handler)
|
cls.__handlers__[event].add(handler)
|
||||||
|
|
||||||
|
|
||||||
def fire_event(self, event, *args, **kwargs):
|
def _fire_event_in_order(self, order, event, *args, **kwargs):
|
||||||
'''Call all handlers for an event.
|
'''Fire event for classes in given order.
|
||||||
|
|
||||||
Handlers are called for class and all parent classess, in method
|
Do not use this method. Use :py:meth:`fire_event` or
|
||||||
resolution order. For each class first are called bound handlers
|
:py:meth:`fire_event_pre`.
|
||||||
(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.
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
if not self.events_enabled:
|
if not self.events_enabled:
|
||||||
return
|
return
|
||||||
|
|
||||||
for cls in self.__class__.__mro__:
|
for cls in order:
|
||||||
# first fire bound (= our own) handlers, then handlers from extensions
|
# first fire bound (= our own) handlers, then handlers from extensions
|
||||||
if not hasattr(cls, '__handlers__'):
|
if not hasattr(cls, '__handlers__'):
|
||||||
continue
|
continue
|
||||||
@ -122,3 +115,42 @@ class Emitter(object):
|
|||||||
# this is from extension or hand-added, so we see method as
|
# this is from extension or hand-added, so we see method as
|
||||||
# unbound, therefore we need to pass self
|
# unbound, therefore we need to pass self
|
||||||
handler(self, event, *args, **kwargs)
|
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(
|
raise KeyError(
|
||||||
'device {!r} of class {} already attached to {!r}'.format(
|
'device {!r} of class {} already attached to {!r}'.format(
|
||||||
device, self._class, self._vm))
|
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._set.add(device)
|
||||||
self._vm.fire_event('device-attached:{}'.format(self._class), device)
|
self._vm.fire_event('device-attached:{}'.format(self._class), device)
|
||||||
|
|
||||||
@ -108,7 +108,7 @@ class DeviceCollection(object):
|
|||||||
raise KeyError(
|
raise KeyError(
|
||||||
'device {!r} of class {} not attached to {!r}'.format(
|
'device {!r} of class {} not attached to {!r}'.format(
|
||||||
device, self._class, self._vm))
|
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._set.remove(device)
|
||||||
self._vm.fire_event('device-detached:{}'.format(self._class), device)
|
self._vm.fire_event('device-detached:{}'.format(self._class), device)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user