from django.conf import settings from common.models import * import xml.etree.ElementTree as ET import sys from xml.dom import minidom from .validators import check_plan_validity import re from decimal import Decimal from jdcal import gcal2jd, jd2gcal import time import datetime import utils.Logger as L import scheduler.tasks as task #import scheduler.tasks log = L.setupLogger("RequestSerializerLogger", "RequestSerializer") def prettify(elem): """ :returns : A pretty-printed XML string for the Element elem """ rough_string = ET.tostring(elem, 'utf-8') reparsed = minidom.parseString(rough_string) return reparsed.toprettyxml(indent=" ") class RequestSerializer(): submit = False relative = False """ Serializes and unserializes a request, with all children (sequences, albums and plans) Format : XML Only serializes the wanted fields Entry point(s) : - serialize """ def serialize(self, req, file_name): """ Serializes the request into the given file """ request = ET.Element("request", name=req.name, scientific_program=req.scientific_program.name, target_type=req.target_type) for seq in req.sequences.all(): sequence = ET.SubElement(request, "sequence", name=seq.name, target_coords=seq.target_coords, jd1=str(seq.jd1), jd2=str(seq.jd2)) sequence.set("duration", str(seq.duration * 86400)) for alb in seq.albums.all(): album = ET.SubElement(sequence, "album", name=alb.name, detector=alb.detector.name) for plan in alb.plans.all(): pl = ET.SubElement(album, "plan", name=plan.name, filter=plan.filter.name, nb_images=str(plan.nb_images)) pl.set("duration", str(plan.duration * 86400)) with open(file_name, "w") as file: file.write(prettify(request)) def unserialize(self, xml_data, pyros_user): TIMESTAMP_JD = 2440587.500000 """ Unserializes the request read into file_name Throws exceptions in case of invalid file or values Directly saves the objects in DB The request still need to be submitted afterward ! :returns : "" (empty string) in case of success, error message (string) instead """ try: root = ET.fromstring(xml_data) except ET.ParseError as E: return "Invalid file : " + str(E) self.pyros_user = pyros_user print("RS: pyros user is ", pyros_user) self.request = None """ self.sequences will be a [(seq, album_list), ...], and same thing for album """ self.sequences = [] ret = self.unserialize_request(root) if ret != "": return ret if (settings.DEBUG): log.info("Request submit " + str(self.submit)) if self.submit: self.request.submitted = 1 self.request.save() for sequence, albums in self.sequences: if self.relative: # 86400 = nb seconds in 24 h # time.localtime(time.time()) donne l'heure française # time.gmttime(time.time()) donne l'heure gmt sequence.jd1 = (time.time() + float(sequence.jd1)) / 86400 + TIMESTAMP_JD sequence.jd2 = (time.time() + float(sequence.jd2)) / 86400 + TIMESTAMP_JD #print("********* jd1,jd2 ", sequence.jd1, sequence.jd2) # EP avirer #sequence.jd1 += float( (1/24)*2 ) #sequence.jd2 += float( (1/24)*2 ) sequence.request = self.request sequence.save() for album, plans in albums: album.sequence = sequence album.save() for plan in plans: plan.album = album plan.save() check_plan_validity(plan) if (self.request.submitted): #ret = task.scheduling.delay(first_schedule=False, alert=False) if settings.USE_CELERY: print("RS: schedule WITH CELERY") #ret = scheduler.tasks.scheduling.delay(first_schedule=False, alert=False) ret = task.scheduling.delay(first_schedule=False, alert=False) else: print("RS: schedule WITHOUT CELERY") #ret = scheduler.tasks.scheduling().run(first_schedule=False, alert=False) ret = task.scheduling().run(first_schedule=False, alert=False) return "" def unserialize_request(self, request): ''' Receives an xml.etree request and unserialize it ''' if request.tag != "request": return "Main object should be a request (found %s instead)" % (request.tag,) possible_attribs = ["name", "scientific_program", "target_type", "submitted", "relative"] self.request = Request(pyros_user=self.pyros_user, is_alert=False, complete=False, submitted=False) for name, value in request.attrib.items(): if name not in possible_attribs: return "Unknown attribute %s in request" % (name,) if name == "scientific_program": try: sp = ScientificProgram.objects.get(name=value) self.request.scientific_program = sp except Exception as E: print(str(E)) return "Invalid scientific program %s" % (value,) elif name == "submitted": try: self.submit = bool(int(value)) except Exception as E: print(str(E)) return ("Invalid value for submitted") elif name == "relative": try: self.relative = bool(int(value)) except Exception as E: print(str(E)) return ("Invalid value for submitted") else: self.request.__dict__[name] = value for sequence in request: ret = self.unserialize_sequence(sequence) if ret != "": return ret return "" def unserialize_sequence(self, sequence): if sequence.tag != "sequence": return "A request can only have 'sequence' children (found %s instead)" % (sequence.tag,) possible_attribs = ["name", "target_coords", "jd1", "jd2", "duration"] seq = Sequence(request=self.request, status=Sequence.INCOMPLETE) for name, value in sequence.attrib.items(): if name not in possible_attribs: return "Unknown attribute %s in sequence" % (name,) if name == "name": seq.name = value elif name == "target_coords": seq.target_coords = value elif name == "jd1": seq.jd1 = Decimal(value) elif name == "jd2": seq.jd2 = Decimal(value) elif name == "duration": seq.duration = Decimal(value) / 86400 # TODO: faire des checks ?? j'imagine, par exemple pour la cohérence des valeurs album_list = [] self.sequences.append((seq, album_list)) for album in sequence: ret = self.unserialize_album(album, seq, album_list) if ret != "": return ret return "" def unserialize_album(self, album, sequence, album_list): if album.tag != "album": return "A sequence can only have 'album' children (found %s instead)" % (album.tag,) possible_attribs = ["name", "detector"] alb = Album(sequence=sequence) for name, value in album.attrib.items(): if name not in possible_attribs: return "Unknown attribute %s in album" % (name,) if name == "detector": try: detector = Detector.objects.get(name=value) alb.detector = detector except Exception as E: print(str(E)) return "Invalid detector %s" % (value,) elif name == "name": alb.name = value plan_list = [] album_list.append((alb, plan_list)) for plan in album: ret = self.unserialize_plan(plan, alb, plan_list) if ret != "": return ret return "" def unserialize_plan(self, plan, album, plan_list): if plan.tag != "plan": return "An album can only have 'plan' children (found %s instead)" % (plan.tag,) possible_attribs = ["name", "filter", "duration", "nb_images"] pl = Plan(album=album) for name, value in plan.attrib.items(): if name not in possible_attribs: return "Unknown attribute %s in plan" % (name,) if name == "filter": try: filter = Filter.objects.get(name=value) pl.filter = filter except Exception as E: return "Invalid filter %s" % (value,) elif name == "name": pl.name = value elif name == "duration": pl.duration = Decimal(value) / 86400 elif name == "nb_images": pl.nb_images = int(value) # TODO: quelques checks ... plan_list.append(pl) return ""