diff --git a/lib/galaxy/tools/parameters/__init__.py b/lib/galaxy/tools/parameters/__init__.py
index 5c5fe29fa32..d694d751efc 100644
--- a/lib/galaxy/tools/parameters/__init__.py
+++ b/lib/galaxy/tools/parameters/__init__.py
@@ -40,26 +40,78 @@ def visit_input_values(inputs, input_values, callback, name_prefix='', label_pre
>>> g = BooleanToolParameter( None, XML( '' ) )
>>> h = TextToolParameter( None, XML( '' ) )
>>> i = TextToolParameter( None, XML( '' ) )
- >>> b.name = 'b'
+ >>> j = TextToolParameter( None, XML( '' ) )
+ >>> b.name = b.title = 'b'
>>> b.inputs = odict([ ('c', c), ('d', d) ])
- >>> d.name = 'd'
+ >>> d.name = d.title = 'd'
>>> d.inputs = odict([ ('e', e), ('f', f) ])
>>> f.test_param = g
>>> f.name = 'f'
>>> f.cases = [ Bunch( value='true', inputs= { 'h': h } ), Bunch( value='false', inputs= { 'i': i } ) ]
>>>
- >>> def visitor( input, value, prefix, prefixed_name, **kwargs ):
- ... print 'name=%s, prefix=%s, prefixed_name=%s, value=%s' % ( input.name, prefix, prefixed_name, value )
- >>> inputs = odict([('a',a),('b',b)])
+ >>> def visitor( input, value, prefix, prefixed_name, prefixed_label, error, **kwargs ):
+ ... print 'name=%s, prefix=%s, prefixed_name=%s, prefixed_label=%s,value=%s' % ( input.name, prefix, prefixed_name, prefixed_label, value )
+ ... if error:
+ ... print error
+ >>> inputs = odict([('a', a),('b', b)])
>>> nested = odict([ ('a', 1), ('b', [ odict([('c', 3), ( 'd', [odict([ ('e', 5), ('f', odict([ ('g', True), ('h', 7) ])) ]) ])]) ]) ])
>>> visit_input_values( inputs, nested, visitor )
- name=a, prefix=, prefixed_name=a, value=1
- name=c, prefix=b_0|, prefixed_name=b_0|c, value=3
- name=e, prefix=b_0|d_0|, prefixed_name=b_0|d_0|e, value=5
- name=g, prefix=b_0|d_0|, prefixed_name=b_0|d_0|f|g, value=True
- name=h, prefix=b_0|d_0|, prefixed_name=b_0|d_0|f|h, value=7
+ name=a, prefix=, prefixed_name=a, prefixed_label=a,value=1
+ name=c, prefix=b_0|, prefixed_name=b_0|c, prefixed_label=b 1 > c,value=3
+ name=e, prefix=b_0|d_0|, prefixed_name=b_0|d_0|e, prefixed_label=b 1 > d 1 > e,value=5
+ name=g, prefix=b_0|d_0|, prefixed_name=b_0|d_0|f|g, prefixed_label=b 1 > d 1 > g,value=True
+ name=h, prefix=b_0|d_0|, prefixed_name=b_0|d_0|f|h, prefixed_label=b 1 > d 1 > h,value=7
>>> params_from_strings( inputs, params_to_strings( inputs, nested, None ), None )[ 'b' ][ 0 ][ 'd' ][ 0 ][ 'f' ][ 'g' ] is True
True
+
+ >>> # Conditional test parameter value does not match any case, warning is shown and child values are not visited
+ >>> f.test_param = j
+ >>> nested['b'][0]['d'][0]['f']['j'] = 'j'
+ >>> visit_input_values( inputs, nested, visitor )
+ name=a, prefix=, prefixed_name=a, prefixed_label=a,value=1
+ name=c, prefix=b_0|, prefixed_name=b_0|c, prefixed_label=b 1 > c,value=3
+ name=e, prefix=b_0|d_0|, prefixed_name=b_0|d_0|e, prefixed_label=b 1 > d 1 > e,value=5
+ name=j, prefix=b_0|d_0|, prefixed_name=b_0|d_0|f|j, prefixed_label=b 1 > d 1 > j,value=j
+ The selected case is unavailable/invalid.
+
+ >>> # Test parameter missing in state, value error
+ >>> del nested['b'][0]['d'][0]['f']['j']
+ >>> visit_input_values( inputs, nested, visitor )
+ name=a, prefix=, prefixed_name=a, prefixed_label=a,value=1
+ name=c, prefix=b_0|, prefixed_name=b_0|c, prefixed_label=b 1 > c,value=3
+ name=e, prefix=b_0|d_0|, prefixed_name=b_0|d_0|e, prefixed_label=b 1 > d 1 > e,value=5
+ name=j, prefix=b_0|d_0|, prefixed_name=b_0|d_0|f|j, prefixed_label=b 1 > d 1 > j,value=None
+ No value found for 'b 1 > d 1 > j'.
+
+ >>> # Conditional parameter missing in state, value error
+ >>> del nested['b'][0]['d'][0]['f']
+ >>> visit_input_values( inputs, nested, visitor )
+ name=a, prefix=, prefixed_name=a, prefixed_label=a,value=1
+ name=c, prefix=b_0|, prefixed_name=b_0|c, prefixed_label=b 1 > c,value=3
+ name=e, prefix=b_0|d_0|, prefixed_name=b_0|d_0|e, prefixed_label=b 1 > d 1 > e,value=5
+ name=j, prefix=b_0|d_0|, prefixed_name=b_0|d_0|f|j, prefixed_label=b 1 > d 1 > j,value=None
+ No value found for 'b 1 > d 1 > j'.
+
+ >>> # Conditional input name has changed e.g. due to tool changes, key error
+ >>> f.name = 'f_1'
+ >>> visit_input_values( inputs, nested, visitor )
+ name=a, prefix=, prefixed_name=a, prefixed_label=a,value=1
+ name=c, prefix=b_0|, prefixed_name=b_0|c, prefixed_label=b 1 > c,value=3
+ name=e, prefix=b_0|d_0|, prefixed_name=b_0|d_0|e, prefixed_label=b 1 > d 1 > e,value=5
+ name=j, prefix=b_0|d_0|, prefixed_name=b_0|d_0|f_1|j, prefixed_label=b 1 > d 1 > j,value=None
+ No value found for 'b 1 > d 1 > j'.
+
+ >>> # Other parameters are missing in state
+ >>> nested = odict([ ('b', [ odict([ ( 'd', [odict([ ('f', odict([ ('g', True), ('h', 7) ])) ]) ])]) ]) ])
+ >>> visit_input_values( inputs, nested, visitor )
+ name=a, prefix=, prefixed_name=a, prefixed_label=a,value=None
+ No value found for 'a'.
+ name=c, prefix=b_0|, prefixed_name=b_0|c, prefixed_label=b 1 > c,value=None
+ No value found for 'b 1 > c'.
+ name=e, prefix=b_0|d_0|, prefixed_name=b_0|d_0|e, prefixed_label=b 1 > d 1 > e,value=None
+ No value found for 'b 1 > d 1 > e'.
+ name=j, prefix=b_0|d_0|, prefixed_name=b_0|d_0|f_1|j, prefixed_label=b 1 > d 1 > j,value=None
+ No value found for 'b 1 > d 1 > j'.
"""
def callback_helper(input, input_values, name_prefix, label_prefix, parent_prefix, context=None, error=None):
args = {
@@ -82,6 +134,12 @@ def visit_input_values(inputs, input_values, callback, name_prefix='', label_pre
if replace:
input_values[input.name] = new_value
+ def get_current_case(input, input_values):
+ try:
+ return input.get_current_case(input_values[input.test_param.name])
+ except (KeyError, ValueError):
+ return -1
+
context = ExpressionContext(input_values, context)
payload = {'context': context, 'no_replacement_value': no_replacement_value}
for input in inputs.values():
@@ -95,15 +153,11 @@ def visit_input_values(inputs, input_values, callback, name_prefix='', label_pre
elif isinstance(input, Conditional):
values = input_values[input.name] = input_values.get(input.name, {})
new_name_prefix = name_prefix + input.name + '|'
- case_error = None
- try:
- input.get_current_case(values[input.test_param.name])
- except:
- case_error = 'The selected case is unavailable/invalid.'
- pass
+ case_error = None if get_current_case(input, values) >= 0 else 'The selected case is unavailable/invalid.'
callback_helper(input.test_param, values, new_name_prefix, label_prefix, parent_prefix=name_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, parent_prefix=name_prefix, **payload)
+ values['__current_case__'] = get_current_case(input, values)
+ if values['__current_case__'] >= 0:
+ visit_input_values(input.cases[values['__current_case__']].inputs, values, callback, new_name_prefix, label_prefix, parent_prefix=name_prefix, **payload)
elif isinstance(input, Section):
values = input_values[input.name] = input_values.get(input.name, {})
new_name_prefix = name_prefix + input.name + '|'