Commit 793d01902f575a3fad242077aa9ae7e9e811ea9a

Authored by Alexis Koralewski
1 parent d6e916dc
Exists in dev

rework routine_manager functions.py

Showing 1 changed file with 216 additions and 202 deletions   Show diff stats
src/core/pyros_django/routine_manager/functions.py
@@ -12,155 +12,33 @@ from django.db import IntegrityError @@ -12,155 +12,33 @@ from django.db import IntegrityError
12 # Project imports 12 # Project imports
13 from src.core.pyros_django.obsconfig.obsconfig_class import OBSConfig 13 from src.core.pyros_django.obsconfig.obsconfig_class import OBSConfig
14 from django.http import HttpRequest 14 from django.http import HttpRequest
  15 +#from silk.profiling.profiler import silk_profile
15 16
  17 +#@silk_profile(name="check_sequence_file")
16 def check_sequence_file_validity_and_save(yaml_content: dict, request: HttpRequest): 18 def check_sequence_file_validity_and_save(yaml_content: dict, request: HttpRequest):
17 ''' Create a sequence in DB from the uploaded sequence (yaml_content) ''' 19 ''' Create a sequence in DB from the uploaded sequence (yaml_content) '''
18 20
19 - # Get boolean to simplified to know if the file is written in simplified mode (i.e. : Each field of the form is directly associated to its value)  
20 - is_simplified = yaml_content.get("simplified", False)  
21 - # Get scientific programs for the user who is submitting the sequence file  
22 - user_sp = request.user.get_scientific_programs()  
23 - # From user sp, get all SP that can observe / submit sequence for the current period  
24 - sp_list = ScientificProgram.objects.observable_programs().filter(id__in=user_sp)  
25 -  
26 # Create a sequence seq object (from yaml_content) to be saved in DB 21 # Create a sequence seq object (from yaml_content) to be saved in DB
27 seq = Sequence.objects.create() 22 seq = Sequence.objects.create()
28 seq.pyros_user = PyrosUser.objects.get(id=request.user.id) 23 seq.pyros_user = PyrosUser.objects.get(id=request.user.id)
29 24
30 # Get the unit config 25 # Get the unit config
31 unit_name = os.environ["unit_name"] 26 unit_name = os.environ["unit_name"]
  27 + #with silk_profile(name="init obsconfig"):
32 config = OBSConfig(os.environ["PATH_TO_OBSCONF_FILE"], unit_name) 28 config = OBSConfig(os.environ["PATH_TO_OBSCONF_FILE"], unit_name)
33 -  
34 - # Create a Sequence form  
35 - sequence_form = SequenceForm(instance=seq, data_from_config=config.getEditableMountAttributes(config.unit_name), layouts = config.get_layouts(config.unit_name), sp_list=sp_list)  
36 result = { 29 result = {
37 "succeed": True, 30 "succeed": True,
38 "errors": [], 31 "errors": [],
39 } 32 }
40 -  
41 - if is_simplified:  
42 - seq.scientific_program = sp_list[yaml_content["sequence"]["scientific_program"]] 33 + # Get boolean to simplified to know if the file is written in simplified mode (i.e. : Each field of the form is directly associated to its value)
  34 + is_simplified = yaml_content.get("simplified", False)
  35 + # Get scientific programs for the user who is submitting the sequence file
  36 + user_sp = request.user.get_scientific_programs()
  37 + process_sequence(yaml_content, seq, config, is_simplified, result, user_sp)
