fgmacedo / python-statemachine

Python Finite State Machines made easy.
MIT License
854 stars 84 forks source link

Breaking changes to Enum support #457

Closed hperrey closed 2 months ago

hperrey commented 2 months ago

Description

The recent changes to how Enums are handled (see 6187213) broke code in existing projects for me, as the type of current_state_value as well as the capitalization of current_state.id changed.

I prefer the new current_state_value and am generally impartial to the capitalization norm, so this is not really an issue for me per-se. However, I did not expect such a change to sneak in via a minor release. Was this intended or did this slip through?

What I Did

Take a simple FSM based on Enums:

from enum import Enum
from statemachine import StateMachine
from statemachine.states import States

class TrafficState(Enum):
    """Available states to cycle through."""

    GREEN = 0
    YELLOW = 1
    RED = 2

class TrafficLightMachine(StateMachine):
    "A traffic light machine"

    states = States.from_enum(
        TrafficState, initial=TrafficState.GREEN
    )

    cycle = (
        states.GREEN.to(states.YELLOW)
        | states.YELLOW.to(states.RED)
        | states.RED.to(states.GREEN)
    )

if __name__ == '__main__':
    fsm = TrafficLightMachine()
    print(f"fsm.current_state.id: {fsm.current_state.id}, {type(fsm.current_state.id)}")
    print(f"fsm.current_state.name: {fsm.current_state.name}, {type(fsm.current_state.name)}")
    print(f"fsm.current_state_value: {fsm.current_state_value}, {type(fsm.current_state_value)}")

This yields on version 2.3.1

fsm.current_state.id: GREEN, <class 'str'>
fsm.current_state.name: Green, <class 'str'>
fsm.current_state_value: 0, <class 'int'>

and

fsm.current_state.id: green, <class 'str'>
fsm.current_state.name: Green, <class 'str'>
fsm.current_state_value: TrafficState.GREEN, <enum 'TrafficState'>

on version 2.3.2 (installed via pip).

fgmacedo commented 2 months ago

Hi @hperrey , how are you? Thanks for reporting this.

It was not intentional, sorry about that.

It was a huge diff between 2.3.1 and 2.3.2 and when creating the Django example project, I've refactored the example to use enum, when encountered an error, instead of fixing the example, I've changed the library 😕.

The lower case I clearly see as something that should be reverted.

The change in the value sounds like a bug fix for me. Do you think that should be reverted also?

Best!

hperrey commented 2 months ago

Hej @fgmacedo !

Thanks for the fast reply and explanation! I really appreciate all the work going into python-statemachine and problems like that happen, of course! :)

It is obviously your call to make, but since you asked, here are my 2 cents :

If you go forward with the latter change, I would suggest to highlight this in the change log -- it wasn't obvious to me where this change came from.

Just a thought: would introducing current_state.enum complicate the API more than it is worth?

fgmacedo commented 2 months ago

Makes sense, thanks for your arguments. I will revert both changes, and make a path towards migrating to the new behavior as default on the next major version (as it sounds like the expected default for me now).