glyph / automat

Self-service finite-state machines for the programmer on the go.
MIT License
591 stars 65 forks source link

mypy considerations (should this have mypy plugin?) #127

Closed moshez closed 3 years ago

moshez commented 4 years ago
import attr
import automat
from typing import Optional

@attr.s(auto_attribs=True)
class MaybeValue:
    _machine = automat.MethodicalMachine()
    _value: Optional[float] = attr.ib(default=None)

    @_machine.input()
    def set_value(self, value: float) -> None:
        "The value has been measured"

    @_machine.input()
    def _get_value(self) -> float:
        "Return the value if it has been measured"

    def __float__(self):
        return self._get_value()

    @_machine.output()
    def _set_value_when_unset(self, value: float) -> None:
        self._value = value

    @_machine.output()
    def _get_value_when_set(self) -> float:
        return self._value

    @_machine.state()
    def value_is_set(self):
        "The value is set"

    @_machine.state(initial=True)
    def value_is_unset(self):
        "The value is set"

    value_is_unset.upon(
        set_value,
        enter=value_is_set,
        outputs=[_set_value_when_unset],
        collector=lambda x: None,
    )
    value_is_set.upon(
        _get_value,
        enter=value_is_set,
        outputs=[_get_value_when_set],
        collector=lambda x: next(iter(x)),
    )
$ mypy --ignore-missing-imports maybe.py 
maybe.py:27: error: Incompatible return value type (got "Optional[float]", expected "float")
Found 1 error in 1 file (checked 1 source file)
moshez commented 4 years ago

The right solution is probably

assert

I'll submit a docs PR

glyph commented 3 years ago

I'll submit a docs PR

Sounds good!

glyph commented 3 years ago

I have been thinking that a mypy-friendlier approach might involve one class per state, so that you can have an _value: Optional[float] in your earlier states and _value: float later, and then somehow enforce the relationship between them. Not quite sure how to make that work though.