From 197333857c6ce1af61b4b9ad148d465600074e8b Mon Sep 17 00:00:00 2001 From: John Chilton Date: Mon, 20 Nov 2017 12:24:27 -0500 Subject: [PATCH] Bug fix - expose proper element_identifier in tool action template expansions. xref https://github.com/galaxyproject/tools-iuc/commit/f57f1bf4816f212b83c08e0e3c3782ebba8b7d9a --- lib/galaxy/tools/actions/__init__.py | 6 ++-- lib/galaxy/tools/evaluation.py | 11 ++++--- lib/galaxy/tools/parameters/wrapped.py | 21 +++++++++---- lib/galaxy/tools/wrappers.py | 18 +++++++++++ test/api/test_tools.py | 30 +++++++++++++++++++ .../tools/identifier_in_actions.xml | 23 ++++++++++++++ test/functional/tools/samples_tool_conf.xml | 1 + 7 files changed, 95 insertions(+), 15 deletions(-) create mode 100644 test/functional/tools/identifier_in_actions.xml diff --git a/lib/galaxy/tools/actions/__init__.py b/lib/galaxy/tools/actions/__init__.py index 17f64e88f5f5..ada7bd8a67da 100644 --- a/lib/galaxy/tools/actions/__init__.py +++ b/lib/galaxy/tools/actions/__init__.py @@ -257,7 +257,7 @@ def execute(self, tool, trans, incoming={}, return_job=False, set_output_hid=Tru # Add the dbkey to the incoming parameters incoming["dbkey"] = input_dbkey # wrapped params are used by change_format action and by output.label; only perform this wrapping once, as needed - wrapped_params = self._wrapped_params(trans, tool, incoming) + wrapped_params = self._wrapped_params(trans, tool, incoming, inp_data) out_data = odict() input_collections = dict((k, v[0][0]) for k, v in inp_dataset_collections.items()) @@ -514,8 +514,8 @@ def handle_output(name, output, hidden=None): trans.log_event("Added job to the job queue, id: %s" % str(job.id), tool_id=job.tool_id) return job, out_data - def _wrapped_params(self, trans, tool, incoming): - wrapped_params = WrappedParameters(trans, tool, incoming) + def _wrapped_params(self, trans, tool, incoming, input_datasets=None): + wrapped_params = WrappedParameters(trans, tool, incoming, input_datasets=input_datasets) return wrapped_params def _get_on_text(self, inp_data): diff --git a/lib/galaxy/tools/evaluation.py b/lib/galaxy/tools/evaluation.py index 582f20b019a2..075107a51e78 100644 --- a/lib/galaxy/tools/evaluation.py +++ b/lib/galaxy/tools/evaluation.py @@ -26,6 +26,7 @@ DatasetCollectionWrapper, DatasetFilenameWrapper, DatasetListWrapper, + ElementIdentifierMapper, InputValueWrapper, RawObjectWrapper, SelectToolParameterWrapper, @@ -234,11 +235,9 @@ def wrap_input(input_values, input): real_path = dataset.file_name if real_path in input_dataset_paths: wrapper_kwds["dataset_path"] = input_dataset_paths[real_path] - identifier_key = identifier_key_dict.get(dataset, None) - if identifier_key: - element_identifier = param_dict.get(identifier_key, None) - if element_identifier: - wrapper_kwds["identifier"] = element_identifier + element_identifier = element_identifier_mapper.identifier(dataset, param_dict) + if element_identifier: + wrapper_kwds["identifier"] = element_identifier input_values[input.name] = \ DatasetFilenameWrapper(dataset, **wrapper_kwds) elif isinstance(input, DataCollectionToolParameter): @@ -266,7 +265,7 @@ def wrap_input(input_values, input): # tools where the inputs don't even get passed through. These # tools (e.g. UCSC) should really be handled in a special way. if self.tool.check_values: - identifier_key_dict = dict((v, "%s|__identifier__" % k) for k, v in input_datasets.items()) # allows lookup of identifier through HDA. + element_identifier_mapper = ElementIdentifierMapper(input_datasets) self.__walk_inputs(self.tool.inputs, param_dict, wrap_input) def __populate_input_dataset_wrappers(self, param_dict, input_datasets, input_dataset_paths): diff --git a/lib/galaxy/tools/parameters/wrapped.py b/lib/galaxy/tools/parameters/wrapped.py index c93b69e065b3..f35555bad138 100644 --- a/lib/galaxy/tools/parameters/wrapped.py +++ b/lib/galaxy/tools/parameters/wrapped.py @@ -12,6 +12,7 @@ DatasetCollectionWrapper, DatasetFilenameWrapper, DatasetListWrapper, + ElementIdentifierMapper, InputValueWrapper, SelectToolParameterWrapper ) @@ -21,11 +22,12 @@ class WrappedParameters(object): - def __init__(self, trans, tool, incoming): + def __init__(self, trans, tool, incoming, input_datasets=None): self.trans = trans self.tool = tool self.incoming = incoming self._params = PARAMS_UNWRAPPED + self._input_datasets = input_datasets @property def params(self): @@ -40,6 +42,8 @@ def wrap_values(self, inputs, input_values, skip_missing_values=False): tool = self.tool incoming = self.incoming + element_identifier_mapper = ElementIdentifierMapper(self._input_datasets) + # Wrap tool inputs as necessary for input in inputs.values(): if input.name not in input_values and skip_missing_values: @@ -64,11 +68,16 @@ def wrap_values(self, inputs, input_values, skip_missing_values=False): tool=tool, name=input.name) elif isinstance(input, DataToolParameter): - input_values[input.name] = \ - DatasetFilenameWrapper(value, - datatypes_registry=trans.app.datatypes_registry, - tool=tool, - name=input.name) + wrapper_kwds = dict( + datatypes_registry=trans.app.datatypes_registry, + tool=tool, + name=input.name + ) + element_identifier = element_identifier_mapper.identifier(value, input_values) + if element_identifier: + wrapper_kwds["identifier"] = element_identifier + + input_values[input.name] = DatasetFilenameWrapper(value, **wrapper_kwds) elif isinstance(input, SelectToolParameter): input_values[input.name] = SelectToolParameterWrapper(input, input_values[input.name], other_values=incoming) elif isinstance(input, DataCollectionToolParameter): diff --git a/lib/galaxy/tools/wrappers.py b/lib/galaxy/tools/wrappers.py index 1ff41a5eb298..31e3314ea3b8 100644 --- a/lib/galaxy/tools/wrappers.py +++ b/lib/galaxy/tools/wrappers.py @@ -430,3 +430,21 @@ def __bool__(self): # not specified or if resulting collection is empty. return self.__input_supplied and bool(self.__element_instance_list) __nonzero__ = __bool__ + + +class ElementIdentifierMapper(object): + """Track mapping of dataset collection elements datasets to element identifiers.""" + + def __init__(self, input_datasets=None): + if input_datasets is not None: + self.identifier_key_dict = dict((v, "%s|__identifier__" % k) for k, v in input_datasets.items()) + else: + self.identifier_key_dict = {} + + def identifier(self, dataset_value, input_values): + identifier_key = self.identifier_key_dict.get(dataset_value, None) + element_identifier = None + if identifier_key: + element_identifier = input_values.get(identifier_key, None) + + return element_identifier diff --git a/test/api/test_tools.py b/test/api/test_tools.py index 0dcfe546bacc..8846c4dcbc23 100644 --- a/test/api/test_tools.py +++ b/test/api/test_tools.py @@ -978,6 +978,36 @@ def test_identifier_with_data_collection(self): output1_content = self.dataset_populator.get_history_dataset_content(history_id, dataset=output1) self.assertEquals(output1_content.strip(), '\n'.join([d['name'] for d in element_identifiers])) + @skip_without_tool("identifier_in_actions") + def test_identifier_in_actions(self): + history_id = self.dataset_populator.new_history() + + element_identifiers = self.dataset_collection_populator.list_identifiers(history_id, contents=["1\t2"]) + + payload = dict( + instance_type="history", + history_id=history_id, + element_identifiers=json.dumps(element_identifiers), + collection_type="list", + ) + + create_response = self._post("dataset_collections", payload) + dataset_collection = create_response.json() + + inputs = { + "input": {'batch': True, 'values': [{'src': 'hdca', 'id': dataset_collection['id']}]}, + } + + self.dataset_populator.wait_for_history(history_id, assert_ok=True) + create_response = self._run("identifier_in_actions", history_id, inputs) + self._assert_status_code_is(create_response, 200) + create = create_response.json() + outputs = create['outputs'] + output1 = outputs[0] + + output_details = self.dataset_populator.get_history_dataset_details(history_id, dataset=output1) + assert output_details["metadata_column_names"][1] == "data1", output_details + @skip_without_tool("cat1") def test_map_over_nested_collections(self): history_id = self.dataset_populator.new_history() diff --git a/test/functional/tools/identifier_in_actions.xml b/test/functional/tools/identifier_in_actions.xml new file mode 100644 index 000000000000..ecccf112a478 --- /dev/null +++ b/test/functional/tools/identifier_in_actions.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/test/functional/tools/samples_tool_conf.xml b/test/functional/tools/samples_tool_conf.xml index 18e55f282f1d..acd9d9dd7304 100644 --- a/test/functional/tools/samples_tool_conf.xml +++ b/test/functional/tools/samples_tool_conf.xml @@ -91,6 +91,7 @@ +