From 60109dea12383f8ea2f6d4251952ccc3859feec5 Mon Sep 17 00:00:00 2001 From: erick Date: Wed, 28 Oct 2009 02:03:51 +0000 Subject: TutorialADT: First pass for modifications following Simon review, still has some changes to do --- (limited to 'tutorius/tutorial.py') diff --git a/tutorius/tutorial.py b/tutorius/tutorial.py index 8970d4f..6a6e089 100644 --- a/tutorius/tutorial.py +++ b/tutorius/tutorial.py @@ -1,3 +1,21 @@ +# Copyright (C) 2009, Tutorius.org +# Copyright (C) 2009, Erick Lavoie +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +#TODO: On update, only properties should be passed as arguments for State.update and Tutorial.update class Tutorial(object): """ This class replaces the previous Tutorial class and @@ -5,19 +23,21 @@ class Tutorial(object): of a tutorial as a state machine """ - _INIT = "INIT" - _END = "END" - _INITIAL_TRANSITION_NAME = _INIT + "/transition0" - _AUTOMATIC_TRANSITION_EVENT = "automatic" + INIT = "INIT" + END = "END" + INITIAL_TRANSITION_NAME = INIT + "/transition0" + AUTOMATIC_TRANSITION_EVENT = "automatic" + + _NAME_SEPARATOR = "/" def __init__(self, name, state_dict=None): """ The constructor for the Tutorial. By default, the tutorial contains only an initial state and an end state. The initial state doesn't contain any action but it contains - a single automatic transition - between the initial state and the end state - . + a single automatic transition + between the initial state and the end state + . The end state doesn't contain any action nor transition. @@ -38,20 +58,20 @@ class Tutorial(object): # http://www.python.org/doc/essays/graphs if not state_dict: self._state_dict = \ - {Tutorial._INIT:State(name=Tutorial._INIT),\ - Tutorial._END:State(name=Tutorial._END)} + {Tutorial.INIT:State(name=Tutorial.INIT),\ + Tutorial.END:State(name=Tutorial.END)} - self.add_transition(Tutorial._INIT, \ - (Tutorial._AUTOMATIC_TRANSITION_EVENT, Tutorial._END)) + self.add_transition(Tutorial.INIT, \ + (Tutorial.AUTOMATIC_TRANSITION_EVENT, Tutorial.END)) else: raise NotImplementedError("Tutorial: Initilization from a dictionary is not supported yet") # Minimally check for the presence of an INIT and an END # state - if not self._state_dict.has_key(Tutorial._INIT): + if not self._state_dict.has_key(Tutorial.INIT): raise Exception("No INIT state found in state_dict") - if not self._state_dict.has_key(Tutorial._END): + if not self._state_dict.has_key(Tutorial.END): raise Exception("No END state found in state_dict") # TODO: Validate once validation is working @@ -103,10 +123,10 @@ class Tutorial(object): @param state_name The name of the state to add an action to @param action The action to be added @return unique name for this action - @raise NameError if state_name doesn't exist + @raise LookupError if state_name doesn't exist """ if not self._state_dict.has_key(state_name): - raise NameError("Tutorial: state <" + state_name +\ + raise LookupError("Tutorial: state <" + state_name +\ "> is not defined") self._validate_action(action) @@ -125,11 +145,11 @@ class Tutorial(object): @param state_name The name of the state to add a transition to @param transition The transition to be added @return unique name for this action - @raise NameError if state_name doesn't exist + @raise LookupError if state_name doesn't exist @raise TransitionAlreadyExists """ if not self._state_dict.has_key(state_name): - raise NameError("Tutorial: state <" + state_name +\ + raise LookupError("Tutorial: state <" + state_name +\ "> is not defined") self._validate_transition(transition) @@ -146,12 +166,12 @@ class Tutorial(object): @param action_name The name of the action to replace @param new_action The action that will replace the old one @return The replaced action - @raise NameError if action_name doesn't exist + @raise LookupError if action_name doesn't exist """ - state_name = action_name[:action_name.find("/")] + state_name = action_name[:action_name.find(Tutorial._NAME_SEPARATOR)] if not self._state_dict.has_key(state_name): - raise NameError("Tutorial: action <" + action_name +\ + raise LookupError("Tutorial: action <" + action_name +\ "> is not defined") self._validate_action(new_action) @@ -167,12 +187,12 @@ class Tutorial(object): @param transition_name The name of the transition to replace @param new_transition The transition that will replace the old one @return The replaced transition - @raise NameError if transition_name doesn't exist + @raise LookupError if transition_name doesn't exist """ - state_name = transition_name[:transition_name.find("/")] + state_name = transition_name[:transition_name.find(Tutorial._NAME_SEPARATOR)] if not self._state_dict.has_key(state_name): - raise NameError("Tutorial: transition <" + transition_name +\ + raise LookupError("Tutorial: transition <" + transition_name +\ "> is not defined") self._validate_transition(new_transition) @@ -185,12 +205,12 @@ class Tutorial(object): @param action_name The name of the action to be deleted @return the action that has been deleted - @raise NameError if transition_name doesn't exist + @raise LookupError if transition_name doesn't exist """ - state_name = action_name[:action_name.find("/")] + state_name = action_name[:action_name.find(Tutorial._NAME_SEPARATOR)] if not self._state_dict.has_key(state_name): - raise NameError("Tutorial: action <" + action_name +\ + raise LookupError("Tutorial: action <" + action_name +\ "> is not defined") return self._state_dict[state_name].delete_action(action_name) @@ -201,12 +221,12 @@ class Tutorial(object): @param transition_name The name of the transition to be deleted @return the transition that has been deleted - @raise NameError if transition_name doesn't exist + @raise LookupError if transition_name doesn't exist """ - state_name = transition_name[:transition_name.find("/")] + state_name = transition_name[:transition_name.find(Tutorial._NAME_SEPARATOR)] if not self._state_dict.has_key(state_name): - raise NameError("Tutorial: transition <" + transition_name +\ + raise LookupError("Tutorial: transition <" + transition_name +\ "> is not defined") return self._state_dict[state_name].delete_transition(transition_name) @@ -223,14 +243,13 @@ class Tutorial(object): @param state_name The name of the state to remove @return The deleted state @raise StateDeletionError when trying to delete the INIT or the END state - @raise NameError if state_name doesn't exist + @raise LookupError if state_name doesn't exist """ - if state_name == Tutorial._INIT or state_name == Tutorial._END: + if state_name == Tutorial.INIT or state_name == Tutorial.END: raise StateDeletionError("<" + state_name + "> cannot be deleted") - if not self._state_dict.has_key(state_name): - raise NameError("Tutorial: state <" + transition_name +\ + raise LookupError("Tutorial: state <" + transition_name +\ "> is not defined") next_states = set(self.get_following_states_dict(state_name).values()) @@ -259,16 +278,18 @@ class Tutorial(object): def get_action_dict(self, state_name=None): """ - Returns a dictionary of all actions for a specific state. + Returns a reference to the dictionary of all actions for a specific + state. If no state_name is provided, returns an action dictionary containing actions for all states. @param state_name The name of the state to list actions from - @return A dictionary of actions with action_name as key and action as value for state_name - @raise NameError if state_name doesn't exist + @return A dictionary of actions with action_name as key and action + as value for state_name + @raise LookupError if state_name doesn't exist """ if state_name and not self._state_dict.has_key(state_name): - raise NameError("Tutorial: state <" + state_name +\ + raise LookupError("Tutorial: state <" + state_name +\ "> is not defined") elif state_name: return self._state_dict.get_action_dict() @@ -286,10 +307,10 @@ class Tutorial(object): @param state_name The name of the state to list actions from @return A dictionary of transitions with transition_name as key and transition as value for state_name - @raise NameError if state_name doesn't exist + @raise LookupError if state_name doesn't exist """ if state_name and not self._state_dict.has_key(state_name): - raise NameError("Tutorial: state <" + state_name +\ + raise LookupError("Tutorial: state <" + state_name +\ "> is not defined") elif state_name: return self._state_dict.get_transition_dict() @@ -302,7 +323,10 @@ class Tutorial(object): def get_state_dict(self): """ - @return A dictionary of all the states in the tutorial with state_name as key and state as value + Returns a reference to the internal state dictionary used by + the Tutorial. + + @return A reference to the dictionary of all the states in the tutorial with state_name as key and state as value """ return self._state_dict @@ -312,10 +336,10 @@ class Tutorial(object): a specific state. @param state_name The name of the state - @raise NameError if state_name doesn't exist + @raise LookupError if state_name doesn't exist """ if not self._state_dict.has_key(state_name): - raise NameError("Tutorial: state <" + state_name +\ + raise LookupError("Tutorial: state <" + state_name +\ "> is not defined") following_states_dict = {} @@ -331,10 +355,10 @@ class Tutorial(object): specific state. @param state_name The name of the state - @raise NameError if state_name doesn't exist + @raise LookupError if state_name doesn't exist """ if not self._state_dict.has_key(state_name): - raise NameError("Tutorial: state <" + state_name +\ + raise LookupError("Tutorial: state <" + state_name +\ "> is not defined") @@ -370,7 +394,7 @@ class Tutorial(object): @param action_list The list of valid actions for this state @param event_list The list of events that will be converted to transitions to state_name @return unique name for this state - @raise NameError if state_name doesn't exist + @raise LookupError if state_name doesn't exist """ raise NotImplementedError @@ -521,11 +545,11 @@ class State(object): self._actions = {} for action in action_list: - self._actions[self._generate_unique_action_name(action)] = action + self.add_action(action) self._transitions = {} for transition in transition_list: - self._transitions[self._generate_unique_transition_name(transition)] = transition + self.add_transition(transition) # Action manipulations @@ -546,12 +570,12 @@ class State(object): @param action_name The name of the action to delete @return The action deleted - @raise NameError if action_name doesn't exist + @raise LookupError if action_name doesn't exist """ if self._actions.has_key(action_name): return self._actions.pop(action_name) else: - raise NameError("Tutorial.State: action <" + action_name + "> is not defined") + raise LookupError("Tutorial.State: action <" + action_name + "> is not defined") def update_action(self, action_name, new_action): """ @@ -560,7 +584,7 @@ class State(object): @param action_name The name of the action to replace @param new_action The action that will replace the old one @return The replaced action - @raise NameError if action_name doesn't exist + @raise LookupError if action_name doesn't exist """ # TODO: For now let's just replace the action with a new one, # we should check to see if we need a replace or an update @@ -570,10 +594,12 @@ class State(object): self._actions[action_name] = new_action return old_action else: - raise NameError("Tutorial.State: action <" + action_name + "> is not defined") + raise LookupError("Tutorial.State: action <" + action_name + "> is not defined") def get_action_dict(self): """ + Return the reference to the internal action dictionary. + @return A dictionary of actions that the state will execute """ return self._actions @@ -611,7 +637,7 @@ class State(object): @param transition_name The name of the transition to replace @param new_transition The transition that will replace the old one @return The replaced transition - @raise NameError if transition_name doesn't exist + @raise LookupError if transition_name doesn't exist """ # TODO: For now let's just replace the transition with a new one, # we should check to see if we need a replace or an update @@ -621,7 +647,7 @@ class State(object): self._transitions[transition_name] = new_transition return old_transition else: - raise NameError("Tutorial.State: transition <" + transition_name + "> is not defined") + raise LookupError("Tutorial.State: transition <" + transition_name + "> is not defined") def delete_transition(self, transition_name): """ @@ -629,15 +655,17 @@ class State(object): @param transition_name The name of the transition to delete @return The transition deleted - @raise NameError if transition_name doesn't exist + @raise LookupError if transition_name doesn't exist """ if self._transitions.has_key(transition_name): return self._transitions.pop(transition_name) else: - raise NameError("Tutorial.State: transition <" + transition_name + "> is not defined") + raise LookupError("Tutorial.State: transition <" + transition_name + "> is not defined") def get_transition_dict(self): """ + Return the reference to the internal transition dictionary. + @return The dictionary of transitions associated with this state. """ return self._transitions @@ -660,7 +688,7 @@ class State(object): #TODO use the action class name to generate a name # to make it easier to debug and know what we are # manipulating - name = self.name + "/" + "action" + str(self.action_name_nb) + name = self.name + Tutorial._NAME_SEPARATOR + "action" + str(self.action_name_nb) self.action_name_nb += 1 return name @@ -676,10 +704,28 @@ class State(object): #TODO use the event class name from the transition to # generate a name to make it easier to debug and know # what we are manipulating - name = self.name + "/" + "transition" + str(self.transition_name_nb) + name = self.name + Tutorial._NAME_SEPARATOR + "transition" + str(self.transition_name_nb) self.transition_name_nb += 1 return name + def __eq__(self, otherState): + """ + Compare current state to otherState. + + Two states are considered equal if and only if: + -every action in this state has a matching action in the + other state with the same properties and values + -every event filters in this state has a matching filter in the + other state having the same properties and values + -both states have the same name. + + + @param otherState The state that will be compared to this one + @return True if the states are the same, False otherwise +` """ + raise NotImplemented + + ################## Error Handling and Exceptions ############################## -- cgit v0.9.1