diff --git a/lib/galaxy/model/__init__.py b/lib/galaxy/model/__init__.py index 352467b04d8..becda4b1455 100644 --- a/lib/galaxy/model/__init__.py +++ b/lib/galaxy/model/__init__.py @@ -2125,6 +2125,10 @@ class DatasetInstance( object ): return False return True + @property + def is_ok(self): + return self.state == self.states.OK + @property def is_pending( self ): """ diff --git a/lib/galaxy/tools/__init__.py b/lib/galaxy/tools/__init__.py index f8c57d9112e..a597b8cc4a1 100755 --- a/lib/galaxy/tools/__init__.py +++ b/lib/galaxy/tools/__init__.py @@ -2235,6 +2235,25 @@ class ZipCollectionTool( DatabaseOperationTool ): ) +class FilterFailedDatasetsTool( DatabaseOperationTool ): + tool_type = 'filter_failed_datasets_collection' + require_dataset_ok = False + + def produce_outputs( self, trans, out_data, output_collections, incoming, history ): + hdca = incoming[ "input" ] + assert hdca.collection.collection_type == "list" + new_elements = odict() + for dce in hdca.collection.elements: + element = dce.element_object + if element.is_ok: + element_identifier = dce.element_identifier + new_elements[element_identifier] = element.copy() + + output_collections.create_collection( + self.outputs.values()[0], "output", elements=new_elements + ) + + # Populate tool_type to ToolClass mappings tool_types = {} for tool_class in [ Tool, SetMetadataTool, OutputParameterJSONTool, diff --git a/lib/galaxy/tools/filter_failed_collection.xml b/lib/galaxy/tools/filter_failed_collection.xml new file mode 100644 index 00000000000..7bd2e93dd2d --- /dev/null +++ b/lib/galaxy/tools/filter_failed_collection.xml @@ -0,0 +1,45 @@ + + datasets from a collection + + + + + + + + + + + + + + + + + + + + + + + + + + + + This tool takes a list dataset collction and filters out the failed + datasets from it. This is useful for continuing a multi-sample analysis + when one of more of the samples fails at some point. + + This tool will create new history datasets from your collection + but your quota usage will not increase. + + diff --git a/lib/galaxy/tools/special_tools.py b/lib/galaxy/tools/special_tools.py index b14415c8f29..4b5c8e7d897 100644 --- a/lib/galaxy/tools/special_tools.py +++ b/lib/galaxy/tools/special_tools.py @@ -6,6 +6,7 @@ SPECIAL_TOOLS = { "history import": "galaxy/tools/imp_exp/imp_history_from_archive.xml", "collection unzip": "galaxy/tools/unzip_collection.xml", "collection zip": "galaxy/tools/zip_collection.xml", + "filter failed datasets": "galaxy/tools/filter_failed_collection.xml", } diff --git a/test/api/helpers.py b/test/api/helpers.py index a72c5dc0051..02ea2717bce 100644 --- a/test/api/helpers.py +++ b/test/api/helpers.py @@ -145,18 +145,24 @@ class BaseDatasetPopulator( object ): return tool_response.json() def get_history_dataset_content( self, history_id, wait=True, **kwds ): - dataset_id = self.__history_dataset_id( history_id, wait=wait, **kwds ) + dataset_id = self.__history_content_id( history_id, wait=wait, **kwds ) display_response = self.__get_contents_request( history_id, "/%s/display" % dataset_id ) assert display_response.status_code == 200, display_response.content return display_response.content def get_history_dataset_details( self, history_id, **kwds ): - dataset_id = self.__history_dataset_id( history_id, **kwds ) + dataset_id = self.__history_content_id( history_id, **kwds ) details_response = self.__get_contents_request( history_id, "/datasets/%s" % dataset_id ) assert details_response.status_code == 200 return details_response.json() - def __history_dataset_id( self, history_id, wait=True, **kwds ): + def get_history_collection_details( self, history_id, **kwds ): + hdca_id = self.__history_content_id( history_id, **kwds ) + details_response = self.__get_contents_request( history_id, "/dataset_collections/%s" % hdca_id ) + assert details_response.status_code == 200, details_response.content + return details_response.json() + + def __history_content_id( self, history_id, wait=True, **kwds ): if wait: assert_ok = kwds.get( "assert_ok", True ) self.wait_for_history( history_id, assert_ok=assert_ok ) diff --git a/test/api/test_tools.py b/test/api/test_tools.py index 190fe6245f7..17b1761955a 100644 --- a/test/api/test_tools.py +++ b/test/api/test_tools.py @@ -165,6 +165,37 @@ class ToolsTestCase( api.ApiTestCase ): implicit_collections = response[ "implicit_collections" ] self.assertEquals( len(implicit_collections), 1 ) + def test_filter_failed( self ): + history_id = self.dataset_populator.new_history() + ok_hdca_id = self.dataset_collection_populator.create_list_in_history( history_id, contents=["0", "1", "0", "1"] ).json()["id"] + exit_code_inputs = { + "input": { 'batch': True, 'values': [ {"src": "hdca", "id": ok_hdca_id} ] }, + } + response = self._run( "exit_code_from_file", history_id, exit_code_inputs, assert_ok=False ).json() + self.dataset_populator.wait_for_history( history_id, assert_ok=False ) + + mixed_implicit_collections = response[ "implicit_collections" ] + self.assertEquals( len(mixed_implicit_collections), 1 ) + mixed_hdca_hid = mixed_implicit_collections[0]["hid"] + mixed_hdca = self.dataset_populator.get_history_collection_details(history_id, hid=mixed_hdca_hid, wait=False) + + def get_state(dce): + return dce["object"]["state"] + + mixed_states = map(get_state, mixed_hdca["elements"]) + assert mixed_states == [u"ok", u"error", u"ok", u"error"], mixed_states + inputs = { + "input": { "src": "hdca", "id": mixed_hdca["id"] }, + } + response = self._run( "__FILTER_FAILED_DATASETS__", history_id, inputs, assert_ok=False ).json() + self.dataset_populator.wait_for_history( history_id, assert_ok=False ) + filter_output_collections = response[ "output_collections" ] + self.assertEquals( len(filter_output_collections), 1 ) + filtered_hid = filter_output_collections[0]["hid"] + filtered_hdca = self.dataset_populator.get_history_collection_details(history_id, hid=filtered_hid, wait=False) + filtered_states = map(get_state, filtered_hdca["elements"]) + assert filtered_states == [u"ok", u"ok"], filtered_states + @skip_without_tool( "multi_select" ) def test_multi_select_as_list( self ): history_id = self.dataset_populator.new_history() diff --git a/test/functional/tools/exit_code_from_file.xml b/test/functional/tools/exit_code_from_file.xml new file mode 100644 index 00000000000..5d66d96aa3c --- /dev/null +++ b/test/functional/tools/exit_code_from_file.xml @@ -0,0 +1,13 @@ + + + sh -c "exit `cat $input`" + + + + + + + + + + diff --git a/test/functional/tools/samples_tool_conf.xml b/test/functional/tools/samples_tool_conf.xml index bbbeed7395f..f41aed6ad32 100644 --- a/test/functional/tools/samples_tool_conf.xml +++ b/test/functional/tools/samples_tool_conf.xml @@ -35,6 +35,7 @@ --> +