<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def publish(obj, event, event_state, **kwargs):
 """Publish an event from an object. This is a really basic pub-sub event system to allow for tracking progress on methods externally. It fires the events for the first match it finds in the object hierarchy, going most specific to least. If no match is found for the exact event+event_state, the most specific event+ANY is fired instead. Multiple callbacks can be bound to the event+event_state if desired. All will be fired in the order they were registered. """

    # short-circuit if nothing is listening
    if len(EVENT_HANDLERS) == 0:
        return

    if inspect.isclass(obj):
        pub_cls = obj
    else:
        pub_cls = obj.__class__
    potential = [x.__name__ for x in inspect.getmro(pub_cls)]

    # if we don't find a match for this event/event_state we fire the events
    # for this event/ANY instead for the closest match
    fallbacks = None
    callbacks = []
    for cls in potential:
        event_key = '.'.join([cls, event, event_state])
        backup_key = '.'.join([cls, event, states.ANY])
        if event_key in EVENT_HANDLERS:
            callbacks = EVENT_HANDLERS[event_key]
            break
        elif fallbacks is None and backup_key in EVENT_HANDLERS:
            fallbacks = EVENT_HANDLERS[backup_key]

    if fallbacks is not None:
        callbacks = fallbacks

    for callback in callbacks:
        callback(obj, **kwargs)
    return