transitions
transitions copied to clipboard
Is this a bug?
This code works fine:
from transitions import EventData, Machine
import time
import random
import datetime as dt
from rich import print
class Device:
state: str
_CURRENT_THRESHOLD = 3
def __init__(self, name: str):
self._name: str = name
self._state: str = "unknown"
self._state_started: dt.datetime = dt.datetime.now()
@property
def name(self) -> str:
return self._name
@property
def state_started(self) -> dt.datetime:
return self._state_started
# def new_current(self, current: float) -> bool:
# raise RuntimeError("Should be overridden!")
# def trigger(self, trigger_name: str) -> bool:
# raise RuntimeError("Should be overridden!")
def is_connected(self, event: EventData) -> bool:
if event.kwargs["current"] > self._CURRENT_THRESHOLD:
return True
else:
return False
def is_disconnected(self, event: EventData) -> bool:
return not self.is_connected(event)
def update_state_started(self, event):
self._state_started = dt.datetime.now()
def secs_in_state(self) -> float:
return (dt.datetime.now() - self._state_started).total_seconds()
sm = Machine(
model=None,
states=["unknown", "connected", "disconnected"],
transitions=[
{
"trigger": "new_current",
"source": ["unknown", "disconnected"],
"dest": "connected",
"conditions": ["is_connected"],
},
{
"trigger": "new_current",
"source": ["unknown", "connected"],
"dest": "disconnected",
"conditions": ["is_disconnected"],
},
],
after_state_change=["update_state_started"],
send_event=True,
# model_override=True,
initial="unknown",
)
svk1 = Device("svk1")
svk2 = Device("svk2")
models = [svk1, svk2]
for model in models:
sm.add_model(model)
print("\nInitial state:")
for model in models:
print(model.name, model.state, model.state_started)
svk1.new_current(current=0)
svk2.new_current(current=5)
print("\nFirst state:")
for model in models:
print(model.name, model.state, model.state_started)
max_current = 5
print("\nOther states:")
for current in range(max_current):
time.sleep(random.random())
svk1_current = current
svk2_current = max_current - current
svk1.new_current(current=svk1_current)
svk2.new_current(current=svk2_current)
print(
f"svk1: current={svk1_current}, state={svk1.state:>12}, started={svk1.state_started}, "
f"svk2: current={svk2_current}, state={svk2.state:>12}, started={svk2.state_started}"
)
but mypy complains:
$ mypy src/state_machine/zoran/check_mypy.py
src/state_machine/zoran/check_mypy.py:86: error: "Device" has no attribute "new_current" [attr-defined]
src/state_machine/zoran/check_mypy.py:87: error: "Device" has no attribute "new_current" [attr-defined]
src/state_machine/zoran/check_mypy.py:100: error: "Device" has no attribute "new_current" [attr-defined]
src/state_machine/zoran/check_mypy.py:101: error: "Device" has no attribute "new_current" [attr-defined]
Found 4 errors in 1 file (checked 1 source file)
To mitigate it I thought that I just have to add commented lines (in essence use model_override=True, and prepare some methods) and that will help. But If I uncomment the lines, when I run the code I get:
Exception has occurred: TypeError
Machine.is_state() takes 3 positional arguments but 4 were given
File "/home/zoran/state_machine/src/state_machine/zoran/check_mypy.py", line 86, in <module>
svk1.new_current(current=0)
TypeError: Machine.is_state() takes 3 positional arguments but 4 were given
I used procedure described at https://github.com/pytransitions/transitions?tab=readme-ov-file#-typing-support, but maybe I have missed something.
I am also not sure if I need def trigger(self, trigger_name: str) -> bool:
in my model or def new_current(self, current: float) -> bool:
is enough.
Expected behavior I expect mypy not to show any errors if lines are uncommented and to be able to run the code with no errors.
Additional context I am using: Python 3.11.9 mypy 1.11.2 (compiled: yes) transitions 0.9.2