Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormike <michael.jmontcalm@gmail.com>2009-03-20 04:50:48 (GMT)
committer mike <michael.jmontcalm@gmail.com>2009-03-20 04:50:48 (GMT)
commitc9f5b6ad86fa1e5e0d7cd5a3418188092141f73b (patch)
treeaa7f10d797186ff10c359fb858520af4047c8222
parenta411058e3825f2257d0a3fec7cc96ccc39713169 (diff)
TutoriusV2 : Adding linear tutorial creator wih basic tests
-rw-r--r--src/sugar/tutorius/Makefile.am3
-rw-r--r--src/sugar/tutorius/core.py2
-rw-r--r--src/sugar/tutorius/filters.py7
-rw-r--r--src/sugar/tutorius/linear_creator.py97
-rw-r--r--src/sugar/tutorius/tests/linear_creatortests.py71
5 files changed, 178 insertions, 2 deletions
diff --git a/src/sugar/tutorius/Makefile.am b/src/sugar/tutorius/Makefile.am
index 1fb11e1..9ff425e 100644
--- a/src/sugar/tutorius/Makefile.am
+++ b/src/sugar/tutorius/Makefile.am
@@ -8,4 +8,5 @@ sugar_PYTHON = \
filters.py \
services.py \
overlayer.py \
- editor.py
+ editor.py \
+ linear_creator.py
diff --git a/src/sugar/tutorius/core.py b/src/sugar/tutorius/core.py
index 2bdacee..901820f 100644
--- a/src/sugar/tutorius/core.py
+++ b/src/sugar/tutorius/core.py
@@ -239,7 +239,7 @@ class State(object):
was just cleared will become a sink and will be the end of the
tutorial.
"""
- self._event_filters.clear()
+ self._event_filters = []
class FiniteStateMachine(State):
"""
diff --git a/src/sugar/tutorius/filters.py b/src/sugar/tutorius/filters.py
index 4c04cf6..3acbb36 100644
--- a/src/sugar/tutorius/filters.py
+++ b/src/sugar/tutorius/filters.py
@@ -37,6 +37,13 @@ class EventFilter(object):
"""
return self._next_state
+ def set_next_state(self, new_next_name):
+ """
+ Setter for the next state. Should only be used during construction of
+ the event_fitler, not while the tutorial is running.
+ """
+ self._next_state = new_next_name
+
def install_handlers(self, callback, **kwargs):
"""
install_handlers is called for eventfilters to setup all
diff --git a/src/sugar/tutorius/linear_creator.py b/src/sugar/tutorius/linear_creator.py
new file mode 100644
index 0000000..02bb497
--- /dev/null
+++ b/src/sugar/tutorius/linear_creator.py
@@ -0,0 +1,97 @@
+# Copyright (C) 2009, Tutorius.org
+# Greatly influenced by sugar/activity/namingalert.py
+#
+# 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
+
+from sugar.tutorius.core import *
+from sugar.tutorius.actions import *
+from sugar.tutorius.filters import *
+
+from copy import deepcopy
+
+class LinearCreator(object):
+ """
+ This class is used to create a FSM from a linear sequence of orders. The
+ orders themselves are meant to be either an action or a transition.
+ """
+
+ def __init__(self):
+ self.fsm = FiniteStateMachine("Sample Tutorial")
+ self.current_actions = []
+ self.nb_state = 0
+
+ def set_name(self, name):
+ """
+ Sets the name of the generated FSM.
+ """
+ self.fsm.name = name
+
+ def action(self, action):
+ """
+ Adds an action to execute in the current state.
+ """
+ self.current_actions.append(action)
+
+ def event(self, event_filter):
+ """
+ Adds a transition to another state. When executing this, all the actions
+ previously called will be bundled in a single state, with the exit
+ condition of this state being the transition just added.
+
+ Whatever the name of the next state you inserted in the event, it will
+ be replaced to point to the next event in the line.
+ """
+ if len(self.current_actions) != 0:
+ state_name = ""
+ if self.nb_state == 0:
+ state_name = "INIT"
+ else:
+ state_name = "State" + str(self.nb_state)
+ # Set the next state name - there is no way the caller should have
+ # to deal with that.
+ next_state_name = "State" + str(self.nb_state+1)
+ event_filter.set_next_state(next_state_name)
+
+ state = State(state_name, action_list=self.current_actions, event_filter_list=[event_filter])
+ self.nb_state += 1
+ self.fsm.add_state(state)
+
+ # Clear the actions from the list
+ self.current_actions = []
+
+ def generate_fsm(self):
+ """
+ Returns a finite state machine corresponding to the sequence of calls
+ that were made from this point on.
+ """
+ # Copy the whole FSM that was generated yet
+ new_fsm = deepcopy(self.fsm)
+
+ # Generate the final state
+ state = None
+ if len(self.current_actions) != 0:
+ state = State("State" + str(self.nb_state), action_list=self.current_actions)
+ # Don't increment the nb_state here - we would break the linearity
+ # because we might generate more stuff with this creator later.
+ # Since we rely on linearity for continuity when generating the
+ # next state's name on an event filter, we cannot increment here.
+ else:
+ state = State("State" + str(self.nb_state))
+
+ # Insert the state in the copy of the FSM
+ new_fsm.add_state(state)
+
+ return new_fsm
+ \ No newline at end of file
diff --git a/src/sugar/tutorius/tests/linear_creatortests.py b/src/sugar/tutorius/tests/linear_creatortests.py
new file mode 100644
index 0000000..b328c45
--- /dev/null
+++ b/src/sugar/tutorius/tests/linear_creatortests.py
@@ -0,0 +1,71 @@
+# Copyright (C) 2009, Tutorius.org
+# Greatly influenced by sugar/activity/namingalert.py
+#
+# 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
+
+from sugar.tutorius.core import *
+from sugar.tutorius.actions import *
+from sugar.tutorius.filters import *
+from sugar.tutorius.linear_creator import *
+from coretests import TriggerEventFilter, CountAction
+
+import unittest
+
+class CreatorTests(unittest.TestCase):
+
+ def test_simple_usage(self):
+ creator = LinearCreator()
+ fsm_name = "SimpleUsageTest"
+
+ creator.set_name(fsm_name)
+
+ # Generate an FSM using the steps
+ creator.action(CountAction())
+ creator.action(CountAction())
+
+ creator.event(TriggerEventFilter("Not important"))
+
+ creator.action(CountAction())
+
+ creator.event(TriggerEventFilter("Not good either..."))
+
+ fsm = creator.generate_fsm()
+ print "------------- Generated FSM -------------------"
+ print str(fsm)
+ print "-----------------------------------------------"
+ # Make sure everything worked!
+ assert fsm.name == fsm_name, "Name was not set properly"
+
+ init_state = fsm.get_state_by_name("INIT")
+
+ assert len(init_state.get_action_list()) == 2, "Creator did not insert all the actions"
+
+ assert init_state.get_event_filter_list()[0].get_next_state() == "State1"
+
+ state1 = fsm.get_state_by_name("State1")
+
+ assert len(state1.get_action_list()) == 1, "Creator did not insert all the actions"
+
+ assert state1.get_event_filter_list()[0].get_next_state() == "State2"
+
+ # Make sure we have the final state and that it's empty
+ state2 = fsm.get_state_by_name("State2")
+
+ assert len(state2.get_action_list()) == 0, "Creator inserted extra actions on wrong state"
+
+ assert len(state2.get_event_filter_list()) == 0, "Creator assigner events to the final state"
+
+if __name__ == '__main__':
+ unittest.main() \ No newline at end of file