Skip to content

Commit

Permalink
Merge branch 'release_20.05' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
nsoranzo committed Jun 1, 2020
2 parents 98b5480 + 49c6f1d commit 3aebb5f
Show file tree
Hide file tree
Showing 8 changed files with 184 additions and 15 deletions.
6 changes: 5 additions & 1 deletion lib/galaxy/tool_util/deps/containers.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,11 @@ def __resolvers_dict(self):

def find_best_container_description(self, enabled_container_types, tool_info, **kwds):
"""Yield best container description of supplied types matching tool info."""
resolved_container_description = self.resolve(enabled_container_types, tool_info, **kwds)
try:
resolved_container_description = self.resolve(enabled_container_types, tool_info, **kwds)
except Exception:
log.exception("Could not get container description for tool '%s'", tool_info.tool_id)
return None
return None if resolved_container_description is None else resolved_container_description.container_description

def resolve(self, enabled_container_types, tool_info, index=None, resolver_type=None, install=True, resolution_cache=None):
Expand Down
7 changes: 4 additions & 3 deletions lib/galaxy/tool_util/deps/mulled/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
QUAY_REPOSITORY_API_ENDPOINT = 'https://quay.io/api/v1/repository'
BUILD_NUMBER_REGEX = re.compile(r'\d+$')
PARSED_TAG = collections.namedtuple('ParsedTag', 'tag version build_string build_number')
QUAY_IO_TIMEOUT = 10


def create_repository(namespace, repo_name, oauth_token):
Expand All @@ -29,7 +30,7 @@ def create_repository(namespace, repo_name, oauth_token):
"description": "",
"visibility": "public",
}
requests.post("https://quay.io/api/v1/repository", json=data, headers=headers)
requests.post("https://quay.io/api/v1/repository", json=data, headers=headers, timeout=QUAY_IO_TIMEOUT)


def quay_versions(namespace, pkg_name):
Expand All @@ -49,7 +50,7 @@ def quay_repository(namespace, pkg_name):
assert namespace is not None
assert pkg_name is not None
url = 'https://quay.io/api/v1/repository/%s/%s' % (namespace, pkg_name)
response = requests.get(url, timeout=None)
response = requests.get(url, timeout=QUAY_IO_TIMEOUT)
data = response.json()
return data

Expand All @@ -65,7 +66,7 @@ def _namespace_has_repo_name(namespace, repo_name, resolution_cache):
repos_parameters = {'public': 'true', 'namespace': namespace}
repos_headers = {'Accept-encoding': 'gzip', 'Accept': 'application/json'}
repos_response = requests.get(
QUAY_REPOSITORY_API_ENDPOINT, headers=repos_headers, params=repos_parameters, timeout=None)
QUAY_REPOSITORY_API_ENDPOINT, headers=repos_headers, params=repos_parameters, timeout=QUAY_IO_TIMEOUT)

repos = repos_response.json()['repositories']
repo_names = [r["name"] for r in repos]
Expand Down
2 changes: 2 additions & 0 deletions lib/galaxy/tool_util/xsd/galaxy.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -4865,6 +4865,8 @@ A contrived example of a tool that uses this is the test tool
By default this file will not contain paths for data or collection inputs. To include simple
paths for data parameters set the ``data_style`` attribute to ``paths`` (see [inputs_as_json_with_paths.xml](https://github.com/galaxyproject/galaxy/blob/dev/test/functional/tools/inputs_as_json_with_paths.xml) for an example).
For tools with profile >= 20.05 a select with ``multiple="true"`` is rendered as an array which is empty if nothing is selected. For older profile versions select lists are rendered as comma separated strings or a literal ``null`` in case nothing is selected.
]]></xs:documentation>
</xs:annotation>
<xs:simpleContent>
Expand Down
2 changes: 1 addition & 1 deletion lib/galaxy/tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2413,7 +2413,7 @@ def exec_before_job(self, app, inp_data, out_data, param_dict=None):
raise Exception("Internal error - param_dict is empty.")

