From 4f205b60de798c6bdebaaa8781334cc39e4a26fa Mon Sep 17 00:00:00 2001 From: mvdbeek Date: Fri, 24 Mar 2023 16:31:39 -0400 Subject: [PATCH 01/15] Add data_manager_mode to tool_run interface --- bioblend/galaxy/tools/__init__.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/bioblend/galaxy/tools/__init__.py b/bioblend/galaxy/tools/__init__.py index cdafb4f64..b2abf83a7 100644 --- a/bioblend/galaxy/tools/__init__.py +++ b/bioblend/galaxy/tools/__init__.py @@ -333,6 +333,7 @@ def run_tool( tool_id: str, tool_inputs: Union[InputsBuilder, dict], input_format: Literal["21.01", "legacy"] = "legacy", + data_manager_mode: Optional[Literal["populate", "dry_run", "bundle"]] = None, ) -> Dict[str, Any]: """ Runs tool specified by ``tool_id`` in history indicated @@ -344,6 +345,16 @@ def run_tool( :type tool_id: str :param tool_id: ID of the tool to be run + :type data_manager_mode: str + :param data_manager_mode: Possible values are 'populate', 'dry_run' and 'bundle'. + + 'populate' is the default behavior for data manager tools and results in tool data table + files being updated after the data manager job completes. + + 'dry_run' will skip any processing after the data manager job completes + + 'bundle' will create a data manager bundle that can be imported on other Galaxy servers. + :type tool_inputs: dict :param tool_inputs: dictionary of input datasets and parameters for the tool (see below) @@ -416,6 +427,10 @@ def run_tool( payload["inputs"] = tool_inputs.to_dict() else: payload["inputs"] = tool_inputs + + if data_manager_mode: + payload["data_manager_mode"] = data_manager_mode + return self._post(payload) def upload_file( From 8e5da2d59b186c7fcd1764ee395b83004d8e94ff Mon Sep 17 00:00:00 2001 From: cat-bro Date: Sat, 25 Mar 2023 12:10:57 +1100 Subject: [PATCH 02/15] Add container_resolution --- bioblend/galaxy/__init__.py | 2 + .../galaxy/container_resolution/__init__.py | 194 ++++++++++++++++++ 2 files changed, 196 insertions(+) create mode 100644 bioblend/galaxy/container_resolution/__init__.py diff --git a/bioblend/galaxy/__init__.py b/bioblend/galaxy/__init__.py index 40a72789a..937b23d28 100644 --- a/bioblend/galaxy/__init__.py +++ b/bioblend/galaxy/__init__.py @@ -5,6 +5,7 @@ from bioblend.galaxy import ( config, + container_resolution, dataset_collections, datasets, datatypes, @@ -93,6 +94,7 @@ def __init__( self.toolshed = toolshed.ToolShedClient(self) self.toolShed = self.toolshed # historical alias self.config = config.ConfigClient(self) + self.container_resolution = container_resolution.ContainerResolutionClient(self) self.visual = visual.VisualClient(self) self.quotas = quotas.QuotaClient(self) self.groups = groups.GroupsClient(self) diff --git a/bioblend/galaxy/container_resolution/__init__.py b/bioblend/galaxy/container_resolution/__init__.py new file mode 100644 index 000000000..2d72830e4 --- /dev/null +++ b/bioblend/galaxy/container_resolution/__init__.py @@ -0,0 +1,194 @@ +""" +Contains interactions dealing with Galaxy container resolvers. +""" +from typing import ( + List, + Optional, +) + +from typing_extensions import Literal + +from bioblend.galaxy.client import Client + + +class ContainerResolutionClient(Client): + module = "container_resolvers" + + def __init__(self, galaxy_instance): + super().__init__(galaxy_instance) + + def get_container_resolvers(self): + """ GET /api/container_resolvers """ + url = self._make_url() + return self._get(url=url) + + def show_container_resolver(self, index: int): + """ GET /api/container_resolvers/ """ + url = f'{self._make_url()}/{index}' + return self._get(url=url) + + def resolve( + self, + index: Optional[int] = None, + tool_id: Optional[str] = None, + resolver_type: Optional[str] = None, + container_type: Optional[str] = None, + requirements_only: bool = False, + install: bool = False, + ) -> dict: + """ + Resolve described requirement against specified container resolvers. + + :type index: int + :param index: index of the dependency resolver with respect to + the dependency resolvers config file + + :type tool_id: str + :param tool_id: tool id to resolve against containers + + :type resolver_type: str + :param resolver_type: restrict to specified resolver type + + :type container_type: str + :param container_type: restrict to specified container type + + :type requirements_only: + :param requirements_only: ignore tool containers, properties - just search based on tool requirements set to True to mimic default behavior of tool dependency API. + + :type install: bool + :param install: allow installation of new containers (for build_mulled containers) the way job resolution will operate, defaults to False + + :rtype: dict + TODO: example + """ + params ={} + if tool_id: + params["tool_id"] = tool_id + if resolver_type: + params["resolver_type"] = resolver_type + if container_type: + params["container_type"] = container_type + params["requirements_only"] = requirements_only + params["install"] = install + if index is not None: + url = "/".join((self._make_url(), str(index), "resolve")) + else: + url = "/".join((self._make_url(), "resolve")) + return self._get(url=url, params=params) + + def resolve_toolbox( + self, + index: Optional[int] = None, + tool_ids: Optional[List[str]] = None, + resolver_type: Optional[str] = None, + container_type: Optional[str] = None, + requirements_only: bool = False, + install: bool = False, + ) -> dict: + """ + Apply resolve() to each tool in the toolbox and return the results as a list. + See documentation for resolve() for a description of parameters that can be + consumed and a description of the resulting items. + + :type index: int + :param index: index of the dependency resolver with respect to + the dependency resolvers config file + + :type tool_ids: list + :param tool_ids: tool_ids to filter toolbox on + + :type resolver_type: str + :param resolver_type: restrict to specified resolver type + + :type container_type: str + :param container_type: restrict to specified container type + + :type install: bool + :param install: allow installation of new containers (for build_mulled containers) the way job resolution will operate, defaults to False + + :rtype: dict + TODO: example + """ + params ={} + if tool_ids: + params["tool_ids"] = ",".join(tool_ids) + if resolver_type: + params["resolver_type"] = resolver_type + if container_type: + params["container_type"] = container_type + params["requirements_only"] = requirements_only + params["install"] = install + if index is not None: + url = "/".join((self._make_url(), str(index), "toolbox")) + else: + url = "/".join((self._make_url(), "toolbox")) + return self._get(url=url, payload=params) + + def resolve_toolbox_with_install( + self, + index: Optional[int] = None, + tool_ids: Optional[List[str]] = None, + resolver_type: Optional[str] = None, + container_type: Optional[str] = None, + requirements_only: bool = False, + install: bool = False, + ) -> list: + """ + Summarize requirements across toolbox (for Tool Management grid). + + :type index: int + :param index: index of the dependency resolver with respect to + the dependency resolvers config file + + :type tool_ids: list + :param tool_ids: tool_ids to filter toolbox on + + :type resolver_type: str + :param resolver_type: restrict to specified resolver type + + :type container_type: str + :param container_type: restrict to specified container type + + :type install: bool + :param install: allow installation of new containers (for build_mulled* containers) the way job resolution will operate, defaults to False + + :rtype: list of dicts + :returns: dictified descriptions of the dependencies, with attribute + `dependency_type: None` if no match was found. + For example:: + + [{'requirements': [{'name': 'canu', + 'specs': [], + 'type': 'package', + 'version': '2.2'}], + 'status': {'cacheable': False, + 'container_description': {'identifier': 'docker://quay.io/biocontainers/canu:2.2--ha47f30e_0', + 'resolve_dependencies': False, + 'shell': '/bin/bash', + 'type': 'singularity'}, + 'container_resolver': {'builds_on_resolution': False, + 'can_uninstall_dependencies': False, + 'model_class': 'MulledSingularityContainerResolver', + 'resolver_type': 'mulled_singularity'}, + 'dependency_type': 'singularity', + 'environment_path': 'docker://quay.io/biocontainers/canu:2.2--ha47f30e_0', + 'exact': True, + 'model_class': 'ContainerDependency', + 'name': None, + 'version': None}, + 'tool_id': 'toolshed.g2.bx.psu.edu/repos/bgruening/canu/canu/2.2+galaxy0'}] + """ + params ={} + if tool_ids: + params["tool_ids"] = ",".join(tool_ids) + if resolver_type: + params["resolver_type"] = resolver_type + if container_type: + params["container_type"] = container_type + params["requirements_only"] = requirements_only + params["install"] = install + if index is not None: + url = "/".join((self._make_url(), str(index), "toolbox", "install")) + else: + url = "/".join((self._make_url(), "toolbox", "install")) + return self._post(url=url, payload=params) From f221d2ef4c78fd5f5675e4b1173381400620a95b Mon Sep 17 00:00:00 2001 From: cat-bro Date: Sat, 25 Mar 2023 13:08:10 +1100 Subject: [PATCH 03/15] remove unused import and fix description --- .../galaxy/container_resolution/__init__.py | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/bioblend/galaxy/container_resolution/__init__.py b/bioblend/galaxy/container_resolution/__init__.py index 2d72830e4..f6691317d 100644 --- a/bioblend/galaxy/container_resolution/__init__.py +++ b/bioblend/galaxy/container_resolution/__init__.py @@ -6,25 +6,20 @@ Optional, ) -from typing_extensions import Literal - from bioblend.galaxy.client import Client class ContainerResolutionClient(Client): module = "container_resolvers" - def __init__(self, galaxy_instance): - super().__init__(galaxy_instance) - - def get_container_resolvers(self): - """ GET /api/container_resolvers """ + def get_container_resolvers(self) -> list: + """GET /api/container_resolvers""" url = self._make_url() return self._get(url=url) - def show_container_resolver(self, index: int): - """ GET /api/container_resolvers/ """ - url = f'{self._make_url()}/{index}' + def show_container_resolver(self, index: int) -> dict: + """GET /api/container_resolvers/""" + url = f"{self._make_url()}/{index}" return self._get(url=url) def resolve( @@ -52,7 +47,7 @@ def resolve( :type container_type: str :param container_type: restrict to specified container type - :type requirements_only: + :type requirements_only: bool :param requirements_only: ignore tool containers, properties - just search based on tool requirements set to True to mimic default behavior of tool dependency API. :type install: bool @@ -61,7 +56,7 @@ def resolve( :rtype: dict TODO: example """ - params ={} + params = {} if tool_id: params["tool_id"] = tool_id if resolver_type: @@ -87,7 +82,7 @@ def resolve_toolbox( ) -> dict: """ Apply resolve() to each tool in the toolbox and return the results as a list. - See documentation for resolve() for a description of parameters that can be + See documentation for resolve() for a description of parameters that can be consumed and a description of the resulting items. :type index: int @@ -103,13 +98,16 @@ def resolve_toolbox( :type container_type: str :param container_type: restrict to specified container type + :type requirements_only: bool + :param requirements_only: ignore tool containers, properties - just search based on tool requirements set to True to mimic default behavior of tool dependency API. + :type install: bool :param install: allow installation of new containers (for build_mulled containers) the way job resolution will operate, defaults to False :rtype: dict TODO: example """ - params ={} + params = {} if tool_ids: params["tool_ids"] = ",".join(tool_ids) if resolver_type: @@ -122,7 +120,7 @@ def resolve_toolbox( url = "/".join((self._make_url(), str(index), "toolbox")) else: url = "/".join((self._make_url(), "toolbox")) - return self._get(url=url, payload=params) + return self._get(url=url, params=params) def resolve_toolbox_with_install( self, @@ -134,7 +132,7 @@ def resolve_toolbox_with_install( install: bool = False, ) -> list: """ - Summarize requirements across toolbox (for Tool Management grid). + Do the resolution of dependencies like resolve_toolbox(), but allow building and installing new containers. :type index: int :param index: index of the dependency resolver with respect to @@ -149,6 +147,9 @@ def resolve_toolbox_with_install( :type container_type: str :param container_type: restrict to specified container type + :type requirements_only: bool + :param requirements_only: ignore tool containers, properties - just search based on tool requirements set to True to mimic default behavior of tool dependency API. + :type install: bool :param install: allow installation of new containers (for build_mulled* containers) the way job resolution will operate, defaults to False @@ -178,7 +179,7 @@ def resolve_toolbox_with_install( 'version': None}, 'tool_id': 'toolshed.g2.bx.psu.edu/repos/bgruening/canu/canu/2.2+galaxy0'}] """ - params ={} + params = {} if tool_ids: params["tool_ids"] = ",".join(tool_ids) if resolver_type: From 3dbede49712d915b4bdb3755db9e1fccb2bbbbdd Mon Sep 17 00:00:00 2001 From: cat-bro Date: Mon, 17 Apr 2023 16:18:07 +1000 Subject: [PATCH 04/15] Update bioblend/galaxy/container_resolution/__init__.py Co-authored-by: M Bernt --- bioblend/galaxy/container_resolution/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bioblend/galaxy/container_resolution/__init__.py b/bioblend/galaxy/container_resolution/__init__.py index f6691317d..b4c8da8db 100644 --- a/bioblend/galaxy/container_resolution/__init__.py +++ b/bioblend/galaxy/container_resolution/__init__.py @@ -114,8 +114,8 @@ def resolve_toolbox( params["resolver_type"] = resolver_type if container_type: params["container_type"] = container_type - params["requirements_only"] = requirements_only - params["install"] = install + params["requirements_only"] = str(requirements_only) + params["install"] = str(install) if index is not None: url = "/".join((self._make_url(), str(index), "toolbox")) else: From 03f6c0412946db301a7f5973e3ae40a927a43011 Mon Sep 17 00:00:00 2001 From: cat-bro Date: Mon, 17 Apr 2023 16:18:16 +1000 Subject: [PATCH 05/15] Update bioblend/galaxy/container_resolution/__init__.py Co-authored-by: M Bernt --- bioblend/galaxy/container_resolution/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bioblend/galaxy/container_resolution/__init__.py b/bioblend/galaxy/container_resolution/__init__.py index b4c8da8db..ee35b3e16 100644 --- a/bioblend/galaxy/container_resolution/__init__.py +++ b/bioblend/galaxy/container_resolution/__init__.py @@ -186,8 +186,7 @@ def resolve_toolbox_with_install( params["resolver_type"] = resolver_type if container_type: params["container_type"] = container_type - params["requirements_only"] = requirements_only - params["install"] = install + params["requirements_only"] = str(requirements_only) if index is not None: url = "/".join((self._make_url(), str(index), "toolbox", "install")) else: From 70eced328864fcfa61d96bb3b79f6a74e91710d8 Mon Sep 17 00:00:00 2001 From: cat-bro Date: Mon, 17 Apr 2023 16:18:25 +1000 Subject: [PATCH 06/15] Update bioblend/galaxy/container_resolution/__init__.py Co-authored-by: M Bernt --- bioblend/galaxy/container_resolution/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bioblend/galaxy/container_resolution/__init__.py b/bioblend/galaxy/container_resolution/__init__.py index ee35b3e16..36dda73ca 100644 --- a/bioblend/galaxy/container_resolution/__init__.py +++ b/bioblend/galaxy/container_resolution/__init__.py @@ -63,8 +63,8 @@ def resolve( params["resolver_type"] = resolver_type if container_type: params["container_type"] = container_type - params["requirements_only"] = requirements_only - params["install"] = install + params["requirements_only"] = str(requirements_only) + params["install"] = str(install) if index is not None: url = "/".join((self._make_url(), str(index), "resolve")) else: From 9daa8c3216062777a88816fd0cfa21ab5d2191b5 Mon Sep 17 00:00:00 2001 From: cat-bro Date: Mon, 17 Apr 2023 16:34:58 +1000 Subject: [PATCH 07/15] tool id is not optional in resolve --- bioblend/galaxy/container_resolution/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bioblend/galaxy/container_resolution/__init__.py b/bioblend/galaxy/container_resolution/__init__.py index 36dda73ca..f9c9e76c9 100644 --- a/bioblend/galaxy/container_resolution/__init__.py +++ b/bioblend/galaxy/container_resolution/__init__.py @@ -25,7 +25,7 @@ def show_container_resolver(self, index: int) -> dict: def resolve( self, index: Optional[int] = None, - tool_id: Optional[str] = None, + tool_id: str = None, resolver_type: Optional[str] = None, container_type: Optional[str] = None, requirements_only: bool = False, From 829edc661bba802da0a4122f4dfc4301bb7db3ac Mon Sep 17 00:00:00 2001 From: cat-bro Date: Mon, 17 Apr 2023 17:52:57 +1000 Subject: [PATCH 08/15] Add return examples for index and show, many thanks @bernt-matthias --- .../galaxy/container_resolution/__init__.py | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/bioblend/galaxy/container_resolution/__init__.py b/bioblend/galaxy/container_resolution/__init__.py index f9c9e76c9..0d2f971f4 100644 --- a/bioblend/galaxy/container_resolution/__init__.py +++ b/bioblend/galaxy/container_resolution/__init__.py @@ -13,12 +13,45 @@ class ContainerResolutionClient(Client): module = "container_resolvers" def get_container_resolvers(self) -> list: - """GET /api/container_resolvers""" + """ + List container resolvers + + :rtype: list + return: List of container resolvers + + For example: + [{'builds_on_resolution': False, + 'can_uninstall_dependencies': False, + 'model_class': 'CachedExplicitSingularityContainerResolver', + 'resolver_type': 'cached_explicit_singularity'}, + {'builds_on_resolution': False, + 'can_uninstall_dependencies': False, + 'model_class': 'CachedMulledSingularityContainerResolver', + 'resolver_type': 'cached_mulled_singularity'}, + {'builds_on_resolution': False, + 'can_uninstall_dependencies': False, + 'model_class': 'MulledSingularityContainerResolver', + 'resolver_type': 'mulled_singularity'}] {'builds_on_resolution': False, + """ url = self._make_url() return self._get(url=url) def show_container_resolver(self, index: int) -> dict: - """GET /api/container_resolvers/""" + """ + Show container resolver + + :type index: int + :param index: index of the dependency resolver with respect to + the dependency resolvers config file + + :rtype: dict + return: Dict of properties of a given container resolver + + {'builds_on_resolution': False, + 'can_uninstall_dependencies': False, + 'model_class': 'CachedMulledSingularityContainerResolver', + 'resolver_type': 'cached_mulled_singularity'} + """ url = f"{self._make_url()}/{index}" return self._get(url=url) From 7d3a9140568f15370ad8b27a629db86994c5816e Mon Sep 17 00:00:00 2001 From: cat-bro Date: Mon, 17 Apr 2023 19:04:44 +1000 Subject: [PATCH 09/15] Update bioblend/galaxy/container_resolution/__init__.py Co-authored-by: M Bernt --- bioblend/galaxy/container_resolution/__init__.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/bioblend/galaxy/container_resolution/__init__.py b/bioblend/galaxy/container_resolution/__init__.py index 0d2f971f4..348cf2158 100644 --- a/bioblend/galaxy/container_resolution/__init__.py +++ b/bioblend/galaxy/container_resolution/__init__.py @@ -183,8 +183,6 @@ def resolve_toolbox_with_install( :type requirements_only: bool :param requirements_only: ignore tool containers, properties - just search based on tool requirements set to True to mimic default behavior of tool dependency API. - :type install: bool - :param install: allow installation of new containers (for build_mulled* containers) the way job resolution will operate, defaults to False :rtype: list of dicts :returns: dictified descriptions of the dependencies, with attribute From f36882bb5ab0b1ec3d4cf70d05f8f3fd7913950d Mon Sep 17 00:00:00 2001 From: cat-bro Date: Mon, 17 Apr 2023 19:04:53 +1000 Subject: [PATCH 10/15] Update bioblend/galaxy/container_resolution/__init__.py Co-authored-by: M Bernt --- bioblend/galaxy/container_resolution/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/bioblend/galaxy/container_resolution/__init__.py b/bioblend/galaxy/container_resolution/__init__.py index 348cf2158..07bb1d808 100644 --- a/bioblend/galaxy/container_resolution/__init__.py +++ b/bioblend/galaxy/container_resolution/__init__.py @@ -162,7 +162,6 @@ def resolve_toolbox_with_install( resolver_type: Optional[str] = None, container_type: Optional[str] = None, requirements_only: bool = False, - install: bool = False, ) -> list: """ Do the resolution of dependencies like resolve_toolbox(), but allow building and installing new containers. From 632b64a16b64998f9f37d2ec69bcfb0259599a9f Mon Sep 17 00:00:00 2001 From: cat-bro Date: Mon, 17 Apr 2023 19:49:18 +1000 Subject: [PATCH 11/15] mandatory argument tool_id goes before optional args in resolve --- bioblend/galaxy/container_resolution/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bioblend/galaxy/container_resolution/__init__.py b/bioblend/galaxy/container_resolution/__init__.py index 07bb1d808..5b893e5fe 100644 --- a/bioblend/galaxy/container_resolution/__init__.py +++ b/bioblend/galaxy/container_resolution/__init__.py @@ -57,8 +57,8 @@ def show_container_resolver(self, index: int) -> dict: def resolve( self, + tool_id: str, index: Optional[int] = None, - tool_id: str = None, resolver_type: Optional[str] = None, container_type: Optional[str] = None, requirements_only: bool = False, From e514fcd0288954ddba1c46754e448f22141bcd4b Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Tue, 6 Jun 2023 16:06:59 +0200 Subject: [PATCH 12/15] fix output type and add example --- .../galaxy/container_resolution/__init__.py | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/bioblend/galaxy/container_resolution/__init__.py b/bioblend/galaxy/container_resolution/__init__.py index 5b893e5fe..e1d1201a2 100644 --- a/bioblend/galaxy/container_resolution/__init__.py +++ b/bioblend/galaxy/container_resolution/__init__.py @@ -87,7 +87,19 @@ def resolve( :param install: allow installation of new containers (for build_mulled containers) the way job resolution will operate, defaults to False :rtype: dict - TODO: example + + For example: + { + 'requirements': [{'name': 'pyarrow', 'specs': [], 'type': 'package', 'version': '4.0.1'}], + 'status': { + 'cacheable': False, + 'container_description': {'identifier': 'quay.io/biocontainers/pyarrow:4.0.1', 'resolve_dependencies': False, 'shell': '/bin/bash', 'type': 'docker'}, + 'container_resolver': {'builds_on_resolution': False, 'can_uninstall_dependencies': False, 'model_class': 'MulledDockerContainerResolver', 'resolver_type': 'mulled'}, + 'dependency_type': 'docker', + ... + }, + 'tool_id': 'CONVERTER_parquet_to_csv' + } """ params = {} if tool_id: @@ -112,7 +124,7 @@ def resolve_toolbox( container_type: Optional[str] = None, requirements_only: bool = False, install: bool = False, - ) -> dict: + ) -> list: """ Apply resolve() to each tool in the toolbox and return the results as a list. See documentation for resolve() for a description of parameters that can be @@ -137,8 +149,9 @@ def resolve_toolbox( :type install: bool :param install: allow installation of new containers (for build_mulled containers) the way job resolution will operate, defaults to False - :rtype: dict - TODO: example + :rtype: list + For example:: + [{'tool_id': 'upload1', 'status': {'model_class': 'NullDependency', 'dependency_type': None, 'exact': True, 'name': None, 'version': None, 'cacheable': False}, 'requirements': []}, ...] """ params = {} if tool_ids: From e212ff66e7289a7f3ea4788b3c181322c2e14a97 Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Tue, 6 Jun 2023 16:07:27 +0200 Subject: [PATCH 13/15] add some tests for container resolution client --- .../TestGalaxyToolContainerResolution.py | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 bioblend/_tests/TestGalaxyToolContainerResolution.py diff --git a/bioblend/_tests/TestGalaxyToolContainerResolution.py b/bioblend/_tests/TestGalaxyToolContainerResolution.py new file mode 100644 index 000000000..5fb0cdc5d --- /dev/null +++ b/bioblend/_tests/TestGalaxyToolContainerResolution.py @@ -0,0 +1,87 @@ +""" +Test functions in bioblend.galaxy.tool_dependencies +""" +from . import ( + GalaxyTestBase, + test_util, +) + + +class TestGalaxyContainerResolution(GalaxyTestBase.GalaxyTestBase): + def test_get_container_resolvers(self): + container_resolvers = self.gi.container_resolution.get_container_resolvers() + assert isinstance(container_resolvers, list) + assert len(container_resolvers) > 0 + assert isinstance(container_resolvers[0], dict) + assert container_resolvers[0]['model_class'] == 'ExplicitContainerResolver' + assert container_resolvers[0]['resolver_type'] == 'explicit' + assert container_resolvers[0]['can_uninstall_dependencies'] is False + assert container_resolvers[0]['builds_on_resolution'] is False + + def test_show_container_resolver(self): + container_resolver = self.gi.container_resolution.show_container_resolver(0) + print(container_resolver) + assert isinstance(container_resolver, dict) + assert container_resolver['model_class'] == 'ExplicitContainerResolver' + assert container_resolver['resolver_type'] == 'explicit' + assert container_resolver['can_uninstall_dependencies'] is False + assert container_resolver['builds_on_resolution'] is False + + def test_resolve(self): + tool = self.gi.container_resolution.resolve(tool_id="CONVERTER_parquet_to_csv") + print(tool) + assert isinstance(tool, dict) + + toolbox_requirements_only = self.gi.container_resolution.resolve(tool_id="CONVERTER_parquet_to_csv", requirements_only=True) + assert isinstance(tool, dict) + # print(toolbox) + # assert False + + def test_resolve_toolbox(self): + toolbox = self.gi.container_resolution.resolve_toolbox() + assert isinstance(toolbox, list) + assert len(toolbox) > 0 + assert isinstance(toolbox[0], dict) + + toolbox_by_tool_ids = self.gi.container_resolution.resolve_toolbox(tool_ids=[toolbox[0]['tool_id']]) + assert isinstance(toolbox_by_tool_ids, list) + assert len(toolbox_by_tool_ids) == 1 + assert isinstance(toolbox_by_tool_ids[0], dict) + + toolbox_by_resolver_type = self.gi.container_resolution.resolve_toolbox(resolver_type='mulled') + assert isinstance(toolbox_by_resolver_type, list) + assert len(toolbox_by_resolver_type) > 0 + assert isinstance(toolbox_by_resolver_type[0], dict) + assert len(toolbox) == len(toolbox_by_resolver_type) + for tool in toolbox_by_resolver_type: + print(tool) + assert tool['status']['dependency_type'] is None or tool['status']['container_resolver']['resolver_type'] == 'mulled' + + toolbox_by_container_type = self.gi.container_resolution.resolve_toolbox(container_type='docker') + assert isinstance(toolbox_by_container_type, list) + assert len(toolbox_by_container_type) > 0 + assert isinstance(toolbox_by_container_type[0], dict) + assert len(toolbox) == len(toolbox_by_container_type) + for tool in toolbox_by_container_type: + assert tool['status']['dependency_type'] is None or tool['status']['dependency_type'] == 'docker' + assert tool['status']['dependency_type'] is None or tool['status']['container_description']['type'] == 'docker' + + toolbox_requirements_only = self.gi.container_resolution.resolve_toolbox(requirements_only=True) + assert isinstance(toolbox_requirements_only, list) + assert len(toolbox_requirements_only) > 0 + assert isinstance(toolbox_requirements_only[0], dict) + assert len(toolbox) == len(toolbox_requirements_only) + + # TODO unless containers are available this may fallback to conda by default? + # depending on Galaxy's config + # toolbox_by_index = self.gi.container_resolution.resolve_toolbox(tool_ids=[toolbox[0]['tool_id']], index=0, install=True) + # assert isinstance(toolbox_by_index, list) + # assert len(toolbox_by_index) > 0 + # assert isinstance(toolbox_by_index[0], dict) + + # TODO unless containers are available this may fallback to conda by default? + # depending on Galaxy's config + # def test_resolve_toolbox_with_install(self): + # toolbox = self.gi.container_resolution.resolve_toolbox_with_install(tool_ids=[]) + # assert isinstance(toolbox, list) + # assert len(toolbox) == 0 From cada187c3c823626c07a3df1e06a28f4b8476a29 Mon Sep 17 00:00:00 2001 From: Matthias Bernt Date: Tue, 6 Jun 2023 21:47:22 +0200 Subject: [PATCH 14/15] test container resolver api only for >= 22.05 --- .../TestGalaxyToolContainerResolution.py | 47 +++++++++++-------- .../galaxy/container_resolution/__init__.py | 1 + 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/bioblend/_tests/TestGalaxyToolContainerResolution.py b/bioblend/_tests/TestGalaxyToolContainerResolution.py index 5fb0cdc5d..6f2c435de 100644 --- a/bioblend/_tests/TestGalaxyToolContainerResolution.py +++ b/bioblend/_tests/TestGalaxyToolContainerResolution.py @@ -8,65 +8,74 @@ class TestGalaxyContainerResolution(GalaxyTestBase.GalaxyTestBase): + @test_util.skip_unless_galaxy("release_22.05") def test_get_container_resolvers(self): container_resolvers = self.gi.container_resolution.get_container_resolvers() assert isinstance(container_resolvers, list) assert len(container_resolvers) > 0 assert isinstance(container_resolvers[0], dict) - assert container_resolvers[0]['model_class'] == 'ExplicitContainerResolver' - assert container_resolvers[0]['resolver_type'] == 'explicit' - assert container_resolvers[0]['can_uninstall_dependencies'] is False - assert container_resolvers[0]['builds_on_resolution'] is False + assert container_resolvers[0]["model_class"] == "ExplicitContainerResolver" + assert container_resolvers[0]["resolver_type"] == "explicit" + assert container_resolvers[0]["can_uninstall_dependencies"] is False + assert container_resolvers[0]["builds_on_resolution"] is False + @test_util.skip_unless_galaxy("release_22.05") def test_show_container_resolver(self): container_resolver = self.gi.container_resolution.show_container_resolver(0) print(container_resolver) assert isinstance(container_resolver, dict) - assert container_resolver['model_class'] == 'ExplicitContainerResolver' - assert container_resolver['resolver_type'] == 'explicit' - assert container_resolver['can_uninstall_dependencies'] is False - assert container_resolver['builds_on_resolution'] is False + assert container_resolver["model_class"] == "ExplicitContainerResolver" + assert container_resolver["resolver_type"] == "explicit" + assert container_resolver["can_uninstall_dependencies"] is False + assert container_resolver["builds_on_resolution"] is False + @test_util.skip_unless_galaxy("release_22.05") def test_resolve(self): tool = self.gi.container_resolution.resolve(tool_id="CONVERTER_parquet_to_csv") print(tool) assert isinstance(tool, dict) - toolbox_requirements_only = self.gi.container_resolution.resolve(tool_id="CONVERTER_parquet_to_csv", requirements_only=True) - assert isinstance(tool, dict) - # print(toolbox) - # assert False + tool_requirements_only = self.gi.container_resolution.resolve( + tool_id="CONVERTER_parquet_to_csv", requirements_only=True + ) + assert isinstance(tool_requirements_only, dict) + @test_util.skip_unless_galaxy("release_22.05") def test_resolve_toolbox(self): toolbox = self.gi.container_resolution.resolve_toolbox() assert isinstance(toolbox, list) assert len(toolbox) > 0 assert isinstance(toolbox[0], dict) - toolbox_by_tool_ids = self.gi.container_resolution.resolve_toolbox(tool_ids=[toolbox[0]['tool_id']]) + toolbox_by_tool_ids = self.gi.container_resolution.resolve_toolbox(tool_ids=[toolbox[0]["tool_id"]]) assert isinstance(toolbox_by_tool_ids, list) assert len(toolbox_by_tool_ids) == 1 assert isinstance(toolbox_by_tool_ids[0], dict) - toolbox_by_resolver_type = self.gi.container_resolution.resolve_toolbox(resolver_type='mulled') + toolbox_by_resolver_type = self.gi.container_resolution.resolve_toolbox(resolver_type="mulled") assert isinstance(toolbox_by_resolver_type, list) assert len(toolbox_by_resolver_type) > 0 assert isinstance(toolbox_by_resolver_type[0], dict) assert len(toolbox) == len(toolbox_by_resolver_type) for tool in toolbox_by_resolver_type: print(tool) - assert tool['status']['dependency_type'] is None or tool['status']['container_resolver']['resolver_type'] == 'mulled' + assert ( + tool["status"]["dependency_type"] is None + or tool["status"]["container_resolver"]["resolver_type"] == "mulled" + ) - toolbox_by_container_type = self.gi.container_resolution.resolve_toolbox(container_type='docker') + toolbox_by_container_type = self.gi.container_resolution.resolve_toolbox(container_type="docker") assert isinstance(toolbox_by_container_type, list) assert len(toolbox_by_container_type) > 0 assert isinstance(toolbox_by_container_type[0], dict) assert len(toolbox) == len(toolbox_by_container_type) for tool in toolbox_by_container_type: - assert tool['status']['dependency_type'] is None or tool['status']['dependency_type'] == 'docker' - assert tool['status']['dependency_type'] is None or tool['status']['container_description']['type'] == 'docker' + assert tool["status"]["dependency_type"] is None or tool["status"]["dependency_type"] == "docker" + assert ( + tool["status"]["dependency_type"] is None or tool["status"]["container_description"]["type"] == "docker" + ) - toolbox_requirements_only = self.gi.container_resolution.resolve_toolbox(requirements_only=True) + toolbox_requirements_only = self.gi.container_resolution.resolve_toolbox(requirements_only=True) assert isinstance(toolbox_requirements_only, list) assert len(toolbox_requirements_only) > 0 assert isinstance(toolbox_requirements_only[0], dict) diff --git a/bioblend/galaxy/container_resolution/__init__.py b/bioblend/galaxy/container_resolution/__init__.py index e1d1201a2..c39d81eba 100644 --- a/bioblend/galaxy/container_resolution/__init__.py +++ b/bioblend/galaxy/container_resolution/__init__.py @@ -1,5 +1,6 @@ """ Contains interactions dealing with Galaxy container resolvers. +Works only with Galaxy > 22.01 """ from typing import ( List, From a7d44ebd61c8eec017ac359f0b0a25271c496edb Mon Sep 17 00:00:00 2001 From: Dannon Baker Date: Tue, 27 Jun 2023 22:09:47 -0400 Subject: [PATCH 15/15] Add 23.1 workflow test target --- .github/workflows/test.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 445680bdd..672eb7181 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -33,6 +33,7 @@ jobs: tox_env: [py37] galaxy_version: - dev + - release_23.1 - release_23.0 - release_22.05 - release_22.01