mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Merge pull request #1764 from guerler/fix_check_and_update_000
Use visit inputs for check_and_update_param_values
This commit is contained in:
@@ -361,12 +361,10 @@ EditorFormView = Backbone.View.extend({
|
||||
self.canvas_manager.draw_overview();
|
||||
// Determine if any parameters were 'upgraded' and provide message
|
||||
upgrade_message = "";
|
||||
$.each( data.upgrade_messages, function( step_id, messages ) {
|
||||
_.each( data.upgrade_messages, function( messages, step_id ) {
|
||||
var details = "";
|
||||
Utils.deepeach( [ messages ], function( d ) {
|
||||
$.each( d, function( i, v ) {
|
||||
details += typeof v === "string" ? "<li>" + v + "</li>" : "";
|
||||
});
|
||||
_.each( messages, function( m ) {
|
||||
details += "<li>" + m + "</li>";
|
||||
});
|
||||
if ( details ) {
|
||||
upgrade_message += "<li>Step " + ( parseInt( step_id, 10 ) + 1 ) + ": " + self.workflow.nodes[ step_id ].name + "<ul>" + details + "</ul></li>";
|
||||
|
||||
+39
-38
@@ -16,6 +16,7 @@ import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import traceback
|
||||
from xml.etree import ElementTree
|
||||
from galaxy import model, util
|
||||
from galaxy.util.xml_macros import load
|
||||
from galaxy.datatypes import metadata
|
||||
@@ -112,6 +113,15 @@ class JobConfiguration( object ):
|
||||
"""
|
||||
DEFAULT_NWORKERS = 4
|
||||
|
||||
JOB_RESOURCE_CONDITIONAL_XML = """<conditional name="__job_resource">
|
||||
<param name="__job_resource__select" type="select" label="Job Resource Parameters">
|
||||
<option value="no">Use default job resource parameters</option>
|
||||
<option value="yes">Specify job resource parameters</option>
|
||||
</param>
|
||||
<when value="no"/>
|
||||
<when value="yes"/>
|
||||
</conditional>"""
|
||||
|
||||
def __init__(self, app):
|
||||
"""Parse the job configuration XML.
|
||||
"""
|
||||
@@ -354,53 +364,44 @@ class JobConfiguration( object ):
|
||||
|
||||
log.debug('Done loading job configuration')
|
||||
|
||||
def get_tool_resource_parameters( self, tool_id ):
|
||||
def get_tool_resource_xml( self, tool_id, tool_type ):
|
||||
""" Given a tool id, return XML elements describing parameters to
|
||||
insert into job resources.
|
||||
|
||||
:tool id: A tool ID (a string)
|
||||
:tool type: A tool type (a string)
|
||||
|
||||
:returns: List of parameter elements.
|
||||
"""
|
||||
fields = []
|
||||
|
||||
if not tool_id:
|
||||
return fields
|
||||
|
||||
# TODO: Only works with exact matches, should handle different kinds of ids
|
||||
# the way destination lookup does.
|
||||
resource_group = None
|
||||
if tool_id in self.tools:
|
||||
resource_group = self.tools[ tool_id ][ 0 ].get_resource_group()
|
||||
resource_group = resource_group or self.default_resource_group
|
||||
|
||||
if resource_group and resource_group in self.resource_groups:
|
||||
fields_names = self.resource_groups[ resource_group ]
|
||||
fields = [ self.resource_parameters[ n ] for n in fields_names ]
|
||||
|
||||
return fields
|
||||
if tool_id and tool_type is 'default':
|
||||
# TODO: Only works with exact matches, should handle different kinds of ids
|
||||
# the way destination lookup does.
|
||||
resource_group = None
|
||||
if tool_id in self.tools:
|
||||
resource_group = self.tools[ tool_id ][ 0 ].get_resource_group()
|
||||
resource_group = resource_group or self.default_resource_group
|
||||
if resource_group and resource_group in self.resource_groups:
|
||||
fields_names = self.resource_groups[ resource_group ]
|
||||
fields = [ self.resource_parameters[ n ] for n in fields_names ]
|
||||
if fields:
|
||||
conditional_element = ElementTree.fromstring( self.JOB_RESOURCE_CONDITIONAL_XML )
|
||||
when_yes_elem = conditional_element.findall( 'when' )[ 1 ]
|
||||
for parameter in fields:
|
||||
when_yes_elem.append( parameter )
|
||||
return conditional_element
|
||||
|
||||
def __parse_resource_parameters( self ):
|
||||
if not os.path.exists( self.app.config.job_resource_params_file ):
|
||||
return
|
||||
|
||||
resource_param_file = self.app.config.job_resource_params_file
|
||||
try:
|
||||
resource_definitions = util.parse_xml( resource_param_file )
|
||||
except Exception as e:
|
||||
raise config_exception(e, resource_param_file)
|
||||
|
||||
resource_definitions_root = resource_definitions.getroot()
|
||||
# TODO: Also handling conditionals would be awesome!
|
||||
for parameter_elem in resource_definitions_root.findall( "param" ):
|
||||
name = parameter_elem.get( "name" )
|
||||
# Considered prepending __job_resource_param__ here and then
|
||||
# stripping it off when making it available to dynamic job
|
||||
# destination. Not needed because resource parameters are wrapped
|
||||
# in a conditional.
|
||||
# # expanded_name = "__job_resource_param__%s" % name
|
||||
# # parameter_elem.set( "name", expanded_name )
|
||||
self.resource_parameters[ name ] = parameter_elem
|
||||
if os.path.exists( self.app.config.job_resource_params_file ):
|
||||
resource_param_file = self.app.config.job_resource_params_file
|
||||
try:
|
||||
resource_definitions = util.parse_xml( resource_param_file )
|
||||
except Exception as e:
|
||||
raise config_exception( e, resource_param_file )
|
||||
resource_definitions_root = resource_definitions.getroot()
|
||||
# TODO: Also handling conditionals would be awesome!
|
||||
for parameter_elem in resource_definitions_root.findall( "param" ):
|
||||
name = parameter_elem.get( "name" )
|
||||
self.resource_parameters[ name ] = parameter_elem
|
||||
|
||||
def __get_default(self, parent, names):
|
||||
"""
|
||||
|
||||
+41
-134
@@ -33,8 +33,7 @@ from galaxy.tools.parameters import params_to_incoming, check_param, params_from
|
||||
from galaxy.tools.parameters import output_collect
|
||||
from galaxy.tools.parameters.basic import (BaseURLToolParameter,
|
||||
DataToolParameter, DataCollectionToolParameter, HiddenToolParameter,
|
||||
SelectToolParameter, ToolParameter,
|
||||
contains_workflow_parameter)
|
||||
SelectToolParameter, ToolParameter)
|
||||
from galaxy.tools.parameters.grouping import Conditional, ConditionalWhen, Repeat, Section, UploadDataset
|
||||
from galaxy.tools.parameters.input_translation import ToolInputTranslator
|
||||
from galaxy.tools.test import parse_tests
|
||||
@@ -66,17 +65,6 @@ import galaxy.jobs
|
||||
|
||||
log = logging.getLogger( __name__ )
|
||||
|
||||
|
||||
JOB_RESOURCE_CONDITIONAL_XML = """<conditional name="__job_resource">
|
||||
<param name="__job_resource__select" type="select" label="Job Resource Parameters">
|
||||
<option value="no">Use default job resource parameters</option>
|
||||
<option value="yes">Specify job resource parameters</option>
|
||||
</param>
|
||||
<when value="no"></when>
|
||||
<when value="yes">
|
||||
</when>
|
||||
</conditional>"""
|
||||
|
||||
HELP_UNINITIALIZED = threading.Lock()
|
||||
|
||||
|
||||
@@ -137,27 +125,8 @@ class ToolBox( BaseGalaxyToolBox ):
|
||||
tool_type = tool_source.parse_tool_type()
|
||||
ToolClass = tool_types.get( tool_type )
|
||||
else:
|
||||
# Normal tool - only insert dynamic resource parameters for these
|
||||
# tools.
|
||||
root = getattr( tool_source, "root", None )
|
||||
# TODO: mucking with the XML directly like this is terrible,
|
||||
# modify inputs directly post load if possible.
|
||||
if root is not None and hasattr( self.app, "job_config" ): # toolshed may not have job_config?
|
||||
tool_id = root.get( 'id' )
|
||||
parameters = self.app.job_config.get_tool_resource_parameters( tool_id )
|
||||
if parameters:
|
||||
inputs = root.find('inputs')
|
||||
# If tool has not inputs, create some so we can insert conditional
|
||||
if inputs is None:
|
||||
inputs = ElementTree.fromstring( "<inputs></inputs>")
|
||||
root.append( inputs )
|
||||
# Insert a conditional allowing user to specify resource parameters.
|
||||
conditional_element = ElementTree.fromstring( JOB_RESOURCE_CONDITIONAL_XML )
|
||||
when_yes_elem = conditional_element.findall( "when" )[ 1 ]
|
||||
for parameter in parameters:
|
||||
when_yes_elem.append( parameter )
|
||||
inputs.append( conditional_element )
|
||||
|
||||
# Normal tool
|
||||
root = getattr( tool_source, 'root', None )
|
||||
ToolClass = Tool
|
||||
tool = ToolClass( config_file, tool_source, self.app, guid=guid, repository_id=repository_id, **kwds )
|
||||
return tool
|
||||
@@ -339,6 +308,8 @@ class Tool( object, Dictifiable ):
|
||||
self.lineage_ids = []
|
||||
# populate toolshed repository info, if available
|
||||
self.populate_tool_shed_info()
|
||||
# add tool resource parameters
|
||||
self.populate_resource_parameters( tool_source )
|
||||
# Parse XML element containing configuration
|
||||
try:
|
||||
self.parse( tool_source, guid=guid )
|
||||
@@ -547,8 +518,9 @@ class Tool( object, Dictifiable ):
|
||||
# Handle toolshed guids
|
||||
self_ids = [ self.id.lower(), self.id.lower().rsplit('/', 1)[0], self.old_id.lower() ]
|
||||
self.all_ids = self_ids
|
||||
|
||||
# In the toolshed context, there is no job config.
|
||||
if 'job_config' in dir(self.app):
|
||||
if hasattr( self.app, 'job_config' ):
|
||||
self.job_tool_configurations = self.app.job_config.get_job_tool_configurations(self_ids)
|
||||
|
||||
# Is this a 'hidden' tool (hidden in tool menu)
|
||||
@@ -728,7 +700,8 @@ class Tool( object, Dictifiable ):
|
||||
# Parse the actual parameters
|
||||
# Handle multiple page case
|
||||
for page_source in pages.page_sources:
|
||||
display, inputs = self.parse_input_page( page_source, enctypes )
|
||||
inputs = self.parse_input_elem( page_source, enctypes )
|
||||
display = page_source.parse_display()
|
||||
self.inputs_by_page.append( inputs )
|
||||
self.inputs.update( inputs )
|
||||
self.display_by_page.append( display )
|
||||
@@ -807,17 +780,6 @@ class Tool( object, Dictifiable ):
|
||||
citations.append( citation )
|
||||
return citations
|
||||
|
||||
def parse_input_page( self, page_source, enctypes ):
|
||||
"""
|
||||
Parse a page of inputs. This basically just calls 'parse_input_elem',
|
||||
but it also deals with possible 'display' elements which are supported
|
||||
only at the top/page level (not in groups).
|
||||
"""
|
||||
inputs = self.parse_input_elem( page_source, enctypes )
|
||||
# Display
|
||||
display = page_source.parse_display()
|
||||
return display, inputs
|
||||
|
||||
def parse_input_elem( self, page_source, enctypes, context=None ):
|
||||
"""
|
||||
Parse a parent element whose children are inputs -- these could be
|
||||
@@ -946,6 +908,17 @@ class Tool( object, Dictifiable ):
|
||||
context[ name ].refresh_on_change = True
|
||||
return param
|
||||
|
||||
def populate_resource_parameters( self, tool_source ):
|
||||
root = getattr( tool_source, 'root', None )
|
||||
if root is not None and hasattr( self.app, 'job_config' ) and hasattr( self.app.job_config, 'get_tool_resource_xml' ):
|
||||
resource_xml = self.app.job_config.get_tool_resource_xml( root.get( 'id' ), self.tool_type )
|
||||
if resource_xml is not None:
|
||||
inputs = root.find( 'inputs' )
|
||||
if inputs is None:
|
||||
inputs = ElementTree.fromstring( '<inputs/>' )
|
||||
root.append( inputs )
|
||||
inputs.append( resource_xml )
|
||||
|
||||
def populate_tool_shed_info( self ):
|
||||
if self.repository_id is not None and self.app.name == 'galaxy':
|
||||
repository_id = self.app.security.decode_id( self.repository_id )
|
||||
@@ -1097,7 +1070,7 @@ class Tool( object, Dictifiable ):
|
||||
return self.code_namespace[name]
|
||||
return None
|
||||
|
||||
def visit_inputs( self, value, callback ):
|
||||
def visit_inputs( self, values, callback ):
|
||||
"""
|
||||
Call the function `callback` on each parameter of this tool. Visits
|
||||
grouping parameters recursively and constructs unique prefixes for
|
||||
@@ -1106,13 +1079,8 @@ class Tool( object, Dictifiable ):
|
||||
`callback( level_prefix, parameter, parameter_value )`
|
||||
"""
|
||||
# HACK: Yet another hack around check_values -- WHY HERE?
|
||||
if not self.check_values:
|
||||
return
|
||||
for input in self.inputs.itervalues():
|
||||
if isinstance( input, ToolParameter ):
|
||||
callback( "", input, value[input.name] )
|
||||
else:
|
||||
input.visit_inputs( "", value[input.name], callback )
|
||||
if self.check_values:
|
||||
visit_input_values( self.inputs, values, callback )
|
||||
|
||||
def handle_input( self, trans, incoming, history=None ):
|
||||
"""
|
||||
@@ -1280,87 +1248,24 @@ class Tool( object, Dictifiable ):
|
||||
"""
|
||||
messages = {}
|
||||
request_context = WorkRequestContext( app=trans.app, user=trans.user, history=trans.history, workflow_building_mode=workflow_building_mode )
|
||||
self.check_and_update_param_values_helper( self.inputs, values, request_context, messages, update_values=update_values )
|
||||
return messages
|
||||
|
||||
def check_and_update_param_values_helper( self, inputs, values, trans, messages, context=None, prefix="", update_values=True ):
|
||||
"""
|
||||
Recursive helper for `check_and_update_param_values_helper`
|
||||
"""
|
||||
context = ExpressionContext( values, context )
|
||||
for input in inputs.itervalues():
|
||||
# No value, insert the default
|
||||
if input.name not in values:
|
||||
if isinstance( input, Conditional ):
|
||||
cond_messages = {}
|
||||
if not input.is_job_resource_conditional:
|
||||
cond_messages = { input.test_param.name: "No value found for '%s%s', using default" % ( prefix, input.test_param.label ) }
|
||||
messages[ input.name ] = cond_messages
|
||||
test_value = input.test_param.get_initial_value( trans, context )
|
||||
current_case = input.get_current_case( test_value )
|
||||
self.check_and_update_param_values_helper( input.cases[ current_case ].inputs, {}, trans, cond_messages, context, prefix, update_values=update_values )
|
||||
elif isinstance( input, Repeat ):
|
||||
if input.min:
|
||||
messages[ input.name ] = []
|
||||
for i in range( input.min ):
|
||||
rep_prefix = prefix + '%s %d > ' % ( input.title, i + 1 )
|
||||
rep_dict = dict()
|
||||
messages[ input.name ].append( rep_dict )
|
||||
self.check_and_update_param_values_helper( input.inputs, {}, trans, rep_dict, context, rep_prefix, update_values=update_values )
|
||||
elif isinstance( input, Section ):
|
||||
messages[ input.name ] = {}
|
||||
self.check_and_update_param_values_helper( input.inputs, {}, trans, messages[ input.name ], context, prefix, update_values=update_values )
|
||||
else:
|
||||
messages[ input.name ] = "No value found for '%s%s', using default" % ( prefix, input.label )
|
||||
values[ input.name ] = input.get_initial_value( trans, context )
|
||||
# Value, visit recursively as usual
|
||||
else:
|
||||
if isinstance( input, Repeat ):
|
||||
for i, d in enumerate( values[ input.name ] ):
|
||||
rep_prefix = prefix + '%s %d > ' % ( input.title, i + 1 )
|
||||
self.check_and_update_param_values_helper( input.inputs, d, trans, messages, context, rep_prefix, update_values=update_values )
|
||||
elif isinstance( input, Conditional ):
|
||||
group_values = values[ input.name ]
|
||||
use_initial_value = False
|
||||
if '__current_case__' in group_values:
|
||||
if int( group_values[ '__current_case__' ] ) >= len( input.cases ):
|
||||
use_initial_value = True
|
||||
else:
|
||||
use_initial_value = True
|
||||
if input.test_param.name not in group_values or use_initial_value:
|
||||
# No test param invalidates the whole conditional
|
||||
values[ input.name ] = group_values = input.get_initial_value( trans, context )
|
||||
messages[ input.test_param.name ] = "No value found for '%s%s', using default" % ( prefix, input.test_param.label )
|
||||
current_case = group_values[ '__current_case__' ]
|
||||
for child_input in input.cases[current_case].inputs.itervalues():
|
||||
messages[ child_input.name ] = "Value no longer valid for '%s%s', replacing with default" % ( prefix, child_input.label )
|
||||
else:
|
||||
current = group_values[ '__current_case__' ]
|
||||
self.check_and_update_param_values_helper( input.cases[current].inputs, group_values, trans, messages, context, prefix, update_values=update_values )
|
||||
elif isinstance( input, Section ):
|
||||
messages[ input.name ] = {}
|
||||
self.check_and_update_param_values_helper( input.inputs, values[ input.name ], trans, messages[ input.name ], context, prefix, update_values=update_values )
|
||||
else:
|
||||
# Regular tool parameter, no recursion needed
|
||||
def validate_inputs( input, value, error, parent, context, prefixed_name, prefixed_label, **kwargs ):
|
||||
if not error:
|
||||
value, error = check_param( request_context, input, value, context )
|
||||
if error:
|
||||
if update_values:
|
||||
try:
|
||||
value = values[ input.name ]
|
||||
if not trans.workflow_building_mode:
|
||||
input.value_from_basic( input.value_to_basic( value, trans.app ), trans.app, ignore_errors=False )
|
||||
input.validate( value, trans )
|
||||
else:
|
||||
# skip check if is workflow parameters
|
||||
ck_param = True
|
||||
search = input.type in [ 'text' ]
|
||||
if trans.workflow_building_mode and contains_workflow_parameter( values[ input.name ], search=search ):
|
||||
ck_param = False
|
||||
# this will fail when a parameter's type has changed to a non-compatible one: e.g. conditional group changed to dataset input
|
||||
if ck_param:
|
||||
input.value_from_basic( input.value_to_basic( value, self.app ), self.app, ignore_errors=False )
|
||||
value = input.get_initial_value( request_context, context )
|
||||
if not prefixed_name.startswith( '__' ):
|
||||
messages[ prefixed_name ] = '%s Using default: \'%s\'.' % ( error, value )
|
||||
parent[ input.name ] = value
|
||||
except:
|
||||
log.info( "Parameter validation failed.", exc_info=True )
|
||||
messages[ input.name ] = "Value no longer valid for '%s%s', replacing with default" % ( prefix, input.label )
|
||||
if update_values:
|
||||
values[ input.name ] = input.get_initial_value( trans, context )
|
||||
messages[ prefixed_name ] = 'Attempt to replace invalid value for \'%s\' failed.' % ( prefixed_label )
|
||||
else:
|
||||
messages[ prefixed_name ] = error
|
||||
|
||||
visit_input_values( self.inputs, values, validate_inputs )
|
||||
return messages
|
||||
|
||||
def build_dependency_shell_commands( self, job_directory=None ):
|
||||
"""Return a list of commands to be run to populate the current environment to include this tools requirements."""
|
||||
@@ -1703,10 +1608,11 @@ class Tool( object, Dictifiable ):
|
||||
|
||||
# load job parameters into incoming
|
||||
tool_message = ''
|
||||
tool_warnings = ''
|
||||
if job:
|
||||
try:
|
||||
job_params = job.get_param_values( self.app, ignore_errors=True )
|
||||
self.check_and_update_param_values( job_params, request_context, update_values=False )
|
||||
tool_warnings = self.check_and_update_param_values( job_params, request_context, update_values=False )
|
||||
self._map_source_to_history( request_context, self.inputs, job_params )
|
||||
tool_message = self._compare_tool_version( job )
|
||||
params_to_incoming( kwd, self.inputs, job_params, self.app )
|
||||
@@ -1873,6 +1779,7 @@ class Tool( object, Dictifiable ):
|
||||
'biostar_url' : self.app.config.biostar_url,
|
||||
'sharable_url' : self.tool_shed_repository.get_sharable_url( self.app ) if self.tool_shed_repository else None,
|
||||
'message' : tool_message,
|
||||
'warnings' : tool_warnings,
|
||||
'versions' : tool_versions,
|
||||
'requirements' : [ { 'name' : r.name, 'version' : r.version } for r in self.requirements ],
|
||||
'errors' : state_errors,
|
||||
|
||||
@@ -50,7 +50,7 @@ class DefaultToolAction( object ):
|
||||
current_user_roles = trans.get_current_user_roles()
|
||||
input_datasets = odict()
|
||||
|
||||
def visitor( prefix, input, value, parent=None ):
|
||||
def visitor( input, value, prefix, parent=None, **kwargs ):
|
||||
|
||||
def process_dataset( data, formats=None ):
|
||||
if not data:
|
||||
@@ -98,12 +98,12 @@ class DefaultToolAction( object ):
|
||||
else:
|
||||
raise Exception('A path for explicit datatype conversion has not been found: %s --/--> %s' % ( input_datasets[ prefix + input.name + str( i + 1 ) ].extension, conversion_extensions ) )
|
||||
if parent:
|
||||
parent[input.name][i] = input_datasets[ prefix + input.name + str( i + 1 ) ]
|
||||
parent[ input.name ][ i ] = input_datasets[ prefix + input.name + str( i + 1 ) ]
|
||||
for conversion_name, conversion_data in conversions:
|
||||
# allow explicit conversion to be stored in job_parameter table
|
||||
parent[ conversion_name ][i] = conversion_data.id # a more robust way to determine JSONable value is desired
|
||||
parent[ conversion_name ][ i ] = conversion_data.id # a more robust way to determine JSONable value is desired
|
||||
else:
|
||||
param_values[input.name][i] = input_datasets[ prefix + input.name + str( i + 1 ) ]
|
||||
param_values[ input.name ][ i ] = input_datasets[ prefix + input.name + str( i + 1 ) ]
|
||||
for conversion_name, conversion_data in conversions:
|
||||
# allow explicit conversion to be stored in job_parameter table
|
||||
param_values[ conversion_name ][i] = conversion_data.id # a more robust way to determine JSONable value is desired
|
||||
@@ -143,10 +143,6 @@ class DefaultToolAction( object ):
|
||||
# Skipping implicit conversion stuff for now, revisit at
|
||||
# some point and figure out if implicitly converting a
|
||||
# dataset collection makes senese.
|
||||
|
||||
# if i == 0:
|
||||
# # Allow copying metadata to output, first item will be source.
|
||||
# input_datasets[ prefix + input.name ] = data.dataset_instance
|
||||
input_datasets[ prefix + input.name + str( i + 1 ) ] = data
|
||||
|
||||
tool.visit_inputs( param_values, visitor )
|
||||
@@ -160,7 +156,7 @@ class DefaultToolAction( object ):
|
||||
|
||||
input_dataset_collections = dict()
|
||||
|
||||
def visitor( prefix, input, value, parent=None ):
|
||||
def visitor( input, value, prefix, parent=None, **kwargs ):
|
||||
if isinstance( input, DataToolParameter ):
|
||||
values = value
|
||||
if not isinstance( values, list ):
|
||||
@@ -322,7 +318,7 @@ class DefaultToolAction( object ):
|
||||
metadata_source = output.metadata_source
|
||||
if metadata_source:
|
||||
if isinstance( metadata_source, string_types ):
|
||||
metadata_source = inp_data[metadata_source]
|
||||
metadata_source = inp_data.get( metadata_source )
|
||||
|
||||
if metadata_source is not None:
|
||||
data.init_meta( copy_from=metadata_source )
|
||||
|
||||
@@ -34,16 +34,6 @@ def execute( trans, tool, param_combinations, history, rerun_remap_job_id=None,
|
||||
# Only workflow invocation code gets to set this, ignore user supplied
|
||||
# values or rerun parameters.
|
||||
del params[ '__workflow_invocation_uuid__' ]
|
||||
|
||||
# If this is a workflow, everything has now been connected so we should validate
|
||||
# the state we about to execute one last time. Consider whether tool executions
|
||||
# should run this as well.
|
||||
if workflow_invocation_uuid:
|
||||
messages = tool.check_and_update_param_values( params, trans, update_values=False )
|
||||
if messages:
|
||||
execution_tracker.record_error( messages )
|
||||
return
|
||||
|
||||
job, result = tool.handle_single_execution( trans, rerun_remap_job_id, params, history, collection_info, execution_cache )
|
||||
if job:
|
||||
message = EXECUTION_SUCCESS_MESSAGE % (tool.id, job.id, job_timer)
|
||||
|
||||
@@ -10,7 +10,7 @@ from galaxy.util.expressions import ExpressionContext
|
||||
REPLACE_ON_TRUTHY = object()
|
||||
|
||||
|
||||
def visit_input_values( inputs, input_values, callback, name_prefix="", label_prefix="", no_replacement_value=REPLACE_ON_TRUTHY, context=None ):
|
||||
def visit_input_values( inputs, input_values, callback, name_prefix='', label_prefix='', parent_prefix='', context=None, no_replacement_value=REPLACE_ON_TRUTHY ):
|
||||
"""
|
||||
Given a tools parameter definition (`inputs`) and a specific set of
|
||||
parameter `values`, call `callback` for each non-grouping parameter,
|
||||
@@ -18,15 +18,35 @@ def visit_input_values( inputs, input_values, callback, name_prefix="", label_pr
|
||||
and a display label.
|
||||
|
||||
If the callback returns a value, it will be replace the old value.
|
||||
|
||||
>>> from xml.etree.ElementTree import XML
|
||||
>>> from galaxy.util.odict import odict
|
||||
>>> from galaxy.tools.parameters.basic import TextToolParameter
|
||||
>>> from galaxy.tools.parameters.grouping import Repeat
|
||||
>>> a = TextToolParameter( None, XML( '<param name="a" type="text"/>' ) )
|
||||
>>> b = Repeat()
|
||||
>>> c = TextToolParameter( None, XML( '<param name="c" type="text"/>' ) )
|
||||
>>> b.name = 'b'
|
||||
>>> b.inputs = { 'c': c }
|
||||
>>> def visitor( input, value, prefixed_name, **kwargs ):
|
||||
... print '%s, %s, %s' % ( input.name, prefixed_name, value )
|
||||
>>> visit_input_values( odict( [ ('a', a), ('b', b ) ] ), odict( [ ('a', 1), ('b', [ { 'c': 3 } ] ) ] ), visitor )
|
||||
a, a, 1
|
||||
c, b_0|c, 3
|
||||
"""
|
||||
def callback_helper( input, input_values, context, name_prefix, label_prefix ):
|
||||
def callback_helper( input, input_values, name_prefix, label_prefix, parent_prefix, context=None, error=None ):
|
||||
args = {
|
||||
'input' : input,
|
||||
'parent' : input_values,
|
||||
'value' : input_values.get( input.name ),
|
||||
'prefixed_name' : '%s%s' % ( name_prefix, input.name ),
|
||||
'prefixed_label' : '%s%s' % ( label_prefix, input.label ),
|
||||
'context' : context
|
||||
'prefixed_label' : '%s%s' % ( label_prefix, input.label or input.name ),
|
||||
'prefix' : parent_prefix,
|
||||
'context' : context,
|
||||
'error' : error
|
||||
}
|
||||
if input.name not in input_values:
|
||||
args[ 'error' ] = 'No value found for \'%s\'.' % args.get( 'prefixed_label' )
|
||||
new_value = callback( **args )
|
||||
if no_replacement_value is REPLACE_ON_TRUTHY:
|
||||
replace = bool( new_value )
|
||||
@@ -36,25 +56,33 @@ def visit_input_values( inputs, input_values, callback, name_prefix="", label_pr
|
||||
input_values[ input.name ] = new_value
|
||||
|
||||
context = ExpressionContext( input_values, context )
|
||||
payload = { 'parent_prefix': name_prefix, 'context': context, 'no_replacement_value': no_replacement_value }
|
||||
for input in inputs.itervalues():
|
||||
if isinstance( input, Repeat ) or isinstance( input, UploadDataset ):
|
||||
for i, d in enumerate( input_values[ input.name ] ):
|
||||
index = d[ '__index__' ]
|
||||
new_name_prefix = name_prefix + '%s_%d|' % ( input.name, index )
|
||||
values = input_values[ input.name ] = input_values.get( input.name, [] )
|
||||
for i, d in enumerate( values ):
|
||||
d[ '__index__' ] = i
|
||||
new_name_prefix = name_prefix + '%s_%d|' % ( input.name, i )
|
||||
new_label_prefix = label_prefix + '%s %d > ' % ( input.title, i + 1 )
|
||||
visit_input_values( input.inputs, d, callback, new_name_prefix, new_label_prefix, no_replacement_value=no_replacement_value, context=context )
|
||||
visit_input_values( input.inputs, d, callback, new_name_prefix, new_label_prefix, **payload )
|
||||
elif isinstance( input, Conditional ):
|
||||
values = input_values[ input.name ]
|
||||
values = input_values[ input.name ] = input_values.get( input.name, {} )
|
||||
new_name_prefix = name_prefix + input.name + '|'
|
||||
callback_helper( input.test_param, values, context, new_name_prefix, label_prefix )
|
||||
values[ '__current_case__' ] = input.get_current_case( values.get( input.test_param.name ) )
|
||||
visit_input_values( input.cases[ values[ '__current_case__' ] ].inputs, values, callback, new_name_prefix, label_prefix, no_replacement_value=no_replacement_value, context=context )
|
||||
case_error = None
|
||||
try:
|
||||
input.get_current_case( values[ input.test_param.name ] )
|
||||
except:
|
||||
case_error = 'The selected case is unavailable/invalid.'
|
||||
pass
|
||||
callback_helper( input.test_param, values, new_name_prefix, label_prefix, parent_prefix, context=context, error=case_error )
|
||||
values[ '__current_case__' ] = input.get_current_case( values[ input.test_param.name ] )
|
||||
visit_input_values( input.cases[ values[ '__current_case__' ] ].inputs, values, callback, new_name_prefix, label_prefix, **payload )
|
||||
elif isinstance( input, Section ):
|
||||
values = input_values[ input.name ]
|
||||
values = input_values[ input.name ] = input_values.get( input.name, {} )
|
||||
new_name_prefix = name_prefix + input.name + '|'
|
||||
visit_input_values( input.inputs, values, callback, new_name_prefix, label_prefix, no_replacement_value=no_replacement_value, context=context )
|
||||
visit_input_values( input.inputs, values, callback, new_name_prefix, label_prefix, **payload )
|
||||
else:
|
||||
callback_helper( input, input_values, context, name_prefix, label_prefix )
|
||||
callback_helper( input, input_values, name_prefix, label_prefix, parent_prefix, context=context )
|
||||
|
||||
|
||||
def check_param( trans, param, incoming_value, param_values ):
|
||||
|
||||
@@ -58,6 +58,7 @@ class ToolParameter( object, Dictifiable ):
|
||||
self.name = ToolParameter.parse_name( input_source )
|
||||
self.type = input_source.get("type")
|
||||
self.hidden = input_source.get("hidden", False)
|
||||
self.optional = input_source.parse_optional()
|
||||
self.is_dynamic = False
|
||||
self.label = input_source.parse_label()
|
||||
self.help = input_source.parse_help()
|
||||
@@ -66,7 +67,6 @@ class ToolParameter( object, Dictifiable ):
|
||||
self.sanitizer = ToolParameterSanitizer.from_element( sanitizer_elem )
|
||||
else:
|
||||
self.sanitizer = None
|
||||
self.html = "no html set"
|
||||
try:
|
||||
# These don't do anything right? These we should
|
||||
# delete these two lines and eliminate checks for
|
||||
@@ -75,9 +75,6 @@ class ToolParameter( object, Dictifiable ):
|
||||
self.condition = input_source.elem().get( "condition", None )
|
||||
except Exception:
|
||||
self.repeat = None
|
||||
|
||||
# Optional DataToolParameters are used in tools like GMAJ and LAJ
|
||||
self.optional = input_source.parse_optional()
|
||||
self.validators = []
|
||||
for elem in input_source.parse_validator_elems():
|
||||
self.validators.append( validation.Validator.from_element( self, elem ) )
|
||||
@@ -89,10 +86,7 @@ class ToolParameter( object, Dictifiable ):
|
||||
|
||||
def get_label( self ):
|
||||
"""Return user friendly name for the parameter"""
|
||||
if self.label:
|
||||
return self.label
|
||||
else:
|
||||
return self.name
|
||||
return self.label if self.label else self.name
|
||||
|
||||
def get_html_field( self, trans=None, value=None, other_values={} ):
|
||||
raise TypeError( "Abstract Method" )
|
||||
@@ -191,10 +185,9 @@ class ToolParameter( object, Dictifiable ):
|
||||
return value
|
||||
|
||||
def validate( self, value, trans=None ):
|
||||
if value == "" and self.optional:
|
||||
return
|
||||
for validator in self.validators:
|
||||
validator.validate( value, trans )
|
||||
if value is not '' or not self.optional:
|
||||
for validator in self.validators:
|
||||
validator.validate( value, trans )
|
||||
|
||||
def to_dict( self, trans, view='collection', value_mapper=None, other_values={} ):
|
||||
""" to_dict tool parameter. This can be overridden by subclasses. """
|
||||
@@ -211,23 +204,23 @@ class ToolParameter( object, Dictifiable ):
|
||||
def build( cls, tool, param ):
|
||||
"""Factory method to create parameter of correct type"""
|
||||
param_name = cls.parse_name( param )
|
||||
param_type = param.get("type")
|
||||
param_type = param.get( 'type' )
|
||||
if not param_type:
|
||||
raise ValueError( "Tool parameter '%s' requires a 'type'" % ( param_name ) )
|
||||
elif param_type not in parameter_types:
|
||||
raise ValueError( "Tool parameter '%s' uses an unknown type '%s'" % ( param_name, param_type ) )
|
||||
else:
|
||||
return parameter_types[param_type]( tool, param )
|
||||
return parameter_types[ param_type ]( tool, param )
|
||||
|
||||
@classmethod
|
||||
def parse_name(cls, input_source):
|
||||
name = input_source.get("name", None)
|
||||
name = input_source.get( 'name' )
|
||||
if name is None:
|
||||
argument = input_source.get("argument")
|
||||
argument = input_source.get( 'argument' )
|
||||
if argument:
|
||||
name = argument.lstrip("-")
|
||||
name = argument.lstrip( '-' )
|
||||
else:
|
||||
raise ValueError("Tool parameter must specify a name.")
|
||||
raise ValueError( "Tool parameter must specify a name." )
|
||||
return name
|
||||
|
||||
|
||||
|
||||
@@ -9,8 +9,6 @@ import os
|
||||
import StringIO
|
||||
import unicodedata
|
||||
from six import text_type
|
||||
|
||||
from basic import ToolParameter
|
||||
from galaxy.datatypes import sniff
|
||||
from galaxy.util import inflector
|
||||
from galaxy.util import relpath
|
||||
@@ -113,15 +111,6 @@ class Repeat( Group ):
|
||||
raise e
|
||||
return rval
|
||||
|
||||
def visit_inputs( self, prefix, value, callback ):
|
||||
for i, d in enumerate( value ):
|
||||
for input in self.inputs.itervalues():
|
||||
new_prefix = prefix + "%s_%d|" % ( self.name, i )
|
||||
if isinstance( input, ToolParameter ):
|
||||
callback( new_prefix, input, d[input.name], parent=d )
|
||||
else:
|
||||
input.visit_inputs( new_prefix, d[input.name], callback )
|
||||
|
||||
def get_initial_value( self, trans, context ):
|
||||
rval = []
|
||||
for i in range( self.default ):
|
||||
@@ -177,13 +166,6 @@ class Section( Group ):
|
||||
raise e
|
||||
return rval
|
||||
|
||||
def visit_inputs( self, prefix, value, callback ):
|
||||
for input in self.inputs.itervalues():
|
||||
if isinstance( input, ToolParameter ):
|
||||
callback( prefix, input, value[input.name], parent=value )
|
||||
else:
|
||||
input.visit_inputs( prefix, value[input.name], callback )
|
||||
|
||||
def get_initial_value( self, trans, context ):
|
||||
rval = {}
|
||||
child_context = ExpressionContext( rval, context )
|
||||
@@ -289,15 +271,6 @@ class UploadDataset( Group ):
|
||||
rval.append( rval_dict )
|
||||
return rval
|
||||
|
||||
def visit_inputs( self, prefix, value, callback ):
|
||||
for i, d in enumerate( value ):
|
||||
for input in self.inputs.itervalues():
|
||||
new_prefix = prefix + "%s_%d|" % ( self.name, i )
|
||||
if isinstance( input, ToolParameter ):
|
||||
callback( new_prefix, input, d[input.name], parent=d )
|
||||
else:
|
||||
input.visit_inputs( new_prefix, d[input.name], callback )
|
||||
|
||||
def get_initial_value( self, trans, context ):
|
||||
d_type = self.get_datatype( trans, context )
|
||||
rval = []
|
||||
@@ -565,9 +538,9 @@ class Conditional( Group ):
|
||||
|
||||
def value_to_basic( self, value, app ):
|
||||
rval = dict()
|
||||
current_case = rval['__current_case__'] = value['__current_case__']
|
||||
rval[ self.test_param.name ] = self.test_param.value_to_basic( value[ self.test_param.name ], app )
|
||||
for input in self.cases[current_case].inputs.itervalues():
|
||||
current_case = rval[ '__current_case__' ] = self.get_current_case( value[ self.test_param.name ] )
|
||||
for input in self.cases[ current_case ].inputs.itervalues():
|
||||
if input.name in value: # parameter might be absent in unverified workflow
|
||||
rval[ input.name ] = input.value_to_basic( value[ input.name ], app )
|
||||
return rval
|
||||
@@ -575,37 +548,20 @@ class Conditional( Group ):
|
||||
def value_from_basic( self, value, app, ignore_errors=False ):
|
||||
rval = dict()
|
||||
try:
|
||||
current_case = rval['__current_case__'] = value['__current_case__']
|
||||
# Test param
|
||||
if ignore_errors and self.test_param.name not in value:
|
||||
# If ignoring errors, do nothing. However this is potentially very
|
||||
# problematic since if we are missing the value of test param,
|
||||
# the entire conditional is wrong.
|
||||
pass
|
||||
else:
|
||||
rval[ self.test_param.name ] = self.test_param.value_from_basic( value[ self.test_param.name ], app, ignore_errors )
|
||||
rval[ self.test_param.name ] = self.test_param.value_from_basic( value.get( self.test_param.name ), app, ignore_errors )
|
||||
current_case = rval[ '__current_case__' ] = self.get_current_case( rval[ self.test_param.name ] )
|
||||
# Inputs associated with current case
|
||||
for input in self.cases[current_case].inputs.itervalues():
|
||||
if ignore_errors and input.name not in value:
|
||||
# If we do not have a value, and are ignoring errors, we simply
|
||||
# do nothing. There will be no value for the parameter in the
|
||||
# conditional's values dictionary.
|
||||
pass
|
||||
else:
|
||||
for input in self.cases[ current_case ].inputs.itervalues():
|
||||
# If we do not have a value, and are ignoring errors, we simply
|
||||
# do nothing. There will be no value for the parameter in the
|
||||
# conditional's values dictionary.
|
||||
if not ignore_errors or input.name in value:
|
||||
rval[ input.name ] = input.value_from_basic( value[ input.name ], app, ignore_errors )
|
||||
except Exception, e:
|
||||
if not ignore_errors:
|
||||
raise e
|
||||
return rval
|
||||
|
||||
def visit_inputs( self, prefix, value, callback ):
|
||||
current_case = value['__current_case__']
|
||||
for input in self.cases[current_case].inputs.itervalues():
|
||||
if isinstance( input, ToolParameter ):
|
||||
callback( prefix, input, value[input.name], parent=value )
|
||||
else:
|
||||
input.visit_inputs( prefix, value[input.name], callback )
|
||||
|
||||
def get_initial_value( self, trans, context ):
|
||||
# State for a conditional is a plain dictionary.
|
||||
rval = {}
|
||||
@@ -633,10 +589,6 @@ class Conditional( Group ):
|
||||
cond_dict[ "test_param" ] = nested_to_dict( self.test_param )
|
||||
return cond_dict
|
||||
|
||||
@property
|
||||
def is_job_resource_conditional(self):
|
||||
return self.name == "__job_resource"
|
||||
|
||||
|
||||
class ConditionalWhen( object, Dictifiable ):
|
||||
dict_collection_visible_keys = ( 'value', )
|
||||
|
||||
@@ -345,7 +345,7 @@ def __cleanup_param_values( inputs, values ):
|
||||
# Scrub dynamic resource related parameters from workflows,
|
||||
# they cause problems and the workflow probably should include
|
||||
# their state in workflow encoding.
|
||||
if input.is_job_resource_conditional:
|
||||
if input.name == '__job_resource':
|
||||
if input.name in values:
|
||||
del values[input.name]
|
||||
return
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -439,7 +439,7 @@ if wf_parms:
|
||||
## <div class="form-row"><input type="submit" name="${step.id}|${prefix}${input.name}_add" value="Add new ${input.title}" /></div>
|
||||
</div>
|
||||
%elif input.type == "conditional":
|
||||
%if input.is_job_resource_conditional:
|
||||
%if input.name == '__job_resource':
|
||||
<% continue %>
|
||||
%endif
|
||||
<% group_values = values[input.name] %>
|
||||
|
||||
+24
-40
@@ -46,7 +46,6 @@ steps:
|
||||
seed_source:
|
||||
seed_source_selector: set_seed
|
||||
seed: asdf
|
||||
__current_case__: 1
|
||||
label: nested_workflow
|
||||
connect:
|
||||
inner_input: first_cat#out_file1
|
||||
@@ -165,7 +164,7 @@ class BaseWorkflowsApiTestCase( api.ApiTestCase, ImporterGalaxyInterface ):
|
||||
invocation_details = invocation_details_response.json()
|
||||
return invocation_details
|
||||
|
||||
def _run_jobs( self, has_workflow, history_id=None, wait=True, source_type=None, jobs_descriptions=None ):
|
||||
def _run_jobs( self, has_workflow, history_id=None, wait=True, source_type=None, jobs_descriptions=None, expected_response=200, assert_ok=True ):
|
||||
def read_test_data(test_dict):
|
||||
test_data_resolver = TestDataResolver()
|
||||
filename = test_data_resolver.get_filename(test_dict["value"])
|
||||
@@ -238,33 +237,26 @@ class BaseWorkflowsApiTestCase( api.ApiTestCase, ImporterGalaxyInterface ):
|
||||
self.dataset_populator.wait_for_history( history_id, assert_ok=True )
|
||||
url = "workflows/%s/usage" % ( workflow_id )
|
||||
invocation_response = self._post( url, data=workflow_request )
|
||||
self._assert_status_code_is( invocation_response, 200 )
|
||||
self._assert_status_code_is( invocation_response, expected_response )
|
||||
invocation = invocation_response.json()
|
||||
invocation_id = invocation[ "id" ]
|
||||
# Wait for workflow to become fully scheduled and then for all jobs
|
||||
# complete.
|
||||
if wait:
|
||||
self._wait_for_workflow( workflow_id, invocation_id, history_id )
|
||||
jobs = self._history_jobs( history_id )
|
||||
return RunJobsSummary(
|
||||
history_id=history_id,
|
||||
workflow_id=workflow_id,
|
||||
invocation_id=invocation_id,
|
||||
inputs=inputs,
|
||||
jobs=jobs,
|
||||
)
|
||||
|
||||
def wait_for_invocation( self, workflow_id, invocation_id ):
|
||||
self.workflow_populator.wait_for_invocation( workflow_id, invocation_id )
|
||||
invocation_id = invocation.get( 'id' )
|
||||
if invocation_id:
|
||||
# Wait for workflow to become fully scheduled and then for all jobs
|
||||
# complete.
|
||||
if wait:
|
||||
self.workflow_populator.wait_for_workflow( workflow_id, invocation_id, history_id, assert_ok=assert_ok )
|
||||
jobs = self._history_jobs( history_id )
|
||||
return RunJobsSummary(
|
||||
history_id=history_id,
|
||||
workflow_id=workflow_id,
|
||||
invocation_id=invocation_id,
|
||||
inputs=inputs,
|
||||
jobs=jobs,
|
||||
)
|
||||
|
||||
def _history_jobs( self, history_id ):
|
||||
return self._get("jobs", { "history_id": history_id, "order_by": "create_time" } ).json()
|
||||
|
||||
def _wait_for_workflow( self, workflow_id, invocation_id, history_id, assert_ok=True ):
|
||||
""" Wait for a workflow invocation to completely schedule and then history
|
||||
to be complete. """
|
||||
self.workflow_populator.wait_for_workflow(workflow_id, invocation_id, history_id, assert_ok=assert_ok)
|
||||
|
||||
|
||||
# Workflow API TODO:
|
||||
# - Allow history_id as param to workflow run action. (hist_id)
|
||||
@@ -971,7 +963,6 @@ steps:
|
||||
seed_source:
|
||||
seed_source_selector: set_seed
|
||||
seed: asdf
|
||||
__current_case__: 1
|
||||
test_data:
|
||||
test_input: "hello world"
|
||||
""", history_id=history_id, wait=False)
|
||||
@@ -1009,13 +1000,13 @@ test_data:
|
||||
type: raw
|
||||
""", history_id=history_id, wait=True)
|
||||
time.sleep(10)
|
||||
self.wait_for_invocation( run_summary.workflow_id, run_summary.invocation_id )
|
||||
self.workflow_populator.wait_for_invocation( run_summary.workflow_id, run_summary.invocation_id )
|
||||
jobs = self._history_jobs( history_id )
|
||||
assert len(jobs) == 1
|
||||
|
||||
def test_run_with_validated_parameter_connection_invalid( self ):
|
||||
history_id = self.dataset_populator.new_history()
|
||||
run_summary = self._run_jobs("""
|
||||
self._run_jobs("""
|
||||
class: GalaxyWorkflow
|
||||
inputs:
|
||||
- label: text_input
|
||||
@@ -1030,10 +1021,7 @@ test_data:
|
||||
text_input:
|
||||
value: ""
|
||||
type: raw
|
||||
""", history_id=history_id, wait=False)
|
||||
self.wait_for_invocation( run_summary.workflow_id, run_summary.invocation_id )
|
||||
jobs = self._history_jobs( history_id )
|
||||
assert len(jobs) == 0
|
||||
""", history_id=history_id, wait=True, assert_ok=False )
|
||||
|
||||
def test_run_with_text_connection( self ):
|
||||
history_id = self.dataset_populator.new_history()
|
||||
@@ -1055,7 +1043,6 @@ steps:
|
||||
seed_source_selector: set_seed
|
||||
seed:
|
||||
$link: text_input
|
||||
__current_case__: 1
|
||||
test_data:
|
||||
data_input:
|
||||
value: 1.bed
|
||||
@@ -1070,9 +1057,9 @@ test_data:
|
||||
self.assertEquals("chr5\t131424298\t131424460\tCCDS4149.1_cds_0_0_chr5_131424299_f\t0\t+\n", content)
|
||||
|
||||
def wait_for_invocation_and_jobs( self, history_id, workflow_id, invocation_id, assert_ok=True ):
|
||||
self.wait_for_invocation( workflow_id, invocation_id )
|
||||
self.workflow_populator.wait_for_invocation( workflow_id, invocation_id )
|
||||
time.sleep(.5)
|
||||
self.dataset_populator.wait_for_history( history_id, assert_ok=True )
|
||||
self.dataset_populator.wait_for_history( history_id, assert_ok=assert_ok )
|
||||
time.sleep(.5)
|
||||
|
||||
def test_cannot_run_inaccessible_workflow( self ):
|
||||
@@ -1251,7 +1238,7 @@ steps:
|
||||
self.dataset_populator.wait_for_history( history_id )
|
||||
self.__review_paused_steps( workflow_id, invocation_id, order_index=2, action=True )
|
||||
|
||||
self._wait_for_workflow( workflow_id, invocation_id, history_id )
|
||||
self.workflow_populator.wait_for_workflow( workflow_id, invocation_id, history_id )
|
||||
time.sleep( 1 )
|
||||
content = self.dataset_populator.get_history_dataset_details( history_id )
|
||||
assert content[ "name" ] == "foo was replaced", content[ "name" ]
|
||||
@@ -1363,17 +1350,14 @@ steps:
|
||||
@skip_without_tool( "validation_repeat" )
|
||||
def test_workflow_import_state_validation_1( self ):
|
||||
history_id = self.dataset_populator.new_history()
|
||||
run_summary = self._run_jobs("""
|
||||
self._run_jobs("""
|
||||
class: GalaxyWorkflow
|
||||
steps:
|
||||
- tool_id: validation_repeat
|
||||
state:
|
||||
r2:
|
||||
- text: ""
|
||||
""", history_id=history_id, wait=False)
|
||||
self.wait_for_invocation( run_summary.workflow_id, run_summary.invocation_id )
|
||||
jobs = self._history_jobs( history_id )
|
||||
assert len(jobs) == 0
|
||||
""", history_id=history_id, wait=False, expected_response=400 )
|
||||
|
||||
def _run_validation_workflow_with_substitions( self, substitions ):
|
||||
workflow = self.workflow_populator.load_workflow_from_resource( "test_workflow_validation_1" )
|
||||
|
||||
@@ -33,7 +33,6 @@ steps:
|
||||
seed_source:
|
||||
seed_source_selector: set_seed
|
||||
seed: asdf
|
||||
__current_case__: 1
|
||||
""")
|
||||
workflow = self._get("workflows/%s/download" % workflow_id).json()
|
||||
|
||||
@@ -180,7 +179,6 @@ steps:
|
||||
seed_source:
|
||||
seed_source_selector: set_seed
|
||||
seed: asdf
|
||||
__current_case__: 1
|
||||
label: nested_workflow
|
||||
connect:
|
||||
inner_input: first_cat#out_file1
|
||||
|
||||
Reference in New Issue
Block a user