43 38
44 - else:  
45 - # pour la lisibilité du code (et éviter la redondance)  
46 - # get scientific program field's attributes  
47 - yaml_seq_sp = yaml_content["sequence"]["scientific_program"]  
48 - sp_index_value = yaml_seq_sp["value"]  
49 - values = yaml_seq_sp["values"]  
50 - # Check if index of sp is valid (in range of possible index from values)  
51 - if sp_index_value < 0 or sp_index_value > len(values):  
52 - result["errors"].append(f"SP value isn't valid, index out of bounds ({sp_index_value} > {len(values)})")  
53 - sp_index_value = 0  
54 - chosen_sp = ScientificProgram.objects.get(name=values[sp_index_value])  
55 - # If the sp is associated to that user, associate the sp to the sequence  
56 - if chosen_sp in sp_list:  
57 - #seq.scientific_program = ScientificProgram.objects.get(name=yaml_content["sequence"]["scientific_program"]["values"][sp_index_value])  
58 - seq.scientific_program = chosen_sp  
59 - else:  
60 - result["errors"].append(f"SP {chosen_sp.name} is not assigned to that user ") 39 + process_albums(yaml_content, result, config, seq, is_simplified)
61 40
62 - seq.config_attributes = {}  
63 -  
64 - # Fill all Sequence form fields  
65 - # keys() inutile ? => for field in sequence_form.fields :  
66 - # Sinon, y a aussi => for key,val in sequence_form.fields.items():  
67 - # => Ca éviterait de faire => sequence_form.fields[field] pour recuperer "val"  
68 - for field, field_attribute in sequence_form.fields.items():  
69 41
70 - #if sequence_form.fields[field].required == False or field == "scientific_program":  
71 - if not field_attribute.required or field=="scientific_program":  
72 - continue  
73 - # pour lisibilité, simplicité et éviter redondance  
74 - yaml_field = yaml_content["sequence"][field]  
75 - value = yaml_field if is_simplified else yaml_field["value"]  
76 - ''' (orig)  
77 - if is_simplified:  
78 - value = yaml_content["sequence"][field]  
79 - else:  
80 - value = yaml_content["sequence"][field]["value"]  
81 - '''  
82 - # If the current field of the sequence isn't found in the file, add an error message to inform the user the missing field  
83 - if field not in yaml_content["sequence"]:  
84 - result["errors"].append(f"{field} not in yaml file")  
85 - else:  
86 - if is_simplified:  
87 - # If the field is a choicefield, get choices and associate the index to the real value  
88 - if sequence_form.fields[field].__dict__.get("_choices"):  
89 - # y a pas conflit ici avec la variable "value" définie au-dessus ? -> Non car on transforme l'ancien value qui est un index en une vraie valeur  
90 - values = [value[0] for value in sequence_form.fields[field].__dict__.get("_choices")]  
91 - value = values[value]  
92 - else:  
93 - if yaml_field.get("values"):  
94 - # Transform the original value which is an index to a "real" value from the "values" attributes  
95 - index_value = yaml_field["value"]  
96 - values = yaml_field["values"]  
97 - if index_value < 0 or index_value > len(yaml_field["values"]):  
98 - result["errors"].append(f"Value of {field} isn't valid, index out of bounds ({index_value} > {len(values)})")  
99 - index_value = 0  
100 - value = yaml_field["values"][index_value]  
101 - else:  
102 - # Transform the string value to a datetime value  
103 - if field == "start_date":  
104 - if type(value) != datetime.datetime:  
105 - #value = datetime.datetime.strptime(yaml_content["sequence"][field]["value"],'%d/%m/%Y %H:%M:%S')  
106 - # ISO format  
107 - value = datetime.datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%f')  
108 - seq.__dict__[field] = value  
109 - ''' (orig)  
110 - else:  
111 - if not is_simplified:  
112 - if yaml_content["sequence"][field].get("values"):  
113 - index_value = yaml_content["sequence"][field]["value"]  
114 - values = yaml_content["sequence"][field]["values"]  
115 - if index_value < 0 or index_value > len(yaml_content["sequence"][field]["values"]):  
116 - result["errors"].append(f"Value of {field} isn't valid, index out of bounds ({index_value} > {len(values)})")  
117 - index_value = 0  
118 - value = yaml_content["sequence"][field]["values"][index_value]  
119 - else:  
120 - if field == "start_date":  
121 - if type(value) != datetime.datetime:  
122 - #value = datetime.datetime.strptime(yaml_content["sequence"][field]["value"],'%d/%m/%Y %H:%M:%S')  
123 - # ISO format  
124 - value = datetime.datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%f')  
125 - seq.__dict__[field] = value  
126 - else:  
127 - if sequence_form.fields[field].__dict__.get("_choices"):  
128 - values = [value[0] for value in sequence_form.fields[field].__dict__.get("_choices")]  
129 - value = values[value]  
130 - '''  
131 -  
132 - # suffisant ? => if field in seq.__dict__  
133 - # If field is an attribute of the sequence, associate the field to the value  
134 - if field in seq.__dict__:  
135 - seq.__dict__[field] = value  
136 - else:  
137 - # else associate field & value in config_attributes sequence's field (JsonField) = variable fields of an sequence  
138 - seq.config_attributes[field] = value  
139 -  
140 - # Create ALBUMS  
141 - albums_from_file = yaml_content["sequence"]["ALBUMS"]  
142 - chosen_layout = seq.config_attributes["layout"]  
143 - if type(chosen_layout) == int:  
144 - layouts = config.get_layouts(config.unit_name)["layouts"]  
145 - chosen_layout = list(layouts.keys())[chosen_layout]  
146 - # Get album of the selected layout  
147 - layout_albums = config.getLayoutByName(unit_name=config.unit_name, name_of_layout=chosen_layout)["ALBUMS"]  
148 -  
149 - # check if we have all the albums of that layout described in the sequence file  
150 - if len(layout_albums) == len(albums_from_file):  
151 - for album in albums_from_file:  
152 - album = album["Album"]  
153 - if album["name"] not in layout_albums:  
154 - result["errors"].append(f"Album {album['name']} is not the chosen layout")  
155 - else:  
156 - # Create album  
157 - Album.objects.create(name=album["name"], sequence=seq, complete=True)  
158 - # Create plan for that album  
159 - plans = [a["Album"].get("Plans") for a in albums_from_file]  
160 - process_plans(plans, result, is_simplified, config, album, seq)  
161 - else:  
162 - result["errors"].append(f"The number of albums doesn't correspond to the chosen layout")  
163 -  
164 # optim possible ? 42 # optim possible ?
165 #[ process_plans(a["Album"].get("Plans")) for a in albums_from_file ] 43 #[ process_plans(a["Album"].get("Plans")) for a in albums_from_file ]
166 # Puis écrire la fonction process_plans() 44 # Puis écrire la fonction process_plans()
@@ -291,19 +169,51 @@ def check_sequence_file_validity_and_save(yaml_content: dict, request: HttpReque @@ -291,19 +169,51 @@ def check_sequence_file_validity_and_save(yaml_content: dict, request: HttpReque
291 result["sequence_id"] = seq.id 169 result["sequence_id"] = seq.id
292 return result 170 return result
293 171
  172 +def process_albums(yaml_content, result, config, seq, is_simplified):
  173 + # Create ALBUMS
  174 + albums_from_file = yaml_content["sequence"]["ALBUMS"]
  175 + chosen_layout = seq.config_attributes["layout"]
  176 + if type(chosen_layout) == int:
  177 + #with silk_profile(name="Get layout from config"):
  178 + layouts = config.get_layouts(config.unit_name)["layouts"]
  179 + chosen_layout = list(layouts)[chosen_layout]
  180 + # Get album of the selected layout
  181 + #with silk_profile(name="Get album of layout from config"):
  182 + layout_albums = config.getLayoutByName(unit_name=config.unit_name, name_of_layout=chosen_layout)["ALBUMS"]
  183 +
  184 + # check if we have all the albums of that layout described in the sequence file
  185 + #with silk_profile(name="Iterate on each album & plan (create)"):
  186 + if len(layout_albums) == len(albums_from_file):
  187 + for album in albums_from_file:
  188 + album = album["Album"]
  189 + if album["name"] not in layout_albums:
  190 + result["errors"].append(f"Album {album['name']} is not the chosen layout")
  191 + else:
  192 + # Create album
  193 + Album.objects.create(name=album["name"], sequence=seq, complete=True)
  194 + # Create plan for that album
  195 + plans = album.get("Plans")
  196 + process_plans(plans, result, is_simplified, config, album, seq)
  197 + else:
  198 + result["errors"].append(f"The number of albums doesn't correspond to the chosen layout")
  199 +
294 200
  201 +#@silk_profile(name="process_plans")
295 def process_plans(plans: dict, result: dict, is_simplified: bool, config: OBSConfig, album: dict, seq: dict): 202 def process_plans(plans: dict, result: dict, is_simplified: bool, config: OBSConfig, album: dict, seq: dict):
296 if plans == None: 203 if plans == None:
297 result["errors"].append(f"Album {album['name']} has no plans. Please add at least one plan") 204 result["errors"].append(f"Album {album['name']} has no plans. Please add at least one plan")
298 # exit function 205 # exit function
299 return None 206 return None
300 for plan in plans: 207 for plan in plans:
301 - new_plan_object = Plan.objects.create(album=Album.objects.get(name=album["name"], sequence=seq), complete=True)  
302 - new_plan_object.config_attributes = {} 208 + #new_plan_object = Plan.objects.create(album=Album.objects.get(name=album["name"], sequence=seq), complete=True)
  209 + #new_plan_object.config_attributes = {}
303 plan = plan["Plan"] 210 plan = plan["Plan"]
  211 + nb_images = 0
304 config_attributes = {} 212 config_attributes = {}
  213 + #with silk_profile(name="Create plan form"):
305 plan_form = PlanForm(data_from_config=config.getEditableChannelAttributes(config.unit_name, list(config.get_channels(config.unit_name).keys())[0]), edited_plan=None) 214 plan_form = PlanForm(data_from_config=config.getEditableChannelAttributes(config.unit_name, list(config.get_channels(config.unit_name).keys())[0]), edited_plan=None)
306 # Process each plan field 215 # Process each plan field
  216 + #with silk_profile(name="iterate on plan fields"):
307 for field in plan_form.fields: 217 for field in plan_form.fields:
308 plan_field = plan[field] 218 plan_field = plan[field]
309 ''' 219 '''
@@ -311,78 +221,180 @@ def process_plans(plans: dict, result: dict, is_simplified: bool, config: OBSCon @@ -311,78 +221,180 @@ def process_plans(plans: dict, result: dict, is_simplified: bool, config: OBSCon
311 max_value = None 221 max_value = None
312 value_type = None 222 value_type = None
313 ''' 223 '''
314 - min_value = max_value = value_type = None  
315 - if field not in plan.keys():  
316 - result["errors"].append(f"Missing field : '{field}' for plan {plans.index(plan)}")  
317 - continue  
318 - # TODO : ajouter max_value, min_value, suppression plan et album si invalides  
319 - if not is_simplified:  
320 - if plan_field.get("value_type"):  
321 - value_type = plan_field["value_type"]  
322 - if type(plan_field["value"]) == str and ast.literal_eval(plan_field["value"]) != value_type:  
323 - result["errors"].append(f"Field {field} value doesn't correspond to the assigned type (type required : {value_type})")  
324 - if plan_field.get("min_value"):  
325 - min_value = plan_field["min_value"]  
326 - if type(min_value) == str:  
327 - min_value = ast.literal_eval(min_value)  
328 - '''  
329 - if type(plan_field["min_value"]) == str:  
330 - min_value = ast.literal_eval(plan_field["min_value"])  
331 - else:  
332 - min_value = plan_field["min_value"]  
333 - '''  
334 - if plan_field.get("max_value"):  
335 - max_value = plan_field["max_value"]  
336 - if type(max_value) == str:  
337 - max_value = ast.literal_eval(max_value)  
338 - '''  
339 - if type(plan_field.get("max_value")) == str:  
340 - max_value = ast.literal_eval(plan_field["max_value"])  
341 - else:  
342 - max_value = plan_field["max_value"]  
343 - '''  
344 if field == "nb_images": 224 if field == "nb_images":
345 - new_plan_object.__dict__[field] = plan_field if is_simplified else plan_field["value"]  
346 - '''  
347 - if is_simplified:  
348 - new_plan_object.__dict__[field] = plan_field  
349 - else:  
350 - new_plan_object.__dict__[field] = plan_field["value"]  
351 - ''' 225 + nb_images = plan_field if is_simplified else plan_field["value"]
352 else: 226 else:
353 - # shortcut possible ?  
354 - #new_plan_object_field = new_plan_object.config_attributes[field]  
355 - if is_simplified:  
356 - new_plan_object.config_attributes[field] = plan_field  
357 - else:  
358 - if plan_field.get("values"):  
359 - index_value = plan_field["value"]  
360 - values = plan_field["values"]  
361 - if index_value < 0 or index_value > len(plan_field["values"]):  
362 - result["errors"].append(f"Value of Plan field '{field}' isn't valid, index out of bounds ({index_value} > {len(values)})")  
363 - index_value = 0  
364 - value = plan_field["values"][index_value]  
365 - try:  
366 - # linked values  
367 - splitted_values = value.split(";")  
368 - config_attributes[field] = {}  
369 - for splitted_value in splitted_values:  
370 - subkey,subvalue = splitted_value.split(":")  
371 - config_attributes[field][subkey] = ast.literal_eval(subvalue)  
372 - # vaudrait mieux préciser l'exception ici  
373 - except:  
374 - # Do nothing, normal string  
375 - config_attributes[field] = ast.literal_eval(value)  
376 - new_plan_object.config_attributes[field] = config_attributes[field]  
377 - else:  
378 - if max_value and min_value:  
379 - if plan_field["value"] > max_value:  
380 - result["errors"].append(f"Plan field {field} doesn't respect max value")  
381 - if plan_field["value"] < min_value:  
382 - result["errors"].append(f"Plan field {field} doesn't respect min value")  
383 - new_plan_object.config_attributes[field] = plan_field["value"] 227 + process_plan_field(result, config_attributes, plan_field, field, plans, plan, is_simplified)
384 # end foreach plan field 228 # end foreach plan field
385 - new_plan_object.save() 229 + Plan.objects.create(album=Album.objects.get(name=album["name"], sequence=seq), complete=True, nb_images=nb_images, config_attributes=config_attributes)
  230 +
  231 +def process_plan_field(result, config_attributes, plan_field, field, plans, plan, is_simplified):
  232 +
  233 +
  234 + if field not in plan.keys():
  235 + result["errors"].append(f"Missing field : '{field}' for plan {plans.index(plan)}")
  236 + # exit function
  237 + return None
  238 + if is_simplified:
  239 + #new_plan_object.config_attributes[field] = plan_field
  240 + config_attributes[field] = plan_field
  241 + else:
  242 + value_type, min_value, max_value = prepare_check_plan_field_value(plan_field, field, result)
  243 + check_and_set_plan_field_value(config_attributes, plan_field, field, result, value_type, min_value, max_value)
  244 +
  245 +
  246 +def check_and_set_plan_field_value(config_attributes, plan_field, field, result, value_type, min_value, max_value):
  247 + # if the value is a index of a list, get the value from this index
  248 + if plan_field.get("values"):
  249 + index_value = plan_field["value"]
  250 + values = plan_field["values"]
  251 + if index_value < 0 or index_value > len(plan_field["values"]):
  252 + result["errors"].append(f"Value of Plan field '{field}' isn't valid, index out of bounds ({index_value} > {len(values)})")
  253 + index_value = 0
  254 + value = plan_field["values"][index_value]
  255 + try:
  256 + # linked values
  257 + splitted_values = value.split(";")
  258 + config_attributes[field] = {}
  259 + for splitted_value in splitted_values:
  260 + subkey,subvalue = splitted_value.split(":")
  261 + config_attributes[field][subkey] = ast.literal_eval(subvalue)
  262 + # vaudrait mieux préciser l'exception ici
  263 + except ValueError:
  264 + # Do nothing, normal string
  265 + config_attributes[field] = ast.literal_eval(value)
  266 + #new_plan_object.config_attributes[field] = config_attributes[field]
  267 + else:
  268 + # check min and max values if they exist
  269 + if max_value and min_value:
  270 + if plan_field["value"] > max_value:
  271 + result["errors"].append(f"Plan field {field} doesn't respect max value")
  272 + if plan_field["value"] < min_value:
  273 + result["errors"].append(f"Plan field {field} doesn't respect min value")
  274 + #new_plan_object.config_attributes[field] = plan_field["value"]
  275 + config_attributes[field] = plan_field["value"]
  276 +
  277 +
  278 +def prepare_check_plan_field_value(plan_field, field, result):
  279 + min_value = max_value = value_type = None
  280 + # get value type, min_value and max_value if they're in the plan form
  281 + if plan_field.get("value_type"):
  282 + value_type = plan_field["value_type"]
  283 + # If value type doesn't match with the value from the form, add an error to result
  284 + if type(plan_field["value"]) == str and ast.literal_eval(plan_field["value"]) != value_type:
  285 + result["errors"].append(f"Field {field} value doesn't correspond to the assigned type (type required : {value_type})")
  286 + if plan_field.get("min_value"):
  287 + min_value = plan_field["min_value"]
  288 + if type(min_value) == str:
  289 + min_value = ast.literal_eval(min_value)
  290 + if plan_field.get("max_value"):
  291 + max_value = plan_field["max_value"]
  292 + if type(max_value) == str:
  293 + max_value = ast.literal_eval(max_value)
  294 + return value_type, min_value, max_value
  295 +
  296 +
  297 +def process_sequence(yaml_content, seq, config, is_simplified, result, user_sp):
  298 +
  299 + # From user sp, get all SP that can observe / submit sequence for the current period
  300 + sp_list = ScientificProgram.objects.observable_programs().filter(id__in=user_sp)
  301 + # Create a Sequence form
  302 + sequence_form = SequenceForm(instance=seq, data_from_config=config.getEditableMountAttributes(config.unit_name), layouts = config.get_layouts(config.unit_name), sp_list=sp_list)
  303 +
  304 + if is_simplified:
  305 + seq.scientific_program = sp_list[yaml_content["sequence"]["scientific_program"]]
  306 + else:
  307 + # get scientific program field's attributes
  308 + yaml_seq_sp = yaml_content["sequence"]["scientific_program"]
  309 + sp_index_value = yaml_seq_sp["value"]
  310 + values = yaml_seq_sp["values"]
  311 + # Check if index of sp is valid (in range of possible index from values)
  312 + if sp_index_value < 0 or sp_index_value > len(values):
  313 + result["errors"].append(f"SP value isn't valid, index out of bounds ({sp_index_value} > {len(values)})")
  314 + sp_index_value = 0
  315 + chosen_sp = ScientificProgram.objects.get(name=values[sp_index_value])
  316 + # If the sp is associated to that user, associate the sp to the sequence
  317 + if chosen_sp in sp_list:
  318 + #seq.scientific_program = ScientificProgram.objects.get(name=yaml_content["sequence"]["scientific_program"]["values"][sp_index_value])
  319 + seq.scientific_program = chosen_sp
  320 + else:
  321 + result["errors"].append(f"SP {chosen_sp.name} is not assigned to that user ")
  322 +
  323 + seq.config_attributes = {}
  324 +
  325 + # Fill all Sequence form fields
  326 + #with silk_profile(name="iterate sequence fields form"):
  327 + for field, field_attributes in sequence_form.fields.items():
  328 + #if sequence_form.fields[field].required == False or field == "scientific_program":
  329 + if not field_attributes.required or field=="scientific_program":
  330 + continue
  331 + # pour lisibilité, simplicité et éviter redondance
  332 + yaml_field = yaml_content["sequence"][field]
  333 + value = yaml_field if is_simplified else yaml_field["value"]
  334 + ''' (orig)
  335 + if is_simplified:
  336 + value = yaml_content["sequence"][field]
  337 + else:
  338 + value = yaml_content["sequence"][field]["value"]
  339 + '''
  340 + # If the current field of the sequence isn't found in the file, add an error message to inform the user the missing field
  341 + if field not in yaml_content["sequence"]:
  342 + result["errors"].append(f"{field} not in yaml file")
  343 + else:
  344 + if is_simplified:
  345 + # If the field is a choicefield, get choices and associate the index to the real value
  346 + if sequence_form.fields[field].__dict__.get("_choices"):
  347 + # y a pas conflit ici avec la variable "value" définie au-dessus ? -> Non car on transforme l'ancien value qui est un index en une vraie valeur
  348 + values = [value[0] for value in sequence_form.fields[field].__dict__.get("_choices")]
  349 + value = values[value]
  350 + else:
  351 + if yaml_field.get("values"):
  352 + # Transform the original value which is an index to a "real" value from the "values" attributes
  353 + index_value = yaml_field["value"]
  354 + values = yaml_field["values"]
  355 + if index_value < 0 or index_value > len(yaml_field["values"]):
  356 + result["errors"].append(f"Value of {field} isn't valid, index out of bounds ({index_value} > {len(values)})")
  357 + index_value = 0
  358 + value = yaml_field["values"][index_value]
  359 + else:
  360 + # Transform the string value to a datetime value
  361 + if field == "start_date":
  362 + if type(value) != datetime.datetime:
  363 + #value = datetime.datetime.strptime(yaml_content["sequence"][field]["value"],'%d/%m/%Y %H:%M:%S')
  364 + # ISO format
  365 + value = datetime.datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%f')
  366 + seq.__dict__[field] = value
  367 + ''' (orig)
  368 + else:
  369 + if not is_simplified:
  370 + if yaml_content["sequence"][field].get("values"):
  371 + index_value = yaml_content["sequence"][field]["value"]
  372 + values = yaml_content["sequence"][field]["values"]
  373 + if index_value < 0 or index_value > len(yaml_content["sequence"][field]["values"]):
  374 + result["errors"].append(f"Value of {field} isn't valid, index out of bounds ({index_value} > {len(values)})")
  375 + index_value = 0
  376 + value = yaml_content["sequence"][field]["values"][index_value]
  377 + else:
  378 + if field == "start_date":
  379 + if type(value) != datetime.datetime:
  380 + #value = datetime.datetime.strptime(yaml_content["sequence"][field]["value"],'%d/%m/%Y %H:%M:%S')
  381 + # ISO format
  382 + value = datetime.datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%f')
  383 + seq.__dict__[field] = value
  384 + else:
  385 + if sequence_form.fields[field].__dict__.get("_choices"):
  386 + values = [value[0] for value in sequence_form.fields[field].__dict__.get("_choices")]
  387 + value = values[value]
  388 + '''
  389 +
  390 + # suffisant ? => if field in seq.__dict__
  391 + # If field is an attribute of the sequence, associate the field to the value
  392 + if field in seq.__dict__:
  393 + seq.__dict__[field] = value
  394 + else:
  395 + # else associate field & value in config_attributes sequence's field (JsonField) = variable fields of an sequence
  396 + seq.config_attributes[field] = value
  397 +
386 398
387 def create_sequence_pickle(sequence): 399 def create_sequence_pickle(sequence):
388 seq_dict = model_to_dict(sequence) 400 seq_dict = model_to_dict(sequence)
@@ -404,4 +416,6 @@ def create_sequence_pickle(sequence): @@ -404,4 +416,6 @@ def create_sequence_pickle(sequence):
404 if not os.path.exists(data_path +f"sequences_pickle/P{period.id}/{sequence.night_id}"): 416 if not os.path.exists(data_path +f"sequences_pickle/P{period.id}/{sequence.night_id}"):
405 os.mkdir(data_path +f"sequences_pickle/P{period.id}/{sequence.night_id}") 417 os.mkdir(data_path +f"sequences_pickle/P{period.id}/{sequence.night_id}")
406 seq_pickle_file_name = data_path +f"./sequences_pickle/P{period.id}/{sequence.night_id}/{sequence.id}.p" 418 seq_pickle_file_name = data_path +f"./sequences_pickle/P{period.id}/{sequence.night_id}/{sequence.id}.p"
  419 + # get guitastro ephemeris
  420 + #fullseq_dict["ephem"] = fn.ephem(sequence.target)
407 pickle.dump(fullseq_dict,open(seq_pickle_file_name,"wb")) 421 pickle.dump(fullseq_dict,open(seq_pickle_file_name,"wb"))
408 \ No newline at end of file 422 \ No newline at end of file