Commit 10252292b688d5588b9e64f5d3eca8cd5af6e4d7

Authored by Alexis Koralewski
1 parent 2c54f472
Exists in dev

Change function to read sequence yml file to understand a simplified version

src/core/pyros_django/api/views.py
1 from django.shortcuts import render 1 from django.shortcuts import render
2 from rest_framework.views import APIView 2 from rest_framework.views import APIView
3 -from rest_framework.response import Response 3 +from rest_framework.response import Response
4 from rest_framework import viewsets, renderers 4 from rest_framework import viewsets, renderers
5 from rest_framework.permissions import IsAuthenticated, AllowAny 5 from rest_framework.permissions import IsAuthenticated, AllowAny
6 from rest_framework.decorators import api_view, permission_classes, action 6 from rest_framework.decorators import api_view, permission_classes, action
@@ -11,7 +11,7 @@ from api.serializers import AgentSurveySerializer, AlbumSerializer, FullSequence @@ -11,7 +11,7 @@ from api.serializers import AgentSurveySerializer, AlbumSerializer, FullSequence
11 from common.models import PyrosUser, SP_Period, ScientificProgram, UserLevel, SP_Period_User, AgentSurvey, AgentCmd 11 from common.models import PyrosUser, SP_Period, ScientificProgram, UserLevel, SP_Period_User, AgentSurvey, AgentCmd
12 from routine_manager.models import Sequence, Album, Plan 12 from routine_manager.models import Sequence, Album, Plan
13 13
14 -from routine_manager.functions import check_sequence_file_validity 14 +from routine_manager.functions import check_sequence_file_validity_and_save
15 from rest_framework.request import Request 15 from rest_framework.request import Request
16 from django.db.models import Q 16 from django.db.models import Q
17 from datetime import datetime, timezone, timedelta 17 from datetime import datetime, timezone, timedelta
@@ -92,7 +92,8 @@ class SequenceViewSet(viewsets.ModelViewSet): @@ -92,7 +92,8 @@ class SequenceViewSet(viewsets.ModelViewSet):
92 if user_role in ("Unit-PI", "Admin"): 92 if user_role in ("Unit-PI", "Admin"):
93 return Sequence.objects.all().order_by("-updated") 93 return Sequence.objects.all().order_by("-updated")
94 else: 94 else:
95 - return Sequence.objects.filter(pyros_user=user).order_by("-updated") 95 + sp_of_user = user.get_scientific_program()
  96 + return Sequence.objects.filter(scientific_program__in=sp_of_user).order_by("-updated")
96 97
97 98
98 class ScientificProgramViewSet(viewsets.ModelViewSet): 99 class ScientificProgramViewSet(viewsets.ModelViewSet):
@@ -235,7 +236,7 @@ class PlanViewSet(viewsets.ModelViewSet): @@ -235,7 +236,7 @@ class PlanViewSet(viewsets.ModelViewSet):
235 @api_view(["PUT"]) 236 @api_view(["PUT"])
236 def submit_sequence_with_json(request): 237 def submit_sequence_with_json(request):
237 sequence_json = request.data 238 sequence_json = request.data
238 - response = check_sequence_file_validity(sequence_json, request) 239 + response = check_sequence_file_validity_and_save(sequence_json, request)
239 if response.get("succeed") == True: 240 if response.get("succeed") == True:
240 seq = Sequence.objects.get(id=response.get("sequence_id")) 241 seq = Sequence.objects.get(id=response.get("sequence_id"))
241 log.info( 242 log.info(
src/core/pyros_django/routine_manager/functions.py
@@ -7,7 +7,8 @@ import datetime @@ -7,7 +7,8 @@ import datetime
7 import os, yaml 7 import os, yaml
8 8
9 9
10 -def check_sequence_file_validity(yaml_content,request): 10 +def check_sequence_file_validity_and_save(yaml_content,request):
  11 + is_simplified = yaml_content.get("simplified", False)
11 sp_of_user = request.user.get_scientific_program() 12 sp_of_user = request.user.get_scientific_program()
12 sp_list = ScientificProgram.objects.observable_programs().filter(id__in=sp_of_user) 13 sp_list = ScientificProgram.objects.observable_programs().filter(id__in=sp_of_user)
13 seq = Sequence.objects.create() 14 seq = Sequence.objects.create()
@@ -19,39 +20,49 @@ def check_sequence_file_validity(yaml_content,request): @@ -19,39 +20,49 @@ def check_sequence_file_validity(yaml_content,request):
19 "succeed": True, 20 "succeed": True,
20 "errors": [], 21 "errors": [],
21 } 22 }
22 - index_value_sp = yaml_content["sequence"]["scientific_program"]["value"]  
23 - values = yaml_content["sequence"]["scientific_program"]["values"]  
24 - if index_value_sp < 0 or index_value_sp > len(yaml_content["sequence"]["scientific_program"]["values"]):  
25 - result["errors"].append(f"Value of scientific program isn't valid, index out of bounds ({index_value_sp} > {len(values)})")  
26 - index_value_sp = 0  
27 - chosen_sp = ScientificProgram.objects.get(name=yaml_content["sequence"]["scientific_program"]["values"][index_value_sp])  
28 - if chosen_sp in sp_list:  
29 - seq.scientific_program = ScientificProgram.objects.get(name=yaml_content["sequence"]["scientific_program"]["values"][index_value_sp]) 23 + if is_simplified:
  24 + seq.scientific_program = sp_list[yaml_content["sequence"]["scientific_program"]]
