Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/tutorius/bundler.py
diff options
context:
space:
mode:
Diffstat (limited to 'tutorius/bundler.py')
-rw-r--r--tutorius/bundler.py61
1 files changed, 38 insertions, 23 deletions
diff --git a/tutorius/bundler.py b/tutorius/bundler.py
index 56bbf3e..c9558b1 100644
--- a/tutorius/bundler.py
+++ b/tutorius/bundler.py
@@ -24,6 +24,7 @@ import logging
import os
import uuid
import xml.dom.minidom
+from xml.dom import NotFoundErr
from sugar.tutorius import addon
from sugar.tutorius.core import Tutorial, State, FiniteStateMachine
@@ -37,8 +38,10 @@ def _get_store_root():
return os.path.join(os.getenv("HOME"),
".sugar",profile_name,"tutorius","data")
# this is where activity bundled tutorials should be, under the activity bundle
-def _get_bundle_root():
- return os.path.join(os.getenv("SUGAR_BUNDLE_PATH"),"data","tutorius","data")
+def _get_bundle_root(base_path=None):
+ base_path = base_path or os.getenv("SUGAR_BUNDLE_PATH")
+ if base_path:
+ return os.path.join(os.getenv("SUGAR_BUNDLE_PATH"),"data","tutorius","data")
INI_ACTIVITY_SECTION = "RELATED_ACTIVITIES"
INI_METADATA_SECTION = "GENERAL_METADATA"
@@ -50,6 +53,7 @@ TUTORIAL_FILENAME = "tutorial.xml"
NODE_COMPONENT = "Component"
NODE_SUBCOMPONENT = "property"
NODE_SUBCOMPONENTLIST = "listproperty"
+NEXT_STATE_ATTR = "next_state"
class TutorialStore(object):
@@ -61,7 +65,7 @@ class TutorialStore(object):
@returns a map of tutorial {names : GUID}.
"""
# check both under the activity data and user installed folders
- paths = [_get_store_root(), _get_bundle_root()]
+ paths = [p for p in [_get_store_root(), _get_bundle_root()] if p ]
tutoGuidName = {}
@@ -89,7 +93,7 @@ class TutorialStore(object):
return tutoGuidName
- def load_tutorial(self, Guid):
+ def load_tutorial(self, Guid, bundle_path=None):
"""
Rebuilds a tutorial object from it's serialized state.
Common storing paths will be scanned.
@@ -97,15 +101,15 @@ class TutorialStore(object):
@param Guid the generic identifier of the tutorial
@returns a Tutorial object containing an FSM
"""
- bundle = TutorialBundler(Guid)
- bundle_path = bundle.get_tutorial_path()
+ bundler = TutorialBundler(Guid, bundle_path=bundle_path)
+ bundler_path = bundler.get_tutorial_path()
config = SafeConfigParser()
- config.read(os.path.join(bundle_path, INI_FILENAME))
+ config.read(os.path.join(bundler_path, INI_FILENAME))
serializer = XMLSerializer()
name = config.get(INI_METADATA_SECTION, INI_NAME_PROPERTY)
- fsm = serializer.load_fsm(Guid)
+ fsm = serializer.load_fsm(Guid, bundler.Path)
tuto = Tutorial(name, fsm)
return tuto
@@ -125,13 +129,13 @@ class Serializer(object):
exception occur. If no GUID is provided, FSM is written in a new file
in the store root.
"""
- NotImplementedError
+ return NotImplementedError()
def load_fsm(self):
"""
Load fsm from disk.
"""
- NotImplementedError
+ return NotImplementedError()
class XMLSerializer(Serializer):
"""
@@ -270,8 +274,9 @@ class XMLSerializer(Serializer):
Create and return a xml Node from a event filters.
"""
eventFiltersList = doc.createElement("EventFiltersList")
- for event_f in event_filters:
- eventFilterNode = self._create_component_node(event_f, doc)
+ for event, state in event_filters:
+ eventFilterNode = self._create_component_node(event, doc)
+ eventFilterNode.setAttribute(NEXT_STATE_ATTR, str(state))
eventFiltersList.appendChild(eventFilterNode)
return eventFiltersList
@@ -385,17 +390,22 @@ class XMLSerializer(Serializer):
@param filters_elem An XML Element representing a list of event filters
"""
- reformed_event_filters_list = []
+ transition_list = []
event_filter_element_list = self._get_direct_descendants_by_tag_name(filters_elem, NODE_COMPONENT)
new_event_filter = None
for event_filter in event_filter_element_list:
+ next_state = event_filter.getAttribute(NEXT_STATE_ATTR)
+ try:
+ event_filter.removeAttribute(NEXT_STATE_ATTR)
+ except NotFoundErr:
+ next_state = None
new_event_filter = self._load_xml_component(event_filter)
if new_event_filter is not None:
- reformed_event_filters_list.append(new_event_filter)
+ transition_list.append((new_event_filter, next_state))
- return reformed_event_filters_list
+ return transition_list
def _load_xml_subcomponents(self, node, properties):
"""
@@ -530,18 +540,18 @@ class XMLSerializer(Serializer):
# Load the event filters
events = self._load_xml_event_filters(fsm_elem.getElementsByTagName("EventFiltersList")[0])
- for event in events:
- fsm.add_event_filter(event)
+ for event, next_state in events:
+ fsm.add_event_filter(event, next_state)
return fsm
- def load_fsm(self, guid):
+ def load_fsm(self, guid, path=None):
"""
Load fsm from xml file whose .ini file guid match argument guid.
"""
# Fetch the directory (if any)
- tutorial_dir = self._find_tutorial_dir_with_guid(guid)
+ tutorial_dir = path or self._find_tutorial_dir_with_guid(guid)
# Open the XML file
tutorial_file = os.path.join(tutorial_dir, TUTORIAL_FILENAME)
@@ -559,7 +569,7 @@ class TutorialBundler(object):
editor.
"""
- def __init__(self,generated_guid = None):
+ def __init__(self,generated_guid = None, bundle_path=None):
"""
Tutorial_bundler constructor. If a GUID is given in the parameter, the
Tutorial_bundler object will be associated with it. If no GUID is given,
@@ -568,6 +578,7 @@ class TutorialBundler(object):
self.Guid = generated_guid or str(uuid.uuid1())
+ #FIXME: Look for the bundle in the activity first (more specific)
#Look for the file in the path if a uid is supplied
if generated_guid:
#General store
@@ -576,9 +587,13 @@ class TutorialBundler(object):
self.Path = os.path.dirname(store_path)
else:
#Bundle store
- bundle_path = os.path.join(_get_bundle_root(), generated_guid, INI_FILENAME)
- if os.path.isfile(bundle_path):
- self.Path = os.path.dirname(bundle_path)
+ base_bundle_path = _get_bundle_root(bundle_path)
+ if base_bundle_path:
+ bundle_path = os.path.join(base_bundle_path, generated_guid, INI_FILENAME)
+ if os.path.isfile(bundle_path):
+ self.Path = os.path.dirname(bundle_path)
+ else:
+ raise IOError(2,"Unable to locate metadata file for guid '%s'" % generated_guid)
else:
raise IOError(2,"Unable to locate metadata file for guid '%s'" % generated_guid)