mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-10-24 02:04:04 +08:00
Implement profile="XX.XX" on tools, better defaults for newer tools.
- set -e in tool command scripts. - Disable implicit extra file collection. All dynamic extra file collection requires a <discover_datasets tag. - Disable format="input" - require explicit metadata targets (metadata_source, format_source). - Disable interpreter= - hacky and doesn't work as expected in too many circumstances. Use $__tool_directory__. - Disable $param_file - grepping the command for the string is impercise. If useful we can add flag to match the flag used to produce inputs as a JSON file. - Disable default version of 1.0.0, the IUC has made it clear they prefer all tools have an explicit version. Fixes #1609.
This commit is contained in:
@@ -20,6 +20,7 @@ from mako.template import Template
|
||||
from paste import httpexceptions
|
||||
from six import string_types
|
||||
|
||||
from galaxy.version import VERSION_MAJOR
|
||||
from galaxy import model
|
||||
from galaxy.managers import histories
|
||||
from galaxy.datatypes.metadata import JobExternalOutputMetadataWrapper
|
||||
@@ -460,6 +461,8 @@ class Tool( object, Dictifiable ):
|
||||
"""
|
||||
Read tool configuration from the element `root` and fill in `self`.
|
||||
"""
|
||||
self.legacy_defaults = tool_source.legacy_defaults
|
||||
tool_profile = tool_source.parse_profile()
|
||||
# Get the UNIQUE id for the tool
|
||||
self.old_id = tool_source.parse_id()
|
||||
if guid is None:
|
||||
@@ -469,6 +472,11 @@ class Tool( object, Dictifiable ):
|
||||
if not self.id:
|
||||
raise Exception( "Missing tool 'id'" )
|
||||
|
||||
if not self.legacy_defaults and VERSION_MAJOR < tool_profile:
|
||||
template = "The tool %s targets version %s of Galaxy, you should upgrade Galaxy to ensure proper functioning of this tool."
|
||||
message = template % (self.id, tool_profile)
|
||||
log.warn(message)
|
||||
|
||||
# Get the (user visible) name of the tool
|
||||
self.name = tool_source.parse_name()
|
||||
if not self.name:
|
||||
@@ -476,8 +484,11 @@ class Tool( object, Dictifiable ):
|
||||
|
||||
self.version = tool_source.parse_version()
|
||||
if not self.version:
|
||||
# For backward compatibility, some tools may not have versions yet.
|
||||
self.version = "1.0.0"
|
||||
if self.legacy_defaults:
|
||||
# For backward compatibility, some tools may not have versions yet.
|
||||
self.version = "1.0.0"
|
||||
else:
|
||||
raise Exception( "Missing tool version.")
|
||||
|
||||
# Support multi-byte tools
|
||||
self.is_multi_byte = tool_source.parse_is_multi_byte()
|
||||
|
||||
@@ -224,7 +224,10 @@ class DefaultToolAction( object ):
|
||||
|
||||
# Deal with input dataset names, 'dbkey' and types
|
||||
input_names = []
|
||||
input_ext = 'data'
|
||||
# format='input" previously would give you a random extension from
|
||||
# the input extensions, now it should just give "input" as the output
|
||||
# format.
|
||||
input_ext = 'data' if tool.legacy_defaults else "input"
|
||||
input_dbkey = incoming.get( "dbkey", "?" )
|
||||
for name, data in reversed(inp_data.items()):
|
||||
if not data:
|
||||
@@ -239,7 +242,8 @@ class DefaultToolAction( object ):
|
||||
else: # HDA
|
||||
if data.hid:
|
||||
input_names.append( 'data %s' % data.hid )
|
||||
input_ext = data.ext
|
||||
if tool.legacy_defaults:
|
||||
input_ext = data.ext
|
||||
|
||||
if data.dbkey not in [None, '?']:
|
||||
input_dbkey = data.dbkey
|
||||
|
||||
@@ -526,7 +526,7 @@ class ToolEvaluator( object ):
|
||||
param_dict = self.param_dict
|
||||
directory = self.local_working_directory
|
||||
command = self.tool.command
|
||||
if command and "$param_file" in command:
|
||||
if self.tool.legacy_defaults and command and "$param_file" in command:
|
||||
fd, param_filename = tempfile.mkstemp( dir=directory )
|
||||
os.close( fd )
|
||||
f = open( param_filename, "w" )
|
||||
|
||||
@@ -133,6 +133,9 @@ class CwlToolSource(ToolSource):
|
||||
containers=containers,
|
||||
))
|
||||
|
||||
def parse_profile(self):
|
||||
return "16.04"
|
||||
|
||||
|
||||
class CwlPageSource(PageSource):
|
||||
|
||||
|
||||
@@ -11,6 +11,11 @@ class ToolSource(object):
|
||||
__metaclass__ = ABCMeta
|
||||
default_is_multi_byte = False
|
||||
|
||||
@property
|
||||
def legacy_defaults(self):
|
||||
# Restore oldest defaults for XML-based tools.
|
||||
return self.parse_profile() == "legacy"
|
||||
|
||||
@abstractmethod
|
||||
def parse_id(self):
|
||||
""" Parse an ID describing the abstract tool. This is not the
|
||||
@@ -158,6 +163,12 @@ class ToolSource(object):
|
||||
doesn't define help text.
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def parse_profile(self):
|
||||
""" Return tool profile to use, currently this should be a Galaxy
|
||||
version (> 16.04) or 'legacy'.
|
||||
"""
|
||||
|
||||
def parse_tests_to_dict(self):
|
||||
return {'tests': []}
|
||||
|
||||
|
||||
@@ -23,9 +23,9 @@ INPUT_DBKEY_TOKEN = "__input__"
|
||||
LEGACY_DEFAULT_DBKEY = None # don't use __input__ for legacy default collection
|
||||
|
||||
|
||||
def dataset_collector_descriptions_from_elem( elem ):
|
||||
def dataset_collector_descriptions_from_elem( elem, legacy=True ):
|
||||
primary_dataset_elems = elem.findall( "discover_datasets" )
|
||||
if not primary_dataset_elems:
|
||||
if len(primary_dataset_elems) == 0 and legacy:
|
||||
return [ DEFAULT_DATASET_COLLECTOR_DESCRIPTION ]
|
||||
else:
|
||||
return map( lambda elem: DatasetCollectionDescription( **elem.attrib ), primary_dataset_elems )
|
||||
|
||||
@@ -112,7 +112,12 @@ class XmlToolSource(ToolSource):
|
||||
|
||||
def parse_interpreter(self):
|
||||
command_el = self._command_el
|
||||
return (command_el is not None) and command_el.get("interpreter", None)
|
||||
interpreter = (command_el is not None) and command_el.get("interpreter", None)
|
||||
if not self.legacy_defaults:
|
||||
log.warn("Deprecated interpeter attribute on command element is now ignored.")
|
||||
interpreter = None
|
||||
|
||||
return interpreter
|
||||
|
||||
def parse_version_command(self):
|
||||
version_cmd = self.root.find("version_command")
|
||||
@@ -195,7 +200,7 @@ class XmlToolSource(ToolSource):
|
||||
|
||||
dataset_collector_descriptions = None
|
||||
if collection_elem.find( "discover_datasets" ) is not None:
|
||||
dataset_collector_descriptions = dataset_collector_descriptions_from_elem( collection_elem )
|
||||
dataset_collector_descriptions = dataset_collector_descriptions_from_elem( collection_elem, legacy=False )
|
||||
structure = ToolOutputCollectionStructure(
|
||||
collection_type=collection_type,
|
||||
collection_type_source=collection_type_source,
|
||||
@@ -262,7 +267,7 @@ class XmlToolSource(ToolSource):
|
||||
output.from_work_dir = data_elem.get("from_work_dir", None)
|
||||
output.hidden = string_as_bool( data_elem.get("hidden", "") )
|
||||
output.actions = ToolOutputActionGroup( output, data_elem.find( 'actions' ) )
|
||||
output.dataset_collector_descriptions = dataset_collector_descriptions_from_elem( data_elem )
|
||||
output.dataset_collector_descriptions = dataset_collector_descriptions_from_elem( data_elem, legacy=self.legacy_defaults )
|
||||
return output
|
||||
|
||||
def parse_stdio(self):
|
||||
@@ -277,6 +282,8 @@ class XmlToolSource(ToolSource):
|
||||
return aggressive_error_checks()
|
||||
else:
|
||||
raise ValueError("Unknown detect_errors value encountered [%s]" % detect_errors)
|
||||
elif len(self.root.findall('stdio')) == 0 and not self.legacy_defaults:
|
||||
return error_on_exit_code()
|
||||
else:
|
||||
parser = StdioParser(self.root)
|
||||
return parser.stdio_exit_codes, parser.stdio_regexes
|
||||
@@ -285,8 +292,10 @@ class XmlToolSource(ToolSource):
|
||||
command_el = self._command_el
|
||||
if command_el is not None:
|
||||
return string_as_bool(command_el.get("strict", "False"))
|
||||
else:
|
||||
elif self.legacy_defaults:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def parse_help(self):
|
||||
help_elem = self.root.find( 'help' )
|
||||
@@ -307,6 +316,20 @@ class XmlToolSource(ToolSource):
|
||||
|
||||
return rval
|
||||
|
||||
@property
|
||||
def legacy_defaults(self):
|
||||
# Pre-16.04 or default XML defaults
|
||||
# - Use standard error for error detection.
|
||||
# - Don't run shells with -e
|
||||
# - Auto-check for implicit multiple outputs.
|
||||
# - Auto-check for $param_file.
|
||||
# - Enable buggy interpreter attribute.
|
||||
return self.parse_profile() == "legacy"
|
||||
|
||||
def parse_profile(self):
|
||||
profile = self.root.get("profile", "legacy")
|
||||
return profile
|
||||
|
||||
|
||||
def _test_elem_to_dict(test_elem, i):
|
||||
rval = dict(
|
||||
|
||||
@@ -168,6 +168,11 @@ class YamlToolSource(ToolSource):
|
||||
|
||||
return rval
|
||||
|
||||
def parse_profile(self):
|
||||
"""
|
||||
"""
|
||||
return self.root_dict.get("profile", "16.04")
|
||||
|
||||
|
||||
def _parse_test(i, test_dict):
|
||||
inputs = test_dict["inputs"]
|
||||
|
||||
@@ -256,6 +256,7 @@ class TestComputeEnviornment( SimpleComputeEnvironment ):
|
||||
class MockTool( object ):
|
||||
|
||||
def __init__( self, app ):
|
||||
self.legacy_defaults = True
|
||||
self.app = app
|
||||
self.hooks_called = []
|
||||
self.environment_variables = []
|
||||
|
||||
Reference in New Issue
Block a user