Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[17.09] Expose proper element_identifier in tool action template expansions #5049

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions lib/galaxy/tools/actions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down Expand Up @@ -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):
Expand Down
11 changes: 5 additions & 6 deletions lib/galaxy/tools/evaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
DatasetCollectionWrapper,
DatasetFilenameWrapper,
DatasetListWrapper,
ElementIdentifierMapper,
InputValueWrapper,
RawObjectWrapper,
SelectToolParameterWrapper,
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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):
Expand Down
21 changes: 15 additions & 6 deletions lib/galaxy/tools/parameters/wrapped.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
DatasetCollectionWrapper,
DatasetFilenameWrapper,
DatasetListWrapper,
ElementIdentifierMapper,
InputValueWrapper,
SelectToolParameterWrapper
)
Expand All @@ -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):
Expand All @@ -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:
Expand All @@ -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):
Expand Down
18 changes: 18 additions & 0 deletions lib/galaxy/tools/wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
30 changes: 30 additions & 0 deletions test/api/test_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
23 changes: 23 additions & 0 deletions test/functional/tools/identifier_in_actions.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<tool id="identifier_in_actions" name="identifier_in_actions" version="1.0.0">
<command><![CDATA[
cp '$input' '$output'
]]></command>
<inputs>
<param name="input" type="data" multiple="false" />
</inputs>
<outputs>
<data format="tabular" name="output">
<actions>
<action name="column_names" type="metadata" default="First,${input.element_identifier}" />
</actions>
</data>
</outputs>
<tests>
<test>
<param name="input" value="2.tabular" />
<output name="output">
<metadata name="column_names" value="First,2.tabular"/>
</output>
</test>
</tests>
</tool>
1 change: 1 addition & 0 deletions test/functional/tools/samples_tool_conf.xml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
<tool file="identifier_multiple_in_conditional.xml" />
<tool file="identifier_multiple_in_repeat.xml" />
<tool file="identifier_collection.xml" />
<tool file="identifier_in_actions.xml" />
<tool file="tool_directory.xml" />
<tool file="output_action_change_format.xml" />
<tool file="collection_paired_test.xml" />
Expand Down