30 else: 25 else:
31 - result["errors"].append(f"Scientific program {chosen_sp.name} is not assigned to that user ") 26 + index_value_sp = yaml_content["sequence"]["scientific_program"]["value"]
  27 + values = yaml_content["sequence"]["scientific_program"]["values"]
  28 + if index_value_sp < 0 or index_value_sp > len(yaml_content["sequence"]["scientific_program"]["values"]):
  29 + result["errors"].append(f"Value of scientific program isn't valid, index out of bounds ({index_value_sp} > {len(values)})")
  30 + index_value_sp = 0
  31 + chosen_sp = ScientificProgram.objects.get(name=yaml_content["sequence"]["scientific_program"]["values"][index_value_sp])
  32 + if chosen_sp in sp_list:
  33 + seq.scientific_program = ScientificProgram.objects.get(name=yaml_content["sequence"]["scientific_program"]["values"][index_value_sp])
  34 + else:
  35 + result["errors"].append(f"Scientific program {chosen_sp.name} is not assigned to that user ")
32 seq.config_attributes = {} 36 seq.config_attributes = {}
33 for field in sequence_form.fields.keys(): 37 for field in sequence_form.fields.keys():
34 if sequence_form.fields[field].required == False or field == "scientific_program": 38 if sequence_form.fields[field].required == False or field == "scientific_program":
35 continue 39 continue
36 - value = yaml_content["sequence"][field]["value"] 40 + if is_simplified:
  41 + value = yaml_content["sequence"][field]
  42 + else:
  43 + value = yaml_content["sequence"][field]["value"]
37 if field not in yaml_content["sequence"]: 44 if field not in yaml_content["sequence"]:
38 result["errors"].append(f"{field} not in yaml file") 45 result["errors"].append(f"{field} not in yaml file")
39 else: 46 else:
40 - if yaml_content["sequence"][field].get("values"):  
41 - index_value = yaml_content["sequence"][field]["value"]  
42 - values = yaml_content["sequence"][field]["values"]  
43 - if index_value < 0 or index_value > len(yaml_content["sequence"][field]["values"]):  
44 - result["errors"].append(f"Value of {field} isn't valid, index out of bounds ({index_value} > {len(values)})")  
45 - index_value = 0  
46 - value = yaml_content["sequence"][field]["values"][index_value] 47 + if not is_simplified:
  48 + if yaml_content["sequence"][field].get("values"):
  49 + index_value = yaml_content["sequence"][field]["value"]
  50 + values = yaml_content["sequence"][field]["values"]
  51 + if index_value < 0 or index_value > len(yaml_content["sequence"][field]["values"]):
  52 + result["errors"].append(f"Value of {field} isn't valid, index out of bounds ({index_value} > {len(values)})")
  53 + index_value = 0
  54 + value = yaml_content["sequence"][field]["values"][index_value]
  55 + else:
  56 + if field == "start_date":
  57 + if type(value) != datetime.datetime:
  58 + #value = datetime.datetime.strptime(yaml_content["sequence"][field]["value"],'%d/%m/%Y %H:%M:%S')
  59 + # ISO format
  60 + value = datetime.datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%f')
  61 + seq.__dict__[field] = value
