From de0c913b8bb3ca01fd0ab5c8286450dbef9b604d Mon Sep 17 00:00:00 2001 From: John Chilton Date: Wed, 30 Dec 2015 11:17:13 +0000 Subject: [PATCH] More work on converting tool inputs to json. - Drop version requirement per commends by @bgruening. - Add examples for conditionals, repeats, sections, colors, and booleans specified truevalue/falsevalue. - Various bug fixes unearthed by new test cases. --- lib/galaxy/tools/__init__.py | 6 +- lib/galaxy/tools/evaluation.py | 7 +- lib/galaxy/tools/parameters/wrapped_json.py | 106 +++++++++++--------- test/functional/tools/inputs_as_json.xml | 53 +++++++++- 4 files changed, 113 insertions(+), 59 deletions(-) diff --git a/lib/galaxy/tools/__init__.py b/lib/galaxy/tools/__init__.py index d80b279f87b..14ad0b7b6fa 100755 --- a/lib/galaxy/tools/__init__.py +++ b/lib/galaxy/tools/__init__.py @@ -646,11 +646,7 @@ class Tool( object, Dictifiable ): name = inputs_elem.get( "name" ) filename = inputs_elem.get( "filename", None ) format = inputs_elem.get("format", "json") - version_str = inputs_elem.get("version", "1") - if not version_str: - raise ValueError("inputs configfile tag must define a version attribute") - version = int(version_str) - content = dict(format=format, version=version) + content = dict(format=format) self.config_files.append( ( name, filename, content ) ) for conf_elem in conf_parent_elem.findall( "configfile" ): name = conf_elem.get( "name" ) diff --git a/lib/galaxy/tools/evaluation.py b/lib/galaxy/tools/evaluation.py index 7f13c1a7df1..3b53819c95e 100644 --- a/lib/galaxy/tools/evaluation.py +++ b/lib/galaxy/tools/evaluation.py @@ -533,8 +533,11 @@ class ToolEvaluator( object ): if isinstance( content, basestring ): return content, True - assert content["format"] == "json" - assert content["version"] == 1 + content_format = content["format"] + if content_format != "json": + template = "Galaxy can only currently convert inputs to json, format [%s] is unhandled" + message = template % content_format + raise Exception(message) return json.dumps(wrapped_json.json_wrap(self.tool.inputs, self.param_dict)), False diff --git a/lib/galaxy/tools/parameters/wrapped_json.py b/lib/galaxy/tools/parameters/wrapped_json.py index e49cee48622..13a935ce3a5 100644 --- a/lib/galaxy/tools/parameters/wrapped_json.py +++ b/lib/galaxy/tools/parameters/wrapped_json.py @@ -2,65 +2,73 @@ import logging log = logging.getLogger(__name__) +SKIP_INPUT = object() + + def json_wrap(inputs, input_values, as_dict=None, handle_files="SKIP"): if as_dict is None: as_dict = {} for input in inputs.itervalues(): input_name = input.name - input_type = input.type value = input_values[input_name] - if input_type == "repeat": - repeat_job_value = [] - for d in input_values[input.name]: - repeat_instance_job_value = {} - json_wrap(input.inputs, d, repeat_instance_job_value) - repeat_job_value.append(repeat_instance_job_value) - as_dict[input_name] = repeat_job_value - if input_type == "conditional": - values = input_values[input_name] - current = values["__current_case__"] - conditional_job_value = {} - json_wrap(input.cases[current].inputs, values, conditional_job_value) - as_dict[input_name] = conditional_job_value - if input_type == "section": - values = input_values[input_name] - section_job_value = {} - json_wrap(input.inputs, values, section_job_value) - as_dict[input_name] = section_job_value - elif input_type == "data" and input.multiple: - if handle_files == "SKIP": - continue - raise NotImplementedError() - elif input_type == "data": - if handle_files == "SKIP": - continue - raise NotImplementedError() - elif input_type == "data_collection": - if handle_files == "SKIP": - continue - raise NotImplementedError() - elif input_type == "select" or input_type == "text": - value = input_values[input_name] - json_value = _cast_if_not_none(value, str) - as_dict[input_name] = json_value - elif input_type == "float": - value = input_values[input_name] - json_value = _cast_if_not_none(value, float, empty_to_none=True) - as_dict[input_name] = json_value - elif input_type == "integer": - value = input_values[input_name] - json_value = _cast_if_not_none(value, int, empty_to_none=True) - as_dict[input_name] = json_value - elif input_type == "boolean": - value = input_values[input_name] - json_value = _cast_if_not_none(value, bool) - as_dict[input_name] = json_value - else: - raise NotImplementedError("input_type [%s] not implemented" % input_type) + json_value = _json_wrap_input(input, value, 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, handle_files="SKIP"): + input_type = input.type + if input_type == "repeat": + repeat_job_value = [] + for d in value: + repeat_instance_job_value = {} + json_wrap(input.inputs, d, repeat_instance_job_value) + repeat_job_value.append(repeat_instance_job_value) + json_value = repeat_job_value + elif input_type == "conditional": + values = value + current = values["__current_case__"] + conditional_job_value = {} + json_wrap(input.cases[current].inputs, values, conditional_job_value) + test_param = input.test_param + test_param_name = test_param.name + test_value = _json_wrap_input(test_param, values[test_param_name]) + conditional_job_value[test_param_name] = test_value + json_value = conditional_job_value + elif input_type == "section": + values = value + section_job_value = {} + json_wrap(input.inputs, values, section_job_value) + json_value = section_job_value + elif input_type == "data" and input.multiple: + if handle_files == "SKIP": + return SKIP_INPUT + raise NotImplementedError() + elif input_type == "data": + if handle_files == "SKIP": + return SKIP_INPUT + raise NotImplementedError() + elif input_type == "data_collection": + if handle_files == "SKIP": + return SKIP_INPUT + raise NotImplementedError() + elif input_type == "select" or input_type == "text" or input_type == "color": + json_value = _cast_if_not_none(value, str) + elif input_type == "float": + json_value = _cast_if_not_none(value, float, empty_to_none=True) + elif input_type == "integer": + json_value = _cast_if_not_none(value, int, empty_to_none=True) + elif input_type == "boolean": + json_value = _cast_if_not_none(value, bool) + else: + raise NotImplementedError("input_type [%s] not implemented" % input_type) + + return json_value + + def _cast_if_not_none(value, cast_to, empty_to_none=False): # log.debug("value [%s], type[%s]" % (value, type(value))) if value is None or (empty_to_none and str(value) == ''): diff --git a/test/functional/tools/inputs_as_json.xml b/test/functional/tools/inputs_as_json.xml index a4f5a4de91c..3e487bb0e9e 100644 --- a/test/functional/tools/inputs_as_json.xml +++ b/test/functional/tools/inputs_as_json.xml @@ -1,4 +1,7 @@ + + python $check_inputs $inputs $test_case + - - python $check_inputs $inputs $test_case - + @@ -46,6 +57,24 @@ with open("output", "w") as f: + + + + + + + + + + + + + + + +
+ +
@@ -55,8 +84,18 @@ with open("output", "w") as f: + + + + + + + + + + @@ -67,8 +106,13 @@ with open("output", "w") as f: + + + + + @@ -76,4 +120,7 @@ with open("output", "w") as f: + + Test tool demonstrating the special inputs config file. +