Commit 137fd65e authored by Frédéric Escudié's avatar Frédéric Escudié
Browse files

Fix serialisation bug with DateParameter.

parent c0924f6e
...@@ -28,6 +28,8 @@ limit_submission = 100 ...@@ -28,6 +28,8 @@ limit_submission = 100
server_socket_host = 127.0.0.1 server_socket_host = 127.0.0.1
# on which socket port should run the web server # on which socket port should run the web server
server_socket_port = 8080 server_socket_port = 8080
# date format
date_format = %d/%m/%Y
[email] [email]
# if you want an email to be sent at the end of the workflow execution # if you want an email to be sent at the end of the workflow execution
......
...@@ -22,6 +22,7 @@ import json ...@@ -22,6 +22,7 @@ import json
import sys import sys
from functools import wraps from functools import wraps
import time import time
import datetime
import os import os
import argparse import argparse
import logging import logging
...@@ -76,6 +77,12 @@ def CORS(): ...@@ -76,6 +77,12 @@ def CORS():
cherrypy.response.headers['Access-Control-Allow-Headers'] = 'Content-Type, Content-Range, Content-Disposition' cherrypy.response.headers['Access-Control-Allow-Headers'] = 'Content-Type, Content-Range, Content-Disposition'
cherrypy.tools.CORS = cherrypy.Tool('before_finalize', CORS) cherrypy.tools.CORS = cherrypy.Tool('before_finalize', CORS)
class JFlowJSONEncoder (json.JSONEncoder):
def default(self, obj):
if isinstance(obj, (datetime.date, datetime.datetime)):
return obj.strftime( JFlowConfigReader().get_date_format() )
else:
return json.JSONEncoder.default(self, obj)
class JFlowServer (object): class JFlowServer (object):
...@@ -94,7 +101,7 @@ class JFlowServer (object): ...@@ -94,7 +101,7 @@ class JFlowServer (object):
value = func(*args, **kw) value = func(*args, **kw)
cherrypy.response.headers["Content-Type"] = "application/json" cherrypy.response.headers["Content-Type"] = "application/json"
# if JSONP request # if JSONP request
if kw.has_key("callback"): return kw["callback"] + "(" + json.dumps(value) + ")" if kw.has_key("callback"): return kw["callback"] + "(" + json.dumps(value, cls=JFlowJSONEncoder) + ")"
# else return the JSON # else return the JSON
else: return json.dumps(value) else: return json.dumps(value)
return wrapper return wrapper
...@@ -146,7 +153,7 @@ class JFlowServer (object): ...@@ -146,7 +153,7 @@ class JFlowServer (object):
"start_time": start_time, "start_time": start_time,
"end_time": end_time, "end_time": end_time,
"components": components} "components": components}
return status return status
@cherrypy.expose @cherrypy.expose
...@@ -173,9 +180,19 @@ class JFlowServer (object): ...@@ -173,9 +180,19 @@ class JFlowServer (object):
"name": param.name, "name": param.name,
"display_name": param.display_name, "display_name": param.display_name,
"group": param.group} "group": param.group}
if hash_param["type"] == "date":
hash_param["format"] = self.jflow_config_reader.get_date_format()
if hash_param["format"] == '%d/%m/%Y':
hash_param["format"] = 'dd/mm/yyyy'
elif hash_param["format"] == '%d/%m/%y':
hash_param["format"] = 'dd/mm/yy'
elif hash_param["format"] == '%Y/%m/%d':
hash_param["format"] = 'yyyy/mm/dd'
elif hash_param["format"] == '%y/%m/%d':
hash_param["format"] = 'yy/mm/dd'
# if it's a multiple type add sub parameters # if it's a multiple type add sub parameters
if type(param.type) == jflow.parameter.MultipleParameters: if type(param.type) == jflow.parameter.MultipleParameters:
hash_param["sub_parameters"] = [] hash_param["sub_parameters"] = []
for sub_param in param.sub_parameters: for sub_param in param.sub_parameters:
hash_param["sub_parameters"].append({"help": sub_param.help, hash_param["sub_parameters"].append({"help": sub_param.help,
"required": sub_param.required, "required": sub_param.required,
...@@ -186,6 +203,16 @@ class JFlowServer (object): ...@@ -186,6 +203,16 @@ class JFlowServer (object):
"name": param.name + JFlowServer.MULTIPLE_TYPE_SPLITER + sub_param.flag, "name": param.name + JFlowServer.MULTIPLE_TYPE_SPLITER + sub_param.flag,
"display_name": sub_param.display_name, "display_name": sub_param.display_name,
"group": param.group}) "group": param.group})
if hash_param["type"] == "date":
hash_param["format"] = self.jflow_config_reader.get_date_format()
if hash_param["format"] == '%d/%m/%Y':
hash_param["format"] = 'dd/mm/yyyy'
elif hash_param["format"] == '%d/%m/%y':
hash_param["format"] = 'dd/mm/yy'
elif hash_param["format"] == '%Y/%m/%d':
hash_param["format"] = 'yyyy/mm/dd'
elif hash_param["format"] == '%y/%m/%d':
hash_param["format"] = 'yy/mm/dd'
parameters.append(hash_param) parameters.append(hash_param)
if parameters_per_groups.has_key(param.group): if parameters_per_groups.has_key(param.group):
parameters_per_groups[param.group].append(hash_param) parameters_per_groups[param.group].append(hash_param)
...@@ -202,27 +229,26 @@ class JFlowServer (object): ...@@ -202,27 +229,26 @@ class JFlowServer (object):
@cherrypy.expose @cherrypy.expose
@jsonify @jsonify
def run_workflow(self, **kwargs): def run_workflow(self, **kwargs):
try: try:
kwargs_modified = {} kwargs_modified = {}
for key in kwargs.keys(): for key in kwargs.keys():
parts = key.split(JFlowServer.MULTIPLE_TYPE_SPLITER) parts = key.split(JFlowServer.MULTIPLE_TYPE_SPLITER)
# if this is a classic Parameter # if this is a classic Parameter
if len(parts) == 1: if len(parts) == 1:
kwargs_modified[key] = kwargs[key] kwargs_modified[key] = kwargs[key]
# if this is a MultiParameter # if this is a MultiParameter
elif len(parts) == 2: elif len(parts) == 2:
if kwargs_modified.has_key(parts[0]): if kwargs_modified.has_key(parts[0]):
kwargs_modified[parts[0]].append((parts[1], kwargs[key])) kwargs_modified[parts[0]].append((parts[1], kwargs[key]))
else: else:
kwargs_modified[parts[0]] = [(parts[1], kwargs[key])] kwargs_modified[parts[0]] = [(parts[1], kwargs[key])]
# if this is a MultiParameterList # if this is a MultiParameterList
# TODO: du cote interface faire qq chose du genre: key.sub_key.1 ... donc si len == 3 # TODO: du cote interface faire qq chose du genre: key.sub_key.1 ... donc si len == 3
# l'objectif etant d'avoir une structure de type: [[(sub_key1: val), (sub_key2: val)], [(sub_key1: val2), (sub_key2: val2)]] # l'objectif etant d'avoir une structure de type: [[(sub_key1: val), (sub_key2: val)], [(sub_key1: val2), (sub_key2: val2)]]
workflow = self.wfmanager.run_workflow(kwargs_modified["workflow_class"], kwargs_modified)
workflow = self.wfmanager.run_workflow(kwargs_modified["workflow_class"], kwargs_modified) return { "status" : 0, "content" : self.jsonify_workflow_status(workflow, True) }
return { "status" : 0, "content" : self.jsonify_workflow_status(workflow, True) } except Exception as err:
except Exception as err: return { "status" : 1, "content" : str(err) }
return { "status" : 1, "content" : str(err) }
@cherrypy.expose @cherrypy.expose
@jsonify @jsonify
......
...@@ -73,7 +73,14 @@ class JFlowConfigReader(object): ...@@ -73,7 +73,14 @@ class JFlowConfigReader(object):
sys.stderr.write("Error: 'makeflow' path connot be retrieved either in the PATH and in the application.properties file!\n") sys.stderr.write("Error: 'makeflow' path connot be retrieved either in the PATH and in the application.properties file!\n")
sys.exit(1) sys.exit(1)
return exec_path return exec_path
def get_date_format(self):
try:
date_format = self.reader.get("global", "date_format")
except:
raise Error("Failed when parsing the config file, no parameter date_format!")
return date_format
def get_batch(self): def get_batch(self):
try: try:
type = self.reader.get("global", "batch_system_type") type = self.reader.get("global", "batch_system_type")
......
...@@ -587,6 +587,14 @@ class DateParameter(datetime.datetime, AbstractParameter): ...@@ -587,6 +587,14 @@ class DateParameter(datetime.datetime, AbstractParameter):
else: else:
return (True if datetime.date(self.year, self.month, self.day) else False) return (True if datetime.date(self.year, self.month, self.day) else False)
def __reduce__(self):
return (DateParameter, (self.name, self.help, self.default, date, self.choices, self.required,
self.flag, self.sub_parameters, self.group, self.display_name), None, None, None)
def __reduce_ex__(self, protocol):
return (DateParameter, (self.name, self.help, self.default, date, self.choices, self.required,
self.flag, self.sub_parameters, self.group, self.display_name), None, None, None)
class AbstractInputFile(AbstractIOFile): class AbstractInputFile(AbstractIOFile):
""" """
...@@ -616,7 +624,7 @@ class AbstractInputFile(AbstractIOFile): ...@@ -616,7 +624,7 @@ class AbstractInputFile(AbstractIOFile):
return [file_path, True] return [file_path, True]
except: except:
return [input, False] return [input, False]
def check(self, ifile): def check(self, ifile):
try: try:
eval(self.file_format) eval(self.file_format)
...@@ -673,7 +681,7 @@ class InputFile(StrParameter, AbstractInputFile): ...@@ -673,7 +681,7 @@ class InputFile(StrParameter, AbstractInputFile):
if is_local: new_path = input if is_local: new_path = input
self.check(new_path) self.check(new_path)
return new_path return new_path
class OutputFile(StrParameter, AbstractOutputFile): class OutputFile(StrParameter, AbstractOutputFile):
......
...@@ -100,7 +100,7 @@ class Workflow(threading.Thread): ...@@ -100,7 +100,7 @@ class Workflow(threading.Thread):
if type: self.engine_arguments += ' -T ' + type if type: self.engine_arguments += ' -T ' + type
if options : self.engine_arguments += ' -B "' + options + '"' if options : self.engine_arguments += ' -B "' + options + '"'
except: self.engine_arguments = None except: self.engine_arguments = None
self.id = id self.id = id
self.name = self.get_name() self.name = self.get_name()
self.description = self.get_description() self.description = self.get_description()
...@@ -669,14 +669,14 @@ class Workflow(threading.Thread): ...@@ -669,14 +669,14 @@ class Workflow(threading.Thread):
# if post processing has ne been done yet # if post processing has ne been done yet
if self.step == 3: if self.step == 3:
self.post_process() self.post_process()
if self.status == self.STATUS_STARTED: self.status = self.STATUS_COMPLETED if self.status == self.STATUS_STARTED: self.status = self.STATUS_COMPLETED
self.end_time = time.time() self.end_time = time.time()
self._serialize() self._serialize()
self._send_email() self._send_email()
except: except:
logging.getLogger("wf." + str(self.id)).exception("RunWorflowException") logging.getLogger("wf." + str(self.id)).exception("RunWorflowException")
raise raise
def _update_status_from_log(self): def _update_status_from_log(self):
# first update the status from weaver folders # first update the status from weaver folders
# TODO update self.end_time # TODO update self.end_time
......
...@@ -508,7 +508,7 @@ jQuery.validator.addMethod("exclude_required", function(value, element, options) ...@@ -508,7 +508,7 @@ jQuery.validator.addMethod("exclude_required", function(value, element, options)
' </select>', ' </select>',
// if param is a date // if param is a date
'{{else param.type == "date"}}', '{{else param.type == "date"}}',
' <div class="input-append date" data-date="${param.default}" data-date-format="dd/mm/yyyy">', ' <div class="input-append date" data-date="${param.default}" data-date-format="${param.format}">',
' <input id="${param.name}" name="${param.name}" class="${param.group} ${input_size} span2" type="text" value="${param.default}">', ' <input id="${param.name}" name="${param.name}" class="${param.group} ${input_size} span2" type="text" value="${param.default}">',
' <button class="btn" type="button"><i class="icon-calendar"></i></button>', ' <button class="btn" type="button"><i class="icon-calendar"></i></button>',
' </div>', ' </div>',
......
...@@ -17,12 +17,12 @@ ...@@ -17,12 +17,12 @@
import argparse import argparse
import datetime import datetime
from jflow.config_reader import JFlowConfigReader
def date(datestr): def date(datestr):
try: try:
return datetime.datetime.strptime(datestr, '%d/%m/%Y') return datetime.datetime.strptime(datestr, JFlowConfigReader().get_date_format())
except: except:
raise argparse.ArgumentTypeError("'" + datestr + "' is an invalid date!") raise argparse.ArgumentTypeError("'" + datestr + "' is an invalid date!")
\ No newline at end of file
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