plexus-python-pulse-demeter 1.1.126__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. plexus/pulse/demeter/__init__.py +6 -0
  2. plexus/pulse/demeter/app/__init__.py +0 -0
  3. plexus/pulse/demeter/app/api/__init__.py +44 -0
  4. plexus/pulse/demeter/app/api/archive_internal_endpoints.py +316 -0
  5. plexus/pulse/demeter/app/api/archive_public_endpoints.py +255 -0
  6. plexus/pulse/demeter/app/api/dataset_internal_endpoints.py +1043 -0
  7. plexus/pulse/demeter/app/api/dataset_public_endpoints.py +2161 -0
  8. plexus/pulse/demeter/app/api/dataset_workflow_endpoints.py +532 -0
  9. plexus/pulse/demeter/app/api/tagging_endpoints.py +323 -0
  10. plexus/pulse/demeter/app/api/user_endpoints.py +78 -0
  11. plexus/pulse/demeter/app/core/__init__.py +0 -0
  12. plexus/pulse/demeter/app/core/database.py +43 -0
  13. plexus/pulse/demeter/app/core/vault.py +29 -0
  14. plexus/pulse/demeter/app/main.py +16 -0
  15. plexus/pulse/demeter/app/models/__init__.py +33 -0
  16. plexus/pulse/demeter/app/models/local.py +249 -0
  17. plexus/pulse/demeter/app/models/registry/__init__.py +112 -0
  18. plexus/pulse/demeter/app/models/registry/archive.py +529 -0
  19. plexus/pulse/demeter/app/models/registry/dataset.py +1531 -0
  20. plexus/pulse/demeter/app/models/registry/tagging.py +478 -0
  21. plexus/pulse/demeter/app/models/registry/user.py +79 -0
  22. plexus/pulse/demeter/tools/__init__.py +0 -0
  23. plexus/pulse/demeter/tools/main.py +306 -0
  24. plexus/pulse/demeter/utils/__init__.py +0 -0
  25. plexus/pulse/demeter/utils/config.py +25 -0
  26. plexus/pulse/demeter/utils/datautils.py +436 -0
  27. plexus_python_pulse_demeter-1.1.126.dist-info/METADATA +36 -0
  28. plexus_python_pulse_demeter-1.1.126.dist-info/RECORD +31 -0
  29. plexus_python_pulse_demeter-1.1.126.dist-info/WHEEL +5 -0
  30. plexus_python_pulse_demeter-1.1.126.dist-info/entry_points.txt +2 -0
  31. plexus_python_pulse_demeter-1.1.126.dist-info/top_level.txt +1 -0
