As an unrelated followup to this answer, which isuses the following working code:
from transitions import Machine
from transitions import EventData
from typing import Callable
from enum import Enum, auto
class Observer:
    def state_changed(self, event_data: EventData):
        print(f"state is now '{event_data.state.name}'")
class State(Enum):
    SOLID = auto()
    LIQUID = auto()
    GAS = auto()
class SubscribableMachine(Machine):
    transitions = [
        {'trigger': 'heat', 'source': State.SOLID, 'dest': State.LIQUID},
        {'trigger': 'heat', 'source': State.LIQUID, 'dest': State.GAS},
        {'trigger': 'cool', 'source': State.GAS, 'dest': State.LIQUID},
        {'trigger': 'cool', 'source': State.LIQUID, 'dest': State.SOLID}
    ]
    def __init__(self):
        super().__init__(states=State, transitions=self.transitions,
                         initial=State.SOLID, send_event=True)
    def subscribe(self, func: Callable, state: State):
        self.get_state(state).on_enter.append(func)
    def unsubscribe(self, func: Callable, state: State):
        self.get_state(state).on_enter.remove(func)
machine = SubscribableMachine()
observer = Observer()
machine.subscribe(observer.state_changed, State.LIQUID)
machine.heat()  # >>> state is now 'LIQUID'
machine.heat()
assert machine.state == State.GAS
machine.unsubscribe(observer.state_changed, State.LIQUID)
machine.cool()  # no output
assert machine.state == State.LIQUID
I would like to have an enum for Trigger as well, just like I have one for State.
Alas, when I try
class Trigger(Enum):
    heat = auto()
    cool = auto()
and
transitions = [
    {'trigger': Trigger.heat, 'source': State.SOLID, 'dest': State.LIQUID},
    {'trigger': Trigger.heat, 'source': State.LIQUID, 'dest': State.GAS},
    {'trigger': Trigger.cool, 'source': State.GAS, 'dest': State.LIQUID},
    {'trigger': Trigger.cool, 'source': State.LIQUID, 'dest': State.SOLID}
]
def __init__(self):
    super().__init__(states=State, transitions=self.transitions,
                     initial=State.SOLID, send_event=True)
I get
Traceback (most recent call last):
  File "C:/code/EPMD/Kodex/Algorithms/src/python/epmd/ablation_points/queries/dfgfdsg.py", line 42, in <module>
    machine = SubscribableMachine()
  File "C:/code/EPMD/Kodex/Algorithms/src/python/epmd/ablation_points/queries/dfgfdsg.py", line 33, in __init__
    initial=State.SOLID, send_event=True)
  File "C:\Code\EPMD\Kodex\EPD_Prerequisite\python_3.7.6\Lib\site-packages\transitions\core.py", line 589, in __init__
    self.add_model(model)
  File "C:\Code\EPMD\Kodex\EPD_Prerequisite\python_3.7.6\Lib\site-packages\transitions\core.py", line 607, in add_model
    self._add_trigger_to_model(trigger, mod)
  File "C:\Code\EPMD\Kodex\EPD_Prerequisite\python_3.7.6\Lib\site-packages\transitions\core.py", line 813, in _add_trigger_to_model
    self._checked_assignment(model, trigger, partial(self.events[trigger].trigger, model))
  File "C:\Code\EPMD\Kodex\EPD_Prerequisite\python_3.7.6\Lib\site-packages\transitions\core.py", line 807, in _checked_assignment
    if hasattr(model, name):
TypeError: hasattr(): attribute name must be string
I can solve it by using Enum's .name:
    transitions = [
        {'trigger': Trigger.heat.name, 'source': State.SOLID, 'dest': State.LIQUID},
        {'trigger': Trigger.heat.name, 'source': State.LIQUID, 'dest': State.GAS},
        {'trigger': Trigger.cool.name, 'source': State.GAS, 'dest': State.LIQUID},
        {'trigger': Trigger.cool.name, 'source': State.LIQUID, 'dest': State.SOLID}
    ]
But the asymmetry between State and Trigger bothers me.
Am I doing something wrong? Why does Enum work for State but not Trigger?