diff --git a/lib/galaxy/tool_util_models/parameters.py b/lib/galaxy/tool_util_models/parameters.py index 3922cf39b70..9bdf85e7cef 100644 --- a/lib/galaxy/tool_util_models/parameters.py +++ b/lib/galaxy/tool_util_models/parameters.py @@ -501,15 +501,14 @@ class FloatParameterModel(BaseGalaxyToolParameterModelDefinition): return False -DataSrcT = Literal["hda", "ldda"] -MultiDataSrcT = Literal["hda", "ldda", "hdca", "dce"] -# @jmchilton you meant CollectionSrcT - fix that at some point please. -CollectionStrT = Literal["hdca"] +# External collection source type. ``dce`` is accepted because a job that maps +# over a nested collection (e.g. subcollection mapping over a ``list:paired``) +# records its input as a ``DatasetCollectionElement``; rerunning such a job +# resubmits that ``dce`` reference through the request model. +CollectionSrcT = Literal["hdca", "dce"] # Internal collection source type - includes dce for subcollection mapping CollectionInternalSrcT = Literal["hdca", "dce"] -TestCaseDataSrcT = Literal["File"] - class LegacyRequestModelAttributes(StrictModel): # Here for bioblend's sake, should be stripped @@ -1267,12 +1266,12 @@ class DataParameterModel(BaseGalaxyToolParameterModelDefinition): class DataCollectionRequest(StrictModel): - src: CollectionStrT + src: CollectionSrcT id: StrictStr class BatchCollectionInstance(StrictModel): - src: CollectionStrT + src: CollectionSrcT id: StrictStr map_over_type: Optional[str] = None diff --git a/lib/galaxy_test/api/test_tools.py b/lib/galaxy_test/api/test_tools.py index b247e732f74..0f0085e39c0 100644 --- a/lib/galaxy_test/api/test_tools.py +++ b/lib/galaxy_test/api/test_tools.py @@ -3194,6 +3194,33 @@ class TestToolsApi(ApiTestCase, TestsTools): assert len(response_object["jobs"]) == 2 assert len(response_object["implicit_collections"]) == 1 + @skip_without_tool("collection_paired_test") + def test_request_paired_collection_input_with_dce(self): + """Regression for https://github.com/galaxyproject/galaxy/issues/22923 + + A job that maps over a ``list:paired`` records its paired-collection + input as a ``DatasetCollectionElement`` (``src: dce``). Rerunning such a + job resubmits that ``dce`` reference through the structured tool-request + path, which must validate against the request model. + """ + with self.dataset_populator.test_history() as history_id: + pair_ids = [] + for _ in range(2): + pair_id = self.dataset_collection_populator.create_pair_in_history( + history_id, contents=["forward", "reverse"], wait=True + ).json()["outputs"][0]["id"] + pair_ids.append(pair_id) + list_hdca = self.dataset_collection_populator.create_list_from_pairs(history_id, pair_ids) + # The element of a list:paired is itself a paired collection, referenced via a dce. + dce_id = list_hdca.json()["elements"][0]["id"] + + inputs = {"f1": {"src": "dce", "id": dce_id}} + response = self.dataset_populator.tool_request_raw("collection_paired_test", inputs, history_id) + self._assert_status_code_is(response, 200) + tool_request_id = response.json()["tool_request_id"] + assert self.dataset_populator.wait_on_tool_request(tool_request_id) + self.dataset_populator.wait_for_history(history_id, assert_ok=True) + @skip_without_tool("identifier_source") def test_default_identifier_source_map_over(self): with self.dataset_populator.test_history() as history_id: diff --git a/test/unit/tool_util/parameter_specification.yml b/test/unit/tool_util/parameter_specification.yml index 0aabb1056d6..8e55e2204e5 100644 --- a/test/unit/tool_util/parameter_specification.yml +++ b/test/unit/tool_util/parameter_specification.yml @@ -1591,9 +1591,16 @@ gx_data_multiple_optional: gx_data_collection: request_valid: - parameter: {src: hdca, id: abcdabcd} + # dce subcollection reference - e.g. rerunning a job that mapped over a list:paired + - parameter: {src: dce, id: abcdabcd} + # batching (multirun) over dce subcollections + - parameter: {__class__: "Batch", values: [{src: dce, id: abcdabcd}]} + - parameter: {__class__: "Batch", values: [{src: dce, id: abcdabcd, map_over_type: paired}]} - parameter: {class: "Collection", collection_type: "list", elements: []} request_invalid: - parameter: {src: hdca, id: 7} + # external request ids must be encoded strings, not decoded ints - for hdca and dce alike + - parameter: {src: dce, id: 7} - parameter: null - parameter: {src: fooda, id: abcdabcd} - parameter: {id: abcdabcd} @@ -1605,9 +1612,12 @@ gx_data_collection: - parameter: {class: "CollectionX", collection_type: "list", elements: []} request_internal_valid: - parameter: {src: hdca, id: 5} + - parameter: {src: dce, id: 5} + - parameter: {__class__: "Batch", values: [{src: dce, id: 5}]} - parameter: {class: "Collection", collection_type: "list", elements: []} request_internal_invalid: - parameter: {src: hdca, id: abcdabcd} + - parameter: {src: dce, id: abcdabcd} - parameter: null - parameter: {src: fooda, id: abcdabcd} - parameter: {id: abcdabcd} @@ -1619,6 +1629,7 @@ gx_data_collection: - parameter: {class: "CollectionX", collection_type: "list", elements: []} request_internal_dereferenced_valid: - parameter: {src: hdca, id: 5} + - parameter: {src: dce, id: 5} request_internal_dereferenced_invalid: - parameter: {src: hdca, id: abcdabcd} # At thsi point the collection should have been dereferenced into datasets, @@ -1759,6 +1770,7 @@ gx_data_collection: gx_data_collection_optional: request_valid: - parameter: {src: hdca, id: abcdabcd} + - parameter: {src: dce, id: abcdabcd} - parameter: null - {} request_invalid: @@ -1771,6 +1783,7 @@ gx_data_collection_optional: - parameter: {} request_internal_valid: - parameter: {src: hdca, id: 5} + - parameter: {src: dce, id: 5} - parameter: null - {} request_internal_invalid: