Event(..., delay=...) and Event(..., internal=...) are accepted at declaration time and then
discarded, so the resulting event has delay=0 and internal=False.
Reproduction
from statemachine import Event, State, StateChart
class Beacon(StateChart):
dark = State(initial=True)
lit = State(final=True)
light = Event(dark.to(lit), delay=500, internal=True)
print(Beacon.light.delay) # 0 , expected 500
print(Beacon.light.internal) # False , expected True
sm.light() fires immediately instead of after 500 ms, and goes to the external queue instead of
the internal one.
Cause
StateMachineMetaclass.add_from_attributes rebuilds the declared event to give it the real id,
and the new instance is constructed without the two fields:
new_event = Event(
transitions=value._transitions,
id=event_id,
name=value.name,
)
delay and internal are declared on Event and honored everywhere downstream
(Event.put reads self.internal, the delayed-event machinery reads delay); they are simply
lost in this one rebuild.
Why the existing test does not catch it
tests/test_statechart_delayed.py::TestDelayedEvents::test_delayed_event_on_event_definition
declares light = Event(dark.to(lit), delay=50) but then triggers the machine with an event
object it builds itself:
BoundEvent(id="light", delay=50, _sm=sm)
so it never reads the declared BeaconsOfGondor.light and passes regardless of what the
metaclass did with delay. A regression test for this issue should assert on the declared
event (SM.light.delay) and drive the machine through it.
Scope
Reproduced on the current develop. Affects the top-level declaration form; the nested
(State.Compound) form drops the two fields as well, for the same reason.
Event(..., delay=...)andEvent(..., internal=...)are accepted at declaration time and thendiscarded, so the resulting event has
delay=0andinternal=False.Reproduction
sm.light()fires immediately instead of after 500 ms, and goes to the external queue instead ofthe internal one.
Cause
StateMachineMetaclass.add_from_attributesrebuilds the declared event to give it the real id,and the new instance is constructed without the two fields:
delayandinternalare declared onEventand honored everywhere downstream(
Event.putreadsself.internal, the delayed-event machinery readsdelay); they are simplylost in this one rebuild.
Why the existing test does not catch it
tests/test_statechart_delayed.py::TestDelayedEvents::test_delayed_event_on_event_definitiondeclares
light = Event(dark.to(lit), delay=50)but then triggers the machine with an eventobject it builds itself:
so it never reads the declared
BeaconsOfGondor.lightand passes regardless of what themetaclass did with
delay. A regression test for this issue should assert on the declaredevent (
SM.light.delay) and drive the machine through it.Scope
Reproduced on the current
develop. Affects the top-level declaration form; the nested(
State.Compound) form drops the two fields as well, for the same reason.