diff --git a/lib/galaxy/tools/__init__.py b/lib/galaxy/tools/__init__.py index 8c12d282533..d80b279f87b 100755 --- a/lib/galaxy/tools/__init__.py +++ b/lib/galaxy/tools/__init__.py @@ -641,11 +641,22 @@ class Tool( object, Dictifiable ): root = tool_source.root conf_parent_elem = root.find("configfiles") if conf_parent_elem is not None: + inputs_elem = conf_parent_elem.find( "inputs" ) + if inputs_elem is not None: + 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) + self.config_files.append( ( name, filename, content ) ) for conf_elem in conf_parent_elem.findall( "configfile" ): name = conf_elem.get( "name" ) filename = conf_elem.get( "filename", None ) - text = conf_elem.text - self.config_files.append( ( name, filename, text ) ) + content = conf_elem.text + self.config_files.append( ( name, filename, content ) ) def __parse_trackster_conf(self, tool_source): self.trackster_conf = None diff --git a/lib/galaxy/tools/evaluation.py b/lib/galaxy/tools/evaluation.py index 72da979a5d9..7f13c1a7df1 100644 --- a/lib/galaxy/tools/evaluation.py +++ b/lib/galaxy/tools/evaluation.py @@ -1,3 +1,4 @@ +import json import os import tempfile @@ -20,6 +21,7 @@ from galaxy.tools.parameters.basic import ( DataCollectionToolParameter, SelectToolParameter, ) +from galaxy.tools.parameters import wrapped_json from galaxy.tools.parameters.grouping import Conditional, Repeat, Section from galaxy.tools import global_tool_errors from galaxy.jobs.datasets import dataset_path_rewrites @@ -472,7 +474,8 @@ class ToolEvaluator( object ): """ param_dict = self.param_dict config_filenames = [] - for name, filename, template_text in self.tool.config_files: + for name, filename, content in self.tool.config_files: + config_text, is_template = self.__build_config_file_text(content) # If a particular filename was forced by the config use it directory = self.local_working_directory if filename is not None: @@ -480,7 +483,7 @@ class ToolEvaluator( object ): else: fd, config_filename = tempfile.mkstemp( dir=directory ) os.close( fd ) - self.__write_workdir_file( config_filename, template_text, param_dict ) + self.__write_workdir_file( config_filename, config_text, param_dict, is_template=is_template ) self.__register_extra_file( name, config_filename ) config_filenames.append( config_filename ) return config_filenames @@ -526,8 +529,20 @@ class ToolEvaluator( object ): else: return None - def __write_workdir_file( self, config_filename, template, context ): - value = fill_template( template, context=context ) + def __build_config_file_text( self, content ): + if isinstance( content, basestring ): + return content, True + + assert content["format"] == "json" + assert content["version"] == 1 + + return json.dumps(wrapped_json.json_wrap(self.tool.inputs, self.param_dict)), False + + def __write_workdir_file( self, config_filename, content, context, is_template=True ): + if is_template: + value = fill_template( content, context=context ) + else: + value = content with open( config_filename, "w" ) as f: f.write( value ) # For running jobs as the actual user, ensure the config file is globally readable diff --git a/lib/galaxy/tools/parameters/wrapped_json.py b/lib/galaxy/tools/parameters/wrapped_json.py new file mode 100644 index 00000000000..e49cee48622 --- /dev/null +++ b/lib/galaxy/tools/parameters/wrapped_json.py @@ -0,0 +1,72 @@ +import logging +log = logging.getLogger(__name__) + + +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) + return as_dict + + +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) == ''): + return None + else: + return cast_to(value) + + +__all__ = ['json_wrap'] diff --git a/test/functional/tools/inputs_as_json.xml b/test/functional/tools/inputs_as_json.xml new file mode 100644 index 00000000000..a4f5a4de91c --- /dev/null +++ b/test/functional/tools/inputs_as_json.xml @@ -0,0 +1,79 @@ + + + + + + + python $check_inputs $inputs $test_case + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/functional/tools/samples_tool_conf.xml b/test/functional/tools/samples_tool_conf.xml index 509a37c78ae..3d7be1d164b 100644 --- a/test/functional/tools/samples_tool_conf.xml +++ b/test/functional/tools/samples_tool_conf.xml @@ -15,6 +15,7 @@ +