# Copyright (C) 2009, Tutorius.org # # 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 import os import logging import copy logger = logging.getLogger("ResourceTranslator") from sugar.tutorius.properties import * from sugar.tutorius.vault import * class ResourceTranslator(object): """ Handles the conversion of resource properties into file properties before action execution. This class works as a decorator to the ProbeManager class, as it is meant to be a transparent layer before sending the action to execution. """ def __init__(self, probe_manager, tutorial_id): """ Creates a new ResourceTranslator for the given tutorial. This translator is tasked with replacing resource properties of the incoming action into actually usable file properties pointing to the correct resource file. This is done by querying the vault for all the resources and creating a new file property from the returned path. @param probe_manager The probe manager to decorate @param tutorial_id The ID of the current tutorial """ self._probe_manager = probe_manager self._tutorial_id = tutorial_id def _replace_resources(self, prop_container): """ Replace the TResourceProperty in the container by their runtime-defined file equivalent. Since the resources are stored in a relative manner in the vault and that only the Vault knows which is the current folder for the current tutorial, it needs to transform the resource identifier into the absolute path for the process to be able to use it properly. This function does not return anything, but its post-condition is that all the resources properties of container have been replaced by its corresponding file property on disk. @param prop_container The property container in which we want to replace all the resources for file properties and to recursively do so for addon and addonlist properties. """ for propname in action.get_properties(): prop_object = getattr(action, propname) prop_type = prop_object.type if prop_type == "resource": # We need to replace the resource by a file representation filepath = vault.get_resource_path(self._tutorial_id, \ prop_object.value) # Create the new file representation file_prop = TFileProperty(filepath) # Replace the property setattr(action, propname, file_prop) elif prob_type == "addon": self._replace_resources(prop_object.value) elif prob_type == "addonlist": for container in prop_object.value: self._replace_resources(container.value) ### ProbeManager interface for decorator ### ## Unchanged functions ## def setCurrentActivity(self, activity_id): self._probe_manager.setCurrentActivity(activity_id) def getCurrentActivity(self): return self._probe_manager.getCurrentActivity() currentActivity = property(fget=getCurrentActivity, fset=setCurrentActivity) def attach(self, activity_id): self._probe_manager.attach(activity_id) def detach(self, activity_id): self._probe_manager.detach(activity_id) def subscribe(self, event, callback): return self._probe_manager.subscribe(event, callback) def unsubscribe(self, event, callback): return self._probe_manager.unsubscribe(event, callback) def unsubscribe_all(self): return self._probe_manager.unsubscribe_all() ## Decorated functions ## def install(self, action): # Make a new copy of the action that we want to install, # because _replace_resources changes the action and we # don't want to modify the caller's action representation new_action = copy.deepcopy(action) # Execute the replacement self._replace_resources(new_action) # Send the new action to the probe manager return self._probe_manager.install(new_action) def update(self, action): # Make a new copy of the action that we want to install, # because _replace_resources changes the action and we # don't want to modify the caller's action representation new_action = copy.deepcopy(action) # Execute the replacement self._replace_resources(new_action) # Send the new action to the probe manager return self._probe_manager.update(new_action) def uninstall(self, action): # Make a new copy of the action that we want to install, # because _replace_resources changes the action and we # don't want to modify the caller's action representation new_action = copy.deepcopy(action) # Execute the replacement self._replace_resources(new_action) # Send the new action to the probe manager return self._probe_manager.uninstall(new_action) def uninstall_all(self): return self._probe_manager.uninstall_all()