def __init__(self, portlet_entity):
        if portlet_entity.xml_path not in PORTLET_XML_READERS:
            PORTLET_XML_READERS[portlet_entity.xml_path] = XMLPortletReader(portlet_entity.xml_path)

        self.reader = PORTLET_XML_READERS[portlet_entity.xml_path]
        self.portlet_entity = portlet_entity
Exemple #2
0
 def __get_portlets(self, path_portlets):
     """
     Given a path in the form of a python package e.g.: "tvb.portlets', import
     the package, get it's folder and look for all the XML files defined 
     there, then read all the portlets defined there and store them in DB.
     """
     portlet_package = __import__(path_portlets, globals(), locals(),
                                  ["__init__"])
     portlet_folder = os.path.dirname(portlet_package.__file__)
     portlets_list = []
     for file_n in os.listdir(portlet_folder):
         try:
             if file_n.endswith('.xml'):
                 complete_file_path = os.path.join(portlet_folder, file_n)
                 portlet_reader = XMLPortletReader(complete_file_path)
                 portlet_list = portlet_reader.get_algorithms_dictionary()
                 self.logger.debug(
                     "Starting to verify currently declared portlets in %s."
                     % (file_n, ))
                 for algo_identifier in portlet_list:
                     adapters_chain = portlet_reader.get_adapters_chain(
                         algo_identifier)
                     is_valid = True
                     for adapter in adapters_chain:
                         class_name = adapter[ABCAdapter.KEY_TYPE].split(
                             '.')[-1]
                         module_name = adapter[ABCAdapter.KEY_TYPE].replace(
                             '.' + class_name, '')
                         try:
                             #Check that module is properly declared
                             module = __import__(module_name,
                                                 globals(),
                                                 fromlist=[class_name])
                             if type(module) != ModuleType:
                                 is_valid = False
                                 self.logger.error(
                                     "Wrong module %s in portlet %s" %
                                     (module_name, algo_identifier))
                                 continue
                             #Check that class is properly declared
                             if not hasattr(module, class_name):
                                 is_valid = False
                                 self.logger.error(
                                     "Wrong class %s in portlet %s." %
                                     (class_name, algo_identifier))
                                 continue
                             #Check inputs that refers to this adapter
                             portlet_inputs = portlet_list[algo_identifier][
                                 ELEM_INPUTS]
                             adapter_instance = PortletConfigurer.build_adapter_from_declaration(
                                 adapter)
                             if adapter_instance is None:
                                 is_valid = False
                                 self.logger.warning(
                                     "No group having class=%s stored for "
                                     "portlet %s." %
                                     (class_name, algo_identifier))
                                 continue
                             adapter_input_names = [
                                 entry[ABCAdapter.KEY_NAME] for entry in
                                 adapter_instance.flaten_input_interface()
                             ]
                             for input_entry in portlet_inputs.values():
                                 if input_entry[ATT_OVERWRITE] == adapter[
                                         ABCAdapter.KEY_NAME]:
                                     if input_entry[
                                             ABCAdapter.
                                             KEY_NAME] not in adapter_input_names:
                                         self.logger.error(
                                             "Invalid input %s for adapter %s"
                                             % (input_entry[
                                                 ABCAdapter.KEY_NAME],
                                                adapter_instance))
                                         is_valid = False
                         except ImportError, _:
                             self.logger.error(
                                 "Invalid adapter declaration %s in portlet %s"
                                 % (adapter[ABCAdapter.KEY_TYPE],
                                    algo_identifier))
                             is_valid = False
                     if is_valid:
                         portlets_list.append(
                             model.Portlet(
                                 algo_identifier, complete_file_path,
                                 portlet_list[algo_identifier]['name']))
         except XmlParserException, excep:
             self.logger.exception(excep)
             self.logger.error("Invalid Portlet description File " +
                               file_n + " will continue without it!!")
Exemple #3
0
    def _prepare_valid_portlets_list(self, portlet_folder, portlets_list):
        for file_n in os.listdir(portlet_folder):
            try:
                if file_n.endswith('.xml'):
                    complete_file_path = os.path.join(portlet_folder, file_n)
                    portlet_reader = XMLPortletReader(complete_file_path)
                    portlet_list = portlet_reader.get_algorithms_dictionary()
                    self.logger.debug(
                        "Starting to verify currently declared portlets in %s."
                        % (file_n, ))
                    for algo_identifier in portlet_list:
                        adapters_chain = portlet_reader.get_adapters_chain(
                            algo_identifier)
                        is_valid = True
                        for adapter in adapters_chain:
                            class_name = adapter[ABCAdapter.KEY_TYPE].split(
                                '.')[-1]
                            module_name = adapter[ABCAdapter.KEY_TYPE].replace(
                                '.' + class_name, '')
                            try:
                                # Check that module is properly declared
                                module = importlib.import_module(module_name)
                                if type(module) != ModuleType:
                                    is_valid = False
                                    self.logger.error(
                                        "Wrong module %s in portlet %s" %
                                        (module_name, algo_identifier))
                                    continue
                                # Check that class is properly declared
                                if not hasattr(module, class_name):
                                    is_valid = False
                                    self.logger.error(
                                        "Wrong class %s in portlet %s." %
                                        (class_name, algo_identifier))
                                    continue
                                # Check inputs that refers to this adapter
                                portlet_inputs = portlet_list[algo_identifier][
                                    ELEM_INPUTS]
                                adapter_instance = self._build_adapter_from_declaration(
                                    adapter)
                                if adapter_instance is None:
                                    is_valid = False
                                    self.logger.warning(
                                        "No group having class=%s stored for portlet %s."
                                        % (class_name, algo_identifier))
                                    continue

                                adapter_form = adapter_instance.get_form()
                                adapter_instance.submit_form(adapter_form())
                                # TODO: implement this for neoforms
                                adapter_form_field_names = {
                                }  # adapter_instance.flaten_input_interface()
                                for input_entry in portlet_inputs.values():
                                    if input_entry[ATT_OVERWRITE] == adapter[
                                            ABCAdapter.KEY_NAME]:
                                        if input_entry[
                                                ABCAdapter.
                                                KEY_NAME] not in adapter_form_field_names:
                                            self.logger.error(
                                                "Invalid input %s for adapter %s"
                                                % (input_entry[
                                                    ABCAdapter.KEY_NAME],
                                                   adapter_instance))
                                            is_valid = False
                            except ImportError:
                                is_valid = False
                                self.logger.error(
                                    "Invalid adapter declaration %s in portlet %s"
                                    % (adapter[ABCAdapter.KEY_TYPE],
                                       algo_identifier))

                        if is_valid:
                            portlets_list.append(
                                Portlet(algo_identifier, complete_file_path,
                                        portlet_list[algo_identifier]['name']))

            except XmlParserException as excep:
                self.logger.exception(excep)
                self.logger.error("Invalid Portlet description File " +
                                  file_n + " will continue without it!!")
 def __init__(self, portlet_entity):
     self.log = get_logger(self.__class__.__module__)
     self.reader = XMLPortletReader.get_instance(portlet_entity.xml_path)
     self.portlet_entity = portlet_entity
