From 74dcbcb643cfd66df071020320ba6c0004e92c17 Mon Sep 17 00:00:00 2001 From: mike Date: Mon, 12 Oct 2009 06:54:12 +0000 Subject: LP 448319 : Refactoring to translate function, adding tests for translation of resources --- (limited to 'tutorius/translator.py') diff --git a/tutorius/translator.py b/tutorius/translator.py index 884714e..9925346 100644 --- a/tutorius/translator.py +++ b/tutorius/translator.py @@ -20,9 +20,9 @@ import copy logger = logging.getLogger("ResourceTranslator") - from sugar.tutorius.properties import * -from sugar.tutorius.vault import * +# TODO : Uncomment this line upon integration with the Vault +##from sugar.tutorius.vault import * class ResourceTranslator(object): """ @@ -30,9 +30,15 @@ class ResourceTranslator(object): 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. + + An architectural note : every different type of translation should have its + own method (translate_resource, etc...), and this function must be called + from the translate method, under the type test. The translation_* method + must take in the input property and give the output property that should + replace it. """ - def __init__(self, probe_manager, tutorial_id): + def __init__(self, probe_manager, tutorial_id, testing=False): """ Creates a new ResourceTranslator for the given tutorial. This translator is tasked with replacing resource properties of the @@ -43,11 +49,15 @@ class ResourceTranslator(object): @param probe_manager The probe manager to decorate @param tutorial_id The ID of the current tutorial + + @param testing Triggers the usage of a fake vault for testing purposes """ self._probe_manager = probe_manager self._tutorial_id = tutorial_id - def _replace_resources(self, prop_container): + self._testing = testing + + def translate_resource(self, res_prop): """ Replace the TResourceProperty in the container by their runtime-defined file equivalent. Since the resources are stored @@ -56,34 +66,81 @@ class ResourceTranslator(object): to transform the resource identifier into the absolute path for the process to be able to use it properly. + @param res_prop The resource property to be translated + @return The TFileProperty corresponding to this resource, containing + an absolute path to the resource + """ + # We need to replace the resource by a file representation + filepath = "" + # TODO : Refactor when the Vault will be available + if not self._testing: + filepath = Vault.get_resource_path(self._tutorial_id, \ + prop_object.value) + else: + filepath = "/tmp/tutorius/temp.txt" + # Create the new file representation + file_prop = TFileProperty(filepath) + + return file_prop + + def translate(self, prop_container): + """ + Applies the required translation to be able to send the container to an + executing endpoint (like a Probe). For each type of property that + requires it, there is translation function that will take care of + mapping the property to its executable form. + 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. + that all the properties of the input container have been replaced + by their corresponding executable versions. + + An example of translation is taking a resource (a relative path to + a file under the tutorial folder) and transforming it into a file + (a full absolute path) to be able to load it when the activity receives + the action. @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 + for propname in prop_container.get_properties(): + prop_value = getattr(prop_container, propname) + prop_type = getattr(type(prop_container), propname).type + # If the property is a resource, then we need to query the + # vault to create its correspondent 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) + # Apply the translation + file_prop = self.translate_resource(prop_value) + # Set the property with the new value + setattr(prop_container, propname, file_prop) + + # If the property is an addon, then its value IS a + # container too - we need to translate it + elif prop_type == "addon": + # Translate the sub properties + self.translate(prop_value) + + # If the property is an addon list, then we need to translate all + # the elements of the list + elif prop_type == "addonlist": + # Now, for each sub-container in the list, we will apply the + # translation processing. This is done by popping the head of + # the list, translating it and inserting it back at the end. + for index in range(0, len(prop_value)): + # Pop the head of the list + container = prop_value[0] + del prop_value[0] + # Translate the sub-container + self.translate(container) + + # Put the value back in the list + prop_value.append(container) + # Change the list contained in the addonlist property, since + # we got a copy of the list when requesting it + setattr(prop_container, propname, prop_value) - ### ProbeManager interface for decorator ### ## Unchanged functions ## @@ -112,35 +169,25 @@ class ResourceTranslator(object): ## 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 + # because translate() 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) + self.translate(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) + self.translate(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) + self.translate(new_action) - # Send the new action to the probe manager return self._probe_manager.uninstall(new_action) def uninstall_all(self): -- cgit v0.9.1