Skip to content

Expanded event ids travel inside a space-separated string, so error_ never worked as a method call #654

Description

@fgmacedo

_expand_event_id turns error_foo into the string "error_foo error.foo", meaning "one event
with two spellings". But a space-separated id is already a public format meaning "this
transition responds to N distinct events":

green.to(yellow, event=Event("cycle slowdown", name="Will be ignored"))
assert sm.slowdown.name == "Slowdown"

tests/test_events.py::TestExplicitEvent::test_multiple_ids_from_the_same_event_will_be_converted_to_multiple_events
pins that behaviour, and the argument is literally named "Will be ignored".

Two meanings on one carrier, wanting opposite handling. By the time Event.split runs, the
string is just a string and cannot tell them apart, so the fix does not belong there.

Measured on develop, with no Event involved at all:

class Bare(StateChart):
    a = State(initial=True)
    b = State(final=True)
    error_foo = a.to(b)

Bare.events           # ['error_foo error.foo']  -- one event with a glued id
Bare.error_foo        # TransitionList -- never became an event
sm.error_foo()        # TypeError: TransitionList only supports the decorator syntax
sm.send("error.foo")  # works

With the Event class the attribute exists but the call is a silent no-op, because it sends an
id that matches no transition:

class T(StateChart):
    a = State(initial=True)
    b = State(final=True)
    error_foo = Event(a.to(b), name="Boom")

T.events              # [('error_foo error.foo', 'Boom')]
sm = T(); sm.error_foo()
sm.configuration_values  # {'a'} -- nothing happened

So the error_ convention documented in AGENTS.md has only ever worked through send(), never
through the method call form. The transitions themselves are fine: they carry the two correct
ids. What is wrong is the registration, which keeps the glued id as a single event in
cls._events and binds it as the class attribute.

done_state_ and done_invoke_ expand the same way and have the same problem.

The fix is to make _expand_event_id return the ids as a list and have the callers register N
events, instead of smuggling a list inside a string. That also removes the limitation that a
nested Event(a.to(b), name=..., delay=...) with an error_ prefix drops its arguments, which
#645 documents and pins in
tests/test_statechart_compound.py::TestEventClassInsideCompound::test_expanded_id_drops_the_declared_arguments.

When fixing: that test asserts today's behaviour and must be inverted; drop the matching
paragraph from docs/events.md and from the nested-Event section of docs/releases/3.2.2.md,
and add an entry for this fix to the open release notes.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions