spyce
home
license
community
download
examples
resources
wishlist
contrib (@sf)
documentation
intro
lang
runtime
modules
tags
install
exits
sourceforge
statistics
freshmeat

Documentation - Modules
[[ Spyce ]]
Python Server Pages
by Rimon Barr

Prev: 4.14 - Compress Up: 4 - Modules Next: 4.16 - TOC

4.15. Automaton

The current release of the automaton module is preliminary and is still in flux. The automaton module provides support for state machine-based application design, which is often useful when designing websites with application flows. The state machine is a directed, labelled graph. It has states (nodes with names), and transitions (directed edges with names). One of the states is defined to be a begin state for the machine. Every state has a send function, a receive function and a set of outgoing edges.

The basic idea behind the operation of the automaton module is as follows: The application is at some state when a request comes in. The receive function for that state is invoked to process the input from the browser. Based on this input the receive function returns some edge label, which takes the application from the current state to its new state. The send function of this new state is invoked to emit the appropriate application page. The data that returns from this page will be processed by the corresponding receive function, and so on. All you need to remember between requests is which state the application is in, which can be done via get or post, or via cookies using the cookie module. Better yet (to keep application states private and on the server for security reasons), one can store the state label in the session using the session module.

A state machine can be defined programmatically using the following functions:

  • state( name, send, recv ):
    Add a new state labelled name with associated send and recv functions.
  • transition( state1, name, state2 ):
    Add a new edge labelled name from state1 to state2. There is always a self-referencing edge with the label None, but this can be overidden.
  • begin( state ):
    Define a given state to be the begin state.
  • define( sm, begin ):
    Define an entire automaton sm all at once, where sm is a hashtable. The keys are the states and the values are triplets with a send function, a receive function and an edge hashtable. The edge hashtable has names of the edges as keys and the target states as values. The begin state is given.

To step through the state machine transitions, you call:

  • step( [state] ):
    If state is specified, then call the receive function of that state. The receive function returns an edge label, which points to the new state. If no state is specified, just set the new state to the begin state of the automaton. Then, call the send function of the new state. Note that the send function is responsible for encoding its own state label, for use on the subsequent client request.

Future releases of this module may add support for different types of send and receive handlers. For example, it is probably useful to be able to internally redirect to various Spyce pages for send processing, rather than inline functions. It may also be possible to pass information among the different functions, which could be useful, for example, in handling error messages during form processing. It may also be useful to define a sequence of states, where previous and next are implicit edges.

The following examples, shows the above in action:

examples/automaton.spy
[[.import name=automaton]]
[[.import name=session args="'session_dir', '/tmp', auto=10"]]
[[\
if not session.auto: session.auto = {
  'name': '',
}

step1send = [[spy:
  <html><body>
    <form action=automaton.spy method=post>
      <table border=0>
        <tr><td colspan=2>Name: <input type=text size=20></td></tr>
        <tr>
          <input type=hidden name=state value=step1>
          <td></td>
          <td align=right><input type=submit name=dir value="next"></td>
        </tr>
      </table>
    </form>
  </body></html>]]
def step1recv():
  if request.post1('dir') == 'next': return 'next'

step2send = [[spy:
  <html><body>
    <form action=automaton.spy method=post>
      <table border=0>
        <tr><td colspan=2>Age: <input type=text size=20></td></tr>
        <tr>
          <input type=hidden name=state value=step2>
          <td align=left><input type=submit name=dir value="prev"></td>
          <td align=right><input type=submit name=dir value="next"></td>
        </tr>
      </table>
    </form>
  </body></html>]]
def step2recv():
  if request.post1('dir') == 'prev': return 'prev'
  if request.post1('dir') == 'next': return 'next'

step3send = [[spy:
  <html><body>
    <form action=automaton.spy method=post>
      step3
      <input type=hidden name=state value=step3>
      <input type=submit name=dir value=prev>
      <input type=submit name=dir value=next>
    </form>
  </body></html>]]
def step3recv():
  if request.post1('dir') == 'prev': return 'prev'
  if request.post1('dir') == 'next': return 'next'

step4send = [[spy:
  <html><body>
    Thanks.
  </body></html>]]
def step4recv():
  pass

automaton.define({
  'step1': ( step1send, step1recv, {
    'next': 'step2',
  }),
  'step2': ( step2send, step2recv, {
    'next': 'step3',
    'prev': 'step1',
  }),
  'step3': ( step3send, step3recv, {
    'next': 'step4',
    'prev': 'step2',
  }),
  'step4': ( step4send, step4recv, {
  }),
}, 'step1')

state = request.post1('state')
automaton.step(state)
]]

[[--
spyce file
spyce inline
function or method reference
inline code
--]]
Run this code.
(requires Spyce-enabled web server)


Prev: 4.14 - Compress Up: 4 - Modules Next: 4.16 - TOC


© 2002-07 Rimon Barr
email: rimon@acm.org
Spyce Powered SourceForge Logo [[ Spyce ]]
Python Server Pages
version 1.3.13