47 else: 62 else:
48 - if field == "start_date":  
49 - if type(yaml_content["sequence"][field]["value"]) != datetime.datetime:  
50 - #value = datetime.datetime.strptime(yaml_content["sequence"][field]["value"],'%d/%m/%Y %H:%M:%S')  
51 - # ISO format  
52 - value = datetime.datetime.strptime(yaml_content["sequence"][field]["value"],'%Y-%m/%dT%H:%M:%S.%f')  
53 - seq.__dict__[field] = value  
54 - continue 63 + if sequence_form.fields[field].__dict__.get("_choices"):
  64 + values = [value[0] for value in sequence_form.fields[field].__dict__.get("_choices")]
  65 + value = values[value]
55 if field in seq.__dict__.keys(): 66 if field in seq.__dict__.keys():
56 seq.__dict__[field] = value 67 seq.__dict__[field] = value
57 else: 68 else:
@@ -92,48 +103,55 @@ def check_sequence_file_validity(yaml_content,request): @@ -92,48 +103,55 @@ def check_sequence_file_validity(yaml_content,request):
92 result["errors"].append(f"Missing field : '{field}' for plan {plans.index(plan)}") 103 result["errors"].append(f"Missing field : '{field}' for plan {plans.index(plan)}")
93 else: 104 else:
94 # TODO : ajouter max_value, min_value, suppression plan et album si invalides 105 # TODO : ajouter max_value, min_value, suppression plan et album si invalides
95 - if plan[field].get("value_type"):  
96 - value_type = plan[field]["value_type"]  
97 - if type(plan[field]["value"]) == str and ast.literal_eval(plan[field]["value"]) != value_type:  
98 - result["errors"].append(f"Field {field} value doesn't correspond to the assigned type (type required : {value_type})")  
99 - if plan[field].get("min_value"):  
100 - if type(plan[field]["min_value"]) == str:  
101 - min_value = ast.literal_eval(plan[field]["min_value"])  
102 - else:  
103 - min_value = plan[field]["min_value"]  
104 - if plan[field].get("max_value"):  
105 - if type(plan[field].get("max_value")) == str:  
106 - max_value = ast.literal_eval(plan[field]["max_value"])  
107 - else:  
108 - max_value = plan[field]["max_value"] 106 + if not is_simplified:
  107 + if plan[field].get("value_type"):
  108 + value_type = plan[field]["value_type"]
  109 + if type(plan[field]["value"]) == str and ast.literal_eval(plan[field]["value"]) != value_type:
  110 + result["errors"].append(f"Field {field} value doesn't correspond to the assigned type (type required : {value_type})")
  111 + if plan[field].get("min_value"):
  112 + if type(plan[field]["min_value"]) == str:
  113 + min_value = ast.literal_eval(plan[field]["min_value"])
  114 + else:
  115 + min_value = plan[field]["min_value"]
  116 + if plan[field].get("max_value"):
  117 + if type(plan[field].get("max_value")) == str:
  118 + max_value = ast.literal_eval(plan[field]["max_value"])
  119 + else:
  120 + max_value = plan[field]["max_value"]
109 if field == "nb_images": 121 if field == "nb_images":
110 - new_plan_object.__dict__[field] = plan[field]["value"] 122 + if is_simplified:
  123 + new_plan_object.__dict__[field] = plan[field]
  124 + else:
  125 + new_plan_object.__dict__[field] = plan[field]["value"]
111 else: 126 else:
112 - if plan[field].get("values"):  
113 - index_value = plan[field]["value"]  
114 - values = plan[field]["values"]  
115 - if index_value < 0 or index_value > len(plan[field]["values"]):  
116 - result["errors"].append(f"Value of Plan field '{field}' isn't valid, index out of bounds ({index_value} > {len(values)})")  
117 - index_value = 0  
118 - value = plan[field]["values"][index_value]  
119 - try:  
120 - # linked values  
121 - splitted_values = value.split(";")  
122 - config_attributes[field] = {}  
123 - for splitted_value in splitted_values:  
124 - subkey,subvalue = splitted_value.split(":")  
125 - config_attributes[field][subkey] = ast.literal_eval(subvalue)  
126 - except:  
127 - # Do nothing, normal string  
128 - config_attributes[field] = ast.literal_eval(value)  
129 - new_plan_object.config_attributes[field] = config_attributes[field] 127 + if not is_simplified:
  128 + if plan[field].get("values"):
  129 + index_value = plan[field]["value"]
  130 + values = plan[field]["values"]
  131 + if index_value < 0 or index_value > len(plan[field]["values"]):
  132 + result["errors"].append(f"Value of Plan field '{field}' isn't valid, index out of bounds ({index_value} > {len(values)})")
  133 + index_value = 0
  134 + value = plan[field]["values"][index_value]
  135 + try:
  136 + # linked values
  137 + splitted_values = value.split(";")
  138 + config_attributes[field] = {}
  139 + for splitted_value in splitted_values:
  140 + subkey,subvalue = splitted_value.split(":")
  141 + config_attributes[field][subkey] = ast.literal_eval(subvalue)
  142 + except:
  143 + # Do nothing, normal string
  144 + config_attributes[field] = ast.literal_eval(value)
  145 + new_plan_object.config_attributes[field] = config_attributes[field]
  146 + else:
  147 + if max_value and min_value:
  148 + if plan[field]["value"] > max_value:
  149 + result["errors"].append(f"Plan field {field} doesn't respect max value")
  150 + if plan[field]["value"] < min_value:
  151 + result["errors"].append(f"Plan field {field} doesn't respect min value")
  152 + new_plan_object.config_attributes[field] = plan[field]["value"]
