comparison env/lib/python3.9/site-packages/galaxy/tool_util/deps/resolvers/unlinked_tool_shed_packages.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 """
2 Backup resolvers for when dependencies can not be loaded from the database.
3 Mainly suited for testing stage.
4
5 Ideally all dependencies will be stored in the database
6 when a tool is added from a Tool Shed.
7
8 That should remain the preferred way of locating dependencies.
9
10 In cases where that is not possible
11 for example during testing this resolver can act as a backup.
12
13 This resolver looks not just for manually added dependencies
14 but also ones added from a Tool Shed.
15
16 This tool is still under development so the default behaviour could change.
17 It has been tested when placed in the same directory as galaxy_packages.py
18
19 At the time of writing July 3 2015 this resolver has to be plugged in.
20 See bottom for instructions on how to add this resolver.
21
22 """
23 import logging
24 from os import listdir
25 from os.path import (
26 exists,
27 getmtime,
28 join
29 )
30
31 from . import (
32 Dependency,
33 NullDependency
34 )
35 from .galaxy_packages import BaseGalaxyPackageDependencyResolver
36
37 log = logging.getLogger(__name__)
38
39 MANUAL = "manual"
40 PREFERRED_OWNERS = MANUAL + ",iuc,devteam"
41
42
43 class UnlinkedToolShedPackageDependencyResolver(BaseGalaxyPackageDependencyResolver):
44 dict_collection_visible_keys = BaseGalaxyPackageDependencyResolver.dict_collection_visible_keys + ['preferred_owners', 'select_by_owner']
45 resolver_type = "unlinked_tool_shed_packages"
46
47 def __init__(self, dependency_manager, **kwds):
48 super().__init__(dependency_manager, **kwds)
49 # Provide a list of preferred owners whose dependency to use
50 self.preferred_owners = kwds.get('preferred_owners', PREFERRED_OWNERS).split(",")
51 # Option to ignore owner and just use last modified time
52 self.select_by_owner = str(kwds.get('select_by_owner', "true")).lower() != "false"
53
54 def _find_dep_versioned(self, name, version, type='package', **kwds):
55 try:
56 possibles = self._find_possible_dependencies(name, version, type)
57 if len(possibles) == 0:
58 log.debug("Unable to find dependency,'%s' '%s' '%s'", name, version, type)
59 return NullDependency(version=version, name=name)
60 elif len(possibles) == 1:
61 # Only one candidate found so ignore any preference rules
62 return possibles[0].dependency
63 else:
64 # Pick the preferred one
65 return self._select_preferred_dependency(possibles).dependency
66 except Exception:
67 log.exception("Unexpected error hunting for dependency '%s' '%s''%s'", name, version, type)
68 return NullDependency(version=version, name=name)
69
70 # Finds all possible dependency to use
71 # Should be extended as required
72 # Returns CandidateDependency objects with data for preference picking
73 def _find_possible_dependencies(self, name, version, type):
74 possibles = []
75 if exists(self.base_path):
76 path = join(self.base_path, name, version)
77 if exists(path):
78 # First try the way without owner/name/revision
79 package = self._galaxy_package_dep(path, version, name, type, True)
80 if not isinstance(package, NullDependency):
81 log.debug("Found dependency '%s' '%s' '%s' at '%s'", name, version, type, path)
82 possibles.append(CandidateDependency(package, path))
83 # now try with an owner/name/revision
84 for owner in listdir(path):
85 owner_path = join(path, owner)
86 for package_name in listdir(owner_path):
87 if package_name.lower().startswith("package_" + name.lower()):
88 package_path = join(owner_path, package_name)
89 for revision in listdir(package_path):
90 revision_path = join(package_path, revision)
91 package = self._galaxy_package_dep(revision_path, version, name, type, True)
92 if not isinstance(package, NullDependency):
93 log.debug("Found dependency '%s' '%s' '%s' at '%s'", name, version, type, revision_path)
94 possibles.append(CandidateDependency(package, package_path, owner))
95 return possibles
96
97 def _select_preferred_dependency(self, possibles, by_owner=None):
98 if by_owner is None:
99 by_owner = self.select_by_owner
100 preferred = []
101 if by_owner:
102 for owner in self.preferred_owners:
103 for candidate in possibles:
104 if candidate.owner == owner:
105 preferred.append(candidate)
106 if len(preferred) == 1:
107 log.debug("Picked dependency based on owner '%s'", owner)
108 return preferred[0]
109 elif len(preferred) > 1:
110 log.debug("Multiple dependency found with owner '%s'", owner)
111 break
112 if len(preferred) == 0:
113 preferred = possibles
114 latest_modified = 0
115 for candidate in preferred:
116 modified = getmtime(candidate.path)
117 if latest_modified < modified:
118 latest_candidate = candidate
119 latest_modified = modified
120 log.debug("Picking dependency at '%s' as it was the last modified", latest_candidate.path)
121 return latest_candidate
122
123 """
124 #Currently no need has been found for expand the verionsless method
125 #This is an example of how it could be done
126 def _find_dep_default( self, name, type='package', **kwds ):
127 try:
128 possibles = TODO
129 if len(possibles) == 0:
130 log.debug("Unable to find dependency,'%s' default '%s'", name, type)
131 return NullDependency(version=None, name=name)
132 elif len(possibles) == 1:
133 #Only one candidate found so ignore any preference rules
134 return possibles[0].dependency
135 else:
136 #Pick the preferred one
137 return self._select_preferred_dependency(possibles, by_owner=False).dependency
138 except Exception:
139 log.exception("Unexpected error hunting for dependency '%s' default '%s'", name, type)
140 return NullDependency(version=None, name=name)
141 """
142
143
144 class CandidateDependency(Dependency):
145 dict_collection_visible_keys = Dependency.dict_collection_visible_keys + ['dependency', 'path', 'owner']
146 dependency_type = 'unlinked_tool_shed_package'
147
148 @property
149 def exact(self):
150 return self.dependency.exact
151
152 def __init__(self, dependency, path, owner=MANUAL):
153 self.dependency = dependency
154 self.path = path
155 self.owner = owner
156
157 def shell_commands(self):
158 """
159 Return shell commands to enable this dependency.
160 """
161 return self.dependency.shell_commands()
162
163
164 __all__ = ('UnlinkedToolShedPackageDependencyResolver', )
165
166 """
167 At the time of writing July 3 2015 this resolver has to be plugged in.
168
169 Adding resolver instructions:
170
171 1. create a dependency_resolvers_config.xml file
172 <dependency_resolvers>
173 <tool_shed_packages />
174 <galaxy_packages />
175 <galaxy_packages versionless="true" />
176 <unlinked_tool_shed_packages />
177 </dependency_resolvers>
178
179
180 1a. ALWAYS add <tool_shed_packages /> first!!!!
181
182 1b. <galaxy_packages /> is optional as
183 this resolver will also find dependency found by that resolver
184 1bi Current default is to use a dependency to find that way first!
185 1bii So an alternative version of dependency_resolvers_config.xml
186 <dependency_resolvers>
187 <tool_shed_packages />
188 <unlinked_tool_shed_packages />
189 <unlinked_tool_shed_packages versionless="true" />
190 </dependency_resolvers>
191
192 1c. See __init__ for optional config values
193 1ci versionless currently is handled by the super class
194 GalaxyPackageDependencyResolver
195
196 2. Add a parameter to config.ini
197 dependency_resolvers_config_file = ./config/dependency_resolvers_config.xml
198
199 2a. File name/path can be different
200 2b. config key must be dependency_resolvers_config_file
201
202 3. For planemo it may be required to specify:
203 --dependency_resolvers_config_file (xml file described in 1 above)
204 --tool_dependency_dir (root of dependencies typically galaxy/dependency_dir)
205 See planemo test --help for more information
206 """