mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
"Input dataset" module now works for running. Many bug fixes to workflows
and tools. Moved some methods related to params out of the Tool class, sets of inputs can also be used in other ways (e.g. for modules). More abstraction needed here.
This commit is contained in:
@@ -142,7 +142,7 @@ class DefaultToolState( object ):
|
||||
"""
|
||||
# Convert parameters to a dictionary of strings, and save curent
|
||||
# page in that dict
|
||||
value = tool.params_to_strings( self.inputs, app )
|
||||
value = params_to_strings( tool.inputs, self.inputs, app )
|
||||
value["__page__"] = self.page
|
||||
value = simplejson.dumps( value )
|
||||
# Make it secure
|
||||
@@ -161,7 +161,7 @@ class DefaultToolState( object ):
|
||||
# Restore from string
|
||||
values = json_fix( simplejson.loads( value ) )
|
||||
self.page = values.pop( "__page__" )
|
||||
self.inputs = tool.params_from_strings( values, app, ignore_errors=True )
|
||||
self.inputs = params_from_strings( tool.inputs, values, app, ignore_errors=True )
|
||||
|
||||
class Tool:
|
||||
"""
|
||||
@@ -740,6 +740,7 @@ class Tool:
|
||||
prefix = "%s|" % ( key )
|
||||
# Deal with the 'test' element and see if it's value changed
|
||||
test_param_key = prefix + input.test_param.name
|
||||
test_param_error = None
|
||||
if test_param_key not in incoming and update_only:
|
||||
# Update only, keep previous value and state, but still
|
||||
# recurse in case there are nested changes
|
||||
@@ -751,7 +752,7 @@ class Tool:
|
||||
# Get value of test param and determine current case
|
||||
test_incoming = incoming.get( prefix + input.test_param.name, None )
|
||||
value, test_param_error = \
|
||||
self.check_param( trans, input.test_param, test_incoming, context )
|
||||
check_param( trans, input.test_param, test_incoming, context )
|
||||
current_case = input.get_current_case( value, trans )
|
||||
if current_case != old_current_case:
|
||||
# Current case has changed, throw away old state
|
||||
@@ -786,74 +787,48 @@ class Tool:
|
||||
# preserve the old error message.
|
||||
if input.name in old_errors:
|
||||
errors[ input.name ] = old_errors[ input.name ]
|
||||
# SelectToolParameters and DataToolParameters whose options are dynamically
|
||||
# generated based on the current value of a dependency parameter require special
|
||||
# handling. When the dependency parameter's value is changed, the form is
|
||||
# submitted ( due to the refresh_on_change behavior ). When this occurs, the
|
||||
# "dependent" parameter's value has not been reset ( dynamically generated based
|
||||
# on the new value of its dependency ) prior to reaching this point, so we need
|
||||
# to regenerate it before it is validated in check_param().
|
||||
incoming_value_generated = False
|
||||
if not( 'runtool_btn' in incoming or 'URL' in incoming ):
|
||||
# Form must have been refreshed, probably due to a refresh_on_change
|
||||
try:
|
||||
if input.is_dynamic:
|
||||
dependencies = input.get_dependencies()
|
||||
for dependency_name in dependencies:
|
||||
dependency_value = changed_dependencies.get( dependency_name, None )
|
||||
if dependency_value:
|
||||
# We need to dynamically generate the current input based on
|
||||
# the changed dependency parameter
|
||||
changed_params = {}
|
||||
changed_params[dependency_name] = dependency_value
|
||||
changed_params[input.name] = input
|
||||
incoming_value = input.get_initial_value( trans, changed_params )
|
||||
incoming_value_generated = True
|
||||
# Delete the dependency_param from chagned_dependencies since its
|
||||
# dependent param has been generated based its new value.
|
||||
del changed_dependencies[dependency_name]
|
||||
break
|
||||
except:
|
||||
pass
|
||||
if not incoming_value_generated:
|
||||
incoming_value = incoming.get( key, None )
|
||||
value, error = self.check_param( trans, input, incoming_value, context )
|
||||
if input.dependent_params and state[ input.name ] != value:
|
||||
# We need to keep track of changed dependency parametrs ( parameters
|
||||
# that have dependent parameters whose options are dynamically generated )
|
||||
changed_dependencies[ input.name ] = value
|
||||
if error:
|
||||
errors[ input.name ] = error
|
||||
state[ input.name ] = value
|
||||
else:
|
||||
# SelectToolParameters and DataToolParameters whose options are dynamically
|
||||
# generated based on the current value of a dependency parameter require special
|
||||
# handling. When the dependency parameter's value is changed, the form is
|
||||
# submitted ( due to the refresh_on_change behavior ). When this occurs, the
|
||||
# "dependent" parameter's value has not been reset ( dynamically generated based
|
||||
# on the new value of its dependency ) prior to reaching this point, so we need
|
||||
# to regenerate it before it is validated in check_param().
|
||||
incoming_value_generated = False
|
||||
if not( 'runtool_btn' in incoming or 'URL' in incoming ):
|
||||
# Form must have been refreshed, probably due to a refresh_on_change
|
||||
try:
|
||||
if input.is_dynamic:
|
||||
dependencies = input.get_dependencies()
|
||||
for dependency_name in dependencies:
|
||||
dependency_value = changed_dependencies.get( dependency_name, None )
|
||||
if dependency_value:
|
||||
# We need to dynamically generate the current input based on
|
||||
# the changed dependency parameter
|
||||
changed_params = {}
|
||||
changed_params[dependency_name] = dependency_value
|
||||
changed_params[input.name] = input
|
||||
incoming_value = input.get_initial_value( trans, changed_params )
|
||||
incoming_value_generated = True
|
||||
# Delete the dependency_param from chagned_dependencies since its
|
||||
# dependent param has been generated based its new value.
|
||||
del changed_dependencies[dependency_name]
|
||||
break
|
||||
except:
|
||||
pass
|
||||
if not incoming_value_generated:
|
||||
incoming_value = incoming.get( key, None )
|
||||
value, error = check_param( trans, input, incoming_value, context )
|
||||
if input.dependent_params and state[ input.name ] != value:
|
||||
# We need to keep track of changed dependency parametrs ( parameters
|
||||
# that have dependent parameters whose options are dynamically generated )
|
||||
changed_dependencies[ input.name ] = value
|
||||
if error:
|
||||
errors[ input.name ] = error
|
||||
state[ input.name ] = value
|
||||
return errors
|
||||
|
||||
def check_param( self, trans, param, incoming_value, param_values ):
|
||||
"""
|
||||
Check the value of a single parameter `param`. The value in
|
||||
`incoming_value` is converted from its HTML encoding and validated.
|
||||
The `param_values` argument contains the processed values of
|
||||
previous parameters (this may actually be an ExpressionContext
|
||||
when dealing with grouping scenarios).
|
||||
"""
|
||||
value = incoming_value
|
||||
error = None
|
||||
try:
|
||||
if param.name == 'file_data':
|
||||
pass
|
||||
elif value is not None or isinstance(param, DataToolParameter):
|
||||
# Convert value from HTML representation
|
||||
value = param.from_html( value, trans, param_values )
|
||||
# Allow the value to be converted if neccesary
|
||||
filtered_value = param.filter_value( value, trans, param_values )
|
||||
# Then do any further validation on the value
|
||||
param.validate( filtered_value, trans.history )
|
||||
elif value is None and isinstance( param, SelectToolParameter ):
|
||||
# An empty select list or column list
|
||||
param.validate( value, trans.history )
|
||||
except ValueError, e:
|
||||
error = str( e )
|
||||
return value, error
|
||||
|
||||
def get_static_param_values( self, trans ):
|
||||
"""
|
||||
Returns a map of parameter names and values if the tool does not
|
||||
@@ -880,34 +855,10 @@ class Tool:
|
||||
return self.tool_action.execute( self, trans, incoming )
|
||||
|
||||
def params_to_strings( self, params, app ):
|
||||
"""
|
||||
Convert a dictionary of parameter values to a dictionary of strings
|
||||
suitable for persisting. The `value_to_basic` method of each parameter
|
||||
is called to convert its value to basic types, the result of which
|
||||
is then json encoded (this allowing complex nested parameters and
|
||||
such).
|
||||
"""
|
||||
rval = dict()
|
||||
for key, value in params.iteritems():
|
||||
if key in self.inputs:
|
||||
value = self.inputs[ key ].value_to_basic( value, app )
|
||||
rval[ key ] = str( simplejson.dumps( value ) )
|
||||
return rval
|
||||
return params_to_strings( self.inputs, params, app )
|
||||
|
||||
def params_from_strings( self, params, app, ignore_errors=False ):
|
||||
"""
|
||||
Convert a dictionary of strings as produced by `params_to_strings`
|
||||
back into parameter values (decode the json representation and then
|
||||
allow each parameter to convert the basic types into the parameters
|
||||
preferred form).
|
||||
"""
|
||||
rval = dict()
|
||||
for key, value in params.iteritems():
|
||||
value = json_fix( simplejson.loads( value ) )
|
||||
if key in self.inputs:
|
||||
value = self.inputs[key].value_from_basic( value, app, ignore_errors )
|
||||
rval[ key ] = value
|
||||
return rval
|
||||
return params_from_strings( self.inputs, params, app, ignore_errors )
|
||||
|
||||
def handle_unvalidated_param_values( self, input_values, app ):
|
||||
"""
|
||||
|
||||
@@ -2,4 +2,62 @@
|
||||
Classes encapsulating Galaxy tool parameters.
|
||||
"""
|
||||
|
||||
from basic import *
|
||||
from basic import *
|
||||
from galaxy.util.json import *
|
||||
|
||||
def check_param( trans, param, incoming_value, param_values ):
|
||||
"""
|
||||
Check the value of a single parameter `param`. The value in
|
||||
`incoming_value` is converted from its HTML encoding and validated.
|
||||
The `param_values` argument contains the processed values of
|
||||
previous parameters (this may actually be an ExpressionContext
|
||||
when dealing with grouping scenarios).
|
||||
"""
|
||||
value = incoming_value
|
||||
error = None
|
||||
try:
|
||||
if param.name == 'file_data':
|
||||
pass
|
||||
elif value is not None or isinstance(param, DataToolParameter):
|
||||
# Convert value from HTML representation
|
||||
value = param.from_html( value, trans, param_values )
|
||||
# Allow the value to be converted if neccesary
|
||||
filtered_value = param.filter_value( value, trans, param_values )
|
||||
# Then do any further validation on the value
|
||||
param.validate( filtered_value, trans.history )
|
||||
elif value is None and isinstance( param, SelectToolParameter ):
|
||||
# An empty select list or column list
|
||||
param.validate( value, trans.history )
|
||||
except ValueError, e:
|
||||
error = str( e )
|
||||
return value, error
|
||||
|
||||
def params_to_strings( params, param_values, app ):
|
||||
"""
|
||||
Convert a dictionary of parameter values to a dictionary of strings
|
||||
suitable for persisting. The `value_to_basic` method of each parameter
|
||||
is called to convert its value to basic types, the result of which
|
||||
is then json encoded (this allowing complex nested parameters and
|
||||
such).
|
||||
"""
|
||||
rval = dict()
|
||||
for key, value in param_values.iteritems():
|
||||
if key in params:
|
||||
value = params[ key ].value_to_basic( value, app )
|
||||
rval[ key ] = str( to_json_string( value ) )
|
||||
return rval
|
||||
|
||||
def params_from_strings( params, param_values, app, ignore_errors=False ):
|
||||
"""
|
||||
Convert a dictionary of strings as produced by `params_to_strings`
|
||||
back into parameter values (decode the json representation and then
|
||||
allow each parameter to convert the basic types into the parameters
|
||||
preferred form).
|
||||
"""
|
||||
rval = dict()
|
||||
for key, value in param_values.iteritems():
|
||||
value = json_fix( from_json_string( value ) )
|
||||
if key in params:
|
||||
value = params[key].value_from_basic( value, app, ignore_errors )
|
||||
rval[ key ] = value
|
||||
return rval
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
__all__ = [ "to_json_string", "from_json_string", "json_fix"]
|
||||
|
||||
import pkg_resources
|
||||
pkg_resources.require( "simplejson" )
|
||||
|
||||
import simplejson
|
||||
|
||||
to_json_string = simplejson.dumps
|
||||
from_json_string = simplejson.loads
|
||||
|
||||
def json_fix( val ):
|
||||
if isinstance( val, list ):
|
||||
return [ json_fix( v ) for v in val ]
|
||||
elif isinstance( val, dict ):
|
||||
return dict( [ ( json_fix( k ), json_fix( v ) ) for ( k, v ) in val.iteritems() ] )
|
||||
elif isinstance( val, unicode ):
|
||||
return val.encode( "utf8" )
|
||||
else:
|
||||
return val
|
||||
@@ -2,11 +2,12 @@ from galaxy.web.base.controller import *
|
||||
|
||||
import simplejson
|
||||
|
||||
from galaxy.tools.parameters import DataToolParameter
|
||||
from galaxy.tools.parameters import DataToolParameter, check_param
|
||||
from galaxy.tools import DefaultToolState
|
||||
from galaxy.tools.parameters.grouping import Repeat, Conditional
|
||||
from galaxy.datatypes.data import Data
|
||||
from galaxy.util.odict import odict
|
||||
from galaxy.util.bunch import Bunch
|
||||
from galaxy.util.topsort import topsort, topsort_levels, CycleError
|
||||
|
||||
class WorkflowController( BaseController ):
|
||||
@@ -60,7 +61,6 @@ class WorkflowController( BaseController ):
|
||||
# Display the management page
|
||||
return self.index( trans )
|
||||
|
||||
|
||||
@web.expose
|
||||
@web.require_login( "edit workflows" )
|
||||
def editor( self, trans, id=None ):
|
||||
@@ -131,9 +131,11 @@ class WorkflowController( BaseController ):
|
||||
rval['name'] = module.name
|
||||
rval['type'] = module.type
|
||||
rval['tool_state'] = state = module.get_state()
|
||||
rval['data_inputs'] = module.get_data_inputs( state )
|
||||
rval['data_outputs'] = module.get_data_outputs( state )
|
||||
rval['form_html'] = module.get_config_form_html( trans, state )
|
||||
rval['data_inputs'] = module.get_data_inputs()
|
||||
rval['data_outputs'] = module.get_data_outputs()
|
||||
rval['form_html'] = trans.fill_template(
|
||||
"workflow/editor_generic_form.mako",
|
||||
form = module.get_config_form() )
|
||||
return rval
|
||||
|
||||
@web.json
|
||||
@@ -184,9 +186,11 @@ class WorkflowController( BaseController ):
|
||||
module = module_types[step.type].from_workflow_step( step )
|
||||
step_dict['name'] = module.name
|
||||
step_dict['tool_state'] = state = module.get_state()
|
||||
step_dict['data_inputs'] = module.get_data_inputs( state )
|
||||
step_dict['data_outputs'] = module.get_data_outputs( state )
|
||||
step_dict['form_html'] = module.get_config_form_html( trans, state )
|
||||
step_dict['data_inputs'] = module.get_data_inputs()
|
||||
step_dict['data_outputs'] = module.get_data_outputs()
|
||||
step_dict['form_html'] = trans.fill_template(
|
||||
"workflow/editor_generic_form.mako",
|
||||
form = module.get_config_form() )
|
||||
# Connections
|
||||
input_conn_dict = {}
|
||||
for conn in step.input_connections:
|
||||
@@ -319,9 +323,12 @@ class WorkflowController( BaseController ):
|
||||
if type( job_ids ) == str:
|
||||
job_ids = [ job_ids ]
|
||||
job_ids = [ int( id ) for id in job_ids ]
|
||||
if type( dataset_ids ) == str:
|
||||
dataset_ids = [ job_ids ]
|
||||
dataset_ids = [ int( id ) for id in dataset_ids ]
|
||||
if dataset_ids:
|
||||
if type( dataset_ids ) == str:
|
||||
dataset_ids = [ job_ids ]
|
||||
dataset_ids = [ int( id ) for id in dataset_ids ]
|
||||
else:
|
||||
dataset_ids = []
|
||||
# Find each job, for security we (implicately) check that they are
|
||||
# associated witha job in the current history.
|
||||
jobs, warnings = get_job_dict( trans )
|
||||
@@ -335,7 +342,6 @@ class WorkflowController( BaseController ):
|
||||
step.type = 'data_input'
|
||||
hid_to_output_pair[ hid ] = ( step, 'output' )
|
||||
steps.append( step )
|
||||
print hid_to_output_pair
|
||||
# Tool steps
|
||||
for job_id in job_ids:
|
||||
assert job_id in jobs_by_id, "Attempt to create workflow with job not connected to current history"
|
||||
@@ -344,6 +350,7 @@ class WorkflowController( BaseController ):
|
||||
param_values = job.get_param_values( trans.app )
|
||||
associations = cleanup_param_values( tool.inputs, param_values )
|
||||
step = model.WorkflowStep()
|
||||
step.type = 'tool'
|
||||
step.tool_id = job.tool_id
|
||||
step.tool_inputs = tool.params_to_strings( param_values, trans.app )
|
||||
# NOTE: We shouldn't need to do two passes here since only
|
||||
@@ -363,7 +370,6 @@ class WorkflowController( BaseController ):
|
||||
# Store created dataset hids
|
||||
for assoc in job.output_datasets:
|
||||
hid_to_output_pair[ assoc.dataset.hid ] = ( step, assoc.name )
|
||||
print hid_to_output_pair
|
||||
# Workflow to populate
|
||||
workflow = model.Workflow()
|
||||
workflow.name = workflow_name
|
||||
@@ -418,54 +424,82 @@ class WorkflowController( BaseController ):
|
||||
p = "%s|" % step.id
|
||||
l = len(p)
|
||||
step_args = dict( ( k[l:], v ) for ( k, v ) in kwargs.iteritems() if k.startswith( p ) )
|
||||
if step.type == 'tool':
|
||||
step_errors = None
|
||||
if step.type == 'tool' or step.type is None:
|
||||
# Get the tool
|
||||
tool = trans.app.toolbox.tools_by_id[ step.tool_id ]
|
||||
# Get the state
|
||||
state = DefaultToolState()
|
||||
state.decode( step_args.pop("tool_state"), tool, trans.app )
|
||||
step.state = state
|
||||
# Connections by input name
|
||||
step.input_connections_by_name = dict( ( conn.input_name, conn ) for conn in step.input_connections )
|
||||
# Get old errors
|
||||
old_errors = state.inputs.pop( "__errors__", {} )
|
||||
# Update the state
|
||||
step_errors = tool.update_state( trans, tool.inputs, step.state.inputs, step_args,
|
||||
update_only=True, old_errors=old_errors )
|
||||
if step_errors:
|
||||
errors[step.id] = state.inputs["__errors__"] = step_errors
|
||||
else:
|
||||
return error( "Modules not yet supported for running" )
|
||||
module = step.module = WorkflowModule.from_workflow_step( step )
|
||||
state = step.state = module.decode_runtime_state( trans, step_args.pop( "tool_state" ) )
|
||||
step_errors = module.update_runtime_state( trans, state, step_args )
|
||||
if step_errors:
|
||||
errors[step.id] = state.inputs["__errors__"] = step_errors
|
||||
# Connections by input name
|
||||
step.input_connections_by_name = dict( ( conn.input_name, conn ) for conn in step.input_connections )
|
||||
if not errors:
|
||||
# Run each step, connecting outputs to inputs
|
||||
outputs = {}
|
||||
for step in workflow.steps:
|
||||
tool = trans.app.toolbox.tools_by_id[ step.tool_id ]
|
||||
inputs = step.state.inputs
|
||||
# Connect up
|
||||
for conn in step.input_connections:
|
||||
inputs[ conn.input_name ] = outputs[ conn.output_step.id ][ conn.output_name ]
|
||||
outputs[ step.id ] = tool.execute( trans, step.state.inputs )
|
||||
if step.type == 'tool' or step.type is None:
|
||||
tool = trans.app.toolbox.tools_by_id[ step.tool_id ]
|
||||
input_values = step.state.inputs
|
||||
# Connect up
|
||||
# TODO: Generalize out visitor
|
||||
def visitor( inputs, input_values, prefix ):
|
||||
for input in inputs.itervalues():
|
||||
if isinstance( input, Repeat ):
|
||||
for i, d in enumerate( input_values[ input.name ] ):
|
||||
index = d['__index__']
|
||||
new_prefix = prefix + "%s_%d|" % ( input.name, index )
|
||||
visitor( input.inputs, d, new_prefix)
|
||||
elif isinstance( input, Conditional ):
|
||||
values = input_values[ input.name ]
|
||||
current = values["__current_case__"]
|
||||
label_prefix = label_prefix
|
||||
prefix = prefix + "|" + input.name
|
||||
visitor( input.cases[current].inputs, values, prefix )
|
||||
else:
|
||||
if isinstance( input, DataToolParameter ):
|
||||
prefixed_name = prefix + input.name
|
||||
if prefixed_name in step.input_connections_by_name:
|
||||
conn = step.input_connections_by_name[ prefixed_name ]
|
||||
input_values[ input.name ] = outputs[ conn.output_step.id ][ conn.output_name ]
|
||||
visitor( tool.inputs, input_values, "" )
|
||||
# Execute it
|
||||
outputs[ step.id ] = tool.execute( trans, step.state.inputs )
|
||||
else:
|
||||
outputs[ step.id ] = step.module.execute( trans, step.state )
|
||||
return trans.fill_template( "workflow/run_complete.mako",
|
||||
workflow=stored,
|
||||
outputs=outputs )
|
||||
else:
|
||||
for step in workflow.steps:
|
||||
if step.type == 'tool':
|
||||
if step.type == 'tool' or step.type is None:
|
||||
# Build a new tool state for the step
|
||||
tool = trans.app.toolbox.tools_by_id[ step.tool_id ]
|
||||
state = DefaultToolState()
|
||||
state.inputs = tool.params_from_strings( step.tool_inputs, trans.app )
|
||||
# Store state with the step
|
||||
step.state = state
|
||||
# Connections by input name
|
||||
step.input_connections_by_name = dict( ( conn.input_name, conn ) for conn in step.input_connections )
|
||||
# This should never actually happen since we don't allow
|
||||
# running workflows with errors (yet?)
|
||||
if step.tool_errors:
|
||||
errors[step.id] = step.tool_errors
|
||||
else:
|
||||
return error( "Modules not yet supported for running" )
|
||||
## Non-tool specific stuff?
|
||||
step.module = WorkflowModule.from_workflow_step( step )
|
||||
step.state = step.module.get_runtime_state()
|
||||
# Connections by input name
|
||||
step.input_connections_by_name = dict( ( conn.input_name, conn ) for conn in step.input_connections )
|
||||
# Render the form
|
||||
return trans.fill_template(
|
||||
"workflow/run.mako",
|
||||
@@ -475,29 +509,66 @@ class WorkflowController( BaseController ):
|
||||
|
||||
## ---- Workflow modules (to be factored out) ---------------------------------
|
||||
|
||||
from elementtree.ElementTree import Element
|
||||
|
||||
## TODO: 'Tool' should be a module rather than a special case
|
||||
|
||||
class InputDataModule( object ):
|
||||
class WorkflowModule( object ):
|
||||
@classmethod
|
||||
def from_workflow_step( cls, step ):
|
||||
assert step.type in module_types, "Unknown module type"
|
||||
return module_types[ step.type ].from_workflow_step( step )
|
||||
|
||||
class InputDataModule( WorkflowModule ):
|
||||
type = "data_input"
|
||||
name = "Input dataset"
|
||||
_inputs = {
|
||||
'input' : DataToolParameter( None, Element( "param", name="input", label="Input Dataset", type="data", format="data" ) )
|
||||
}
|
||||
@classmethod
|
||||
def from_state( cls, state ):
|
||||
return cls()
|
||||
@classmethod
|
||||
def from_workflow_step( cls, state ):
|
||||
def from_workflow_step( cls, step ):
|
||||
return cls()
|
||||
def get_state( self ):
|
||||
return None
|
||||
def get_data_inputs( self, state ):
|
||||
return []
|
||||
def get_data_outputs( self, state ):
|
||||
return [ dict( name='output', extension='input' ) ]
|
||||
def get_config_form_html( self, trans, state ):
|
||||
form = web.FormBuilder( title=self.name )
|
||||
return trans.fill_template( "workflow/editor_generic_form.mako", form=form )
|
||||
def save_to_step( self, step ):
|
||||
pass
|
||||
|
||||
def get_data_inputs( self ):
|
||||
return []
|
||||
def get_data_outputs( self ):
|
||||
return [ dict( name='output', extension='input' ) ]
|
||||
def get_config_form( self ):
|
||||
return web.FormBuilder( title=self.name )
|
||||
|
||||
def get_runtime_inputs( self ):
|
||||
return self._inputs
|
||||
def get_runtime_state( self ):
|
||||
state = DefaultToolState()
|
||||
state.inputs = dict( input=None )
|
||||
return state
|
||||
def encode_runtime_state( self, trans, state ):
|
||||
fake_tool = Bunch( inputs = self.get_runtime_inputs() )
|
||||
return state.encode( fake_tool, trans.app )
|
||||
def decode_runtime_state( self, trans, string ):
|
||||
fake_tool = Bunch( inputs = self.get_runtime_inputs() )
|
||||
state = DefaultToolState()
|
||||
state.decode( string, fake_tool, trans.app )
|
||||
return state
|
||||
def update_runtime_state( self, trans, state, values ):
|
||||
errors = {}
|
||||
for name, param in self._inputs.iteritems():
|
||||
value, error = check_param( trans, param, values[name], values )
|
||||
state.inputs[ name ] = value
|
||||
if error:
|
||||
errors[ name ] = error
|
||||
return errors
|
||||
|
||||
def execute( self, trans, state ):
|
||||
return dict( output=state.inputs['input'])
|
||||
|
||||
module_types = dict( data_input=InputDataModule )
|
||||
|
||||
## ---- Utility methods -------------------------------------------------------
|
||||
|
||||
@@ -257,7 +257,9 @@ $.extend( Node.prototype, {
|
||||
},
|
||||
init_field_data : function ( data ) {
|
||||
var f = this.element;
|
||||
this.type = data.type
|
||||
if ( data.type ) {
|
||||
this.type = data.type;
|
||||
}
|
||||
this.form_html = data.form_html;
|
||||
this.tool_state = data.tool_state;
|
||||
this.tool_errors = data.tool_errors;
|
||||
@@ -281,7 +283,11 @@ $.extend( Node.prototype, {
|
||||
$.each( data.data_outputs, function( i, output ) {
|
||||
var t = $( "<div class='terminal output-terminal'></div>" );
|
||||
node.enable_output_terminal( t, output.name, output.extension );
|
||||
b.append( $("<div class='form-row dataRow'>" + output.name + "</div>" ).append( t ) );
|
||||
var label = output.name
|
||||
if ( output.extension != 'input' ) {
|
||||
label = label + " (" + output.extension + ")";
|
||||
}
|
||||
b.append( $("<div class='form-row dataRow'>" + label + "</div>" ).append( t ) );
|
||||
});
|
||||
workflow.node_changed( this );
|
||||
},
|
||||
|
||||
+16
-109
@@ -7,8 +7,8 @@
|
||||
<script type='text/javascript' src="/static/scripts/galaxy.panels.js"> </script>
|
||||
<script type="text/javascript">
|
||||
ensure_dd_helper();
|
||||
var lp = make_left_panel( $("#left"), $("#center"), $("#left-border" ) );
|
||||
var rp = make_right_panel( $("#right"), $("#center"), $("#right-border" ) );
|
||||
make_left_panel( $("#left"), $("#center"), $("#left-border" ) );
|
||||
make_right_panel( $("#right"), $("#center"), $("#right-border" ) );
|
||||
## handle_minwidth_hint = rp.handle_minwidth_hint;
|
||||
</script>
|
||||
</%def>
|
||||
@@ -20,6 +20,7 @@
|
||||
<script type='text/javascript' src="/static/scripts/jquery.js"> </script>
|
||||
<script type='text/javascript' src="/static/scripts/jquery.dimensions.js"> </script>
|
||||
<script type='text/javascript' src="/static/scripts/jquery.ui.js"> </script>
|
||||
<script type='text/javascript' src="/static/scripts/galaxy.ui.scrollPanel.js"> </script>
|
||||
<script type='text/javascript' src="/static/scripts/jquery.hoverIntent.js"> </script>
|
||||
<script type='text/javascript' src="/static/scripts/jquery.form.js"> </script>
|
||||
<script type='text/javascript' src="/static/scripts/jquery.json.js"> </script>
|
||||
@@ -73,7 +74,7 @@
|
||||
// Load workflow definition
|
||||
$.ajax( {
|
||||
url: "${h.url_for( action='load_workflow' )}",
|
||||
data: { id: "${trans.security.encode_id( workflow_id )}" },
|
||||
data: { id: "${trans.security.encode_id( workflow_id )}", "_": "true" },
|
||||
dataType: 'json',
|
||||
success: function( data ) {
|
||||
reset();
|
||||
@@ -147,66 +148,6 @@
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Scrolling
|
||||
$.ui.plugin.add("draggable", "scrollPanel", {
|
||||
drag: function(e, ui) {
|
||||
var o = ui.options,
|
||||
i = ui.instance,
|
||||
panel = o.panel,
|
||||
panel_pos = panel.position(),
|
||||
viewport = panel.parent();
|
||||
moved = false;
|
||||
nudge = 23;
|
||||
// Legal panel range
|
||||
var p_min_x = - ( panel.width() - viewport.width() ),
|
||||
p_min_y = - ( panel.height() - viewport.height() ),
|
||||
p_max_x = 0,
|
||||
p_max_y = 0;
|
||||
var min_vis_x = - panel_pos.left,
|
||||
max_vis_x = min_vis_x + viewport.width(),
|
||||
min_vis_y = - panel_pos.top,
|
||||
max_vis_y = min_vis_y + viewport.height();
|
||||
// Move it
|
||||
if ( ( panel_pos.left < p_max_x ) && ( ui.position.left < min_vis_x ) ) {
|
||||
var t = Math.min( nudge, p_max_x - panel_pos.left );
|
||||
panel.css( "left", panel_pos.left + t );
|
||||
moved = true;
|
||||
ui.instance.offset.left += t;
|
||||
ui.position.left = min_vis_x - t
|
||||
}
|
||||
if ( ( panel_pos.left > p_min_x ) && ( ( ui.position.left + ui.element.width() ) > max_vis_x ) ) {
|
||||
var t = Math.min( nudge, panel_pos.left - p_min_x );
|
||||
panel.css( "left", panel_pos.left - t );
|
||||
moved = true;
|
||||
ui.instance.offset.left -= t
|
||||
ui.position.left = max_vis_x + t - ui.element.width();
|
||||
}
|
||||
if ( ( panel_pos.top < p_max_y ) && ( ui.position.top < min_vis_y ) ) {
|
||||
var t = Math.min( nudge, p_max_y - panel_pos.top );
|
||||
panel.css( "top", panel_pos.top + t );
|
||||
moved = true;
|
||||
ui.instance.offset.top += t;
|
||||
ui.position.top = min_vis_y - t;
|
||||
}
|
||||
if ( ( panel_pos.top > p_min_y ) && ( ( ui.position.top + ui.element.height() ) > max_vis_y ) ) {
|
||||
var t = Math.min( nudge, panel_pos.top - p_min_x );
|
||||
panel.css( "top", panel_pos.top - t );
|
||||
moved = true;
|
||||
ui.instance.offset.top -= t
|
||||
ui.position.top = max_vis_y + t - ui.element.height();
|
||||
}
|
||||
// Update offsets
|
||||
if ( moved ) {
|
||||
$.ui.ddmanager.prepareOffsets( ui.instance, e );
|
||||
}
|
||||
// Still contain in panel
|
||||
ui.position.left = Math.max( ui.position.left, 0 );
|
||||
ui.position.top = Math.max( ui.position.top, 0 );
|
||||
ui.position.left = Math.min( ui.position.left, panel.width() - ui.element.width() );
|
||||
ui.position.top = Math.min( ui.position.top, panel.height() - ui.element.height() );
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var workflow = null;
|
||||
@@ -226,8 +167,10 @@
|
||||
$("div.toolFormInCanvas").each( function() {
|
||||
x = Math.min( x, $(this).position().left );
|
||||
y = Math.min( x, $(this).position().left );
|
||||
});
|
||||
$("#canvas-container").css( { left: - x + 20, top: - y + 20 } );
|
||||
});
|
||||
x = Math.min( - x + 20, 0 );
|
||||
y = Math.min( - y + 20, 0 );
|
||||
$("#canvas-container").css( { left: x, top: y } );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,7 +181,8 @@
|
||||
workflow.activate_node( node );
|
||||
$.ajax( {
|
||||
url: "${h.url_for( action='get_tool_info' )}",
|
||||
data: { tool_id: id, "_": "true" },
|
||||
data: { tool_id: id, "_": "true" },
|
||||
global: false,
|
||||
dataType: "json",
|
||||
success: function( data ) {
|
||||
node.init_field_data( data );
|
||||
@@ -292,6 +236,10 @@
|
||||
beforeSubmit: function( data ) {
|
||||
data.push( { name: 'tool_state', value: node.tool_state } );
|
||||
data.push( { name: '_', value: "true" } );
|
||||
$("#tool-form-save-button").each( function() {
|
||||
this.value = "Saving...";
|
||||
this.disabled = true;
|
||||
});
|
||||
}
|
||||
}).each( function() {
|
||||
form = this;
|
||||
@@ -324,7 +272,8 @@
|
||||
type: "POST",
|
||||
data: {
|
||||
id: "${trans.security.encode_id( workflow_id )}",
|
||||
workflow_data: $.toJSON( workflow.to_simple() )
|
||||
workflow_data: $.toJSON( workflow.to_simple() ),
|
||||
"_": "true"
|
||||
},
|
||||
dataType: 'json',
|
||||
success: function( data ) {
|
||||
@@ -349,48 +298,6 @@
|
||||
});
|
||||
}
|
||||
|
||||
var load_workflow = function () {
|
||||
var body = $("#load-dialog-form").clone();
|
||||
var form = body.find( "form" ).ajaxForm( {
|
||||
dataType: 'json',
|
||||
success: function( data ) {
|
||||
reset();
|
||||
workflow.from_simple( data );
|
||||
workflow.has_changes = false;
|
||||
show_modal( "Workflow loaded", "Workflow loaded.", {
|
||||
"Ok" : function () { hide_modal(); }
|
||||
});
|
||||
},
|
||||
beforeSubmit: function( data ) {
|
||||
show_modal( "Loading workflow", "progress" );
|
||||
}
|
||||
});
|
||||
if ( workflow.has_changes ) {
|
||||
body.prepend( "<div class='warningmark'>Your unsaved changes will be lost!</div>" );
|
||||
}
|
||||
show_modal( "Load workflow", body, {
|
||||
"Cancel" : hide_modal,
|
||||
"Load": function() { form.submit() }
|
||||
} );
|
||||
}
|
||||
|
||||
var clear_workflow = function () {
|
||||
reset();
|
||||
hide_modal();
|
||||
}
|
||||
|
||||
var create_new_workflow_dialog = function () {
|
||||
if ( workflow.has_changes ) {
|
||||
show_modal( "Create new workflow",
|
||||
"Your workflow has unsaved changes which will be lost", {
|
||||
"Cancel" : hide_modal,
|
||||
"Continue": clear_workflow
|
||||
});
|
||||
} else {
|
||||
clear_workflow();
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</%def>
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
${do_inputs( inputs, values, errors, "" )}
|
||||
%endfor
|
||||
<div class="form-row">
|
||||
<input type="submit" value="Save"></input>
|
||||
<input type="submit" id="tool-form-save-button" value="Save"></input>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
+23
-12
@@ -31,10 +31,10 @@ from galaxy.tools.parameters import DataToolParameter
|
||||
<div class="repeat-group-item">
|
||||
<div class="form-title-row"><b>${input.title} ${i + 1}</b></div>
|
||||
${do_inputs( input.inputs, repeat_values[ i ], rep_errors, prefix + input.name + "_" + str(i) + "|", step )}
|
||||
<div class="form-row"><input type="submit" name="${step.id}|${prefix}${input.name}_${i}_remove" value="Remove ${input.title} ${i+1}" /></div>
|
||||
</div>
|
||||
## <div class="form-row"><input type="submit" name="${step.id}|${prefix}${input.name}_${i}_remove" value="Remove ${input.title} ${i+1}" /></div>
|
||||
</div>
|
||||
%endfor
|
||||
<div class="form-row"><input type="submit" name="${step.id}|${prefix}${input.name}_add" value="Add new ${input.title}" /></div>
|
||||
## <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":
|
||||
<% group_values = values[input.name] %>
|
||||
@@ -50,6 +50,7 @@ from galaxy.tools.parameters import DataToolParameter
|
||||
</%def>
|
||||
|
||||
<%def name="row_for_param( param, value, error_dict, prefix, step )">
|
||||
## -- ${param.name} -- ${step.state.inputs} --
|
||||
%if error_dict.has_key( param.name ):
|
||||
<% cls = "form-row form-row-error" %>
|
||||
%else:
|
||||
@@ -86,15 +87,25 @@ from galaxy.tools.parameters import DataToolParameter
|
||||
## <input type="hidden" name="workflow_name" value="${workflow.name | h}" />
|
||||
<input type="submit" value="Run workflow" />
|
||||
%for i, step in enumerate( steps ):
|
||||
<% tool = app.toolbox.tools_by_id[step.tool_id] %>
|
||||
<input type="hidden" name="${step.id}|tool_state" value="${step.state.encode( tool, app )}">
|
||||
<div class="toolForm">
|
||||
<div class="toolFormTitle">Step ${int(step.order_index)+1}: ${tool.name}</div>
|
||||
<div class="toolFormBody">
|
||||
${do_inputs( tool.inputs, step.state.inputs, errors.get( step.id, dict() ), "", step )}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
%if step.type == 'tool' or step.type is None:
|
||||
<% tool = app.toolbox.tools_by_id[step.tool_id] %>
|
||||
<input type="hidden" name="${step.id}|tool_state" value="${step.state.encode( tool, app )}">
|
||||
<div class="toolForm">
|
||||
<div class="toolFormTitle">Step ${int(step.order_index)+1}: ${tool.name}</div>
|
||||
<div class="toolFormBody">
|
||||
${do_inputs( tool.inputs, step.state.inputs, errors.get( step.id, dict() ), "", step )}
|
||||
</div>
|
||||
</div>
|
||||
%else:
|
||||
<% module = step.module %>
|
||||
<input type="hidden" name="${step.id}|tool_state" value="${module.encode_runtime_state( t, step.state )}">
|
||||
<div class="toolForm">
|
||||
<div class="toolFormTitle">Step ${int(step.order_index)+1}: ${module.name}</div>
|
||||
<div class="toolFormBody">
|
||||
${do_inputs( module.get_runtime_inputs(), step.state.inputs, errors.get( step.id, dict() ), "", step )}
|
||||
</div>
|
||||
</div>
|
||||
%endif
|
||||
%endfor
|
||||
</form>
|
||||
</body>
|
||||
Reference in New Issue
Block a user