Pycider Module
Deciders
- class pycider.deciders.AdaptDecider(fci: Callable[[C], CO | None], fei: Callable[[E], EO | None], feo: Callable[[EO], E], fsi: Callable[[S], SO], decider: Decider[EO, CO, SO])
A decider that translates from one set of events/commands/states to another.
The AdaptDecider takes in a decider and makes a translation layer between the commands, events, and state internally and a new resulting type of command, event, and map. The purpose of this is to allow a Decider of one type to interact with a Decider of another type through translation.
- build() BaseDecider[E, C, S, SO]
Create an adapted decider.
- Returns:
A Decider with its functions wrapped by translation functions.
- class pycider.deciders.BaseDecider
This decider allows for a different input and output state type.
BaseDecider should only be used when the input and output state type should be different. Otherwise use Decider.
- abstract decide(command: C, state: SI) Iterator[E]
Return a set of events from a command and state.
- Parameters
command: Action to be performed state: State of the current decider
- Returns
An iterator of events resulting from the command.
- abstract evolve(state: SI, event: E) SO
Returns an updated state based on the current event.
- Paramters
state: State of the current decider event: Event
- Returns
An updated state
- abstract initial_state() SO
Starting state for a decider.
- Returns
The base state a decider
- class pycider.deciders.ComposeDecider(left_dx: Decider[EX, CX, SX], right_dy: Decider[EY, CY, SY])
Combine two deciders into a single decider.
This creates a Decider that is combined into a Left and Right side. There is a type for Left or Right in pycider.types. To execute commands after composing two targets you need to pass in commands in the following shape:
Left(C) or Right(C) where C is the command to be executed. This code will make sure the proper decider receives the command.
- class pycider.deciders.Decider
This is a BaseDecider where the input and output state are the same.
This is the Decider that should preferably be used unless you explcitly need control over a different input and output type for the state.
- class pycider.deciders.ManyDecider(identifier_type: Type[I])
Manage many instances of the same Decider using a Identifier.
This Decider is useful if you have multiple of the same Decider that can be differentiated by a unique element. For example a list of transaction Deciders which all have a unique transaction key, or a list of clients that all have a unique client id. Using this you can execute commands by executing with a many decider commands in a tuple of (I, C) where I is the unique identifier and C is the desired command to be executed.
- class pycider.deciders.Map2Decider(f: Callable[[SX, SY], S], dx: BaseDecider[E, C, SI, SX], dy: BaseDecider[E, C, SI, SY])
- class pycider.deciders.MapDecider(f: Callable[[SA], SB], d: BaseDecider[E, C, SI, SA])
Map allows the translation of a Decider’s state into a different state.
- build() BaseDecider[E, C, SI, SB]
Build a whose state is represented as the function f(state).
- Returns:
A new Decider where evolve and initial_state both return f(state_operation).
Processes
- class pycider.processes.IProcess
Prototype for Process implementations.
All Processes should be implemented using this prototype.
- abstract evolve(state: S, event: E) S
Returns an updated state based on the current event.
- Paramters
state: State of the current process event: Event generated from commands procesed
- Returns
An updated state.
- abstract initial_state() S
Returns the starting state for a process.
- Returns
A state representing the start of a process.
- abstract is_terminal(state: S) bool
Returns if a process’s state is terminal.
- Parameters
state: State of the current process
- Returns
A boolean indicating if a process has run till completion.
- class pycider.processes.ProcessAdapt(select_event: Callable[[EI], EO | None], convert_command: Callable[[CO], CI], p: IProcess[EO, CO, S])
Adapt process Commands / Events into new output Commands and Events.
- class pycider.processes.ProcessCombineWithDecider(proc: IProcess[E, C, PS], decider: Decider[E, C, DS])
Combine a Processor with a Decider together.
- build() Decider[E, C, tuple[DS, PS]]
Combine a Process and a Decider into a single Decider.
- Results:
A single Decider.
Note: This function’s generated decide function deviates from the model used by the original material. decide in this code takes a command and state tuple.
For each command issued this code will do the following:
create a command list commands initialized as [commands]
create a event list events initialized as []
run decider.decide on a popped entry from commands
append the results to events array
create a copy of state and run decider.evolve on it
run process.react to generate new commands appended to the commands list.
run process.evolve on each new event.
loop back to 2 with remaining commands and the copy of decider’s state.
one commands is empty, return all events collected during the above.
The state of neither process nor decider is actually changed by decide. You will still need to call evolve to reach the final end states.
Utilities
- class pycider.utils.InMemory(decider: Decider[E, C, S])
Runs a decider in memory, performing decide and evolving the state.
- command(command: C) Iterator[E]
Decide over a command and evolves the internal state.
- Parameters:
command – Command to decide over
- Returns:
An iterator over the events.
- state: S
State of the decider