job = {}
json_wrap(self.inputs, param_dict, job, handle_files='OBJECT')
json_wrap(self.inputs, param_dict, self.profile, job, handle_files='OBJECT')
expression_inputs = {
'job': job,
'script': self._expression,
Expand Down
5 changes: 4 additions & 1 deletion lib/galaxy/tools/evaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,10 @@ def __build_config_file_text(self, content):
message = template % content_format
raise Exception(message)

return json.dumps(wrapped_json.json_wrap(self.tool.inputs, self.param_dict, handle_files=handle_files)), False
return json.dumps(wrapped_json.json_wrap(self.tool.inputs,
self.param_dict,
self.tool.profile,
handle_files=handle_files)), False

def __write_workdir_file(self, config_filename, content, context, is_template=True, strip=False):
parent_dir = os.path.dirname(config_filename)
Expand Down
24 changes: 15 additions & 9 deletions lib/galaxy/tools/parameters/wrapped_json.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
import logging

import packaging.version

log = logging.getLogger(__name__)

SKIP_INPUT = object()


def json_wrap(inputs, input_values, as_dict=None, handle_files="skip"):
def json_wrap(inputs, input_values, profile, as_dict=None, handle_files="skip"):
if as_dict is None:
as_dict = {}

for input in inputs.values():
input_name = input.name
value_wrapper = input_values[input_name]
json_value = _json_wrap_input(input, value_wrapper, handle_files=handle_files)
json_value = _json_wrap_input(input, value_wrapper, profile,
handle_files=handle_files)
if json_value is SKIP_INPUT:
continue
as_dict[input_name] = json_value
return as_dict


def _json_wrap_input(input, value_wrapper, handle_files="skip"):
def _json_wrap_input(input, value_wrapper, profile, handle_files="skip"):
input_type = input.type

def _data_input_to_path(v):
Expand All @@ -32,23 +35,26 @@ def _data_input_to_path(v):
repeat_job_value = []
for d in value_wrapper:
repeat_instance_job_value = {}
json_wrap(input.inputs, d, repeat_instance_job_value, handle_files=handle_files)
json_wrap(input.inputs, d, profile, repeat_instance_job_value,
handle_files=handle_files)
repeat_job_value.append(repeat_instance_job_value)
json_value = repeat_job_value
elif input_type == "conditional":
values = value_wrapper
current = values["__current_case__"]
conditional_job_value = {}
json_wrap(input.cases[current].inputs, values, conditional_job_value, handle_files=handle_files)
json_wrap(input.cases[current].inputs, values, profile,
conditional_job_value, handle_files=handle_files)
test_param = input.test_param
test_param_name = test_param.name
test_value = _json_wrap_input(test_param, values[test_param_name], handle_files=handle_files)
test_value = _json_wrap_input(test_param, values[test_param_name],
profile, handle_files=handle_files)
conditional_job_value[test_param_name] = test_value
json_value = conditional_job_value
elif input_type == "section":
values = value_wrapper
section_job_value = {}
json_wrap(input.inputs, values, section_job_value, handle_files=handle_files)
json_wrap(input.inputs, values, profile, section_job_value, handle_files=handle_files)
json_value = section_job_value
elif input_type == "data" and input.multiple:
if handle_files == "paths":
Expand Down Expand Up @@ -88,10 +94,10 @@ def _data_input_to_path(v):
elif input_type == "boolean":
json_value = _cast_if_not_none(value_wrapper, bool)
elif input_type == "select":
if input.multiple:
if input.multiple and packaging.version.parse(str(profile)) >= packaging.version.parse('20.05'):
json_value = [_ for _ in _cast_if_not_none(value_wrapper.value, list)]
else:
json_value = _cast_if_not_none(value_wrapper.value, str)
json_value = _cast_if_not_none(value_wrapper, str)
elif input_type == "data_column":
# value is a SelectToolParameterWrapper()
if input.multiple:
Expand Down
152 changes: 152 additions & 0 deletions test/functional/tools/inputs_as_json_profile.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
<!-- test if profile version of inputs json generation works, i.e.
- multiple selects get comma separated string (lists >= 20.05)
- empty optional selects get "None" ([] >= 20.05) -->
<tool id="inputs_as_json" name="inputs_as_json" profile="20.01" version="1.0.0">
<command detect_errors="exit_code"><![CDATA[
cat inputs.json &&
python $check_inputs inputs.json $test_case
]]></command>
<configfiles>
<inputs name="inputs" filename="inputs.json" />
<!-- Can specify with fixed path in working directory instead:
<inputs name="inputs" filename="input.json" />
-->
<configfile name="check_inputs"><![CDATA[
import json
import sys
input_json_path = sys.argv[1]
test_case = sys.argv[2]
as_dict = json.load(open(input_json_path, "r"))
def assert_equals(x, y):
assert x == y, "%s[%s] != %s[%s] " % (x, type(x), y, type(y))
if test_case == "1":
assert_equals(as_dict["test_case"], 1)
assert_equals(as_dict["text_test"], "foo")
assert_equals(as_dict["booltest"], True)
assert_equals(as_dict["booltest2"], True)
assert_equals(as_dict["inttest"], 12456)
assert_equals(as_dict["floattest"], 6.789)
assert_equals(as_dict["radio_select"], "a_radio")
assert_equals(as_dict["optional_select"], "None")
assert_equals(as_dict["optional_multiple_select"], "None")
assert_equals(as_dict["repeat"][0]["r"], "000000")
assert_equals(as_dict["repeat"][1]["r"], "FFFFFF")
assert_equals(as_dict["cond"]["more_text"], "fdefault")
assert_equals(as_dict["section_example"]["section_text"], "section_default")
assert "data_input" not in as_dict
elif test_case == "2":
assert_equals(as_dict["test_case"], 2)
assert_equals(as_dict["text_test"], "bar")
assert_equals(as_dict["booltest"], False)
assert_equals(as_dict["booltest2"], False)
assert_equals(as_dict["inttest"], None)
assert_equals(as_dict["floattest"], 1.0)
assert_equals(as_dict["radio_select"], "a_radio")
assert_equals(as_dict["optional_select"], "a")
assert_equals(as_dict["optional_multiple_select"], 'a,b')
assert_equals(as_dict["repeat"][0]["r"], "000000")
assert_equals(as_dict["cond"]["cond_test"], "second")
assert_equals(as_dict["cond"]["more_text"], "sdefault")
assert_equals(as_dict["section_example"]["section_text"], "section_default")
assert "data_input" not in as_dict
with open("output", "w") as f:
f.write("okay\n")
]]></configfile>
</configfiles>
<inputs>
<param name="test_case" type="integer" value="0" />
<param name="text_test" type="text" />
<param name="booltest" truevalue="booltrue" falsevalue="boolfalse" checked="false" type="boolean" />
<param name="booltest2" truevalue="booltrue" falsevalue="boolfalse" checked="false" type="boolean" />
<param name="inttest" type="integer" optional="true" />
<param name="floattest" value="1.0" type="float" />
<param name="radio_select" type="select" display="radio">
<option value="a_radio" selected="true">A Radio</option>
<option value="b_radio">B Radio</option>
<option value="c_radio">C Radio</option>
</param>
<param name="data_input" type="data" optional="true" />
<param name="optional_select" type="select" optional="true">
<option value="a">A</option>
<option value="b">B</option>
<option value="c">C</option>
</param>
<param name="optional_multiple_select" type="select" optional="true" multiple="true">
<option value="a">A</option>
<option value="b">B</option>
<option value="c">C</option>
</param>
<repeat name="repeat" title="Repeat" min="1">
<param name="r" type="color" />
</repeat>
<conditional name="cond">
<param name="cond_test" type="select">
<option value="first" selected="true">First</option>
<option value="second">Second</option>
</param>
<when value="first">
<param name="more_text" type="text" value="fdefault" />
</when>
<when value="second">
<param name="more_text" type="text" value="sdefault" />
</when>
</conditional>
<section name="section_example" title="Section Example">
<param name="section_text" type="text" value="section_default" />
</section>
</inputs>
<outputs>
<data name="out_file1" from_work_dir="output" format="txt" />
</outputs>
<tests>
<test>
<param name="test_case" value="1" />
<param name="text_test" value="foo" />
<param name="booltest" value="true" />
<param name="booltest2" value="booltrue" />
<param name="inttest" value="12456" />
<param name="floattest" value="6.789" />
<repeat name="repeat">
<param name="r" value="000000"/>
</repeat>
<repeat name="repeat">
<param name="r" value="FFFFFF"/>
</repeat>
<conditional name="cond">
<param name="cond_test" value="first" />
</conditional>
<output name="out_file1">
<assert_contents>
<has_line line="okay" />
</assert_contents>
</output>
</test>
<test>
<param name="test_case" value="2" />
<param name="text_test" value="bar" />
<param name="booltest" value="false" />
<param name="booltest2" value="boolfalse" />
<param name="data_input" value="simple_line.txt" />
<param name="optional_select" value="a"/>
<param name="optional_multiple_select" value="a,b"/>
<!-- Testing null integers -->
<!-- <param name="inttest" value="12456" /> -->
<param name="r" value="000000" />
<conditional name="cond">
<param name="cond_test" value="second" />
</conditional>
<output name="out_file1">
<assert_contents>
<has_line line="okay" />
</assert_contents>
</output>
</test>
</tests>
<help>
Test tool demonstrating the special inputs config file.
</help>
</tool>
1 change: 1 addition & 0 deletions test/functional/tools/samples_tool_conf.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
<tool file="tool_provided_metadata_12.xml" />
<tool file="empty_datasets.xml" />
<tool file="inputs_as_json.xml" />
<tool file="inputs_as_json_profile.xml" />
<tool file="inputs_as_json_with_paths.xml" />
<tool file="filter_static_regexp.xml" />
<tool file="dbkey_filter_input.xml" />
Expand Down

0 comments on commit 3aebb5f

Please sign in to comment.