130 else: 153 else:
131 - if max_value and min_value:  
132 - if plan[field]["value"] > max_value:  
133 - result["errors"].append(f"Plan field {field} doesn't respect max value")  
134 - if plan[field]["value"] < min_value:  
135 - result["errors"].append(f"Plan field {field} doesn't respect min value")  
136 - new_plan_object.config_attributes[field] = plan[field]["value"] 154 + new_plan_object.config_attributes[field] = plan[field]
137 new_plan_object.save() 155 new_plan_object.save()
138 156
139 157
src/core/pyros_django/routine_manager/views.py
@@ -28,7 +28,7 @@ from .forms import SequenceForm, AlbumForm, PlanForm, uneditablePlanForm @@ -28,7 +28,7 @@ from .forms import SequenceForm, AlbumForm, PlanForm, uneditablePlanForm
28 #from .forms import RequestForm, SequenceForm, AlbumForm, PlanForm, uneditablePlanForm 28 #from .forms import RequestForm, SequenceForm, AlbumForm, PlanForm, uneditablePlanForm
29 29
30 from .validators import check_plan_validity, check_album_validity, check_sequence_validity, check_request_validity 30 from .validators import check_plan_validity, check_album_validity, check_sequence_validity, check_request_validity
31 -from .functions import check_sequence_file_validity 31 +from .functions import check_sequence_file_validity_and_save
32 from .RequestSerializer import RequestSerializer 32 from .RequestSerializer import RequestSerializer
33 import scheduler 33 import scheduler
34 from django.contrib import messages 34 from django.contrib import messages
@@ -854,7 +854,7 @@ def import_sequence(request): @@ -854,7 +854,7 @@ def import_sequence(request):
854 message = "File is too big (more than 1 000 000 bytes)" 854 message = "File is too big (more than 1 000 000 bytes)"
855 else: 855 else:
856 yaml_content = yaml.safe_load(file.read()) 856 yaml_content = yaml.safe_load(file.read())
857 - import_response = check_sequence_file_validity( 857 + import_response = check_sequence_file_validity_and_save(
858 yaml_content, request) 858 yaml_content, request)
859 if import_response["succeed"]: 859 if import_response["succeed"]:
860 message = "Request imported successfully. Please check it before submitting for scheduling." 860 message = "Request imported successfully. Please check it before submitting for scheduling."
@@ -896,10 +896,13 @@ def export_sequence(request, seq_id: int, type: str): @@ -896,10 +896,13 @@ def export_sequence(request, seq_id: int, type: str):
896 elif field == "start_date": 896 elif field == "start_date":
897 #field_dict["value"] = seq.start_date.strftime("%d/%m/%Y %H:%M:%S") 897 #field_dict["value"] = seq.start_date.strftime("%d/%m/%Y %H:%M:%S")
898 # ISO format 898 # ISO format
899 - field_dict["value"] = seq.start_date.strftime("Y-%m/%dT%H:%M:%S.%f") 899 + field_dict["value"] = seq.start_date.strftime("%Y-%m-%dT%H:%M:%S.%f")
900 field_dict["value_type"] = "str" 900 field_dict["value_type"] = "str"
901 else: 901 else:
902 - field_dict["value_type"] = sequence_form.fields[field].widget.input_type 902 + if hasattr(sequence_form.fields[field].widget,"input_type"):
  903 + field_dict["value_type"] = sequence_form.fields[field].widget.input_type
  904 + else:
  905 + field_dict["value_type"] = "str"
903 if seq.__dict__.get(field) == None: 906 if seq.__dict__.get(field) == None:
904 value = seq.config_attributes.get(field) 907 value = seq.config_attributes.get(field)
905 else: 908 else: