def getfiltereddatatypes(self, name, parent_div, tree_session_key, filters): """ Given the name from the input tree, the dataType required and a number of filters, return the available dataType that satisfy the conditions imposed. """ previous_tree = self.context.get_session_tree_for_key(tree_session_key) if previous_tree is None: base.set_error_message( "Adapter Interface not in session for filtering!") raise cherrypy.HTTPRedirect("/tvb?error=True") current_node = self._get_node(previous_tree, name) if current_node is None: raise Exception("Could not find node :" + name) datatype = current_node[ABCAdapter.KEY_DATATYPE] filters = json.loads(filters) availablefilter = json.loads( FilterChain.get_filters_for_type(datatype)) for i, filter_ in enumerate(filters[FILTER_FIELDS]): #Check for filter input of type 'date' as these need to be converted if filter_ in availablefilter and availablefilter[filter_][ FILTER_TYPE] == 'date': try: filter_ = string2date(filter_, False) filters[FILTER_VALUES][i] = filter_ except ValueError, excep: raise excep
def getfiltereddatatypes(self, name, parent_div, tree_session_key, filters): """ Given the name from the input tree, the dataType required and a number of filters, return the available dataType that satisfy the conditions imposed. """ previous_tree = self.context.get_session_tree_for_key(tree_session_key) if previous_tree is None: common.set_error_message("Adapter Interface not in session for filtering!") raise cherrypy.HTTPRedirect("/tvb?error=True") current_node = self._get_node(previous_tree, name) if current_node is None: raise Exception("Could not find node :" + name) datatype = current_node[ABCAdapter.KEY_DATATYPE] filters = json.loads(filters) availablefilter = json.loads(FilterChain.get_filters_for_type(datatype)) for i, filter_ in enumerate(filters[FILTER_FIELDS]): #Check for filter input of type 'date' as these need to be converted if filter_ in availablefilter and availablefilter[filter_][FILTER_TYPE] == 'date': try: temp_date = string2date(filters[FILTER_VALUES][i], False) filters[FILTER_VALUES][i] = temp_date except ValueError: raise #In order for the filter object not to "stack up" on multiple calls to #this method, create a deepCopy to work with if ABCAdapter.KEY_CONDITION in current_node: new_filter = copy.deepcopy(current_node[ABCAdapter.KEY_CONDITION]) else: new_filter = FilterChain() new_filter.fields.extend(filters[FILTER_FIELDS]) new_filter.operations.extend(filters[FILTER_OPERATIONS]) new_filter.values.extend(filters[FILTER_VALUES]) #Get dataTypes that match the filters from DB then populate with values values, total_count = InputTreeManager().populate_option_values_for_dtype( common.get_current_project().id, datatype, new_filter, self.context.get_current_step() ) #Create a dictionary that matches what the template expects parameters = {ABCAdapter.KEY_NAME: name, ABCAdapter.KEY_FILTERABLE: availablefilter, ABCAdapter.KEY_TYPE: ABCAdapter.TYPE_SELECT, ABCAdapter.KEY_OPTIONS: values, ABCAdapter.KEY_DATATYPE: datatype} if total_count > MAXIMUM_DATA_TYPES_DISPLAYED: parameters[KEY_WARNING] = WARNING_OVERFLOW if ABCAdapter.KEY_REQUIRED in current_node: parameters[ABCAdapter.KEY_REQUIRED] = current_node[ABCAdapter.KEY_REQUIRED] if len(values) > 0 and string2bool(str(parameters[ABCAdapter.KEY_REQUIRED])): parameters[ABCAdapter.KEY_DEFAULT] = str(values[-1][ABCAdapter.KEY_VALUE]) previous_selected = self.context.get_current_default(name) if previous_selected in [str(vv['value']) for vv in values]: parameters[ABCAdapter.KEY_DEFAULT] = previous_selected template_specification = {"inputRow": parameters, "disabled": False, "parentDivId": parent_div, common.KEY_SESSION_TREE: tree_session_key} return self.fill_default_attributes(template_specification)
def getfiltereddatatypes(self, name, parent_div, tree_session_key, filters): """ Given the name from the input tree, the dataType required and a number of filters, return the available dataType that satisfy the conditions imposed. """ previous_tree = self.context.get_session_tree_for_key(tree_session_key) if previous_tree is None: common.set_error_message("Adapter Interface not in session for filtering!") raise cherrypy.HTTPRedirect("/tvb?error=True") current_node = self._get_node(previous_tree, name) if current_node is None: raise Exception("Could not find node :" + name) datatype = current_node[ABCAdapter.KEY_DATATYPE] filters = json.loads(filters) availablefilter = json.loads(FilterChain.get_filters_for_type(datatype)) for i, filter_ in enumerate(filters[FILTER_FIELDS]): # Check for filter input of type 'date' as these need to be converted if filter_ in availablefilter and availablefilter[filter_][FILTER_TYPE] == 'date': try: temp_date = string2date(filters[FILTER_VALUES][i], False) filters[FILTER_VALUES][i] = temp_date except ValueError: raise # In order for the filter object not to "stack up" on multiple calls to # this method, create a deepCopy to work with if ABCAdapter.KEY_CONDITION in current_node: new_filter = copy.deepcopy(current_node[ABCAdapter.KEY_CONDITION]) else: new_filter = FilterChain() new_filter.fields.extend(filters[FILTER_FIELDS]) new_filter.operations.extend(filters[FILTER_OPERATIONS]) new_filter.values.extend(filters[FILTER_VALUES]) # Get dataTypes that match the filters from DB then populate with values values, total_count = InputTreeManager().populate_option_values_for_dtype( common.get_current_project().id, datatype, new_filter, self.context.get_current_step()) # Create a dictionary that matches what the template expects parameters = {ABCAdapter.KEY_NAME: name, ABCAdapter.KEY_FILTERABLE: availablefilter, ABCAdapter.KEY_TYPE: ABCAdapter.TYPE_SELECT, ABCAdapter.KEY_OPTIONS: values, ABCAdapter.KEY_DATATYPE: datatype} if total_count > MAXIMUM_DATA_TYPES_DISPLAYED: parameters[KEY_WARNING] = WARNING_OVERFLOW if ABCAdapter.KEY_REQUIRED in current_node: parameters[ABCAdapter.KEY_REQUIRED] = current_node[ABCAdapter.KEY_REQUIRED] if len(values) > 0 and string2bool(str(parameters[ABCAdapter.KEY_REQUIRED])): parameters[ABCAdapter.KEY_DEFAULT] = str(values[-1][ABCAdapter.KEY_VALUE]) previous_selected = self.context.get_current_default(name) if previous_selected in [str(vv['value']) for vv in values]: parameters[ABCAdapter.KEY_DEFAULT] = previous_selected template_specification = {"inputRow": parameters, "disabled": False, "parentDivId": parent_div, common.KEY_SESSION_TREE: tree_session_key} return self.fill_default_attributes(template_specification)
def fill_input_tree_with_options(self, attributes_list, project_id, category_key): """ For a datatype node in the input tree, load all instances from the db that fit the filters. """ result = [] for param in attributes_list: if getattr(param, KEY_UI_HIDE, False): continue transformed_param = copy(param) if isinstance(param, (itr.DatatypeNode, itr.ComplexDtypeNode)): filter_condition = param.conditions if filter_condition is None: filter_condition = FilterChain('') filter_condition.add_condition(FilterChain.datatype + ".visible", "==", True) complex_dt_attributes = None if isinstance(param, itr.ComplexDtypeNode): complex_dt_attributes = self.fill_input_tree_with_options(param.attributes, project_id, category_key) values, total_count = self.populate_option_values_for_dtype(project_id, param.type, filter_condition, category_key, complex_dt_attributes) if total_count > MAXIMUM_DATA_TYPES_DISPLAYED: transformed_param.warning = WARNING_OVERFLOW if param.required and len(values) > 0 and param.default is None: transformed_param.default = str(values[-1][KEY_VALUE]) transformed_param.filterable = FilterChain.get_filters_for_type(param.type) transformed_param.type = TYPE_SELECT # todo this type transfer is not nice transformed_param.datatype = param.type # If Portlet dynamic parameter, don't add the options instead # just add the default value. if getattr(param, KEY_DYNAMIC, False): dynamic_param = {KEY_NAME: param.default, KEY_VALUE: param.default} transformed_param.options = [dynamic_param] else: transformed_param.options = values ### DataType-attributes are no longer necessary, they were already copied on each OPTION transformed_param.attributes = [] # todo check if this is ok elif isinstance(param, itr.SelectTypeNode): transformed_param.options = self.fill_input_tree_with_options(param.options, project_id, category_key) if len(param.options) > 0 and param.default is None: transformed_param.default = str(param.options[-1].value) elif isinstance(param, (itr.TypeNode, itr.DictNode)): #ComplexDatatypeNode enters here! transformed_param.attributes = self.fill_input_tree_with_options(param.attributes, project_id, category_key) result.append(transformed_param) return result
def getfiltereddatatypes(self, name, parent_div, tree_session_key, filters): """ Given the name from the input tree, the dataType required and a number of filters, return the available dataType that satisfy the conditions imposed. """ previous_tree = self.context.get_session_tree_for_key(tree_session_key) if previous_tree is None: base.set_error_message("Adapter Interface not in session for filtering!") raise cherrypy.HTTPRedirect("/tvb?error=True") current_node = self._get_node(previous_tree, name) if current_node is None: raise Exception("Could not find node :" + name) datatype = current_node[ABCAdapter.KEY_DATATYPE] filters = json.loads(filters) availablefilter = json.loads(FilterChain.get_filters_for_type(datatype)) for i, filter_ in enumerate(filters[FILTER_FIELDS]): #Check for filter input of type 'date' as these need to be converted if filter_ in availablefilter and availablefilter[filter_][FILTER_TYPE] == 'date': try: filter_ = string2date(filter_, False) filters[FILTER_VALUES][i] = filter_ except ValueError, excep: raise excep
def prepare_parameters(self, attributes_list, project_id, category_key): """ Private method, to be called recursively. It will receive a list of Attributes, and it will populate 'options' entry with data references from DB. """ result = [] for param in attributes_list: if (ABCAdapter.KEY_UI_HIDE in param) and param[ABCAdapter.KEY_UI_HIDE]: continue transformed_param = copy(param) if (ABCAdapter.KEY_TYPE in param) and not (param[ABCAdapter.KEY_TYPE] in ABCAdapter.STATIC_ACCEPTED_TYPES): if ABCAdapter.KEY_CONDITION in param: filter_condition = param[ABCAdapter.KEY_CONDITION] filter_condition.add_condition(FilterChain.datatype + ".visible", "==", True) else: filter_condition = FilterChain('', [FilterChain.datatype + '.visible'], [True], operations=["=="]) data_list = self.get_available_datatypes(project_id, param[ABCAdapter.KEY_TYPE], filter_condition) complex_dt_attributes = None if (ABCAdapter.KEY_ATTRIBUTES in param and param[ABCAdapter.KEY_ATTRIBUTES] is not None and len(param[ABCAdapter.KEY_ATTRIBUTES])) > 0: complex_dt_attributes = self.prepare_parameters(param[ABCAdapter.KEY_ATTRIBUTES], project_id, category_key) values = self.populate_values(data_list, param[ABCAdapter.KEY_TYPE], category_key, complex_dt_attributes) if (ABCAdapter.KEY_REQUIRED in transformed_param and transformed_param[ABCAdapter.KEY_REQUIRED] and len(values) > 0 and (ABCAdapter.KEY_DEFAULT not in transformed_param or transformed_param[ABCAdapter.KEY_DEFAULT] is None or transformed_param[ABCAdapter.KEY_DEFAULT] == 'None')): def_val = str(values[-1][ABCAdapter.KEY_VALUE]) transformed_param[ABCAdapter.KEY_DEFAULT] = def_val transformed_param[ABCAdapter.KEY_FILTERABLE] = FilterChain.get_filters_for_type( param[ABCAdapter.KEY_TYPE]) transformed_param[ABCAdapter.KEY_TYPE] = ABCAdapter.TYPE_SELECT # If Portlet dynamic parameter, don't add the options instead # just add the default value. if KEY_DYNAMIC in param: dynamic_param = {ABCAdapter.KEY_NAME: param[ABCAdapter.KEY_DEFAULT], ABCAdapter.KEY_VALUE: param[ABCAdapter.KEY_DEFAULT]} transformed_param[ABCAdapter.KEY_OPTIONS] = [dynamic_param] else: transformed_param[ABCAdapter.KEY_OPTIONS] = values if type(param[ABCAdapter.KEY_TYPE]) == str: transformed_param[ABCAdapter.KEY_DATATYPE] = param[ABCAdapter.KEY_TYPE] else: data_type = param[ABCAdapter.KEY_TYPE] transformed_param[ABCAdapter.KEY_DATATYPE] = data_type.__module__ + '.' + data_type.__name__ ### DataType-attributes are no longer necessary, they were already copied on each OPTION transformed_param[ABCAdapter.KEY_ATTRIBUTES] = [] else: if ABCAdapter.KEY_OPTIONS in param and param[ABCAdapter.KEY_OPTIONS] is not None: transformed_param[ABCAdapter.KEY_OPTIONS] = self.prepare_parameters(param[ABCAdapter.KEY_OPTIONS], project_id, category_key) if (ABCAdapter.KEY_REQUIRED in transformed_param) and transformed_param[ABCAdapter.KEY_REQUIRED] \ and (len(param[ABCAdapter.KEY_OPTIONS]) > 0) and \ ((ABCAdapter.KEY_DEFAULT not in transformed_param) or transformed_param[ABCAdapter.KEY_DEFAULT] is None or transformed_param[ABCAdapter.KEY_DEFAULT] == 'None'): def_val = str(param[ABCAdapter.KEY_OPTIONS][-1][ABCAdapter.KEY_VALUE]) transformed_param[ABCAdapter.KEY_DEFAULT] = def_val if (ABCAdapter.KEY_ATTRIBUTES in param) and (param[ABCAdapter.KEY_ATTRIBUTES] is not None): transformed_param[ABCAdapter.KEY_ATTRIBUTES] = self.prepare_parameters( param[ABCAdapter.KEY_ATTRIBUTES], project_id, category_key) result.append(transformed_param) return result
def prepare_parameters(self, attributes_list, project_id, category_key): """ Private method, to be called recursively. It will receive a list of Attributes, and it will populate 'options' entry with data references from DB. """ result = [] for param in attributes_list: if param.get(ABCAdapter.KEY_UI_HIDE): continue transformed_param = copy(param) if (ABCAdapter.KEY_TYPE in param) and not (param[ABCAdapter.KEY_TYPE] in ABCAdapter.STATIC_ACCEPTED_TYPES): if ABCAdapter.KEY_CONDITION in param: filter_condition = param[ABCAdapter.KEY_CONDITION] else: filter_condition = FilterChain('') filter_condition.add_condition(FilterChain.datatype + ".visible", "==", True) data_list, total_count = self.get_available_datatypes(project_id, param[ABCAdapter.KEY_TYPE], filter_condition) if total_count > self.MAXIMUM_DATA_TYPES_DISPLAYED: transformed_param[self.KEY_WARNING] = self.WARNING_OVERFLOW complex_dt_attributes = None if param.get(ABCAdapter.KEY_ATTRIBUTES): complex_dt_attributes = self.prepare_parameters(param[ABCAdapter.KEY_ATTRIBUTES], project_id, category_key) values = self.populate_values(data_list, param[ABCAdapter.KEY_TYPE], category_key, complex_dt_attributes) if (transformed_param.get(ABCAdapter.KEY_REQUIRED) and len(values) > 0 and transformed_param.get(ABCAdapter.KEY_DEFAULT) in [None, 'None']): transformed_param[ABCAdapter.KEY_DEFAULT] = str(values[-1][ABCAdapter.KEY_VALUE]) transformed_param[ABCAdapter.KEY_FILTERABLE] = FilterChain.get_filters_for_type( param[ABCAdapter.KEY_TYPE]) transformed_param[ABCAdapter.KEY_TYPE] = ABCAdapter.TYPE_SELECT # If Portlet dynamic parameter, don't add the options instead # just add the default value. if KEY_DYNAMIC in param: dynamic_param = {ABCAdapter.KEY_NAME: param[ABCAdapter.KEY_DEFAULT], ABCAdapter.KEY_VALUE: param[ABCAdapter.KEY_DEFAULT]} transformed_param[ABCAdapter.KEY_OPTIONS] = [dynamic_param] else: transformed_param[ABCAdapter.KEY_OPTIONS] = values if type(param[ABCAdapter.KEY_TYPE]) == str: transformed_param[ABCAdapter.KEY_DATATYPE] = param[ABCAdapter.KEY_TYPE] else: data_type = param[ABCAdapter.KEY_TYPE] transformed_param[ABCAdapter.KEY_DATATYPE] = data_type.__module__ + '.' + data_type.__name__ ### DataType-attributes are no longer necessary, they were already copied on each OPTION transformed_param[ABCAdapter.KEY_ATTRIBUTES] = [] else: if param.get(ABCAdapter.KEY_OPTIONS) is not None: transformed_param[ABCAdapter.KEY_OPTIONS] = self.prepare_parameters(param[ABCAdapter.KEY_OPTIONS], project_id, category_key) if (transformed_param.get(ABCAdapter.KEY_REQUIRED) and len(param[ABCAdapter.KEY_OPTIONS]) > 0 and (transformed_param.get(ABCAdapter.KEY_DEFAULT) in [None, 'None'])): def_val = str(param[ABCAdapter.KEY_OPTIONS][-1][ABCAdapter.KEY_VALUE]) transformed_param[ABCAdapter.KEY_DEFAULT] = def_val if param.get(ABCAdapter.KEY_ATTRIBUTES) is not None: transformed_param[ABCAdapter.KEY_ATTRIBUTES] = self.prepare_parameters( param[ABCAdapter.KEY_ATTRIBUTES], project_id, category_key) result.append(transformed_param) return result
def fill_input_tree_with_options(self, attributes_list, project_id, category_key): """ For a datatype node in the input tree, load all instances from the db that fit the filters. """ result = [] for param in attributes_list: if param.get(KEY_UI_HIDE): continue transformed_param = copy(param) if KEY_TYPE in param and param[ KEY_TYPE] not in STATIC_ACCEPTED_TYPES: if KEY_CONDITION in param: filter_condition = param[KEY_CONDITION] else: filter_condition = FilterChain('') filter_condition.add_condition( FilterChain.datatype + ".visible", "==", True) values, total_count = self.populate_option_values_for_dtype( project_id, param[KEY_TYPE], filter_condition, category_key) if param.get( KEY_ATTRIBUTES ): # copy complex datatype attributes to all options complex_dt_attributes = self.fill_input_tree_with_options( param[KEY_ATTRIBUTES], project_id, category_key) for value in values: if value[KEY_NAME] != 'All': value[KEY_ATTRIBUTES] = complex_dt_attributes if total_count > MAXIMUM_DATA_TYPES_DISPLAYED: transformed_param[KEY_WARNING] = WARNING_OVERFLOW if param.get(KEY_REQUIRED) and len(values) > 0 and param.get( KEY_DEFAULT) is None: transformed_param[KEY_DEFAULT] = str(values[-1][KEY_VALUE]) transformed_param[ KEY_FILTERABLE] = FilterChain.get_filters_for_type( param[KEY_TYPE]) transformed_param[KEY_TYPE] = TYPE_SELECT # If Portlet dynamic parameter, don't add the options instead # just add the default value. if KEY_DYNAMIC in param: dynamic_param = { KEY_NAME: param[KEY_DEFAULT], KEY_VALUE: param[KEY_DEFAULT] } transformed_param[KEY_OPTIONS] = [dynamic_param] else: transformed_param[KEY_OPTIONS] = values if type(param[KEY_TYPE]) == str: transformed_param[KEY_DATATYPE] = param[KEY_TYPE] else: data_type = param[KEY_TYPE] transformed_param[ KEY_DATATYPE] = data_type.__module__ + '.' + data_type.__name__ ### DataType-attributes are no longer necessary, they were already copied on each OPTION transformed_param[KEY_ATTRIBUTES] = [] else: if param.get(KEY_OPTIONS) is not None: transformed_param[ KEY_OPTIONS] = self.fill_input_tree_with_options( param[KEY_OPTIONS], project_id, category_key) if param.get(KEY_REQUIRED) and len( param[KEY_OPTIONS]) > 0 and param.get( KEY_DEFAULT) is None: transformed_param[KEY_DEFAULT] = str( param[KEY_OPTIONS][-1][KEY_VALUE]) if param.get(KEY_ATTRIBUTES) is not None: transformed_param[ KEY_ATTRIBUTES] = self.fill_input_tree_with_options( param[KEY_ATTRIBUTES], project_id, category_key) result.append(transformed_param) return result
def fill_input_tree_with_options(self, attributes_list, project_id, category_key): """ For a datatype node in the input tree, load all instances from the db that fit the filters. """ result = [] for param in attributes_list: if getattr(param, KEY_UI_HIDE, False): continue transformed_param = copy(param) if isinstance(param, (itr.DatatypeNode, itr.ComplexDtypeNode)): filter_condition = param.conditions if filter_condition is None: filter_condition = FilterChain('') filter_condition.add_condition( FilterChain.datatype + ".visible", "==", True) complex_dt_attributes = None if isinstance(param, itr.ComplexDtypeNode): complex_dt_attributes = self.fill_input_tree_with_options( param.attributes, project_id, category_key) values, total_count = self.populate_option_values_for_dtype( project_id, param.type, filter_condition, category_key, complex_dt_attributes) if total_count > MAXIMUM_DATA_TYPES_DISPLAYED: transformed_param.warning = WARNING_OVERFLOW if param.required and len( values) > 0 and param.default is None: transformed_param.default = str(values[-1][KEY_VALUE]) transformed_param.filterable = FilterChain.get_filters_for_type( param.type) transformed_param.type = TYPE_SELECT # todo this type transfer is not nice transformed_param.datatype = param.type # If Portlet dynamic parameter, don't add the options instead # just add the default value. if getattr(param, KEY_DYNAMIC, False): dynamic_param = { KEY_NAME: param.default, KEY_VALUE: param.default } transformed_param.options = [dynamic_param] else: transformed_param.options = values ### DataType-attributes are no longer necessary, they were already copied on each OPTION transformed_param.attributes = [] # todo check if this is ok elif isinstance(param, itr.SelectTypeNode): transformed_param.options = self.fill_input_tree_with_options( param.options, project_id, category_key) if len(param.options) > 0 and param.default is None: transformed_param.default = str(param.options[-1].value) elif isinstance(param, (itr.TypeNode, itr.DictNode)): #ComplexDatatypeNode enters here! transformed_param.attributes = self.fill_input_tree_with_options( param.attributes, project_id, category_key) result.append(transformed_param) return result
def fill_input_tree_with_options(self, attributes_list, project_id, category_key): """ For a datatype node in the input tree, load all instances from the db that fit the filters. """ result = [] for param in attributes_list: if param.get(KEY_UI_HIDE): continue transformed_param = copy(param) if KEY_TYPE in param and param[KEY_TYPE] not in STATIC_ACCEPTED_TYPES: if KEY_CONDITION in param: filter_condition = param[KEY_CONDITION] else: filter_condition = FilterChain('') filter_condition.add_condition(FilterChain.datatype + ".visible", "==", True) values, total_count = self.populate_option_values_for_dtype(project_id, param[KEY_TYPE], filter_condition, category_key) if param.get(KEY_ATTRIBUTES): # copy complex datatype attributes to all options complex_dt_attributes = self.fill_input_tree_with_options(param[KEY_ATTRIBUTES], project_id, category_key) for value in values: if value[KEY_NAME] != 'All': value[KEY_ATTRIBUTES] = complex_dt_attributes if total_count > MAXIMUM_DATA_TYPES_DISPLAYED: transformed_param[KEY_WARNING] = WARNING_OVERFLOW if param.get(KEY_REQUIRED) and len(values) > 0 and param.get(KEY_DEFAULT) is None: transformed_param[KEY_DEFAULT] = str(values[-1][KEY_VALUE]) transformed_param[KEY_FILTERABLE] = FilterChain.get_filters_for_type(param[KEY_TYPE]) transformed_param[KEY_TYPE] = TYPE_SELECT # If Portlet dynamic parameter, don't add the options instead # just add the default value. if KEY_DYNAMIC in param: dynamic_param = {KEY_NAME: param[KEY_DEFAULT], KEY_VALUE: param[KEY_DEFAULT]} transformed_param[KEY_OPTIONS] = [dynamic_param] else: transformed_param[KEY_OPTIONS] = values if type(param[KEY_TYPE]) == str: transformed_param[KEY_DATATYPE] = param[KEY_TYPE] else: data_type = param[KEY_TYPE] transformed_param[KEY_DATATYPE] = data_type.__module__ + '.' + data_type.__name__ ### DataType-attributes are no longer necessary, they were already copied on each OPTION transformed_param[KEY_ATTRIBUTES] = [] else: if param.get(KEY_OPTIONS) is not None: transformed_param[KEY_OPTIONS] = self.fill_input_tree_with_options(param[KEY_OPTIONS], project_id, category_key) if param.get(KEY_REQUIRED) and len(param[KEY_OPTIONS]) > 0 and param.get(KEY_DEFAULT) is None: transformed_param[KEY_DEFAULT] = str(param[KEY_OPTIONS][-1][KEY_VALUE]) if param.get(KEY_ATTRIBUTES) is not None: transformed_param[KEY_ATTRIBUTES] = self.fill_input_tree_with_options(param[KEY_ATTRIBUTES], project_id, category_key) result.append(transformed_param) return result