details: http://www.bx.psu.edu/hg/galaxy/rev/dae0313bf5bb changeset: 2381:dae0313bf5bb user: James Taylor james@jamestaylor.org date: Wed Apr 29 13:46:02 2009 -0400 description: Handle the addition of new tool parameters better in the workflow editor. Default values will be filled in and a message displayed to the user
7 file(s) affected in this change:
lib/galaxy/tools/__init__.py lib/galaxy/tools/parameters/grouping.py lib/galaxy/web/controllers/workflow.py lib/galaxy/workflow/modules.py static/scripts/galaxy.workflow_editor.canvas.js templates/workflow/editor.mako tools/maf/interval2maf.xml
diffs (252 lines):
diff -r 22b08d47f7ba -r dae0313bf5bb lib/galaxy/tools/__init__.py --- a/lib/galaxy/tools/__init__.py Wed Apr 29 11:53:22 2009 -0400 +++ b/lib/galaxy/tools/__init__.py Wed Apr 29 13:46:02 2009 -0400 @@ -676,25 +676,7 @@ """ context = ExpressionContext( state, context ) for input in inputs.itervalues(): - if isinstance( input, Repeat ): - # Repeat elements are always initialized to have 0 units. - state[ input.name ] = [] - elif isinstance( input, Conditional ): - # State for a conditional is a plain dictionary. - s = state[ input.name ] = {} - # Get the default value for the 'test element' and use it - # to determine the current case - test_value = input.test_param.get_initial_value( trans, context ) - current_case = input.get_current_case( test_value, trans ) - # Store the current case in a special value - s['__current_case__'] = current_case - # Store the value of the test element - s[ input.test_param.name ] = test_value - # Recursively fill in state for selected case - self.fill_in_new_state( trans, input.cases[current_case].inputs, s, context ) - else: - # `input` is just a plain parameter, get its default value - state[ input.name ] = input.get_initial_value( trans, context ) + state[ input.name ] = input.get_initial_value( trans, context )
def get_param_html_map( self, trans, page=0, other_values={} ): """ @@ -1057,6 +1039,41 @@
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 ): + """ + Check that all parameters have values, and fill in with default + values where neccesary. 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 ) + return messages + + def check_and_update_param_values_helper( self, inputs, values, trans, messages, context=None, prefix="" ): + """ + 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: + messages.append( 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 ) + elif isinstance( input, Conditional ): + group_values = values[ input.name ] + current = group_values["__current_case__"] + self.check_and_update_param_values_helper( input.cases[current].inputs, group_values, trans, messages, context, prefix ) + else: + # Regular tool parameter, no recursion needed + pass
def handle_unvalidated_param_values( self, input_values, app ): """ diff -r 22b08d47f7ba -r dae0313bf5bb lib/galaxy/tools/parameters/grouping.py --- a/lib/galaxy/tools/parameters/grouping.py Wed Apr 29 11:53:22 2009 -0400 +++ b/lib/galaxy/tools/parameters/grouping.py Wed Apr 29 13:46:02 2009 -0400 @@ -3,6 +3,7 @@ """
from basic import ToolParameter +from galaxy.util.expressions import ExpressionContext
class Group( object ): def __init__( self ): @@ -19,6 +20,11 @@ into the preferred value form. """ return value + def get_initial_value( self, trans, context ): + """ + Return the initial state/value for this group + """ + raise TypeError( "Not implemented" )
class Repeat( Group ): type = "repeat" @@ -65,7 +71,9 @@ if isinstance( input, ToolParameter ): callback( new_prefix, input, d[input.name], parent = d ) else: - input.visit_inputs( new_prefix, d[input.name], callback ) + input.visit_inputs( new_prefix, d[input.name], callback ) + def get_initial_value( self, trans, context ): + return []
class Conditional( Group ): type = "conditional" @@ -109,6 +117,22 @@ 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 = {} + # Get the default value for the 'test element' and use it + # to determine the current case + test_value = self.test_param.get_initial_value( trans, context ) + current_case = self.get_current_case( test_value, trans ) + # Store the current case in a special value + rval['__current_case__'] = current_case + # Store the value of the test element + rval[ self.test_param.name ] = test_value + # Fill in state for selected case + child_context = ExpressionContext( rval, context ) + for child_input in self.cases[current_case].inputs.itervalues(): + rval[ child_input.name ] = child_input.get_initial_value( trans, child_context ) + return rval
class ConditionalWhen( object ): def __init__( self ): diff -r 22b08d47f7ba -r dae0313bf5bb lib/galaxy/web/controllers/workflow.py --- a/lib/galaxy/web/controllers/workflow.py Wed Apr 29 11:53:22 2009 -0400 +++ b/lib/galaxy/web/controllers/workflow.py Wed Apr 29 13:46:02 2009 -0400 @@ -300,9 +300,16 @@ data = {} data['name'] = workflow.name data['steps'] = {} + data['upgrade_messages'] = {} # For each step, rebuild the form and encode the state for step in workflow.steps: + # Load from database representation module = module_factory.from_workflow_step( trans, step ) + # Fix any missing parameters + upgrade_message = module.check_and_update_state() + if upgrade_message: + data['upgrade_messages'][step.order_index] = upgrade_message + # Pack atrributes into plain dictionary step_dict = { 'id': step.order_index, 'type': module.type, @@ -312,7 +319,7 @@ 'tool_errors': module.get_errors(), 'data_inputs': module.get_data_inputs(), 'data_outputs': module.get_data_outputs(), - 'form_html': module.get_config_form() + 'form_html': module.get_config_form(), } # Connections input_conn_dict = {} @@ -324,6 +331,7 @@ step_dict['position'] = step.position # Add to return value data['steps'][step.order_index] = step_dict + print data['upgrade_messages'] return data
@web.json diff -r 22b08d47f7ba -r dae0313bf5bb lib/galaxy/workflow/modules.py --- a/lib/galaxy/workflow/modules.py Wed Apr 29 11:53:22 2009 -0400 +++ b/lib/galaxy/workflow/modules.py Wed Apr 29 13:46:02 2009 -0400 @@ -60,6 +60,13 @@ pass def get_config_form( self ): raise TypeError( "Abstract method" ) + + def check_and_update_state( self ): + """ + If the state is not in sync with the current implementation of the + module, try to update. Returns a list of messages to be displayed + """ + pass
## ---- Run time ---------------------------------------------------------
@@ -236,7 +243,11 @@ return value, error # Update state using incoming values errors = self.tool.update_state( self.trans, self.tool.inputs, self.state.inputs, incoming, item_callback=item_callback ) - self.errors = errors or None + self.errors = errors or None + + def check_and_update_state( self ): + return self.tool.check_and_update_param_values( self.state.inputs, self.trans ) + def add_dummy_datasets( self, connections=None): if connections: # Store onnections by input name diff -r 22b08d47f7ba -r dae0313bf5bb static/scripts/galaxy.workflow_editor.canvas.js --- a/static/scripts/galaxy.workflow_editor.canvas.js Wed Apr 29 11:53:22 2009 -0400 +++ b/static/scripts/galaxy.workflow_editor.canvas.js Wed Apr 29 13:46:02 2009 -0400 @@ -255,6 +255,7 @@ if ( data.type ) { this.type = data.type; } + this.name = data.name; this.form_html = data.form_html; this.tool_state = data.tool_state; this.tool_errors = data.tool_errors; diff -r 22b08d47f7ba -r dae0313bf5bb templates/workflow/editor.mako --- a/templates/workflow/editor.mako Wed Apr 29 11:53:22 2009 -0400 +++ b/templates/workflow/editor.mako Wed Apr 29 13:46:02 2009 -0400 @@ -78,7 +78,18 @@ workflow.fit_canvas_to_nodes(); scroll_to_nodes(); canvas_manager.draw_overview(); - hide_modal(); + // Determine if any parameters were 'upgraded' and provide message + upgrade_message = "" + $.each( data['upgrade_messages'], function( k, v ) { + upgrade_message += ( "<li>Step " + ( parseInt(k) + 1 ) + ": " + workflow.nodes[k].name + " -- " + v.join( ", " ) ); + }); + if ( upgrade_message ) { + show_modal( "Workflow loaded with changes", + "Values were not found for the following parameters (possibly a result of tool upgrades), <br/> default values have been used. Please review the following parameters and then save.<ul>" + upgrade_message + "</ul>", + { "Continue" : hide_modal } ); + } else { + hide_modal(); + } }, beforeSubmit: function( data ) { show_modal( "Loading workflow", "progress" ); @@ -88,7 +99,9 @@ });
$(document).ajaxError( function ( e, x ) { - show_modal( "Server error", x.responseText, { "Ignore error" : hide_modal } ); + console.log( e, x ); + var message = x.responseText || x.statusText || "Could not connect to server"; + show_modal( "Server error", message, { "Ignore error" : hide_modal } ); return false; });
diff -r 22b08d47f7ba -r dae0313bf5bb tools/maf/interval2maf.xml --- a/tools/maf/interval2maf.xml Wed Apr 29 11:53:22 2009 -0400 +++ b/tools/maf/interval2maf.xml Wed Apr 29 13:46:02 2009 -0400 @@ -6,6 +6,7 @@ #end if </command> <inputs> + <param type="text" name="TEST" label="Test" /> <param format="interval" name="input1" type="data" label="Choose intervals"> <validator type="unspecified_build" /> </param>
galaxy-dev@lists.galaxyproject.org