diff --git a/docs/releases/3.1.0.md b/docs/releases/3.1.0.md index 6748db51..f5334276 100644 --- a/docs/releases/3.1.0.md +++ b/docs/releases/3.1.0.md @@ -170,4 +170,14 @@ machine instance concurrently. This is now documented in the The docstring also now includes a `deprecated` directive for Sphinx autodoc. [#604](https://github.com/fgmacedo/python-statemachine/issues/604). +- `Configuration.add()`/`discard()` now write through the model setter, ensuring state + changes are persisted correctly on domain models (e.g., Django models with custom setters). + Previously the configuration was updated in-place without notifying the model layer. + [#596](https://github.com/fgmacedo/python-statemachine/pull/596). + +- `States.from_enum()` now works correctly inside compound and parallel states. Previously + the states were silently not collected when used as a nested state declaration. + [#607](https://github.com/fgmacedo/python-statemachine/pull/607), + fixes [#606](https://github.com/fgmacedo/python-statemachine/issues/606). + ## Misc in 3.1.0 diff --git a/statemachine/statemachine.py b/statemachine/statemachine.py index 1f9b12f9..ca36f0c1 100644 --- a/statemachine/statemachine.py +++ b/statemachine/statemachine.py @@ -55,9 +55,13 @@ class StateChart(Generic[TModel], metaclass=StateMachineMetaclass): start_value: An optional start state value if there's no current state assigned on the :ref:`domain models`. Default: ``None``. - listeners: An optional list of objects that provies attributes to be used as callbacks. + listeners: An optional list of objects that provides attributes to be used as callbacks. See :ref:`listeners` for more details. + **kwargs: Additional keyword arguments available for dependency injection into + callbacks. These are passed to class listener ``setup()`` methods and to the + initial activation callbacks (e.g. ``on_enter_``). + """ TransitionNotAllowed = TransitionNotAllowed @@ -145,9 +149,13 @@ def __init__( **kwargs: Any, ): self.model: TModel = model if model is not None else Model() # type: ignore[assignment] - self.history_values: Dict[ - str, List[State] - ] = {} # Mapping of compound states to last active state(s). + """The external model object that holds domain state, or an internal + :class:`Model` instance when none is provided. See :ref:`domain models`.""" + + self.history_values: Dict[str, List[State]] = {} + """Mapping from compound state IDs to the list of states that were active + the last time that compound state was exited. Used by history pseudo-states + to restore previous configurations.""" self.state_field = state_field self.start_configuration_values = ( [start_value] if start_value is not None else list(self.start_configuration_values) @@ -416,6 +424,7 @@ def current_state(self, value): @property def events(self) -> "List[Event]": + """List of all :ref:`Event` instances declared on this state machine.""" return [getattr(self, event) for event in self.__class__._events] @property