Fixes for Tool.check_and_update_param_values_helper() to check that the type of value provided is valid for the input parameter currently declared. Fixes an issue where rurun would select the wrong input dataset.

This commit is contained in:
Daniel Blankenberg
2013-01-10 14:57:37 -05:00
parent 979c1a6a16
commit bbbd1b4c0d
6 changed files with 75 additions and 51 deletions
+6 -5
View File
@@ -2128,16 +2128,16 @@ class Tool:
return params_to_strings( self.inputs, params, app )
def params_from_strings( self, params, app, ignore_errors=False ):
return params_from_strings( self.inputs, params, app, ignore_errors )
def check_and_update_param_values( self, values, trans ):
def check_and_update_param_values( self, values, trans, update_values=True ):
"""
Check that all parameters have values, and fill in with default
values where necessary. This could be called after loading values
from a database in case new parameters have been added.
"""
messages = {}
self.check_and_update_param_values_helper( self.inputs, values, trans, messages )
self.check_and_update_param_values_helper( self.inputs, values, trans, messages, update_values=update_values )
return messages
def check_and_update_param_values_helper( self, inputs, values, trans, messages, context=None, prefix="" ):
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`
"""
@@ -2183,10 +2183,11 @@ class Tool:
# Regular tool parameter, no recursion needed
try:
#this will fail when a parameter's type has changed to a non-compatible one: e.g. conditional group changed to dataset input
input.value_from_basic( values[ input.name ], trans.app, ignore_errors=False )
input.value_from_basic( input.value_to_basic( values[ input.name ], trans.app ), trans.app, ignore_errors=False )
except:
messages[ input.name ] = "Value no longer valid for '%s%s', replaced with default" % ( prefix, input.label )
values[ input.name ] = input.get_initial_value( trans, context )
if update_values:
values[ input.name ] = input.get_initial_value( trans, context )
def handle_unvalidated_param_values( self, input_values, app ):
"""
Find any instances of `UnvalidatedValue` within input_values and
+8 -5
View File
@@ -747,9 +747,9 @@ class SelectToolParameter( ToolParameter ):
return { "__class__": "RuntimeValue" }
return value
def value_from_basic( self, value, app, ignore_errors=False ):
if isinstance( value, dict ) and value["__class__"] == "UnvalidatedValue":
if isinstance( value, dict ) and value.get( "__class__", None ) == "UnvalidatedValue":
return UnvalidatedValue( value["value"] )
return super( SelectToolParameter, self ).value_from_basic( value, app )
return super( SelectToolParameter, self ).value_from_basic( value, app, ignore_errors=ignore_errors )
def need_late_validation( self, trans, context ):
"""
Determine whether we need to wait to validate this parameters value
@@ -943,7 +943,7 @@ class ColumnListParameter( SelectToolParameter ):
if not isinstance( value, list ):
value = value.split( '\n' )
for column in value:
for column2 in column.split( ',' ):
for column2 in str( column ).split( ',' ):
column2 = column2.strip()
if column2:
column_list.append( column2 )
@@ -1586,8 +1586,11 @@ class DataToolParameter( ToolParameter ):
elif isinstance( value, list) and len(value) > 0 and isinstance( value[0], DummyDataset):
return None
elif isinstance( value, list ):
return ",".join( [ val if isinstance( val, basestring ) else str(val.id) for val in value] )
return value.id
return ",".join( [ str( self.to_string( val, app ) ) for val in value ] )
try:
return value.id
except:
return str( value )
def to_python( self, value, app ):
# Both of these values indicate that no dataset is selected. However, 'None'
+39 -31
View File
@@ -68,21 +68,25 @@ class Repeat( Group ):
return rval
def value_from_basic( self, value, app, ignore_errors=False ):
rval = []
for i, d in enumerate( value ):
rval_dict = {}
# If the special __index__ key is not set, create it (for backward
# compatibility)
rval_dict['__index__'] = d.get( '__index__', i )
# Restore child inputs
for input in self.inputs.itervalues():
if ignore_errors and input.name not in d:
# 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:
rval_dict[ input.name ] = input.value_from_basic( d[input.name], app, ignore_errors )
rval.append( rval_dict )
try:
for i, d in enumerate( value ):
rval_dict = {}
# If the special __index__ key is not set, create it (for backward
# compatibility)
rval_dict['__index__'] = d.get( '__index__', i )
# Restore child inputs
for input in self.inputs.itervalues():
if ignore_errors and input.name not in d:
# 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:
rval_dict[ input.name ] = input.value_from_basic( d[input.name], app, ignore_errors )
rval.append( rval_dict )
except Exception, e:
if not ignore_errors:
raise e
return rval
def visit_inputs( self, prefix, value, callback ):
for i, d in enumerate( value ):
@@ -441,24 +445,28 @@ class Conditional( Group ):
return rval
def value_from_basic( self, value, app, ignore_errors=False ):
rval = dict()
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 )
# 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.
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[ input.name ] = input.value_from_basic( value[ input.name ], app, ignore_errors )
rval[ self.test_param.name ] = self.test_param.value_from_basic( value[ self.test_param.name ], app, ignore_errors )
# 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:
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__']
+7 -4
View File
@@ -182,10 +182,13 @@ class MetadataValidator( Validator ):
def from_element( cls, param, elem ):
return cls( message=elem.get( 'message', None ), check=elem.get( 'check', "" ), skip=elem.get( 'skip', "" ) )
def validate( self, value, history=None ):
if value and value.missing_meta( check = self.check, skip = self.skip ):
if self.message is None:
self.message = "Metadata missing, click the pencil icon in the history item to edit / save the metadata attributes"
raise ValueError( self.message )
if value:
if not isinstance( value, model.DatasetInstance ):
raise ValueError( 'A non-dataset value was provided.' )
if value.missing_meta( check = self.check, skip = self.skip ):
if self.message is None:
self.message = "Metadata missing, click the pencil icon in the history item to edit / save the metadata attributes"
raise ValueError( self.message )
class UnspecifiedBuildValidator( Validator ):
"""
+7
View File
@@ -32,3 +32,10 @@ def new_secure_hash( text_type=None ):
def hmac_new( key, value ):
return hmac.new( key, value, sha ).hexdigest()
def is_hashable( value ):
try:
hash( value )
except:
return False
return True
@@ -4,6 +4,7 @@ Upload class
from galaxy.web.base.controller import *
from galaxy.util.bunch import Bunch
from galaxy.util.hash_util import is_hashable
from galaxy.tools import DefaultToolState
from galaxy.tools.parameters.basic import UnvalidatedValue
from galaxy.tools.parameters import params_to_incoming
@@ -174,7 +175,7 @@ class ToolRunner( BaseUIController ):
params_objects = job.get_param_values( trans.app, ignore_errors = True )
except:
raise Exception( "Failed to get parameters for dataset id %d " % data.id )
upgrade_messages = tool.check_and_update_param_values( params_objects, trans )
upgrade_messages = tool.check_and_update_param_values( params_objects, trans, update_values=False )
# Need to remap dataset parameters. Job parameters point to original
# dataset used; parameter should be the analygous dataset in the
# current history.
@@ -199,12 +200,13 @@ class ToolRunner( BaseUIController ):
if isinstance(value,list):
values = []
for val in value:
if val in history.datasets:
values.append( val )
elif val in hda_source_dict:
values.append( hda_source_dict[ val ])
if is_hashable( val ):
if val in history.datasets:
values.append( val )
elif val in hda_source_dict:
values.append( hda_source_dict[ val ])
return values
if value not in history.datasets and value in hda_source_dict:
if is_hashable( value ) and value not in history.datasets and value in hda_source_dict:
return hda_source_dict[ value ]
visit_input_values( tool.inputs, params_objects, rerun_callback )
# Create a fake tool_state for the tool, with the parameters values