root/galaxy-central/lib/galaxy/jobs/actions/post.py

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

import galaxy-central

行番号 
1import logging, datetime
2
3from galaxy.util.json import to_json_string
4
5#  For email notification PJA
6from email.MIMEText import MIMEText
7import smtplib
8
9log = logging.getLogger( __name__ )
10
11# DBTODO This still needs refactoring and general cleanup.
12
13def get_form_template(action_type, title, content, help, on_output = True ):
14    if on_output:
15        form = """
16            if (pja.action_type == "%s"){
17                p_str = "<div class='pjaForm toolForm'><span class='action_tag' style='display:none'>"+ pja.action_type + pja.output_name + "</span><div class='toolFormTitle'> %s <br/> on " + pja.output_name + "\
18                <div style='float: right;' class='buttons'><img src='/static/images/delete_icon.png'></div></div><div class='toolFormBody'>";
19                %s
20                p_str += "</div><div class='toolParamHelp'>%s</div></div>";
21            }""" % (action_type, title, content, help)
22    else:
23        form =  """
24            if (pja.action_type == "%s"){
25                p_str = "<div class='pjaForm toolForm'><span class='action_tag' style='display:none'>"+ pja.action_type + "</span><div class='toolFormTitle'> %s \
26                <div style='float: right;' class='buttons'><img src='/static/images/delete_icon.png'></div></div><div class='toolFormBody'>";
27                %s
28                p_str += "</div><div class='toolParamHelp'>%s</div></div>";
29            }""" % (action_type, title, content, help)
30    return form
31
32# def get_field(action, argument, i_type, label = None):
33#     fstr = ''
34#     fname = """pja__"+pja.output_name+"__%s__%s""" % (action, argument)
35#     if label:
36#         fstr += """<label for='pja__"+pja.output_name+"__ColumnSetAction__chromCol'>Chrom Column</label>"""
37#     fstr += """<input type='text' value=" + chromCol + " name='pja__"+pja.output_name+"__ColumnSetAction__chromCol'/>"""
38
39class DefaultJobAction(object):
40    name = "DefaultJobAction"
41    verbose_name = "Default Job"
42
43   
44    @classmethod
45    def execute(cls, app, sa_session, action, job):
46        pass
47
48    @classmethod
49    def get_config_form(cls, trans):
50        return "<p>Default Job Action Config Form</p>"
51
52    @classmethod
53    def get_short_str(cls, pja):
54        if pja.action_arguments:
55            return "%s -> %s" % (pja.action_type, pja.action_arguments)
56        else:
57            return "%s" % pja.action_type
58
59
60class EmailAction(DefaultJobAction):
61    name = "EmailAction"
62    verbose_name = "Email Notification"
63
64   
65    @classmethod
66    def execute(cls, app, sa_session, action, job):
67        smtp_server = app.config.smtp_server
68        if action.action_arguments:
69            if action.action_arguments.has_key('host'):
70                host = action.action_arguments['host']
71        else:
72            host = 'usegalaxy.org'
73        if smtp_server is None:
74            log.error("Mail is not configured for this galaxy instance.  Workflow action aborting after logging mail to info.")
75            frm = 'galaxy-noreply@%s' % host
76            to  = job.user.email
77            outdata = ', '.join(ds.dataset.display_name() for ds in job.output_datasets)
78            msg = MIMEText( "Your Galaxy job generating dataset '%s' is complete as of %s." % (outdata, datetime.datetime.now().strftime( "%I:%M" )))
79            msg[ 'To' ] = to
80            msg[ 'From' ] = frm
81            msg[ 'Subject' ] = "Galaxy notification regarding history '%s'" % (job.history.name)
82            log.info(msg)
83            return
84        # Build the email message
85        frm = 'galaxy-noreply@%s' % host
86        to  = job.user.email
87        outdata = ', '.join(ds.dataset.display_name() for ds in job.output_datasets)
88        msg = MIMEText( "Your Galaxy job generating dataset '%s' is complete as of %s." % (outdata, datetime.datetime.now().strftime( "%I:%M" )))
89        msg[ 'To' ] = to
90        msg[ 'From' ] = frm
91        msg[ 'Subject' ] = "Galaxy workflow step notification '%s'" % (job.history.name)
92        try:
93            s = smtplib.SMTP()
94            s.connect( smtp_server )
95            s.sendmail( frm, [ to ], msg.as_string() )
96            s.close()
97        except Exception, e:
98            log.error("EmailAction PJA Failed, exception: %s" % e)
99           
100    @classmethod
101    def get_config_form(cls, trans):
102        form = """
103                p_str += "<label for='pja__"+pja.output_name+"__EmailAction'>There are no additional options for this action.  You will be emailed upon job completion.</label>\
104                            <input type='hidden' value='%s' name='pja__"+pja.output_name+"__EmailAction__host'/><input type='hidden' name='pja__"+pja.output_name+"__EmailAction'/>";
105            """ % trans.request.host
106        return get_form_template(cls.name, cls.verbose_name, form, "This action will send an email notifying you when the job is done.", on_output = False)
107
108    @classmethod
109    def get_short_str(cls, pja):
110        if pja.action_arguments:
111            if pja.action_arguments.has_key('host'):
112                return "Email the current user from server %s when this job is complete." % pja.action_arguments['host']
113        else:
114            return "Email the current user when this job is complete."
115
116
117class ChangeDatatypeAction(DefaultJobAction):
118    name = "ChangeDatatypeAction"
119    verbose_name = "Change Datatype"
120    @classmethod
121    def execute(cls, app, sa_session, action, job):
122        for dataset_assoc in job.output_datasets:
123            if action.output_name == '' or dataset_assoc.name == action.output_name:
124                app.datatypes_registry.change_datatype( dataset_assoc.dataset, action.action_arguments['newtype'])
125
126    @classmethod
127    def get_config_form(cls, trans):
128        dt_list = ""
129        dtnames = [ dtype_name for dtype_name, dtype_value in trans.app.datatypes_registry.datatypes_by_extension.iteritems()]
130        dtnames.sort()
131        for dt_name in dtnames:
132            dt_list += """<option id='pja__"+pja.output_name+"__ChangeDatatypeAction__newtype__%s' value='%s'>%s</option>""" % (dt_name, dt_name, dt_name)
133        ps = """
134                        p_str += "<label for='pja__"+pja.output_name+"__ChangeDatatypeAction__newtype'>New Datatype:</label>\
135                            <select id='pja__"+pja.output_name+"__ChangeDatatypeAction__newtype' name='pja__"+pja.output_name+"__ChangeDatatypeAction__newtype'>\
136                        %s\
137                        </select>";
138                if (pja.action_arguments != undefined && pja.action_arguments.newtype != undefined){
139                 p_str += "<scrip" + "t type='text/javascript'>$('#pja__" + pja.output_name + "__ChangeDatatypeAction__newtype').val('" + pja.action_arguments.newtype + "');</scrip" + "t>";
140                }
141                    """ % dt_list
142            # Note the scrip + t hack above.  Is there a better way?
143        return get_form_template(cls.name, cls.verbose_name, ps, 'This action will change the datatype of the output to the indicated value.')
144   
145    @classmethod
146    def get_short_str(cls, pja):
147        return "Set the datatype of output '%s' to '%s'" % (pja.output_name, pja.action_arguments['newtype'])
148
149
150class RenameDatasetAction(DefaultJobAction):
151    name = "RenameDatasetAction"
152    verbose_name = "Rename Dataset"
153
154    @classmethod
155    def execute(cls, app, sa_session, action, job):
156        for dataset_assoc in job.output_datasets:
157            if action.output_name == '' or dataset_assoc.name == action.output_name:
158                dataset_assoc.dataset.name = action.action_arguments['newname']
159
160    @classmethod
161    def get_config_form(cls, trans):
162        form = """
163                        if ((pja.action_arguments != undefined) && (pja.action_arguments.newname != undefined)){
164                                p_str += "<label for='pja__"+pja.output_name+"__RenameDatasetAction__newname'>New output name:</label>\
165                                          <input type='text' name='pja__"+pja.output_name+"__RenameDatasetAction__newname' value='"+pja.action_arguments.newname + "'/>";
166                        }
167                        else{
168                                p_str += "<label for='pja__"+pja.output_name+"__RenameDatasetAction__newname'>New output name:</label>\
169                                          <input type='text' name='pja__"+pja.output_name+"__RenameDatasetAction__newname' value=''/>";
170                        }
171                    """
172        return get_form_template(cls.name, cls.verbose_name, form, "This action will rename the result dataset.")
173   
174    @classmethod
175    def get_short_str(cls, pja):
176        return "Rename output '%s' to '%s'." % (pja.output_name, pja.action_arguments['newname'])
177
178
179class HideDatasetAction(DefaultJobAction):
180    name = "HideDatasetAction"
181    verbose_name = "Hide Dataset"
182   
183    @classmethod
184    def execute(cls, app, sa_session, action, job):
185        for dataset_assoc in job.output_datasets:
186            if action.output_name == '' or dataset_assoc.name == action.output_name:
187                dataset_assoc.dataset.visible=False
188
189    @classmethod
190    def get_config_form(cls, trans):
191        form = """
192                p_str += "<label for='pja__"+pja.output_name+"__HideDatasetAction'>There are no additional options for this action.</label>\
193                            <input type='hidden' name='pja__"+pja.output_name+"__HideDatasetAction'/>";
194            """
195        return get_form_template(cls.name, cls.verbose_name, form, "This action will hide the result dataset.")
196
197    @classmethod
198    def get_short_str(cls, trans):
199        return "Hide this dataset."
200
201class DeleteDatasetAction(DefaultJobAction):
202    # This is disabled for right now.  Deleting a dataset in the middle of a workflow causes errors (obviously) for the subsequent steps using the data.
203    name = "DeleteDatasetAction"
204    verbose_name = "Delete Dataset"
205
206    @classmethod
207    def execute(cls, app, sa_session, action, job):
208        for dataset_assoc in job.output_datasets:
209            if action.output_name == '' or dataset_assoc.name == action.output_name:
210                dataset_assoc.dataset.deleted=True
211
212    @classmethod
213    def get_config_form(cls, trans):
214        form = """
215                p_str += "<label for='pja__"+pja.output_name+"__DeleteDatasetAction'>There are no additional options for this action.  This dataset will be marked deleted.</label>\
216                            <input type='hidden' name='pja__"+pja.output_name+"__DeleteDatasetAction'/>";
217            """
218        return get_form_template(cls.name, cls.verbose_name, form, "This action will rename the result dataset.")
219   
220    @classmethod
221    def get_short_str(cls, pja):
222        return "Delete this dataset after creation."
223
224
225
226class ColumnSetAction(DefaultJobAction):
227    name = "ColumnSetAction"
228    verbose_name = "Assign Columns"
229    @classmethod
230    def execute(cls, app, sa_session, action, job):
231        for dataset_assoc in job.output_datasets:
232            if action.output_name == '' or dataset_assoc.name == action.output_name:
233                for k, v in action.action_arguments.items():
234                    if v != '':
235                        # Try to use both pure integer and 'cX' format.
236                        if v[0] == 'c':
237                            v = v[1:]
238                        v = int(v)
239                        if v != 0:
240                            setattr(dataset_assoc.dataset.metadata, k, v)
241
242    @classmethod
243    def get_config_form(cls, trans):
244        form = """
245            var chrom_col = ''
246            if (pja.action_arguments != undefined){
247                (pja.action_arguments.chromCol == undefined) ? chromCol = "" : chromCol=pja.action_arguments.chromCol;
248                (pja.action_arguments.startCol == undefined) ? startCol = "" : startCol=pja.action_arguments.startCol;
249                (pja.action_arguments.endCol == undefined) ? endCol = "" : endCol=pja.action_arguments.endCol;
250                (pja.action_arguments.strandCol == undefined) ? strandCol = "" : strandCol=pja.action_arguments.strandCol;
251                (pja.action_arguments.nameCol == undefined) ? nameCol = "" : nameCol=pja.action_arguments.nameCol;
252            }else{
253                chromCol = '';
254                startCol = '';
255                endCol = '';
256                strandCol = '';
257                nameCol = '';
258            }
259            p_str += "<p>Leave any of these fields blank if they do not need to be set.</p>\
260                    <label for='pja__"+pja.output_name+"__ColumnSetAction__chromCol'>Chrom Column</label>\
261                        <input type='text' value='" + chromCol + "' name='pja__"+pja.output_name+"__ColumnSetAction__chromCol'/>\
262                    <label for='pja__"+pja.output_name+"__ColumnSetAction__startCol'>Start Column</label>\
263                        <input type='text' value='" + startCol + "' name='pja__"+pja.output_name+"__ColumnSetAction__startCol'/>\
264                    <label for='pja__"+pja.output_name+"__ColumnSetAction__endCol'>End Column</label>\
265                        <input type='text' value='" + endCol + "' name='pja__"+pja.output_name+"__ColumnSetAction__endCol'/>\
266                    <label for='pja__"+pja.output_name+"__ColumnSetAction__strandCol'>Strand Column</label>\
267                        <input type='text' value='" + strandCol + "' name='pja__"+pja.output_name+"__ColumnSetAction__strandCol'/>\
268                    <label for='pja__"+pja.output_name+"__ColumnSetAction__nameCol'>Name Column</label>\
269                        <input type='text' value='" + nameCol + "' name='pja__"+pja.output_name+"__ColumnSetAction__nameCol'/>\";
270            """
271        return get_form_template(cls.name, cls.verbose_name, form, "This action will set column assignments in the output dataset.  Blank fields are ignored.")
272
273    @classmethod
274    def get_short_str(cls, pja):
275        return "Set the following metadata values:<br/>" + "<br/>".join(['%s : %s' % (k, v) for k, v in pja.action_arguments.iteritems()])
276
277
278class SetMetadataAction(DefaultJobAction):
279    name = "SetMetadataAction"
280    # DBTODO Setting of Metadata is currently broken and disabled.  It should not be used (yet).
281   
282    @classmethod
283    def execute(cls, app, sa_session, action, job):
284        for data in job.output_datasets:
285            data.set_metadata( action.action_arguments['newtype'] )
286           
287    @classmethod
288    def get_config_form(cls, trans):
289        #         dt_list = ""
290        #         mdict = {}
291        #         for dtype_name, dtype_value in trans.app.datatypes_registry.datatypes_by_extension.iteritems():
292        #             for mn, mt in dtype_value.metadata_spec.items():
293        #                 if mt.visible:
294        #                     mdict[mt.desc] = mt.param.get_html(value= mn).replace('"', "'").strip().replace('\n','')
295        #         for k, v in mdict.items():
296        #             dt_list += "<p><strong>" + k + ":</strong><br/>" + v + "</p>"
297        #         form = """
298        #           p_str += "%s";
299        #   """ % dt_list
300        # return get_form_template('SetMetadataAction', 'Set Metadata', form, "This action will change metadata for the dataset.")
301        form = """
302          p_str += "<p>Leave any of these fields blank if they do not need to be set.</p><label for='pja__"+pja.output_name+"__SetMetadataAction__chromCol'>Chrom Column</label>\
303                        <input type='text' name='pja__"+pja.output_name+"__SetMetadataAction__chromCol'/>\
304                    <label for='pja__"+pja.output_name+"__SetMetadataAction__startCol'>Start Column</label>\
305                        <input type='text' name='pja__"+pja.output_name+"__SetMetadataAction__startCol'/>\
306                    <label for='pja__"+pja.output_name+"__SetMetadataAction__endCol'>End Column</label>\
307                        <input type='text' name='pja__"+pja.output_name+"__SetMetadataAction__endCol'/>\
308                    <label for='pja__"+pja.output_name+"__SetMetadataAction__comment_lines'>Comment Lines</label>\
309                        <input type='text' name='pja__"+pja.output_name+"__SetMetadataAction__comment_lines'/>\
310                      ";
311            """
312        return get_form_template(cls.name, cls.verbose_name, form, "This action will set metadata in the output dataset.")
313
314
315
316class ActionBox(object):
317   
318    actions = { "RenameDatasetAction" : RenameDatasetAction,
319                "HideDatasetAction" : HideDatasetAction,
320                "ChangeDatatypeAction": ChangeDatatypeAction,
321                "ColumnSetAction" : ColumnSetAction,
322                "EmailAction" : EmailAction,
323                # "SetMetadataAction" : SetMetadataAction,
324                # "DeleteDatasetAction" : DeleteDatasetAction,
325                }
326    immediate_actions = ['ChangeDatatypeAction', 'RenameDatasetAction']
327
328    @classmethod
329    def get_short_str(cls, action):
330        if action.action_type in ActionBox.actions:
331            return ActionBox.actions[action.action_type].get_short_str(action)
332        else:
333            return "Unknown Action"
334
335    @classmethod
336    def handle_incoming(cls, incoming):
337        npd = {}
338        for key, val in incoming.iteritems():
339            if key.startswith('pja'):
340                sp = key.split('__')
341                ao_key = sp[2] + sp[1]
342                # flag / output_name / pjatype / desc
343                if not ao_key in npd:
344                    npd[ao_key] = {'action_type' : sp[2],
345                                  'output_name' : sp[1],
346                                  'action_arguments' : {}}
347                if len(sp) > 3:
348                    if sp[3] == 'output_name':
349                        npd[ao_key]['output_name'] = val
350                    else:
351                        npd[ao_key]['action_arguments'][sp[3]] = val
352            else:
353                # Not pja stuff.
354                pass
355        return to_json_string(npd)
356           
357    @classmethod
358    def get_add_list(cls):
359        addlist = "<select id='new_pja_list' name='new_pja_list'>"
360        for action in ActionBox.actions:
361            addlist += "<option value='%s'>%s</option>" % (ActionBox.actions[action].name, ActionBox.actions[action].verbose_name)
362        addlist += "</select>"
363        return addlist
364       
365    @classmethod
366    def get_forms(cls, trans):
367        forms = ""
368        for action in ActionBox.actions:
369            forms += ActionBox.actions[action].get_config_form(trans)
370        return forms
371   
372    @classmethod
373    def execute(cls, app, sa_session, pja, job):
374        if ActionBox.actions.has_key(pja.action_type):
375            ActionBox.actions[pja.action_type].execute(app, sa_session, pja, job)
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。