pypercard.state_machine

PyperCard is a simple HyperCard inspired framework for PyScript for building graphical apps in Python.

Based on original pre-COVID work by Nicholas H.Tollervey.

Copyright (c) 2023 Anaconda Inc.

Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Module Contents

Classes

Machine

A simple Finite State Machine (FSM) implementation.

State

A state in a state machine :)

Transition

A possible transition from one state to another.

Acceptor

Acceptors determine whether the received input is allowed.

API

class pypercard.state_machine.Machine(model=None, states=None, transitions=None, initial_state_name='', history=None, context=None)

A simple Finite State Machine (FSM) implementation.

Initialization

Constructor.

property current_state

Return the current state.

property is_done

Return True iff there are no transitions out of the current state.

The machine inherently has no notion of success or failure - it only knows whether there is any possible way out of the current state. The state machine writer can add meaning to the ‘done’ states with naming conventions and/or state subclasses etc.

add_state(state, transitions=None)

Add a state and (optionally) its transitions to the machine.

goto(state_name, run_hooks=True)

Goto a specific state.

If run_hooks is True (the default), then this calls any on exit hooks on the current state and any on enter hooks on the target state.

next(input_)

Attempt to transition from the current state with the given input.

Return either:-

  1. the name of the state we transitioned to.

  2. an empty string if either no transition accepted the input, or one did accept it but chose to stay on the current state.

history_pop_previous()

Return the name of the previous state in the history.

This pops the current and previous states from the history ready for the transition to the previous state (where the previous state will get added to the history).

TODO: This only works if this method is called from a transition…

start(state_name=None)

Start the machine.

pprint(indent='')

Pretty-print the object.

_do_transition(transition, input_)

Do the specified transition!

_enter_state(state)

Enter the specified state.

_exit_state(state)

Exit the specified state.

class pypercard.state_machine.State(name, on_enter=None, on_exit=None)

A state in a state machine :)

Initialization

Constructor.

pprint(indent='')

Pretty-print the object.

call_on_enter_hooks(machine)

Call all on_enter hooks.

call_on_exit_hooks(machine)

Call all on_exit hooks.

class pypercard.state_machine.Transition(source, acceptor, target=None, context_object_name='', before=None, after=None)

A possible transition from one state to another.

Initialization

Constructor.

If ‘source’ is the string ‘*’ then it is a possible transition from any state.

pprint(indent='')

Pretty-print the object.

accepts(machine, input_)

Return True iff the specified input is accepted.

By default, this simply calls the transition’s acceptor.

get_context_object(machine, input_)

Return the object to add to the machine’s context iff this transition succeeds.

By default, we delegate this to the acceptor since state machine builders usually build acceptors, not transitions.

get_target(machine, input_)

Get the target state name.

call_before_hooks(machine, input_)

Call any before hooks.

call_after_hooks(machine, input_)

Call any before hooks.

class pypercard.state_machine.Acceptor(fn=None)

Acceptors determine whether the received input is allowed.

Initialization

Constructor.

__str__()

Pretty-print the object.

accepts(machine, transition, input_)

Return True iff the specified input is accepted.

If no function ‘fn’ is specified this defaults to returning true (i.e. it accepts everything :) ).

get_context_object(machine, transition, input_)

Return the object to add to the machine’s context iff this acceptor accepts!