Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is this a bug? #689

Open
zljubisic opened this issue Sep 14, 2024 · 0 comments
Open

Is this a bug? #689

zljubisic opened this issue Sep 14, 2024 · 0 comments
Assignees
Labels

Comments

@zljubisic
Copy link

zljubisic commented Sep 14, 2024

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants