pytransitions / transitions

A lightweight, object-oriented finite state machine implementation in Python with many extensions
MIT License
5.68k stars 530 forks source link

GraphMachine does not like it when you use enums for the states #391

Closed dwightmulcahy closed 4 years ago

dwightmulcahy commented 4 years ago

so this minimal example will bomb when you use states that are enums...

  File "/Users/dwight-personal/PycharmProjects/healthcheck/statemachine.py", line 24, in __init__
    self.machine = GraphMachine(model=self, use_pygraphviz=False, states=Health.States, initial=Health.States.UNKNOWN)
  File "/Users/dwight-personal/PycharmProjects/healthcheck/venv/lib/python3.7/site-packages/transitions/extensions/diagrams.py", line 138, in __init__
    _ = model.get_graph(title=self.title, force_new=True)  # initialises graph
  File "/Users/dwight-personal/PycharmProjects/healthcheck/venv/lib/python3.7/site-packages/transitions/extensions/diagrams.py", line 164, in _get_graph
    grph = self.graph_cls(self, title=title if title is not None else self.title)
  File "/Users/dwight-personal/PycharmProjects/healthcheck/venv/lib/python3.7/site-packages/transitions/extensions/diagrams_graphviz.py", line 40, in __init__
    self.generate(title)
  File "/Users/dwight-personal/PycharmProjects/healthcheck/venv/lib/python3.7/site-packages/transitions/extensions/diagrams_graphviz.py", line 110, in generate
    self._add_nodes(states, fsm_graph)
  File "/Users/dwight-personal/PycharmProjects/healthcheck/venv/lib/python3.7/site-packages/transitions/extensions/diagrams_graphviz.py", line 58, in _add_nodes
    **self.machine.style_attributes['node'][style])
  File "/Users/dwight-personal/PycharmProjects/healthcheck/venv/lib/python3.7/site-packages/graphviz/dot.py", line 130, in node
    name = self._quote(name)
  File "/Users/dwight-personal/PycharmProjects/healthcheck/venv/lib/python3.7/site-packages/graphviz/lang.py", line 63, in quote
    if is_html_string(identifier) and not isinstance(identifier, NoHtml):
TypeError: expected string or bytes-like object

as an example:

class Health(object):
    class States(enum.Enum):
        UNKNOWN = 0
...
    def __init__(self):
        self.machine = GraphMachine(model=self, use_pygraphviz=False, states=Health.States, initial=Health.States.UNKNOWN)
...
        self.machine.get_graph().draw('my_state_diagram.png', prog='dot')
dwightmulcahy commented 4 years ago

diagrams_graphviz.py should be stringifying the node labels.

aleneum commented 4 years ago

Hi @dwightmulcahy,

does this issue still persist? I would have thought that d28e8c2e11708dd82a86d04cc630608fef6bdd09 tackles this.

I tested:

import enum
from transitions.extensions.diagrams import GraphMachine

class Health(object):
    class States(enum.Enum):
        UNKNOWN = 0

machine = GraphMachine(use_pygraphviz=False, states=Health.States, initial=Health.States.UNKNOWN)
machine.get_graph().draw('my_state_diagram.png', prog='dot')

and it produces

my_state_diagram

aleneum commented 4 years ago

Graph.set_node_style had been called with the enum instance rather than the enum's name. should be fixed in master.