Commit 74a34af4 authored by Jerome Mariette's avatar Jerome Mariette
Browse files

display error, and handle errors with raise instead of sys.exit

parent 0e480b39
......@@ -312,11 +312,13 @@ class Component(object):
elif exec_path is None and os.path.isfile(os.path.join(os.path.dirname(inspect.getfile(self.__class__)), "bin", software)):
exec_path = os.path.join(os.path.dirname(inspect.getfile(self.__class__)), "bin", software)
elif exec_path is None and which(software) == None:
display_error_message("'" + software + "' path connot be retrieved either in the PATH and in the application.properties file!")
logging.getLogger("jflow").exception("'" + software + "' path connot be retrieved either in the PATH and in the application.properties file!")
raise Exception("'" + software + "' path connot be retrieved either in the PATH and in the application.properties file!")
elif exec_path is None and which(software) != None:
exec_path = software
elif exec_path != None and not os.path.isfile(exec_path):
display_error_message("'" + exec_path + "' set for '" + software + "' does not exists, please provide a valid path!")
logging.getLogger("jflow").exception("'" + exec_path + "' set for '" + software + "' does not exists, please provide a valid path!")
raise Exception("'" + exec_path + "' set for '" + software + "' does not exists, please provide a valid path!")
return exec_path
def get_nameid(self):
......
......@@ -70,7 +70,8 @@ class JFlowConfigReader(object):
exec_path = None
if exec_path is None: exec_path = "makeflow"
if which(exec_path) == None:
display_error_message("'makeflow' path connot be retrieved either in the PATH and in the application.properties file!")
logging.getLogger("jflow").exception("'makeflow' path connot be retrieved either in the PATH and in the application.properties file!")
raise Exception("'makeflow' path connot be retrieved either in the PATH and in the application.properties file!")
return exec_path
def get_date_format(self):
......
......@@ -766,7 +766,7 @@ class AbstractInputFile(AbstractIOFile):
# Parts of download
local_file.write(buffer)
local_file.close()
logging.getLogger("AbstractInputFile.download_urlfile").debug("URL file '{0}' successfully downloaded as: {1}".format(input, file_path))
logging.getLogger("jflow").debug("URL file '{0}' successfully downloaded as: {1}".format(input, file_path))
return [file_path, True]
except:
return [input, False]
......@@ -780,9 +780,9 @@ class AbstractInputFile(AbstractIOFile):
try:
eval(self.file_format)(ifile)
except jflow.InvalidFormatError as e:
display_error_message(str(e))
raise Exception (str(e))
else:
display_error_message("Invalid file format '" + self.file_format + "'!")
raise Exception("Invalid file format '" + self.file_format + "'!")
class AbstractOutputFile(AbstractIOFile):
"""
......
......@@ -88,7 +88,9 @@ class Workflow(threading.Thread):
PROPERTIES_FILE_NAME = "workflow.properties"
MAKEFLOW_LOG_FILE_NAME = "Makeflow.makeflowlog"
DUMP_FILE_NAME = ".workflow.dump"
STDERR_FILE_NAME = "wf_stderr.txt"
WORKING = ".working"
OLD_EXTENSION = ".old"
STATUS_STARTED = "started"
STATUS_COMPLETED = "completed"
......@@ -151,7 +153,7 @@ class Workflow(threading.Thread):
if not os.path.isdir(self.directory):
os.makedirs(self.directory, 0751)
if self.stderr is None:
self.set_stderr()
self.stderr = self._set_stderr()
self._serialize()
def add_input_file(self, name, help, file_format="any", default=None, type="inputfile",
......@@ -288,7 +290,8 @@ class Workflow(threading.Thread):
elif parameter.__class__ == InputFileList:
if value == "" : value = [] # from GUI
iovalues = []
for file in parameter.prepare_input_files(value):
prepared_files = parameter.prepare_input_files(value)
for file in prepared_files:
iovalues.append(IOFile(file, parameter.file_format, parameter.linkTrace_nameid, None))
new_param = InputFileList( parameter.name, parameter.help, file_format=parameter.file_format, default=iovalues,
type=parameter.type, choices=parameter.choices, required=parameter.required, flag=parameter.flag,
......@@ -296,7 +299,8 @@ class Workflow(threading.Thread):
new_param.linkTrace_nameid = parameter.linkTrace_nameid
elif parameter.__class__ == InputFile:
if value == "" : value = None # from GUI
new_param = InputFile( parameter.name, parameter.help, file_format=parameter.file_format, default=parameter.prepare_input_file(value),
prepared_file = parameter.prepare_input_file(value)
new_param = InputFile( parameter.name, parameter.help, file_format=parameter.file_format, default=prepared_file,
type=parameter.type, choices=parameter.choices, required=parameter.required, flag=parameter.flag,
group=parameter.group, display_name=parameter.display_name )
new_param.linkTrace_nameid = parameter.linkTrace_nameid
......@@ -367,19 +371,6 @@ class Workflow(threading.Thread):
for orphan_node in all_nodes.keys():
gr.del_node(orphan_node)
return gr
def set_stderr(self):
if hasattr(self, "stderr") and self.stderr is not None:
os.rename( self.stderr, os.path.join(self.directory, str(time.time()) + "wf_stderr.old") )
stderr = os.path.join(self.directory, "wf_stderr.txt")
logger = logging.getLogger( "wf." + str(self.id) )
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter( '%(asctime)s :: %(message)s' )
file_handler = FileHandler(stderr, 'a')
file_handler.setLevel(logging.ERROR)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
self.stderr = stderr
def delete(self):
if self.get_status() in [self.STATUS_COMPLETED, self.STATUS_FAILED, self.STATUS_ABORTED]:
......@@ -488,7 +479,7 @@ class Workflow(threading.Thread):
FH_stderr = open( self.stderr )
lines = FH_stderr.readlines()
while line_idx < len(lines):
if lines[line_idx].strip().endswith("RunWorflowException"):
if lines[line_idx].strip().startswith("##"):
error["title"] = lines[line_idx].rstrip()
error["msg"] = list()
error["traceback"] = list()
......@@ -501,8 +492,8 @@ class Workflow(threading.Thread):
})
line_idx += 2
# Error message
while line_idx < len(lines) and not lines[line_idx].strip().endswith("RunWorflowException"):
error["msg"].append( lines[line_idx].strip() )
while line_idx < len(lines) and not lines[line_idx].strip().startswith("##"):
error["msg"].append( lines[line_idx].strip().split(":", 1)[1][1:] )
line_idx += 1
line_idx -= 1
line_idx += 1
......@@ -582,7 +573,7 @@ class Workflow(threading.Thread):
s.close()
except:
logging.getLogger("wf." + str(self.id)).debug("Impossible to connect to smtp server '" + smtps + "'")
def get_parameters_per_groups(self):
name = self.get_name()
description = self.get_description()
......@@ -611,11 +602,11 @@ class Workflow(threading.Thread):
elif exec_path is None and os.path.isfile(os.path.join(os.path.dirname(inspect.getfile(self.__class__)), "bin", software)):
exec_path = os.path.join(os.path.dirname(inspect.getfile(self.__class__)), "bin", software)
elif exec_path is None and utils.which(software) == None:
utils.display_error_message("'" + software + "' path connot be retrieved either in the PATH and in the application.properties file!")
raise Exception("'" + software + "' path connot be retrieved either in the PATH and in the application.properties file!")
elif exec_path is None and utils.which(software) != None:
exec_path = software
elif exec_path != None and not os.path.isfile(exec_path):
utils.display_error_message("'" + exec_path + "' set for '" + software + "' does not exists, please provide a valid path!")
raise Exception("'" + exec_path + "' set for '" + software + "' does not exists, please provide a valid path!")
return exec_path
def add_component(self, component_name, args=[], kwargs={}, component_prefix="default"):
......@@ -775,9 +766,9 @@ class Workflow(threading.Thread):
self.end_time = time.time()
self._serialize()
self._send_email()
except:
logging.getLogger("wf." + str(self.id)).exception("RunWorflowException")
raise
except Exception as e:
logging.getLogger("wf." + str(self.id)).exception(str(e))
utils.display_error_message(str(e))
def _update_status_from_log(self):
# first update the status from weaver folders
......@@ -851,7 +842,7 @@ class Workflow(threading.Thread):
cpt.reset()
found = True
if not found:
utils.display_error_message("Impossible to reset component '" + component_name + "'! This one is not part of the workflow")
raise Exception("Impossible to reset component '" + component_name + "'! This one is not part of the workflow")
self.reseted_components.append(component_name)
self.status = self.STATUS_RESETED
self._serialize()
......@@ -875,6 +866,19 @@ class Workflow(threading.Thread):
sys.stdout.write('{0:>10} {1:>10} {2}\n'.format('', 'COMMAND', node.command))
def _set_stderr(self):
if hasattr(self, "stderr") and self.stderr is not None:
os.rename( self.stderr, os.path.join(self.directory, str(time.time()) + self.STDERR_FILE_NAME + self.OLD_EXTENSION) )
stderr = os.path.join(self.directory, self.STDERR_FILE_NAME)
logger = logging.getLogger( "wf." + str(self.id) )
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter( '## %(asctime)s :: %(message)s' )
file_handler = FileHandler(stderr, 'a')
file_handler.setLevel(logging.ERROR)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
return stderr
def _execute_weaver(self, engine_wrapper=None):
# Add nest path and path to script to Python module path to allow
# for importing modules outside of $PYTHONPATH
......@@ -962,7 +966,7 @@ class Workflow(threading.Thread):
if issubclass(obj, jflow.component.Component) and obj.__name__ != jflow.component.Component.__name__:
pckge[class_name] = modname
except Exception as e:
logging.getLogger("Workflow._import_components").debug("Component <{0}> cannot be loaded: {1}".format(modname, e))
logging.getLogger("wf." + str(self.id)).debug("Component <{0}> cannot be loaded: {1}".format(modname, e))
# finally import workflows shared packages
workflows_dir = os.path.dirname(os.path.dirname(inspect.getfile(self.__class__)))
for importer, modname, ispkg in pkgutil.iter_modules([os.path.join(workflows_dir, "components")], "workflows.components."):
......@@ -972,7 +976,7 @@ class Workflow(threading.Thread):
if issubclass(obj, jflow.component.Component) and obj.__name__ != jflow.component.Component.__name__:
pckge[class_name] = modname
except Exception as e:
logging.getLogger("Workflow._import_components").debug("Component <{0}> cannot be loaded: {1}".format(modname, e))
logging.getLogger("wf." + str(self.id)).debug("Component <{0}> cannot be loaded: {1}".format(modname, e))
return pckge
def _import(self, module, symbols):
......
......@@ -127,6 +127,7 @@ class WorkflowsManager(object):
del workflows_dump[rworkflow_id]
workflow_dump.close()
except:
logging.getLogger("jflow").debug("Workflow #" + rworkflow_id + " connot be retrieved in the available workflows!")
utils.display_error_message("Workflow #" + rworkflow_id + " connot be retrieved in the available workflows!")
# and save them
pickle.dump(workflows_dump, open(self.dump_file, "w"))
......@@ -187,7 +188,8 @@ class WorkflowsManager(object):
workflow = pickle.load(workflow_dump)
workflow_dump.close()
else:
utils.display_error_message("Workflow with id " + str(rworkflow_id) + " cannot be retrived")
logging.getLogger("jflow").debug("Workflow #" + str(rworkflow_id) + " connot be retrieved in the available workflows!")
utils.display_error_message("Workflow #" + str(rworkflow_id) + " connot be retrieved in the available workflows!")
return workflow
def get_workflow_directory(self, wname, wid):
......
......@@ -70,7 +70,7 @@
if (this.options.forceUsingWorkflow) {
var workflow = this.reformatWorkflowJSON(this.options.forceUsingWorkflow);
this.$element.html("");
$.tmpl(this.options.headTemplate, {workflow: workflow}).appendTo(this.$element);
$.tmpl(this.options.headTemplate, {workflow: workflow, verbose:this.options.verbose}).appendTo(this.$element);
$.tmpl(this.options.listTemplate, {workflow: workflow}).appendTo(this.$element);
// force for first display, then reload an update
this.options.forceUsingWorkflow = null;
......@@ -104,7 +104,7 @@
success: function(data) {
var workflow = $this.reformatWorkflowJSON(data);
$this.$element.html("");
$.tmpl($this.options.headTemplate, {workflow: workflow}).appendTo($this.$element);
$.tmpl($this.options.headTemplate, {workflow: workflow, verbose:$this.options.verbose}).appendTo($this.$element);
$.tmpl($this.options.listTemplate, {workflow: workflow}).appendTo($this.$element);
// handle if there is some error
......@@ -164,7 +164,7 @@
success: function(data) {
var workflow = $this.reformatWorkflowJSON(data);
$this.$element.html("");
$.tmpl($this.options.headTemplate, {workflow: workflow}).appendTo($this.$element);
$.tmpl($this.options.headTemplate, {workflow: workflow, verbose:$this.options.verbose}).appendTo($this.$element);
$.tmpl($this.options.graphTemplate, {workflow: workflow}).appendTo($this.$element);
// prepare the data
......@@ -457,10 +457,12 @@
'<dd>${workflow.elapsed_time}</dd>',
'</dl>',
'<div id="wfstatus_error_panel" class="alert alert-danger" role="alert" style="display:none;">',
' <strong>Error message :</strong><br/>',
' <strong>Error!</strong>',
' <span id="wfstatus_error_msg"></span><br/>',
' <strong>Error location :</strong><br/>',
' <span id="wfstatus_error_location"></span>',
' {{if verbose}}',
' <strong>Error location:</strong><br/>',
' <span id="wfstatus_error_location"></span>',
' {{/if}}',
'</div>'].join('\n'),
listTemplate: ['<dl class="dl-horizontal">',
'{{each(index, component) workflow.components}}',
......@@ -487,6 +489,7 @@
'</div>'].join('\n'),
workflowID: null,
forceUsingWorkflow: null,
verbose: false,
display: "graph"
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment