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:
Wojtek Porczyk 2014-12-29 13:07:20 +01:00
父節點 41fef46db2
當前提交 9fa3d60d0b
共有 3 個檔案被更改,包括 48 行新增16 行删除

查看文件

@ -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)