@@ -0,0 +1,532 @@
1
+ import datetime
2
+ import uuid as py_uuid
3
+
4
+ import pydantic as pdt
5
+ import sqlalchemy.exc as sa_exc
6
+ import sqlalchemy.orm as sa_orm
7
+ from fastapi import APIRouter, Depends
8
+ from fastapi.params import Body, Query
9
+ from plexus.common.utils.jsonutils import JsonObject
10
+ from plexus.pulse.common.utils.apiutils import managed_db_session
11
+ from plexus.pulse.common.utils.ormutils import (
12
+ clone_revision_model_instance,
13
+ db_create_revision_model,
14
+ db_update_revision_model,
15
+ model_name_of,
16
+ )
17
+
18
+ from plexus.pulse.demeter.app.api import current_dt_clock
19
+ from plexus.pulse.demeter.app.core.database import make_session
20
+ from plexus.pulse.demeter.app.models.registry import JobStatusFlag
21
+ from plexus.pulse.demeter.app.models.registry.dataset import (
22
+ DatasetPromotion as DatasetPromotion,
23
+ DatasetRegistration as Registration,
24
+ ModelAssessment as Assessment,
25
+ ModelAssessmentPromotion as AssessmentPromotion,
26
+ ModelEvaluation as Evaluation,
27
+ ModelExperiment as Experiment,
28
+ ModelExperimentPromotion as ExperimentPromotion,
29
+ ModelTraining as Training,
30
+ RegisteredDataset as Dataset,
31
+ )
32
+ from plexus.pulse.demeter.app.models.registry.dataset import (
33
+ DatasetPromotionTable as DatasetPromotionTable,
34
+ DatasetRegistrationTable as RegistrationTable,
35
+ ModelAssessmentPromotionTable as AssessmentPromotionTable,
36
+ ModelAssessmentTable as AssessmentTable,
37
+ ModelEvaluationTable as EvaluationTable,
38
+ ModelExperimentPromotionTable as ExperimentPromotionTable,
39
+ ModelExperimentTable as ExperimentTable,
40
+ ModelTrainingTable as TrainingTable,
41
+ RegisteredDatasetTable as DatasetTable,
42
+ )
43
+
44
+ router = APIRouter(prefix="/pulse_demeter/dataset_workflow", tags=["dataset_workflow"])
45
+
46
+
47
+ class RegistrationRequest(pdt.BaseModel):
48
+ uuid: py_uuid.UUID = pdt.Field(default_factory=py_uuid.uuid4)
49
+ resource_path: str
50
+ props: JsonObject = None
51
+ dataset: Dataset
52
+
53
+
54
+ class RegistrationTableAndDatasetTable(pdt.BaseModel):
55
+ registration: RegistrationTable
56
+ dataset: DatasetTable
57
+
58
+
59
+ @router.post("/submit_dataset_registration/", response_model=RegistrationTableAndDatasetTable)
60
+ def submit_dataset_registration(
61
+ request: RegistrationRequest = Body(),
62
+ current_dt: datetime.datetime = Depends(current_dt_clock),
63
+ db: sa_orm.Session = Depends(make_session),
64
+ ) -> RegistrationTableAndDatasetTable:
65
+ with managed_db_session(db):
66
+ db_dataset = db_create_revision_model(db, DatasetTable, request.dataset, current_dt)
67
+ registration = Registration(uuid=request.uuid,
68
+ dataset_uuid=db_dataset.uuid,
69
+ resource_path=request.resource_path,
70
+ props=request.props)
71
+ db_registration = db_create_revision_model(db, RegistrationTable, registration, current_dt)
72
+
73
+ return RegistrationTableAndDatasetTable(registration=db_registration, dataset=db_dataset)
74
+
75
+
76
+ @router.put("/mark_dataset_registration/", response_model=RegistrationTableAndDatasetTable)
77
+ def mark_dataset_registration(
78
+ uuid: py_uuid.UUID = Query(),
79
+ flags: int = Query(0),
80
+ current_dt: datetime.datetime = Depends(current_dt_clock),
81
+ db: sa_orm.Session = Depends(make_session),
82
+ ) -> RegistrationTableAndDatasetTable:
83
+ with managed_db_session(db):
84
+ db_registration = (
85
+ db
86
+ .query(RegistrationTable)
87
+ .where(RegistrationTable.expired_at.is_(None), RegistrationTable.uuid == uuid)
88
+ .one_or_none()
89
+ )
90
+ if db_registration is None:
91
+ raise sa_exc.NoResultFound(f"'{model_name_of(RegistrationTable)}' with uuid '{uuid}' not found")
92
+
93
+ registration = clone_revision_model_instance(RegistrationTable, db_registration, clear_meta_fields=False)
94
+ if registration.flags != flags:
95
+ registration.flags = flags
96
+ db_registration = db_update_revision_model(db,
97
+ RegistrationTable,
98
+ registration,
99
+ registration.record_sqn,
100
+ current_dt)
101
+
102
+ db_dataset = (
103
+ db
104
+ .query(DatasetTable)
105
+ .where(DatasetTable.expired_at.is_(None), DatasetTable.uuid == db_registration.dataset_uuid)
106
+ .one_or_none()
107
+ )
108
+ if db_dataset is None:
109
+ raise sa_exc.NoResultFound(
110
+ f"'{model_name_of(DatasetTable)}' with uuid '{db_registration.dataset_uuid}' not found")
111
+
112
+ return RegistrationTableAndDatasetTable(registration=db_registration, dataset=db_dataset)
113
+
114
+
115
+ @router.put("/finish_dataset_registration/", response_model=RegistrationTableAndDatasetTable)
116
+ def finish_dataset_registration(
117
+ uuid: py_uuid.UUID = Query(),
118
+ current_dt: datetime.datetime = Depends(current_dt_clock),
119
+ db: sa_orm.Session = Depends(make_session),
120
+ ) -> RegistrationTableAndDatasetTable:
121
+ return mark_dataset_registration(uuid=uuid, flags=JobStatusFlag.Completed.value, current_dt=current_dt, db=db)
122
+
123
+
124
+ @router.put("/fail_dataset_registration/", response_model=RegistrationTableAndDatasetTable)
125
+ def fail_dataset_registration(
126
+ uuid: py_uuid.UUID = Query(),
127
+ current_dt: datetime.datetime = Depends(current_dt_clock),
128
+ db: sa_orm.Session = Depends(make_session),
129
+ ) -> RegistrationTableAndDatasetTable:
130
+ return mark_dataset_registration(uuid=uuid, flags=JobStatusFlag.Failed.value, current_dt=current_dt, db=db)
131
+
132
+
133
+ @router.post("/submit_dataset_promotion/", response_model=DatasetPromotionTable)
134
+ def submit_dataset_promotion(
135
+ uuid: py_uuid.UUID = Query(default_factory=py_uuid.uuid4),
136
+ dataset_uuid: py_uuid.UUID = Query(),
137
+ reviewer_sso_sid: int = Query(),
138
+ props: JsonObject | None = Query(default_factory=dict),
139
+ current_dt: datetime.datetime = Depends(current_dt_clock),
140
+ db: sa_orm.Session = Depends(make_session),
141
+ ) -> DatasetPromotionTable:
142
+ with managed_db_session(db):
143
+ promotion = DatasetPromotion(
144
+ uuid=uuid,
145
+ dataset_uuid=dataset_uuid,
146
+ reviewer_sso_sid=reviewer_sso_sid,
147
+ props=props,
148
+ )
149
+ return db_create_revision_model(db, DatasetPromotionTable, promotion, current_dt)
150
+
151
+
152
+ @router.put("/mark_dataset_promotion/", response_model=DatasetPromotionTable)
153
+ def mark_dataset_promotion(
154
+ uuid: py_uuid.UUID = Query(),
155
+ flags: int = Query(0),
156
+ current_dt: datetime.datetime = Depends(current_dt_clock),
157
+ db: sa_orm.Session = Depends(make_session),
158
+ ) -> DatasetPromotionTable:
159
+ with managed_db_session(db):
160
+ db_promotion = (
161
+ db
162
+ .query(DatasetPromotionTable)
163
+ .where(DatasetPromotionTable.expired_at.is_(None), DatasetPromotionTable.uuid == uuid)
164
+ .one_or_none()
165
+ )
166
+ if db_promotion is None:
167
+ raise sa_exc.NoResultFound(f"'{model_name_of(DatasetPromotionTable)}' with uuid '{uuid}' not found")
168
+
169
+ promotion = clone_revision_model_instance(DatasetPromotionTable, db_promotion, clear_meta_fields=False)
170
+ if promotion.flags != flags:
171
+ promotion.flags = flags
172
+ db_promotion = db_update_revision_model(db,
173
+ DatasetPromotionTable,
174
+ promotion,
175
+ promotion.record_sqn,
176
+ current_dt)
177
+
178
+ return db_promotion
179
+
180
+
181
+ @router.put("/finish_dataset_promotion/", response_model=DatasetPromotionTable)
182
+ def finish_dataset_promotion(
183
+ uuid: py_uuid.UUID = Query(),
184
+ current_dt: datetime.datetime = Depends(current_dt_clock),
185
+ db: sa_orm.Session = Depends(make_session),
186
+ ) -> DatasetPromotionTable:
187
+ return mark_dataset_promotion(uuid=uuid, flags=JobStatusFlag.Completed.value, current_dt=current_dt, db=db)
188
+
189
+
190
+ @router.put("/fail_dataset_promotion/", response_model=DatasetPromotionTable)
191
+ def fail_dataset_promotion(
192
+ uuid: py_uuid.UUID = Query(),
193
+ current_dt: datetime.datetime = Depends(current_dt_clock),
194
+ db: sa_orm.Session = Depends(make_session),
195
+ ) -> DatasetPromotionTable:
196
+ return mark_dataset_promotion(uuid=uuid, flags=JobStatusFlag.Failed.value, current_dt=current_dt, db=db)
197
+
198
+
199
+ class TrainingRequest(pdt.BaseModel):
200
+ uuid: py_uuid.UUID = pdt.Field(default_factory=py_uuid.uuid4)
201
+ props: JsonObject = None
202
+ experiment: Experiment
203
+
204
+
205
+ class TrainingTableAndExperimentTable(pdt.BaseModel):
206
+ training: TrainingTable
207
+ experiment: ExperimentTable
208
+
209
+
210
+ @router.post("/submit_model_training/", response_model=TrainingTableAndExperimentTable)
211
+ def submit_model_training(
212
+ request: TrainingRequest = Body(),
213
+ current_dt: datetime.datetime = Depends(current_dt_clock),
214
+ db: sa_orm.Session = Depends(make_session),
215
+ ) -> TrainingTableAndExperimentTable:
216
+ with managed_db_session(db):
217
+ db_experiment = db_create_revision_model(db, ExperimentTable, request.experiment, current_dt)
218
+ training = Training(uuid=request.uuid, experiment_uuid=db_experiment.uuid, props=request.props)
219
+ db_training = db_create_revision_model(db, TrainingTable, training, current_dt)
220
+
221
+ return TrainingTableAndExperimentTable(training=db_training, experiment=db_experiment)
222
+
223
+
224
+ @router.put("/mark_model_training/", response_model=TrainingTableAndExperimentTable)
225
+ def mark_model_training(
226
+ uuid: py_uuid.UUID = Query(),
227
+ flags: int = Query(0),
228
+ current_dt: datetime.datetime = Depends(current_dt_clock),
229
+ db: sa_orm.Session = Depends(make_session),
230
+ ) -> TrainingTableAndExperimentTable:
231
+ with managed_db_session(db):
232
+ db_training = (
233
+ db
234
+ .query(TrainingTable)
235
+ .where(TrainingTable.expired_at.is_(None), TrainingTable.uuid == uuid)
236
+ .one_or_none()
237
+ )
238
+ if db_training is None:
239
+ raise sa_exc.NoResultFound(f"'{model_name_of(TrainingTable)}' with uuid '{uuid}' not found")
240
+
241
+ training = clone_revision_model_instance(TrainingTable, db_training, clear_meta_fields=False)
242
+ if training.flags != flags:
243
+ training.flags = flags
244
+ db_training = db_update_revision_model(db, TrainingTable, training, training.record_sqn, current_dt)
245
+
246
+ db_experiment = (
247
+ db
248
+ .query(ExperimentTable)
249
+ .where(ExperimentTable.expired_at.is_(None), ExperimentTable.uuid == db_training.experiment_uuid)
250
+ .one_or_none()
251
+ )
252
+ if db_experiment is None:
253
+ raise sa_exc.NoResultFound(
254
+ f"'{model_name_of(ExperimentTable)}' with uuid '{db_training.experiment_uuid}' not found")
255
+
256
+ return TrainingTableAndExperimentTable(training=db_training, experiment=db_experiment)
257
+
258
+
259
+ class ExperimentResult(pdt.BaseModel):
260
+ path: str
261
+ checkpoint_path: str
262
+
263
+
264
+ @router.put("/finish_model_training/", response_model=TrainingTableAndExperimentTable)
265
+ def finish_model_training(
266
+ uuid: py_uuid.UUID = Query(),
267
+ result: ExperimentResult = Body(),
268
+ current_dt: datetime.datetime = Depends(current_dt_clock),
269
+ db: sa_orm.Session = Depends(make_session),
270
+ ) -> TrainingTableAndExperimentTable:
271
+ with managed_db_session(db):
272
+ training_and_experiment = mark_model_training(uuid=uuid,
273
+ flags=JobStatusFlag.Completed.value,
274
+ current_dt=current_dt,
275
+ db=db)
276
+
277
+ experiment = clone_revision_model_instance(ExperimentTable,
278
+ training_and_experiment.experiment,
279
+ clear_meta_fields=False)
280
+ experiment.path = result.path
281
+ experiment.checkpoint_path = result.checkpoint_path
282
+ db_experiment = db_update_revision_model(db,
283
+ ExperimentTable,
284
+ experiment,
285
+ experiment.record_sqn,
286
+ current_dt)
287
+
288
+ return TrainingTableAndExperimentTable(training=training_and_experiment.training,
289
+ experiment=db_experiment)
290
+
291
+
292
+ @router.put("/fail_model_training/", response_model=TrainingTableAndExperimentTable)
293
+ def fail_model_training(
294
+ uuid: py_uuid.UUID = Query(),
295
+ current_dt: datetime.datetime = Depends(current_dt_clock),
296
+ db: sa_orm.Session = Depends(make_session),
297
+ ) -> TrainingTableAndExperimentTable:
298
+ return mark_model_training(uuid=uuid, flags=JobStatusFlag.Failed.value, current_dt=current_dt, db=db)
299
+
300
+
301
+ @router.post("/submit_experiment_promotion/", response_model=ExperimentPromotionTable)
302
+ def submit_experiment_promotion(
303
+ uuid: py_uuid.UUID = Query(default_factory=py_uuid.uuid4),
304
+ experiment_uuid: py_uuid.UUID = Query(),
305
+ reviewer_sso_sid: int = Query(),
306
+ props: JsonObject | None = Query(default_factory=dict),
307
+ current_dt: datetime.datetime = Depends(current_dt_clock),
308
+ db: sa_orm.Session = Depends(make_session),
309
+ ) -> ExperimentPromotionTable:
310
+ with managed_db_session(db):
311
+ promotion = ExperimentPromotion(
312
+ uuid=uuid,
313
+ experiment_uuid=experiment_uuid,
314
+ reviewer_sso_sid=reviewer_sso_sid,
315
+ props=props,
316
+ )
317
+ return db_create_revision_model(db, ExperimentPromotionTable, promotion, current_dt)
318
+
319
+
320
+ @router.put("/mark_experiment_promotion/", response_model=ExperimentPromotionTable)
321
+ def mark_experiment_promotion(
322
+ uuid: py_uuid.UUID = Query(),
323
+ flags: int = Query(0),
324
+ current_dt: datetime.datetime = Depends(current_dt_clock),
325
+ db: sa_orm.Session = Depends(make_session),
326
+ ) -> ExperimentPromotionTable:
327
+ with managed_db_session(db):
328
+ db_promotion = (
329
+ db
330
+ .query(ExperimentPromotionTable)
331
+ .where(ExperimentPromotionTable.expired_at.is_(None), ExperimentPromotionTable.uuid == uuid)
332
+ .one_or_none()
333
+ )
334
+ if db_promotion is None:
335
+ raise sa_exc.NoResultFound(f"'{model_name_of(ExperimentPromotionTable)}' with uuid '{uuid}' not found")
336
+
337
+ promotion = clone_revision_model_instance(ExperimentPromotionTable, db_promotion, clear_meta_fields=False)
338
+ if promotion.flags != flags:
339
+ promotion.flags = flags
340
+ db_promotion = db_update_revision_model(db,
341
+ ExperimentPromotionTable,
342
+ promotion,
343
+ promotion.record_sqn,
344
+ current_dt)
345
+
346
+ return db_promotion
347
+
348
+
349
+ @router.put("/finish_experiment_promotion/", response_model=ExperimentPromotionTable)
350
+ def finish_experiment_promotion(
351
+ uuid: py_uuid.UUID = Query(),
352
+ current_dt: datetime.datetime = Depends(current_dt_clock),
353
+ db: sa_orm.Session = Depends(make_session),
354
+ ) -> ExperimentPromotionTable:
355
+ return mark_experiment_promotion(uuid=uuid, flags=JobStatusFlag.Completed.value, current_dt=current_dt, db=db)
356
+
357
+
358
+ @router.put("/fail_experiment_promotion/", response_model=ExperimentPromotionTable)
359
+ def fail_experiment_promotion(
360
+ uuid: py_uuid.UUID = Query(),
361
+ current_dt: datetime.datetime = Depends(current_dt_clock),
362
+ db: sa_orm.Session = Depends(make_session),
363
+ ) -> ExperimentPromotionTable:
364
+ return mark_experiment_promotion(uuid=uuid, flags=JobStatusFlag.Failed.value, current_dt=current_dt, db=db)
365
+
366
+
367
+ class EvaluationRequest(pdt.BaseModel):
368
+ uuid: py_uuid.UUID = pdt.Field(default_factory=py_uuid.uuid4)
369
+ props: JsonObject = None
370
+ assessment: Assessment
371
+
372
+
373
+ class EvaluationTableAndAssessmentTable(pdt.BaseModel):
374
+ evaluation: EvaluationTable
375
+ assessment: AssessmentTable
376
+
377
+
378
+ @router.post("/submit_model_evaluation/", response_model=EvaluationTableAndAssessmentTable)
379
+ def submit_model_evaluation(
380
+ request: EvaluationRequest = Body(),
381
+ current_dt: datetime.datetime = Depends(current_dt_clock),
382
+ db: sa_orm.Session = Depends(make_session),
383
+ ) -> EvaluationTableAndAssessmentTable:
384
+ with managed_db_session(db):
385
+ db_assessment = db_create_revision_model(db, AssessmentTable, request.assessment, current_dt)
386
+ evaluation = Evaluation(uuid=request.uuid, assessment_uuid=db_assessment.uuid, props=request.props)
387
+ db_evaluation = db_create_revision_model(db, EvaluationTable, evaluation, current_dt)
388
+
389
+ return EvaluationTableAndAssessmentTable(evaluation=db_evaluation, assessment=db_assessment)
390
+
391
+
392
+ @router.put("/mark_model_evaluation/", response_model=EvaluationTableAndAssessmentTable)
393
+ def mark_model_evaluation(
394
+ uuid: py_uuid.UUID = Query(),
395
+ flags: int = Query(0),
396
+ current_dt: datetime.datetime = Depends(current_dt_clock),
397
+ db: sa_orm.Session = Depends(make_session),
398
+ ) -> EvaluationTableAndAssessmentTable:
399
+ with managed_db_session(db):
400
+ db_evaluation = (
401
+ db
402
+ .query(EvaluationTable)
403
+ .where(EvaluationTable.expired_at.is_(None), EvaluationTable.uuid == uuid)
404
+ .one_or_none()
405
+ )
406
+ if db_evaluation is None:
407
+ raise sa_exc.NoResultFound(f"'{model_name_of(EvaluationTable)}' with uuid '{uuid}' not found")
408
+
409
+ evaluation = clone_revision_model_instance(EvaluationTable, db_evaluation, clear_meta_fields=False)
410
+ if evaluation.flags != flags:
411
+ evaluation.flags = flags
412
+ db_evaluation = db_update_revision_model(db, EvaluationTable, evaluation, evaluation.record_sqn, current_dt)
413
+
414
+ db_assessment = (
415
+ db
416
+ .query(AssessmentTable)
417
+ .where(AssessmentTable.expired_at.is_(None), AssessmentTable.uuid == db_evaluation.assessment_uuid)
418
+ .one_or_none()
419
+ )
420
+ if db_assessment is None:
421
+ raise sa_exc.NoResultFound(
422
+ f"'{model_name_of(AssessmentTable)}' with uuid '{db_evaluation.assessment_uuid}' not found")
423
+
424
+ return EvaluationTableAndAssessmentTable(evaluation=db_evaluation, assessment=db_assessment)
425
+
426
+
427
+ class AssessmentResult(pdt.BaseModel):
428
+ path: str
429
+ assessment_data: JsonObject
430
+
431
+
432
+ @router.put("/finish_model_evaluation/", response_model=EvaluationTableAndAssessmentTable)
433
+ def finish_model_evaluation(
434
+ uuid: py_uuid.UUID = Query(),
435
+ result: AssessmentResult = Body(),
436
+ current_dt: datetime.datetime = Depends(current_dt_clock),
437
+ db: sa_orm.Session = Depends(make_session),
438
+ ) -> EvaluationTableAndAssessmentTable:
439
+ with managed_db_session(db):
440
+ evaluation_and_assessment = mark_model_evaluation(uuid=uuid,
441
+ flags=JobStatusFlag.Completed.value,
442
+ current_dt=current_dt,
443
+ db=db)
444
+
445
+ assessment = clone_revision_model_instance(AssessmentTable,
446
+ evaluation_and_assessment.assessment,
447
+ clear_meta_fields=False)
448
+ assessment.path = result.path
449
+ assessment.assessment_data = result.assessment_data
450
+ db_assessment = db_update_revision_model(db,
451
+ AssessmentTable,
452
+ assessment,
453
+ assessment.record_sqn,
454
+ current_dt)
455
+
456
+ return EvaluationTableAndAssessmentTable(evaluation=evaluation_and_assessment.evaluation,
457
+ assessment=db_assessment)
458
+
459
+
460
+ @router.put("/fail_model_evaluation/", response_model=EvaluationTableAndAssessmentTable)
461
+ def fail_model_evaluation(
462
+ uuid: py_uuid.UUID = Query(),
463
+ current_dt: datetime.datetime = Depends(current_dt_clock),
464
+ db: sa_orm.Session = Depends(make_session),
465
+ ) -> EvaluationTableAndAssessmentTable:
466
+ return mark_model_evaluation(uuid=uuid, flags=JobStatusFlag.Failed.value, current_dt=current_dt, db=db)
467
+
468
+
469
+ @router.post("/submit_assessment_promotion/", response_model=AssessmentPromotionTable)
470
+ def submit_assessment_promotion(
471
+ uuid: py_uuid.UUID = Query(default_factory=py_uuid.uuid4),
472
+ assessment_uuid: py_uuid.UUID = Query(),
473
+ reviewer_sso_sid: int = Query(),
474
+ props: JsonObject | None = Query(default_factory=dict),
475
+ current_dt: datetime.datetime = Depends(current_dt_clock),
476
+ db: sa_orm.Session = Depends(make_session),
477
+ ) -> AssessmentPromotionTable:
478
+ with managed_db_session(db):
479
+ promotion = AssessmentPromotion(
480
+ uuid=uuid,
481
+ assessment_uuid=assessment_uuid,
482
+ reviewer_sso_sid=reviewer_sso_sid,
483
+ props=props,
484
+ )
485
+ return db_create_revision_model(db, AssessmentPromotionTable, promotion, current_dt)
486
+
487
+
488
+ @router.put("/mark_assessment_promotion/", response_model=AssessmentPromotionTable)
489
+ def mark_assessment_promotion(
490
+ uuid: py_uuid.UUID = Query(),
491
+ flags: int = Query(0),
492
+ current_dt: datetime.datetime = Depends(current_dt_clock),
493
+ db: sa_orm.Session = Depends(make_session),
494
+ ) -> AssessmentPromotionTable:
495
+ with managed_db_session(db):
496
+ db_promotion = (
497
+ db
498
+ .query(AssessmentPromotionTable)
499
+ .where(AssessmentPromotionTable.expired_at.is_(None), AssessmentPromotionTable.uuid == uuid)
500
+ .one_or_none()
501
+ )
502
+ if db_promotion is None:
503
+ raise sa_exc.NoResultFound(f"'{model_name_of(AssessmentPromotionTable)}' with uuid '{uuid}' not found")
504
+
505
+ promotion = clone_revision_model_instance(AssessmentPromotionTable, db_promotion, clear_meta_fields=False)
506
+ if promotion.flags != flags:
507
+ promotion.flags = flags
508
+ db_promotion = db_update_revision_model(db,
509
+ AssessmentPromotionTable,
510
+ promotion,
511
+ promotion.record_sqn,
512
+ current_dt)
513
+
514
+ return db_promotion
515
+
516
+
517
+ @router.put("/finish_assessment_promotion/", response_model=AssessmentPromotionTable)
518
+ def finish_assessment_promotion(
519
+ uuid: py_uuid.UUID = Query(),
520
+ current_dt: datetime.datetime = Depends(current_dt_clock),
521
+ db: sa_orm.Session = Depends(make_session),
522
+ ) -> AssessmentPromotionTable:
523
+ return mark_assessment_promotion(uuid=uuid, flags=JobStatusFlag.Completed.value, current_dt=current_dt, db=db)
524
+
525
+
526
+ @router.put("/fail_assessment_promotion/", response_model=AssessmentPromotionTable)
527
+ def fail_assessment_promotion(
528
+ uuid: py_uuid.UUID = Query(),
529
+ current_dt: datetime.datetime = Depends(current_dt_clock),
530
+ db: sa_orm.Session = Depends(make_session),
531
+ ) -> AssessmentPromotionTable:
532
+ return mark_assessment_promotion(uuid=uuid, flags=JobStatusFlag.Failed.value, current_dt=current_dt, db=db)