Skip to content

validators in a dict/JSON transition definition is silently dropped #628

@csentis

Description

@csentis

validators in a dict/JSON transition definition is silently dropped

Summary

create_machine_class_from_definition (the statemachine.io dict adapter) threads cond, unless, on, before, and after from each transition definition into Transition(...), but not validators. As a result, a validators entry in a dict- or JSON-defined machine is silently ignored — it never reaches the Transition, so it never runs at send().

Separately, the TransitionDict TypedDict declares validators: bool, which is the wrong type — it should be the same callback-spec union as cond/unless (str | ActionProtocol | Sequence[...]).

This matters because, per the docs, validators are the intended channel for explicit transition rejection with a reason (raise to abort), distinct from cond/unless (silent disallow). Users building machines from dict/JSON definitions currently have no way to attach that channel.

Reproduction

from statemachine.io import create_machine_class_from_definition

class Rejected(Exception):
    pass

def reject(*args, **kwargs):
    raise Rejected("not allowed")

SM = create_machine_class_from_definition(
    "M",
    states={
        "s1": {"initial": True, "on": {"go": [{"target": "s2", "validators": reject}]}},
        "s2": {"final": True},
    },
)
sm = SM()
sm.send("go")          # expected: raises Rejected; actual: succeeds, lands in s2
assert sm.current_state.id == "s1"

Expected

The validators callbacks supplied in the definition are materialized onto the Transition (which already accepts validators= in its constructor) and run at send(), exactly like cond/unless/on/before/after.

Environment

  • python-statemachine main (also reproduces on 3.1.2)
  • The fix is a one-line addition to transition_kwargs plus a TypedDict type correction.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions