イベントをキャンセル可能にする

StopIteration 風に StopPropagation を投げる。

# -*- coding: utf-8 -*-
# event canceling support

from zope import event
from zope.app.event.dispatching import dispatch


class StopPropagation(Exception):
    """stop event bubbling"""


def newdispatch(*event):
    """call zope.app.event.dispatching.dispatch with StopPropagation handling."""

    try:
        dispatch(*event)
    except StopPropagation:
        pass


# try to replace event handler.
try:
    event.subscribers.remove(dispatch)
except ValueError:
    pass
else:
    event.subscribers.append(newdispatch)
    # bind zope.event.StopPropagation
    setattr(event, 'StopPropagation', StopPropagation)