Skip to content

Commit 9697dea

Browse files
authored
fix: use *args/**kwargs in AddCallbacksMixin.__call__ to silence Pyright (#511) (#560)
Pyright/Pylance cannot follow the metaclass transformation from TransitionList to Event, so it sees sm.event() as calling TransitionList.__call__(self, f) and reports a missing argument. Change the signature to *args, **kwargs with runtime validation, which preserves the decorator syntax while silencing the false positive. Closes #511
1 parent 1f6013c commit 9697dea

2 files changed

Lines changed: 23 additions & 2 deletions

File tree

statemachine/transition_mixin.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
11
from typing import Callable
22

33
from .callbacks import CallbackGroup
4+
from .i18n import _
45

56

67
class AddCallbacksMixin:
78
def _add_callback(self, callback, grouper: CallbackGroup, is_event=False, **kwargs):
89
raise NotImplementedError
910

10-
def __call__(self, f):
11-
return self._add_callback(f, CallbackGroup.ON, is_event=True)
11+
def __call__(self, *args, **kwargs):
12+
if len(args) == 1 and callable(args[0]) and not kwargs:
13+
return self._add_callback(args[0], CallbackGroup.ON, is_event=True)
14+
raise TypeError(
15+
_("{} only supports the decorator syntax to register callbacks.").format(
16+
type(self).__name__
17+
)
18+
)
1219

1320
def before(self, f: Callable):
1421
"""Adds a ``before`` :ref:`transition actions` callback to every :ref:`transition` in the

tests/test_transitions.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,20 @@ def test_transition_call_can_only_be_used_as_decorator():
7171
transition("not a callable")
7272

7373

74+
def test_transition_list_call_can_only_be_used_as_decorator():
75+
source, dest = State("Source"), State("Destination")
76+
transition_list = source.to(dest)
77+
78+
with pytest.raises(TypeError, match="TransitionList"):
79+
transition_list("not a callable")
80+
81+
with pytest.raises(TypeError, match="TransitionList"):
82+
transition_list()
83+
84+
with pytest.raises(TypeError, match="TransitionList"):
85+
transition_list(42, extra="kwarg")
86+
87+
7488
@pytest.fixture(params=["bounded", "unbounded"])
7589
def transition_callback_machine(request):
7690
if request.param == "bounded":

0 commit comments

Comments
 (0)