comparison env/lib/python3.9/site-packages/cwltool/software_requirements.py @ 0:4f3585e2f14b draft default tip

"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author shellac
date Mon, 22 Mar 2021 18:12:50 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4f3585e2f14b
1 """This module handles resolution of SoftwareRequirement hints.
2
3 This is accomplished mainly by adapting cwltool internals to galaxy-lib's
4 concept of "dependencies". Despite the name, galaxy-lib is a light weight
5 library that can be used to map SoftwareRequirements in all sorts of ways -
6 Homebrew, Conda, custom scripts, environment modules. We'd be happy to find
7 ways to adapt new packages managers and such as well.
8 """
9
10 import argparse # pylint: disable=unused-import
11 import os
12 import string
13 from typing import Dict, List, MutableMapping, MutableSequence, Optional, Union, cast
14
15 from typing_extensions import TYPE_CHECKING
16
17 if TYPE_CHECKING:
18 from .builder import Builder, HasReqsHints
19
20 try:
21 from galaxy.tool_util import deps
22 from galaxy.tool_util.deps.requirements import ToolRequirement, ToolRequirements
23 except ImportError:
24 ToolRequirement = None # type: ignore
25 ToolRequirements = None # type: ignore
26 deps = None # type: ignore
27
28
29 SOFTWARE_REQUIREMENTS_ENABLED = deps is not None
30
31 COMMAND_WITH_DEPENDENCIES_TEMPLATE = string.Template(
32 """#!/bin/bash
33 $handle_dependencies
34 python3 "run_job.py" "job.json"
35 """
36 )
37
38
39 class DependenciesConfiguration:
40 """Dependency configuration class, for RuntimeContext.job_script_provider."""
41
42 def __init__(self, args: argparse.Namespace) -> None:
43 """Initialize."""
44 conf_file = getattr(args, "beta_dependency_resolvers_configuration", None)
45 tool_dependency_dir = getattr(args, "beta_dependencies_directory", None)
46 conda_dependencies = getattr(args, "beta_conda_dependencies", None)
47 if conf_file is not None and os.path.exists(conf_file):
48 self.use_tool_dependencies = True
49 if tool_dependency_dir is None:
50 tool_dependency_dir = os.path.abspath(os.path.dirname(conf_file))
51 self.tool_dependency_dir = tool_dependency_dir
52 self.dependency_resolvers_config_file = os.path.abspath(conf_file)
53 elif conda_dependencies is not None:
54 if tool_dependency_dir is None:
55 tool_dependency_dir = os.path.abspath("./cwltool_deps")
56 self.tool_dependency_dir = tool_dependency_dir
57 self.use_tool_dependencies = True
58 self.dependency_resolvers_config_file = None
59 else:
60 self.use_tool_dependencies = False
61
62 def build_job_script(self, builder: "Builder", command: List[str]) -> str:
63 ensure_galaxy_lib_available()
64 resolution_config_dict = {
65 "use": self.use_tool_dependencies,
66 "default_base_path": self.tool_dependency_dir,
67 }
68 app_config = {
69 "conda_auto_install": True,
70 "conda_auto_init": True,
71 }
72 tool_dependency_manager = deps.build_dependency_manager(
73 app_config_dict=app_config,
74 resolution_config_dict=resolution_config_dict,
75 conf_file=self.dependency_resolvers_config_file,
76 ) # type: deps.DependencyManager
77 dependencies = get_dependencies(builder)
78 handle_dependencies = "" # str
79 if dependencies:
80 handle_dependencies = "\n".join(
81 tool_dependency_manager.dependency_shell_commands(
82 dependencies, job_directory=builder.tmpdir
83 )
84 )
85
86 template_kwds = dict(
87 handle_dependencies=handle_dependencies
88 ) # type: Dict[str, str]
89 job_script = COMMAND_WITH_DEPENDENCIES_TEMPLATE.substitute(template_kwds)
90 return job_script
91
92
93 def get_dependencies(builder: "HasReqsHints") -> ToolRequirements:
94 (software_requirement, _) = builder.get_requirement("SoftwareRequirement")
95 dependencies = [] # type: List[ToolRequirement]
96 if software_requirement and software_requirement.get("packages"):
97 packages = cast(
98 MutableSequence[MutableMapping[str, Union[str, MutableSequence[str]]]],
99 software_requirement.get("packages"),
100 )
101 for package in packages:
102 version = package.get("version", None)
103 if isinstance(version, MutableSequence):
104 if version:
105 version = version[0]
106 else:
107 version = None
108 specs = [{"uri": s} for s in package.get("specs", [])]
109 dependencies.append(
110 ToolRequirement.from_dict(
111 dict(
112 name=cast(str, package["package"]).split("#")[-1],
113 version=version,
114 type="package",
115 specs=specs,
116 )
117 )
118 )
119
120 return ToolRequirements.from_list(dependencies)
121
122
123 def get_container_from_software_requirements(
124 use_biocontainers: bool, builder: "HasReqsHints"
125 ) -> Optional[str]:
126 if use_biocontainers:
127 ensure_galaxy_lib_available()
128 from galaxy.tool_util.deps.containers import (
129 DOCKER_CONTAINER_TYPE,
130 ContainerRegistry,
131 )
132 from galaxy.tool_util.deps.dependencies import AppInfo, ToolInfo
133
134 app_info = AppInfo(
135 involucro_auto_init=True,
136 enable_mulled_containers=True,
137 container_image_cache_path=".",
138 ) # type: AppInfo
139 container_registry = ContainerRegistry(app_info) # type: ContainerRegistry
140 requirements = get_dependencies(builder)
141 tool_info = ToolInfo(requirements=requirements) # type: ToolInfo
142 container_description = container_registry.find_best_container_description(
143 [DOCKER_CONTAINER_TYPE], tool_info
144 )
145 if container_description:
146 return container_description.identifier
147
148 return None
149
150
151 def ensure_galaxy_lib_available() -> None:
152 if not SOFTWARE_REQUIREMENTS_ENABLED:
153 raise Exception(
154 "Optional Python library galaxy-lib not available, it is required for this configuration."
155 )