Commit 10252292b688d5588b9e64f5d3eca8cd5af6e4d7
1 parent
2c54f472
Exists in
dev
Change function to read sequence yml file to understand a simplified version
Showing
3 changed files
with
94 additions
and
72 deletions
Show diff stats
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: |