automaton.py :  » Web-Frameworks » Spyce » spyce-2.1 » contrib » modules » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Web Frameworks » Spyce 
Spyce » spyce 2.1 » contrib » modules » automaton.py
##################################################
# SPYCE - Python-based HTML Scripting
# Copyright (c) 2002 Rimon Barr.
#
# Refer to spyce.py
# CVS: $Id: automaton.py 860 2006-04-30 01:18:25Z ellisj $
##################################################

from spyceModule import spyceModule

__doc__ = '''
[[toc.n('Automaton', 'mod_automaton')]]

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 thebrowser.Basedonthis import 
input the receive function returns some edge label, which takes the
application from thecurrentstatetoitsnewstate.Thesendfunctionofthis import 
new state is invoked to emit the appropriate application page. The data that
returns from thispagewillbeprocessedbythecorrespondingreceive import 
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 labeled "name" with associated "send" and "recv"
    functions.

  transition ( state1, name, state2 )
    Add a new edge labelled "name" from toThere import 
    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.

See automaton.spy for example usage.
'''

SEND = 0
RECV = 1
EDGES = 2

class automaton(spyceModule):
  def start(self):
    "Initialise an empty automaton"
    self.clear()
  def clear(self):
    self._nodes = {}
    self._edges = {}
  # defining the automaton
  def state(self, name, send, recv):
    "Add a new automaton state"
    self._nodes[name] = send, recv
    self.transition(name, None, name)
  def transition(self, state1, edge, state2):
    "Add a new automaton transition"
    if not self._nodes.has_key(state1):
      raise 'state %s does not exist' % state1
    if not self._nodes.has_key(state2):
      raise 'state %s does not exist' % state2
    self._edges[(state1, edge)] = state2
  node=state
  edge=transition
  def begin(self, name):
    if not self._nodes.has_key(name):
      raise 'state %s does not exist' % name
    self._begin = name
  def define(self, sm, start):
    self.clear()
    for s1 in sm.keys():
      self.node(s1, sm[s1][SEND], sm[s1][RECV])
    for s1 in sm.keys():
      for e in sm[s1][EDGES].keys():
        self.edge(s1, e, sm[s1][EDGES][e])
    self.begin(start)

  # running the automaton
  def step(self, state=None):
    """Run the automaton one step: recv (old state), transition, 
    send (new state)"""
    if state==None:
      state = self._begin
    else:
      try: _, recv = self._nodes[state]
      except: raise 'invalid state: %s' % state
      edge = recv()
      try: state = self._edges[(state, edge)]
      except: raise 'invalid transition: %s,%s' % (state, edge)
    try: send, _ = self._nodes[state]
    except: raise 'invalid state: %s' % state
    send()


# rimtodo: cached state-machines

www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.