root/galaxy-central/lib/galaxy/workflow/modules.py @ 2

リビジョン 2, 12.9 KB (コミッタ: hatakeyama, 14 年 前)

import galaxy-central

行番号 
1from elementtree.ElementTree import Element
2
3from galaxy import web
4from galaxy.tools.parameters import DataToolParameter, DummyDataset, RuntimeValue, check_param, visit_input_values
5from galaxy.tools import DefaultToolState
6from galaxy.tools.parameters.grouping import Repeat, Conditional
7from galaxy.util.bunch import Bunch
8from galaxy.util.json import from_json_string, to_json_string
9from galaxy.jobs.actions.post import ActionBox
10from galaxy.model import PostJobAction
11
12class WorkflowModule( object ):
13   
14    def __init__( self, trans ):
15        self.trans = trans
16   
17    ## ---- Creating modules from various representations ---------------------
18   
19    @classmethod
20    def new( Class, trans, tool_id=None ):
21        """
22        Create a new instance of the module with default state
23        """
24        return Class( trans )
25    @classmethod
26    def from_dict( Class, trans, d ):
27        """
28        Create a new instance of the module initialized from values in the
29        dictionary `d`.
30        """
31        return Class( trans )
32    @classmethod
33    def from_workflow_step( Class, trans, step ):
34        return Class( trans )
35
36    ## ---- Saving in various forms ------------------------------------------
37   
38    def save_to_step( self, step ):
39        step.type = self.type
40       
41    ## ---- General attributes -----------------------------------------------
42   
43    def get_type( self ):
44        return self.type
45    def get_name( self ):
46        return self.name
47    def get_tool_id( self ):
48        return None
49    def get_tooltip( self ):
50        return None
51   
52    ## ---- Configuration time -----------------------------------------------
53   
54    def get_state( self ):
55        return None
56    def get_errors( self ):
57        return None
58    def get_data_inputs( self ):
59        return []
60    def get_data_outputs( self ):
61        return []
62    def update_state( self ):
63        pass
64    def get_config_form( self ):
65        raise TypeError( "Abstract method" )
66       
67    def check_and_update_state( self ):
68        """
69        If the state is not in sync with the current implementation of the
70        module, try to update. Returns a list of messages to be displayed
71        """
72        pass
73   
74    ## ---- Run time ---------------------------------------------------------
75   
76    def get_runtime_inputs( self ):
77        raise TypeError( "Abstract method" )
78    def get_runtime_state( self ):
79        raise TypeError( "Abstract method" )
80    def encode_runtime_state( self, trans, state ):
81        raise TypeError( "Abstract method" )
82    def decode_runtime_state( self, trans, string ):
83        raise TypeError( "Abstract method" )
84    def update_runtime_state( self, trans, state, values ):
85        raise TypeError( "Abstract method" )
86   
87    def execute( self, trans, state ):
88        raise TypeError( "Abstract method" )
89
90class InputDataModule( WorkflowModule ):
91    type = "data_input"
92    name = "Input dataset"
93
94    @classmethod
95    def new( Class, trans, tool_id=None ):
96        module = Class( trans )
97        module.state = dict( name="Input Dataset" )
98        return module
99    @classmethod
100    def from_dict( Class, trans, d, secure=True ):
101        module = Class( trans )
102        state = from_json_string( d["tool_state"] )
103        module.state = dict( name=state.get( "name", "Input Dataset" ) )
104        return module
105    @classmethod
106    def from_workflow_step( Class, trans, step ):
107        module = Class( trans )
108        module.state = dict( name="Input Dataset" )
109        if step.tool_inputs and "name" in step.tool_inputs:
110            module.state['name'] = step.tool_inputs[ 'name' ]
111        return module
112    def save_to_step( self, step ):
113        step.type = self.type
114        step.tool_id = None
115        step.tool_inputs = self.state
116
117    def get_data_inputs( self ):
118        return []
119    def get_data_outputs( self ):
120        return [ dict( name='output', extensions=['input'] ) ]
121    def get_config_form( self ):
122        form = web.FormBuilder( title=self.name ) \
123            .add_text( "name", "Name", value=self.state['name'] )
124        return self.trans.fill_template( "workflow/editor_generic_form.mako",
125                                         module=self, form=form )
126    def get_state( self, secure=True ):
127        return to_json_string( self.state )
128   
129    def update_state( self, incoming ):
130        self.state['name'] = incoming.get( 'name', 'Input Dataset' )
131   
132    def get_runtime_inputs( self ):
133        label = self.state.get( "name", "Input Dataset" )
134        return dict( input=DataToolParameter( None, Element( "param", name="input", label=label, type="data", format="data" ) ) )
135    def get_runtime_state( self ):
136        state = DefaultToolState()
137        state.inputs = dict( input=None )
138        return state
139    def encode_runtime_state( self, trans, state ):
140        fake_tool = Bunch( inputs = self.get_runtime_inputs() )
141        return state.encode( fake_tool, trans.app )
142    def decode_runtime_state( self, trans, string ):
143        fake_tool = Bunch( inputs = self.get_runtime_inputs() )
144        state = DefaultToolState()
145        state.decode( string, fake_tool, trans.app )
146        return state
147    def update_runtime_state( self, trans, state, values ):
148        errors = {}
149        for name, param in self.get_runtime_inputs().iteritems():
150            value, error = check_param( trans, param, values.get( name, None ), values )
151            state.inputs[ name ] = value
152            if error:
153                errors[ name ] = error
154        return errors
155   
156    def execute( self, trans, state ):
157        return None, dict( output=state.inputs['input'])
158   
159class ToolModule( WorkflowModule ):
160   
161    type = "tool"
162   
163    def __init__( self, trans, tool_id ):
164        self.trans = trans
165        self.tool_id = tool_id
166        self.tool = trans.app.toolbox.tools_by_id[ tool_id ]
167        self.post_job_actions = {}
168        self.workflow_outputs = []
169        self.state = None
170        self.errors = None
171
172    @classmethod
173    def new( Class, trans, tool_id=None ):
174        module = Class( trans, tool_id )
175        module.state = module.tool.new_state( trans, all_pages=True )
176        return module
177       
178    @classmethod
179    def from_dict( Class, trans, d, secure=True ):
180        tool_id = d['tool_id']
181        module = Class( trans, tool_id )
182        module.state = DefaultToolState()
183        module.state.decode( d["tool_state"], module.tool, module.trans.app, secure=secure )
184        module.errors = d.get( "tool_errors", None )
185        module.post_job_actions = d.get("post_job_actions", {})
186        module.workflow_outputs = d.get("workflow_outputs", [])
187        return module
188       
189    @classmethod
190    def from_workflow_step( Class, trans, step ):
191        tool_id = step.tool_id
192        module = Class( trans, tool_id )
193        module.state = DefaultToolState()
194        module.state.inputs = module.tool.params_from_strings( step.tool_inputs, trans.app, ignore_errors=True )
195        module.errors = step.tool_errors
196        # module.post_job_actions = step.post_job_actions
197        module.workflow_outputs = step.workflow_outputs
198        pjadict = {}
199        for pja in step.post_job_actions:
200            pjadict[pja.action_type] = pja
201        module.post_job_actions = pjadict
202        return module
203
204    def save_to_step( self, step ):
205        step.type = self.type
206        step.tool_id = self.tool_id
207        step.tool_version = self.get_tool_version()
208        step.tool_inputs = self.tool.params_to_strings( self.state.inputs, self.trans.app )
209        step.tool_errors = self.errors
210        for k, v in self.post_job_actions.iteritems():
211            # Must have action_type, step.  output and a_args are optional.
212            if 'output_name' in v:
213                output_name = v['output_name']
214            else:
215                output_name = None
216            if 'action_arguments' in v:
217                action_arguments = v['action_arguments']
218            else:
219                action_arguments = None
220            n_p = PostJobAction(v['action_type'], step, output_name, action_arguments)
221
222    def get_name( self ):
223        return self.tool.name
224    def get_tool_id( self ):
225        return self.tool_id
226    def get_tool_version( self ):
227        return self.tool.version
228    def get_state( self, secure=True ):
229        return self.state.encode( self.tool, self.trans.app, secure=secure )
230    def get_errors( self ):
231        return self.errors
232    def get_tooltip( self ):
233        return self.tool.help
234       
235    def get_data_inputs( self ):
236        data_inputs = []
237        def callback( input, value, prefixed_name, prefixed_label ):
238            if isinstance( input, DataToolParameter ):
239                data_inputs.append( dict(
240                    name=prefixed_name,
241                    label=prefixed_label,
242                    extensions=input.extensions ) )
243        visit_input_values( self.tool.inputs, self.state.inputs, callback )
244        return data_inputs
245    def get_data_outputs( self ):
246        data_outputs = []
247        for name, tool_output in self.tool.outputs.iteritems():
248            formats = [ tool_output.format ]
249            for change_elem in tool_output.change_format:
250                for when_elem in change_elem.findall( 'when' ):
251                    format = when_elem.get( 'format', None )
252                    if format and format not in formats:
253                        formats.append( format )
254            data_outputs.append( dict( name=name, extensions=formats ) )
255        return data_outputs
256   
257    def get_post_job_actions( self ):
258        return self.post_job_actions
259       
260    def get_config_form( self ):
261        self.add_dummy_datasets()
262        return self.trans.fill_template( "workflow/editor_tool_form.mako",
263            tool=self.tool, values=self.state.inputs, errors=( self.errors or {} ) )
264
265    def update_state( self, incoming ):       
266        # Build a callback that handles setting an input to be required at
267        # runtime. We still process all other parameters the user might have
268        # set. We also need to make sure all datasets have a dummy value
269        # for dependencies to see
270       
271        self.post_job_actions = ActionBox.handle_incoming(incoming)
272       
273        make_runtime_key = incoming.get( 'make_runtime', None )
274        make_buildtime_key = incoming.get( 'make_buildtime', None )
275        def item_callback( trans, key, input, value, error, old_value, context ):
276            # Dummy value for Data parameters
277            if isinstance( input, DataToolParameter ):
278                return DummyDataset(), None
279            # Deal with build/runtime (does not apply to Data parameters)
280            if key == make_buildtime_key:
281                return input.get_initial_value( trans, context ), None
282            elif isinstance( old_value, RuntimeValue ):
283                return old_value, None
284            elif key == make_runtime_key:
285                return RuntimeValue(), None
286            else:
287                return value, error
288        # Update state using incoming values
289        errors = self.tool.update_state( self.trans, self.tool.inputs, self.state.inputs, incoming, item_callback=item_callback )
290        self.errors = errors or None
291       
292    def check_and_update_state( self ):
293        return self.tool.check_and_update_param_values( self.state.inputs, self.trans )
294       
295    def add_dummy_datasets( self, connections=None):
296        if connections:
297            # Store onnections by input name
298            input_connections_by_name = \
299                dict( ( conn.input_name, conn ) for conn in connections )
300        else:
301            input_connections_by_name = {}
302        # Any connected input needs to have value DummyDataset (these
303        # are not persisted so we need to do it every time)
304        def callback( input, value, prefixed_name, prefixed_label ):
305            if isinstance( input, DataToolParameter ):
306                if connections is None or prefixed_name in input_connections_by_name:
307                    return DummyDataset()
308        visit_input_values( self.tool.inputs, self.state.inputs, callback )
309   
310   
311class WorkflowModuleFactory( object ):
312    def __init__( self, module_types ):
313        self.module_types = module_types
314    def new( self, trans, type, tool_id=None ):
315        """
316        Return module for type and (optional) tool_id intialized with
317        new / default state.
318        """
319        assert type in self.module_types
320        return self.module_types[type].new( trans, tool_id )
321    def from_dict( self, trans, d, **kwargs ):
322        """
323        Return module initialized from the data in dictionary `d`.
324        """
325        type = d['type']
326        assert type in self.module_types
327        return self.module_types[type].from_dict( trans, d, **kwargs )   
328    def from_workflow_step( self, trans, step ):
329        """
330        Return module initializd from the WorkflowStep object `step`.
331        """
332        type = step.type
333        return self.module_types[type].from_workflow_step( trans, step )
334   
335module_factory = WorkflowModuleFactory( dict( data_input=InputDataModule, tool=ToolModule ) )
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。