Exemple #5
0
class PortletConfigurer(object):
    """
    Helper class that handles all the functionality required from a portlet.
    Given a portlet entity, this will allow the following:
    
    - return a configurable interface in the form of a dictionary 
        equivalent to the input tree of an adapter
    - create a new PortletConfiguration entity, or update a already
        created one with a new set of parameters
        
    """
    def __init__(self, portlet_entity):
        self.log = get_logger(self.__class__.__module__)
        self.reader = XMLPortletReader(portlet_entity.xml_path)
        self.portlet_entity = portlet_entity

    @property
    def portlet_id(self):
        """Portlet DB identifier"""
        return self.portlet_entity.id

    @property
    def algo_identifier(self):
        """Unique identifier for current portlet."""
        return self.portlet_entity.algorithm_identifier

    @property
    def ui_name(self):
        """ Portlet name to be displayed in UI"""
        return self.portlet_entity.name

    def get_configurable_interface(self):
        """
        Given an algorithm identifier, go trough the adapter chain, and merge
        their input tree with the declared overwrites 
        """
        chain_adapters = self.reader.get_adapters_chain(self.algo_identifier)
        result = []
        for adapter_declaration in chain_adapters:
            adapter_instance = self.build_adapter_from_declaration(
                adapter_declaration)

            all_portlet_defined_params = self.reader.get_inputs(
                self.algo_identifier)
            specific_adapter_overwrites = [
                entry for entry in all_portlet_defined_params
                if ATT_OVERWRITE in entry and entry[ATT_OVERWRITE] ==
                adapter_declaration[ABCAdapter.KEY_NAME]
            ]
            alg_inputs = adapter_instance.get_input_tree()
            replace_values = self._prepare_input_tree(
                alg_inputs, specific_adapter_overwrites)
            adapter_configuration = AdapterConfiguration(
                replace_values, adapter_instance.stored_adapter)
            result.append(adapter_configuration)
        return result

    @classmethod
    def build_adapter_from_declaration(cls, adapter_declaration):
        """
        Build and adapter from the declaration in the portlets xml.
        """
        adapter_import_path = adapter_declaration[ABCAdapter.KEY_TYPE]
        class_name = adapter_import_path.split('.')[-1]
        module = adapter_import_path.replace('.' + class_name, '')
        algo = dao.get_algorithm_by_module(module, class_name)
        if algo is not None:
            return ABCAdapter.build_adapter(algo)
        else:
            return None

    def _prepare_input_tree(self, input_list, default_values, prefix=''):
        """
        Replace the default values from the portlet interface in the adapters 
        interfaces.
        :param input_list: the adapter input tree
        :param default_values: the dictionary of overwrites declared in the 
            portlet xml
        :param prefix: in case of a group adapter, the prefix to be added to 
            each name for the selected subalgorithm
        """
        for param in input_list:
            for one_value in default_values:
                if one_value[ABCAdapter.
                             KEY_NAME] == prefix + param[ABCAdapter.KEY_NAME]:
                    param[ABCAdapter.KEY_DEFAULT] = one_value[
                        ABCAdapter.KEY_DEFAULT]
                    if one_value[ABCAdapter.KEY_TYPE] == KEY_DYNAMIC:
                        ## For now just display all dynamic parameters as being disabled.
                        ## If at some point we would like user to be able to select dynamic entry
                        ## should treat this case differently.
                        param[ABCAdapter.KEY_DISABLED] = True
                        param[KEY_DYNAMIC] = True

            if param.get(ABCAdapter.KEY_OPTIONS) is not None:
                new_prefix = prefix + param[
                    ABCAdapter.KEY_NAME] + ABCAdapter.KEYWORD_PARAMS
                self._prepare_input_tree(param[ABCAdapter.KEY_OPTIONS],
                                         default_values, new_prefix)

            if param.get(ABCAdapter.KEY_ATTRIBUTES) is not None:
                new_prefix = prefix
                if param.get(ABCAdapter.KEY_TYPE) == 'dict':
                    new_prefix = prefix + param[
                        ABCAdapter.KEY_NAME] + ABCAdapter.KEYWORD_PARAMS
                self._prepare_input_tree(param[ABCAdapter.KEY_ATTRIBUTES],
                                         default_values, new_prefix)
        return input_list

    @staticmethod
    def update_default_values(portlet_interface, portlet_configuration):
        """
        :param portlet_interface: a list of AdapterConfiguration entities.
        :param portlet_configuration: a PortletConfiguration entity.
        
        Update the defaults from each AdapterConfiguration entity with the 
        values stored in the corresponding workflow step held in the 
        PortletConfiguration entity.
        """
        # Check for any defaults first in analyzer steps
        if portlet_configuration.analyzers:
            for adapter_idx in xrange(len(portlet_interface[:-1])):
                saved_configuration = portlet_configuration.analyzers[
                    adapter_idx]
                replaced_defaults_dict = InputTreeManager.fill_defaults(
                    portlet_interface[adapter_idx].interface,
                    saved_configuration.static_param)
                portlet_interface[
                    adapter_idx].interface = replaced_defaults_dict

        # Check for visualization defaults
        if portlet_configuration.visualizer:
            saved_configuration = portlet_configuration.visualizer
            replaced_defaults_dict = InputTreeManager.fill_defaults(
                portlet_interface[-1].interface,
                saved_configuration.static_param)
            portlet_interface[-1].interface = replaced_defaults_dict

    def _portlet_dynamic2workflow_step(self, value):
        """
        Given a value in portlet specific declaration, eg: step_0[0], return a 
        dictionary as expected from a workflow step:
            {'step_idx' : 0, 'datatype_idx' : 0}
        """
        step_idx, datatype_idx = value.replace('step_',
                                               '').replace(']', '').split('[')
        try:
            datatype_idx = int(datatype_idx)
            self.log.debug(
                "%s defines an output as an entry to a workflow step." %
                (value, ))
        except ValueError, _:
            self.log.debug(
                "%s defines an input as an entry to a workflow step." %
                (value, ))
        workflow_value = {
            wf_cfg.STEP_INDEX_KEY: int(step_idx),
            wf_cfg.DATATYPE_INDEX_KEY: datatype_idx
        }
        return workflow_value