pytransitions / transitions

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

enum based example crashes with transitions==0.7.0 #366

Closed attila123 closed 4 years ago

attila123 commented 4 years ago

Hi, after reading the documentation I decided to use enums for the states. But I had some crash issue so I tried the example directly from https://github.com/pytransitions/transitions/blob/master/README.md as it is:

import enum  # Python 2.7 users need to have 'enum34' installed
from transitions import Machine

class States(enum.Enum):
    ERROR = 0
    RED = 1
    YELLOW = 2
    GREEN = 3

transitions = [['proceed', States.RED, States.YELLOW],
               ['proceed', States.YELLOW, States.GREEN],
               ['error', '*', States.ERROR]]

m = Machine(states=States, transitions=transitions, initial=States.RED)
assert m.is_RED()
assert m.state is States.RED
state = m.get_state(States.RED)  # get transitions.State object
print(state.name)  # >>> RED
m.proceed()
m.proceed()
assert m.is_GREEN()
m.error()
assert m.state is States.ERROR

So I copy-pasted it to a new .py file in my PyCharm project (transitions==0.7.0 was already added to my requirements.txt and installed in the venv), and run it, and it also crashes (I use Python 3.7.4 in Linux):

/path/to/my/project/.tox/py37/bin/python /path/to/my/project/tmp_transitions_enum.py
Traceback (most recent call last):
  File "/path/to/my/project/tmp_transitions_enum.py", line 14, in <module>
    m = Machine(states=States, transitions=transitions, initial=States.RED)
  File "/path/to/my/project/.tox/py37/lib/python3.7/site-packages/transitions/core.py", line 552, in __init__
    self.add_states(states)
  File "/path/to/my/project/.tox/py37/lib/python3.7/site-packages/transitions/core.py", line 755, in add_states
    self.states[state.name] = state
  File "/path/to/my/project/.tox/py37/lib/python3.7/enum.py", line 349, in __getattr__
    raise AttributeError(name) from None
AttributeError: name

Process finished with exit code 1

Update:

To prove that my environment is otherwise OK, with minimal changes I converted the example to string based states and then it runs fine (exits successfully):

import enum  # Python 2.7 users need to have 'enum34' installed
from transitions import Machine

states = ['ERROR', 'RED', 'YELLOW', 'GREEN']

transitions = [['proceed', 'RED', 'YELLOW'],
               ['proceed', 'YELLOW', 'GREEN'],
               ['error', '*', 'ERROR']]

m = Machine(states=states, transitions=transitions, initial='RED')
assert m.is_RED()
assert m.state is 'RED'
state = m.get_state('RED')  # get transitions.State object
print(state.name)  # >>> RED
m.proceed()
m.proceed()
assert m.is_GREEN()
m.error()
assert m.state is 'ERROR'

As a workaround, I think I will go with the following state name pattern, which will be the easiest to convert back to enums after this issue fixed:

import enum  # Python 2.7 users need to have 'enum34' installed
from transitions import Machine

states = ['States_ERROR', 'States_RED', 'States_YELLOW', 'States_GREEN']

transitions = [['proceed', 'States_RED', 'States_YELLOW'],
               ['proceed', 'States_YELLOW', 'States_GREEN'],
               ['error', '*', 'States_ERROR']]

m = Machine(states=states, transitions=transitions, initial='States_RED')
assert m.is_States_RED()
assert m.state is 'States_RED'
state = m.get_state('States_RED')  # get transitions.State object
print(state.name)  # >>> RED
m.proceed()
m.proceed()
assert m.is_States_GREEN()
m.error()
assert m.state is 'States_ERROR'
aleneum commented 4 years ago

Hi @attila123,

So I copy-pasted it to a new .py file in my PyCharm project (transitions==0.7.0 was already added to my requirements.txt and installed in the venv)

Enum support is a currently unreleased feature. It's not supported in 0.7.0. If you want to try it out you have to install transitions 0.7.1 from the repo.

attila123 commented 4 years ago

Hi @aleneum, Thank you very much for the quick reply. My project's build system uses dependencies only from pypi (and I don't want to change that), so for now I will then stick with the string based states. Hmm, but I can use string "constants" for the states anyway, and will unit test my code anyway, so it does not hurt much. Just curious: Is the enum based states considered "stable" in master? Any plans to release 0.7.1? Maybe we can leave this issue open until 0.7.1 is released, someone else might bump into this same issue.

aleneum commented 4 years ago

Hi @attila123,

Is the enum based states considered "stable" in master?

we haven't encountered major setbacks yet. From my experience it is stable.

Any plans to release 0.7.1?

no specific date so far. If more users consider it stable, we could release mid of September.

Maybe we can leave this issue open until 0.7.1 is released, someone else might bump into this same issue.

Sure, I will close this issue when 0.7.1 is released.