Source code for galaxy.webapps.galaxy.api.tool_dependencies
"""
API operations allowing clients to manage tool dependencies.
"""
import logging
from typing import Optional
from galaxy.managers.context import ProvidesAppContext
from galaxy.structured_app import StructuredApp
from galaxy.tool_util.deps import views
from galaxy.web import (
expose_api,
require_admin,
)
from . import BaseGalaxyAPIController
log = logging.getLogger(__name__)
[docs]class ToolDependenciesAPIController(BaseGalaxyAPIController):
[docs] def __init__(self, app: StructuredApp):
super().__init__(app)
self._view = views.DependencyResolversView(app)
[docs] @require_admin
@expose_api
def index(self, trans: ProvidesAppContext, **kwd):
"""
GET /api/dependency_resolvers
"""
return self._view.index()
[docs] @require_admin
@expose_api
def show(self, trans: ProvidesAppContext, id: str):
"""
GET /api/dependency_resolvers/<id>
"""
return self._view.show(id)
[docs] @require_admin
@expose_api
def update(self, trans):
"""
PUT /api/dependency_resolvers
Reload tool dependency resolution configuration.
"""
return self._view.reload()
[docs] @require_admin
@expose_api
def resolver_dependency(self, trans: ProvidesAppContext, id: str, **kwds):
"""
GET /api/dependency_resolvers/{index}/dependency
Resolve described requirement against specified dependency resolver.
:type index: int
:param index: index of the dependency resolver
:type kwds: dict
:param kwds: dictionary structure containing extra parameters
:type name: str
:param name: name of the requirement to find a dependency for (required)
:type version: str
:param version: version of the requirement to find a dependency for (required)
:type exact: bool
:param exact: require an exact match to specify requirement (do not discard
version information to resolve dependency).
:rtype: dict
:returns: a dictified description of the dependency, with attribute
``dependency_type: None`` if no match was found.
"""
return self._view.resolver_dependency(id, **kwds)
[docs] @require_admin
@expose_api
def install_dependency(self, trans: ProvidesAppContext, id: Optional[str] = None, **kwds):
"""
POST /api/dependency_resolvers/{index}/dependency
POST /api/dependency_resolvers/dependency
Install described requirement against specified dependency resolver.
:type index: int
:param index: index of the dependency resolver
:type kwds: dict
:param kwds: dictionary structure containing extra parameters
:type name: str
:param name: name of the requirement to find a dependency for (required)
:type version: str
:param version: version of the requirement to find a dependency for (required)
:type exact: bool
:param exact: require an exact match to specify requirement (do not discard
version information to resolve dependency).
:type tool_id: str
:param tool_id: tool_id to install requirements for
:rtype: dict
:returns: a dictified description of the dependency, with attribute
``dependency_type: None`` if no match was found.
"""
self._view.install_dependency(id, **kwds)
return self._view.manager_dependency(**kwds)
[docs] @require_admin
@expose_api
def manager_dependency(self, trans: ProvidesAppContext, **kwds):
"""
GET /api/dependency_resolvers/dependency
Resolve described requirement against all dependency resolvers, returning
the match with highest priority.
:type index: int
:param index: index of the dependency resolver
:type kwds: dict
:param kwds: dictionary structure containing extra parameters
:type name: str
:param name: name of the requirement to find a dependency for (required)
:type version: str
:param version: version of the requirement to find a dependency for (required)
:type exact: bool
:param exact: require an exact match to specify requirement (do not discard
version information to resolve dependency).
:rtype: dict
:returns: a dictified description of the dependency, with type: None
if no match was found.
"""
return self._view.manager_dependency(**kwds)
[docs] @require_admin
@expose_api
def resolver_requirements(self, trans: ProvidesAppContext, id, **kwds):
"""
GET /api/dependency_resolvers/{index}/requirements
Find all "simple" requirements that could be resolved "exactly"
by this dependency resolver. The dependency resolver must implement
ListDependencyResolver.
:type index: int
:param index: index of the dependency resolver
:rtype: dict
:returns: a dictified description of the requirement that could
be resolved.
"""
return self._view.resolver_requirements(id)
[docs] @require_admin
@expose_api
def manager_requirements(self, trans: ProvidesAppContext, **kwds):
"""
GET /api/dependency_resolvers/requirements
Find all "simple" requirements that could be resolved "exactly"
by all dependency resolvers that support this operation.
:type index: int
:param index: index of the dependency resolver
:rtype: dict
:returns: a dictified description of the requirement that could
be resolved (keyed on 'requirement') and the index of
the corresponding resolver (keyed on 'index').
"""
return self._view.manager_requirements()
[docs] @require_admin
@expose_api
def clean(self, trans: ProvidesAppContext, id=None, **kwds):
"""
POST /api/dependency_resolvers/{index}/clean
Cleans up intermediate files created by resolvers during the dependency
installation.
:type index: int
:param index: index of the dependency resolver
:rtype: dict
:returns: a dictified description of the requirement that could
be resolved (keyed on 'requirement') and the index of
the corresponding resolver (keyed on 'index').
"""
return self._view.clean(id, **kwds)
[docs] @expose_api
@require_admin
def summarize_toolbox(self, trans: ProvidesAppContext, **kwds):
"""
GET /api/dependency_resolvers/toolbox
Summarize requirements across toolbox (for Tool Management grid). This is an experiemental
API particularly tied to the GUI - expect breaking changes until this notice is removed.
Container resolution via this API is especially experimental and the container resolution
API should be used to summarize this information instead in most cases.
:type index: int
:param index: index of the dependency resolver
:type tool_ids: str
:param tool_ids: tool_id to install dependency for
:type resolver_type: str
:param resolver_type: restrict to uninstall to specified resolver type
:type include_containers: bool
:param include_containers: include container resolvers in resolution
:type container_type: str
:param container_type: restrict to uninstall to specified container type
:type index_by: str
:param index_by: By default consider only context of requirements, group tools by requirements.
Set this to 'tools' to summarize across all tools though. Tools may provide additional
context for container resolution for instance.
:rtype: list
:returns: dictified descriptions of the dependencies, with attribute
``dependency_type: None`` if no match was found.
"""
kwds["for_json"] = True
index_by = kwds.get("index_by", "requirements")
if index_by == "requirements":
return self._view.summarize_requirements(**kwds)
else:
return self._view.summarize_tools(**kwds)
[docs] @expose_api
@require_admin
def toolbox_install(self, trans: ProvidesAppContext, payload, index=None, **kwds):
"""
POST /api/dependency_resolvers/{index}/toolbox/install
POST /api/dependency_resolvers/toolbox/install
Install described requirement against specified dependency resolver(s). This is an experiemental
API particularly tied to the GUI - expect breaking changes until this notice is removed.
:type index: int
:param index: index of the dependency resolver
:type tool_ids: str
:param tool_ids: tool_id to install dependency for
:type resolver_type: str
:param resolver_type: restrict to uninstall to specified resolver type
:type include_containers: bool
:param include_containers: include container resolvers in resolution
:type container_type: str
:param container_type: restrict to uninstall to specified container type
"""
tools_by_id = trans.app.toolbox.tools_by_id.copy()
tool_ids = payload.get("tool_ids")
requirements = {tools_by_id[tid].tool_requirements for tid in tool_ids}
install_kwds = {}
for source in [payload, kwds]:
if "include_containers" in source:
install_kwds["include_containers"] = source["container_type"]
if "container_type" in kwds:
install_kwds["container_type"] = source["container_type"]
if "resolver_type" in source:
install_kwds["resolver_type"] = source["resolver_type"]
[self._view.install_dependencies(requirements=r, index=index, **install_kwds) for r in requirements]
[docs] @expose_api
@require_admin
def toolbox_uninstall(self, trans: ProvidesAppContext, payload, index=None, **kwds):
"""
POST /api/dependency_resolvers/{index}/toolbox/uninstall
POST /api/dependency_resolvers/toolbox/uninstall
Uninstall described requirement against specified dependency resolver(s). This is an experiemental
API particularly tied to the GUI - expect breaking changes until this notice is removed.
:type index: int
:param index: index of the dependency resolver
:type tool_ids: str
:param tool_ids: tool_id to install dependency for
:type include_containers: bool
:param include_containers: include container resolvers in resolution
:type container_type: str
:param container_type: restrict to uninstall to specified container type
:type resolver_type: str
:param resolver_type: restrict to uninstall to specified resolver type
"""
tools_by_id = self.app.toolbox.tools_by_id.copy()
tool_ids = payload.get("tool_ids")
requirements = {tools_by_id[tid].tool_requirements for tid in tool_ids}
install_kwds = {}
for source in [payload, kwds]:
if "include_containers" in source:
install_kwds["include_containers"] = source["container_type"]
if "container_type" in kwds:
install_kwds["container_type"] = source["container_type"]
if "resolver_type" in source:
install_kwds["resolver_type"] = source["resolver_type"]
[self._view.uninstall_dependencies(index=index, requirements=r, **install_kwds) for r in requirements]
[docs] @expose_api
@require_admin
def unused_dependency_paths(self, trans: ProvidesAppContext, **kwds):
"""
GET /api/dependency_resolvers/unused_paths
"""
return list(self._view.unused_dependency_paths)
[docs] @expose_api
@require_admin
def delete_unused_dependency_paths(self, trans: ProvidesAppContext, payload, **kwds):
"""
PUT /api/dependency_resolvers/unused_paths
"""
paths = payload.get("paths")
self._view.remove_unused_dependency_paths(paths)