+160
-22
lines changedFilter options
+160
-22
lines changed Original file line number Diff line number Diff line change
@@ -143,6 +143,7 @@ def _requirements_to_dependencies_dict(self, requirements, **kwds):
143
143
# Check requirements all at once
144
144
all_unmet = len(requirement_to_dependency) == 0
145
145
if all_unmet and hasattr(resolver, "resolve_all"):
146
+
# TODO: Handle specs.
146
147
dependencies = resolver.resolve_all(resolvable_requirements, **kwds)
147
148
if dependencies:
148
149
assert len(dependencies) == len(resolvable_requirements)
@@ -158,7 +159,17 @@ def _requirements_to_dependencies_dict(self, requirements, **kwds):
158
159
continue
159
160
160
161
if requirement.type in ['package', 'set_environment']:
161
-
dependency = resolver.resolve( requirement.name, requirement.version, requirement.type, **kwds )
162
+
name = requirement.name
163
+
version = requirement.version
164
+
specs = requirement.specs
165
+
166
+
if hasattr(resolver, "find_specification"):
167
+
spec = resolver.find_specification(specs)
168
+
if spec is not None:
169
+
name = spec.short_name
170
+
version = spec.version or version
171
+
172
+
dependency = resolver.resolve( name, version, requirement.type, **kwds )
162
173
if require_exact and not dependency.exact:
163
174
continue
164
175
Original file line number Diff line number Diff line change
@@ -10,20 +10,48 @@ class ToolRequirement( object ):
10
10
run (for example, a program, package, or library). Requirements can
11
11
optionally assert a specific version.
12
12
"""
13
-
def __init__( self, name=None, type=None, version=None ):
13
+
def __init__( self, name=None, type=None, version=None, specs=[] ):
14
14
self.name = name
15
15
self.type = type
16
16
self.version = version
17
+
self.specs = specs
17
18
18
19
def to_dict( self ):
19
-
return dict(name=self.name, type=self.type, version=self.version)
20
+
specs = [s.to_dict() for s in self.specs]
21
+
return dict(name=self.name, type=self.type, version=self.version, specs=specs)
20
22
21
23
@staticmethod
22
24
def from_dict( dict ):
23
25
version = dict.get( "version", None )
24
26
name = dict.get("name", None)
25
27
type = dict.get("type", None)
26
-
return ToolRequirement( name=name, type=type, version=version )
28
+
specs = [RequirementSpecification.from_dict(s) for s in dict.get("specs", [])]
29
+
return ToolRequirement( name=name, type=type, version=version, specs=specs )
30
+
31
+
32
+
class RequirementSpecification(object):
33
+
"""Refine a requirement using a URI."""
34
+
35
+
def __init__(self, uri, version=None):
36
+
self.uri = uri
37
+
self.version = version
38
+
39
+
@property
40
+
def specifies_version(self):
41
+
return self.version is not None
42
+
43
+
@property
44
+
def short_name(self):
45
+
return self.uri.split("/")[-1]
46
+
47
+
def to_dict(self):
48
+
return dict(uri=self.uri, version=self.version)
49
+
50
+
@staticmethod
51
+
def from_dict(dict):
52
+
uri = dict.get["uri"]
53
+
version = dict.get("version", None)
54
+
return RequirementSpecification(uri=uri, version=version)
27
55
28
56
def __eq__(self, other):
29
57
return self.name == other.name and self.type == other.type and self.version == other.version
@@ -110,10 +138,29 @@ def parse_requirements_from_xml( xml_root ):
110
138
111
139
requirements = []
112
140
for requirement_elem in requirement_elems:
113
-
name = xml_text( requirement_elem )
141
+
if "name" in requirement_elem.attrib:
142
+
name = requirement_elem.get( "name" )
143
+
spec_elems = requirement_elem.findall("specification")
144
+
specs = map(specification_from_element, spec_elems)
145
+
else:
146
+
name = xml_text( requirement_elem )
147
+
spec_uris_raw = requirement_elem.attrib.get("specification_uris", "")
148
+
specs = []
149
+
for spec_uri in spec_uris_raw.split(","):
150
+
if not spec_uri:
151
+
continue
152
+
version = None
153
+
if "@" in spec_uri:
154
+
uri, version = spec_uri.split("@", 1)
155
+
else:
156
+
uri = spec_uri
157
+
uri = uri.strip()
158
+
if version:
159
+
version = version.strip()
160
+
specs.append(RequirementSpecification(uri, version))
114
161
type = requirement_elem.get( "type", DEFAULT_REQUIREMENT_TYPE )
115
162
version = requirement_elem.get( "version", DEFAULT_REQUIREMENT_VERSION )
116
-
requirement = ToolRequirement( name=name, type=type, version=version )
163
+
requirement = ToolRequirement( name=name, type=type, version=version, specs=specs )
117
164
requirements.append( requirement )
118
165
119
166
container_elems = []
@@ -125,6 +172,12 @@ def parse_requirements_from_xml( xml_root ):
125
172
return requirements, containers
126
173
127
174
175
+
def specification_from_element(specification_elem):
176
+
uri = specification_elem.get("uri", None)
177
+
version = specification_elem.get("version", None)
178
+
return RequirementSpecification(uri, version)
179
+
180
+
128
181
def container_from_element(container_elem):
129
182
identifier = xml_text(container_elem)
130
183
type = container_elem.get("type", DEFAULT_CONTAINER_TYPE)
Original file line number Diff line number Diff line change
@@ -67,6 +67,34 @@ def _to_requirement(self, name, version=None):
67
67
return ToolRequirement(name=name, type="package", version=version)
68
68
69
69
70
+
class SpecificationAwareDependencyResolver:
71
+
"""Mix this into a :class:`DependencyResolver` to implement URI specification matching.
72
+
73
+
Allows adapting generic requirements to more specific URIs - to tailor name
74
+
or version to specified resolution system.
75
+
"""
76
+
__metaclass__ = ABCMeta
77
+
78
+
@abstractmethod
79
+
def find_specification(self, specs):
80
+
"""Find closest matching specification for discovered resolver."""
81
+
82
+
83
+
class SpecificationPatternDependencyResolver:
84
+
"""Implement the :class:`SpecificationAwareDependencyResolver` with a regex pattern."""
85
+
86
+
@abstractproperty
87
+
def _specification_pattern(self):
88
+
"""Pattern of URI to match against."""
89
+
90
+
def find_specification(self, specs):
91
+
pattern = self._specification_pattern
92
+
for spec in specs:
93
+
if pattern.match(spec.uri):
94
+
return spec
95
+
return None
96
+
97
+
70
98
class InstallableDependencyResolver:
71
99
""" Mix this into a ``DependencyResolver`` and implement to indicate
72
100
the dependency resolver can attempt to install new dependencies.
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
5
5
6
6
import logging
7
7
import os
8
+
import re
8
9
9
10
import galaxy.tools.deps.installable
10
11
@@ -29,6 +30,7 @@
29
30
InstallableDependencyResolver,
30
31
ListableDependencyResolver,
31
32
NullDependency,
33
+
SpecificationPatternDependencyResolver,
32
34
)
33
35
34
36
@@ -39,9 +41,10 @@
39
41
log = logging.getLogger(__name__)
40
42
41
43
42
-
class CondaDependencyResolver(DependencyResolver, ListableDependencyResolver, InstallableDependencyResolver):
44
+
class CondaDependencyResolver(DependencyResolver, ListableDependencyResolver, InstallableDependencyResolver, SpecificationPatternDependencyResolver):
43
45
dict_collection_visible_keys = DependencyResolver.dict_collection_visible_keys + ['conda_prefix', 'versionless', 'ensure_channels', 'auto_install']
44
46
resolver_type = "conda"
47
+
_specification_pattern = re.compile(r"https\:\/\/anaconda.org\/\w+\/\w+")
45
48
46
49
def __init__(self, dependency_manager, **kwds):
47
50
self.versionless = _string_as_bool(kwds.get('versionless', 'false'))
Original file line number Diff line number Diff line change
@@ -227,7 +227,7 @@ complete descriptions of the runtime of a tool.
227
227
</xs:sequence>
228
228
</xs:complexType>
229
229
230
-
<xs:complexType name="Requirement">
230
+
<xs:complexType name="Requirement" mixed="true">
231
231
<xs:annotation>
232
232
<xs:documentation xml:lang="en"><![CDATA[
233
233
@@ -276,20 +276,29 @@ resolver.
276
276
277
277
]]></xs:documentation>
278
278
</xs:annotation>
279
-
<xs:simpleContent>
280
-
<xs:extension base="xs:string">
281
-
<xs:attribute name="type" type="RequirementType" use="required">
282
-
<xs:annotation>
283
-
<xs:documentation xml:lang="en"> This value defines the which type of the 3rd party module required by this tool. </xs:documentation>
284
-
</xs:annotation>
285
-
</xs:attribute>
286
-
<xs:attribute name="version" type="xs:string">
287
-
<xs:annotation>
288
-
<xs:documentation xml:lang="en"> For package type requirements this value defines a specific version of the tool dependency. </xs:documentation>
289
-
</xs:annotation>
290
-
</xs:attribute>
291
-
</xs:extension>
292
-
</xs:simpleContent>
279
+
<xs:sequence>
280
+
<xs:element name="specification" minOccurs="0" maxOccurs="unbounded" type="xs:anyType" />
281
+
</xs:sequence>
282
+
<xs:attribute name="type" type="RequirementType" use="required">
283
+
<xs:annotation>
284
+
<xs:documentation xml:lang="en"> This value defines the which type of the 3rd party module required by this tool. </xs:documentation>
285
+
</xs:annotation>
286
+
</xs:attribute>
287
+
<xs:attribute name="version" type="xs:string">
288
+
<xs:annotation>
289
+
<xs:documentation xml:lang="en"> For package type requirements this value defines a specific version of the tool dependency. </xs:documentation>
290
+
</xs:annotation>
291
+
</xs:attribute>
292
+
<xs:attribute name="name" type="xs:string">
293
+
<xs:annotation>
294
+
<xs:documentation xml:lang="en">Name of requirement (if body of ``requirement`` element contains specification URIs).</xs:documentation>
295
+
</xs:annotation>
296
+
</xs:attribute>
297
+
<xs:attribute name="specification_uris" type="xs:string">
298
+
<xs:annotation>
299
+
<xs:documentation xml:lang="en">URIs and versions of requirement specification.</xs:documentation>
300
+
</xs:annotation>
301
+
</xs:attribute>
293
302
</xs:complexType>
294
303
<xs:complexType name="Container">
295
304
<xs:annotation>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
1
+
<tool id="requirement_specification_1" name="requirement_specification_1" version="0.1.0" profile="16.10">
2
+
<command><![CDATA[
3
+
blastn -help > $out_file1 ;
4
+
echo "Moo" >> $out_file1 ;
5
+
]]></command>
6
+
<requirements>
7
+
<requirement type="package" version="2.2.31" name="blast+">
8
+
<specification uri="https://anaconda.org/bioconda/blast" />
9
+
<specification uri="https://packages.debian.org/sid/ncbi-blast+" version="2.2.31-3" />
10
+
</requirement>
11
+
</requirements>
12
+
<inputs>
13
+
<param name="input1" type="data" optional="true" />
14
+
</inputs>
15
+
<outputs>
16
+
<data name="out_file1" format="txt" />
17
+
</outputs>
18
+
</tool>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
1
+
<tool id="requirement_specification_2" name="requirement_specification_2" version="0.1.0" profile="16.01">
2
+
<command><![CDATA[
3
+
blastn -help > $out_file1 ;
4
+
echo "Moo" >> $out_file1 ;
5
+
]]></command>
6
+
<requirements>
7
+
<!-- Demonstrate backward-compatible-ish specification_uri syntax. -->
8
+
<requirement type="package" version="2.2" specification_uris="https://anaconda.org/bioconda/blast@2.2.31,https://packages.debian.org/jessie/ncbi-blast+@2.2.29-3">blast+</requirement>
9
+
</requirements>
10
+
<inputs>
11
+
<param name="input1" type="data" optional="true" />
12
+
</inputs>
13
+
<outputs>
14
+
<data name="out_file1" format="txt" />
15
+
</outputs>
16
+
</tool>
You can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4