'Dispatch an event.
When C{event} is L{None}, an XPath type event is triggered, and
C{obj} is assumed to be an instance of
L{Element<twisted.words.xish.domish.Element>}. Otherwise, C{event}
holds the name of the named event being triggered. In the latter case,
C{obj} can be anything.
@param obj: The object to be dispatched.
@param event: Optional event name.
@type event: C{str}'

def dispatch(self, obj, event=None):

    foundTarget = False
    self._dispatchDepth += 1
    if (event != None):
        observers = self._eventObservers
        match = (lambda query, obj: (query == event))
    else:
        observers = self._xpathObservers
        match = (lambda query, obj: query.matches(obj))
    priorities = list(observers.keys())
    priorities.sort()
    priorities.reverse()
    emptyLists = []
    for priority in priorities:
        for (query, callbacklist) in iteritems(observers[priority]):
            if match(query, obj):
                callbacklist.callback(obj)
                foundTarget = True
                if callbacklist.isEmpty():
                    emptyLists.append((priority, query))
    for (priority, query) in emptyLists:
        del observers[priority][query]
    self._dispatchDepth -= 1
    if (self._dispatchDepth == 0):
        for f in self._updateQueue:
            f()
        self._updateQueue = []
    return foundTarget
