import abc from collections.abc import Callable from typing import ( Any, Optional, ) from unittest import SkipTest from requests import Response from galaxy.tool_util.verify.interactor import GalaxyInteractorApi from galaxy.util import unicodify from galaxy_test.base.api_asserts import assert_status_code_is DEFAULT_TOOL_SHED_URL = "https://toolshed.g2.bx.psu.edu" OperationT = Callable[[dict[str, Any]], Response] class UsesShedApi: @property @abc.abstractmethod def galaxy_interactor(self) -> GalaxyInteractorApi: ... def delete_repo_request(self, payload: dict[str, Any]) -> Response: return self.galaxy_interactor._delete("tool_shed_repositories", data=payload, admin=True) def install_repo_request(self, payload: dict[str, Any]) -> Response: return self.galaxy_interactor._post( "tool_shed_repositories/new/install_repository_revision", data=payload, admin=True ) def repository_operation( self, operation: OperationT, owner: str, name: str, changeset: str, tool_shed_url: str = DEFAULT_TOOL_SHED_URL, tool_panel_section_id: Optional[str] = None, ) -> dict[str, Any]: payload = {"tool_shed_url": tool_shed_url, "name": name, "owner": owner, "changeset_revision": changeset} if tool_panel_section_id: payload["tool_panel_section_id"] = tool_panel_section_id create_response = operation(payload) assert_status_code_is(create_response, 200) return create_response.json() def install_repository( self, owner: str, name: str, changeset: str, tool_shed_url: str = DEFAULT_TOOL_SHED_URL, tool_panel_section_id: Optional[str] = None, ) -> dict[str, Any]: try: return self.repository_operation( operation=self.install_repo_request, owner=owner, name=name, changeset=changeset, tool_shed_url=tool_shed_url, tool_panel_section_id=tool_panel_section_id, ) except AssertionError as e: if "Error attempting to retrieve installation information from tool shed" in unicodify(e): raise SkipTest(f"Toolshed '{tool_shed_url}' unavailable") raise def uninstall_repository( self, owner: str, name: str, changeset: str, tool_shed_url: str = DEFAULT_TOOL_SHED_URL ) -> dict[str, Any]: return self.repository_operation( operation=self.delete_repo_request, owner=owner, name=name, changeset=changeset, tool_shed_url=tool_shed_url ) def index_repositories( self, owner: Optional[str] = None, name: Optional[str] = None, changeset: Optional[str] = None ) -> list[dict[str, Any]]: params: dict[str, str] = {} if owner is not None: params["owner"] = owner if name is not None: params["name"] = name if changeset is not None: params["changeset"] = changeset params["deleted"] = "false" params["uninstalled"] = "false" response = self.galaxy_interactor._get("tool_shed_repositories", params, admin=True) response.raise_for_status() return response.json() def get_installed_repository_for( self, owner: Optional[str] = None, name: Optional[str] = None, changeset: Optional[str] = None ) -> Optional[dict[str, Any]]: index = self.index_repositories(owner, name, changeset) if len(index) == 0: return None elif len(index) > 1: raise AssertionError(f"expected at most one repository in response {index}") else: return index[0] def get_installed_repository(self, id: str) -> dict[str, Any]: response = self.galaxy_interactor._get(f"tool_shed_repositories/{id}", admin=True) response.raise_for_status() return response.json()