comparison env/lib/python3.7/site-packages/planemo/conda.py @ 5:9b1c78e6ba9c draft default tip

"planemo upload commit 6c0a8142489327ece472c84e558c47da711a9142"
author shellac
date Mon, 01 Jun 2020 08:59:25 -0400
parents 79f47841a781
children
comparison
equal deleted inserted replaced
4:79f47841a781 5:9b1c78e6ba9c
1 """Planemo specific utilities for dealing with conda.
2
3 The extend galaxy-tool-util's features with planemo specific idioms.
4 """
5
6 from __future__ import absolute_import
7
8 import collections
9 import os
10 import threading
11
12 from galaxy.tool_util.deps import conda_util
13
14 from planemo.exit_codes import EXIT_CODE_FAILED_DEPENDENCIES, ExitCodeException
15 from planemo.io import error, shell
16 from planemo.tools import yield_tool_sources_on_paths
17
18 MESSAGE_ERROR_FAILED_INSTALL = "Attempted to install conda and failed."
19 MESSAGE_ERROR_CANNOT_INSTALL = "Cannot install Conda - perhaps due to a failed installation or permission problems."
20 MESSAGE_ERROR_NOT_INSTALLING = "Conda not configured - run ``planemo conda_init`` or pass ``--conda_auto_init`` to continue."
21
22 BEST_PRACTICE_CHANNELS = ["conda-forge", "bioconda", "defaults"]
23
24
25 def build_conda_context(ctx, **kwds):
26 """Build a galaxy-tool-util CondaContext tailored to planemo use.
27
28 Using planemo's common command-line/global config options.
29 """
30 condarc_override_default = os.path.join(ctx.workspace, "condarc")
31 conda_prefix = kwds.get("conda_prefix", None)
32 use_planemo_shell = kwds.get("use_planemo_shell_exec", True)
33 ensure_channels = kwds.get("conda_ensure_channels", "")
34 condarc_override = kwds.get("condarc", condarc_override_default)
35 use_local = kwds.get("conda_use_local", False)
36 shell_exec = shell if use_planemo_shell else None
37 conda_context = conda_util.CondaContext(conda_prefix=conda_prefix,
38 ensure_channels=ensure_channels,
39 condarc_override=condarc_override,
40 use_local=use_local,
41 shell_exec=shell_exec)
42 handle_auto_init = kwds.get("handle_auto_init", False)
43 if handle_auto_init and not conda_context.is_installed():
44 auto_init = kwds.get("conda_auto_init", True)
45 failed = True
46 if auto_init:
47 if conda_context.can_install_conda():
48 if conda_util.install_conda(conda_context):
49 error(MESSAGE_ERROR_FAILED_INSTALL)
50 else:
51 failed = False
52 else:
53 error(MESSAGE_ERROR_CANNOT_INSTALL)
54 else:
55 error(MESSAGE_ERROR_NOT_INSTALLING)
56
57 if failed:
58 raise ExitCodeException(EXIT_CODE_FAILED_DEPENDENCIES)
59 if handle_auto_init:
60 conda_context.ensure_conda_build_installed_if_needed()
61 return conda_context
62
63
64 def collect_conda_targets(ctx, paths, recursive=False, found_tool_callback=None):
65 """Load CondaTarget objects from supplied artifact sources.
66
67 If a tool contains more than one requirement, the requirements will each
68 appear once in the output.
69 """
70 conda_targets = set([])
71 real_paths = []
72 for path in paths:
73 if not os.path.exists(path):
74 targets = target_str_to_targets(path)
75 [conda_targets.add(_) for _ in targets]
76 else:
77 real_paths.append(path)
78
79 for (tool_path, tool_source) in yield_tool_sources_on_paths(ctx, real_paths, recursive=recursive, exclude_deprecated=True):
80 if found_tool_callback:
81 found_tool_callback(tool_path)
82 for target in tool_source_conda_targets(tool_source):
83 conda_targets.add(target)
84 return conda_targets
85
86
87 # Copied and modified from mulled stuff - need to syncronize these concepts.
88 def target_str_to_targets(targets_raw):
89 def parse_target(target_str):
90 if "=" in target_str:
91 package_name, version = target_str.split("=", 1)
92 else:
93 package_name = target_str
94 version = None
95 target = conda_util.CondaTarget(package_name, version)
96 return target
97
98 targets = [parse_target(_) for _ in targets_raw.split(",")]
99 return targets
100
101
102 def collect_conda_target_lists(ctx, paths, recursive=False, found_tool_callback=None):
103 """Load CondaTarget lists from supplied artifact sources.
104
105 If a tool contains more than one requirement, the requirements will all
106 appear together as one list element of the output list.
107 """
108 conda_target_lists, _ = collect_conda_target_lists_and_tool_paths(ctx, paths, recursive=recursive, found_tool_callback=found_tool_callback)
109 return conda_target_lists
110
111
112 def collect_conda_target_lists_and_tool_paths(ctx, paths, recursive=False, found_tool_callback=None):
113 """Load CondaTarget lists from supplied artifact sources.
114
115 If a tool contains more than one requirement, the requirements will all
116 appear together as one list element of the output list.
117 """
118 conda_target_lists = set([])
119 tool_paths = collections.defaultdict(list)
120 for (tool_path, tool_source) in yield_tool_sources_on_paths(ctx, paths, recursive=recursive, yield_load_errors=False):
121 if found_tool_callback:
122 found_tool_callback(tool_path)
123 targets = frozenset(tool_source_conda_targets(tool_source))
124 conda_target_lists.add(targets)
125 tool_paths[targets].append(tool_path)
126
127 # Turn them into lists so the order matches before returning...
128 conda_target_lists = list(conda_target_lists)
129 conda_target_tool_paths = [tool_paths[c] for c in conda_target_lists]
130
131 return conda_target_lists, conda_target_tool_paths
132
133
134 def tool_source_conda_targets(tool_source):
135 """Load CondaTarget object from supplied abstract tool source."""
136 requirements, _ = tool_source.parse_requirements_and_containers()
137 return conda_util.requirements_to_conda_targets(requirements)
138
139
140 best_practice_search_first = threading.local()
141
142
143 def best_practice_search(conda_target, conda_context=None, platform=None):
144 # Call it in offline mode after the first time.
145 try:
146 best_practice_search_first.previously_called
147 # TODO: Undo this...
148 offline = False
149 except AttributeError:
150 best_practice_search_first.previously_called = True
151 offline = False
152
153 if not conda_context:
154 conda_context = conda_util.CondaContext()
155 return conda_util.best_search_result(
156 conda_target,
157 conda_context=conda_context,
158 channels_override=BEST_PRACTICE_CHANNELS,
159 offline=offline,
160 platform=platform,
161 )
162
163
164 __all__ = (
165 "BEST_PRACTICE_CHANNELS",
166 "best_practice_search",
167 "build_conda_context",
168 "collect_conda_targets",
169 "collect_conda_target_lists",
170 "collect_conda_target_lists_and_tool_paths",
171 "tool_source_conda_targets",
172 )