code: def publish(obj, event, event_state, **kwargs):
      
      # 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
docs: 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.