@@ -89,6 +89,7 @@ def setUpClass(cls) -> None:
8989 """Set up test class"""
9090 example_configs = UploadJobConfigsV2 (
9191 job_type = "default" ,
92+ user_email = "test@example.com" ,
9293 project_name = "Behavior Platform" ,
9394 platform = Platform .BEHAVIOR ,
9495 modalities = [Modality .BEHAVIOR_VIDEOS ],
@@ -315,6 +316,7 @@ def setUpClass(cls) -> None:
315316 """Set up example configs to be used in tests"""
316317 example_upload_config = UploadJobConfigsV2 (
317318 job_type = "default" ,
319+ user_email = "test@example.com" ,
318320 project_name = "Behavior Platform" ,
319321 platform = Platform .BEHAVIOR ,
320322 modalities = [
@@ -351,7 +353,7 @@ def test_max_length(self):
351353 with self .assertRaises (ValidationError ) as e :
352354 SubmitJobRequestV2 (
353355 upload_jobs = [upload_job for _ in range (0 , 51 )],
354- user_email = "abc@example.com"
356+ user_email = "abc@example.com" ,
355357 )
356358 expected_message = (
357359 "List should have at most 50 items after validation, not 51"
@@ -366,8 +368,7 @@ def test_default_settings(self):
366368 ** self .example_upload_config .model_dump (round_trip = True )
367369 )
368370 job_settings = SubmitJobRequestV2 (
369- upload_jobs = [upload_job ],
370- user_email = "abc@example.com"
371+ upload_jobs = [upload_job ], user_email = "abc@example.com"
371372 )
372373 self .assertEqual ("abc@example.com" , job_settings .user_email )
373374 self .assertEqual ({"fail" }, job_settings .email_notification_types )
@@ -417,28 +418,29 @@ def test_email_validation(self):
417418 self .assertIn (expected_error_message , actual_error_message )
418419
419420 def test_propagate_email_settings (self ):
420- """Tests global email settings is propagated to individual jobs."""
421+ """Tests that global email is propagated to jobs without email,
422+ and email notification types are propagated to jobs without them."""
421423 example_job_configs = self .example_upload_config .model_dump (
422424 exclude = {"user_email" , "email_notification_types" }, round_trip = True
423425 )
424426 new_job = UploadJobConfigsV2 (
425- user_email = "xyz@example.org" ,
426427 email_notification_types = ["all" ],
427428 ** example_job_configs ,
428429 )
429430 job_settings = SubmitJobRequestV2 (
430- user_email = "abc @example.org " ,
431+ user_email = "global @example.com " ,
431432 email_notification_types = {"begin" , "fail" },
432433 upload_jobs = [
433434 new_job ,
434435 UploadJobConfigsV2 (** example_job_configs ),
435436 ],
436437 )
438+ self .assertEqual ("global@example.com" , job_settings .user_email )
437439 self .assertEqual (
438- "xyz @example.org " , job_settings .upload_jobs [0 ].user_email
440+ "global @example.com " , job_settings .upload_jobs [0 ].user_email
439441 )
440442 self .assertEqual (
441- "abc @example.org " , job_settings .upload_jobs [1 ].user_email
443+ "global @example.com " , job_settings .upload_jobs [1 ].user_email
442444 )
443445 self .assertEqual (
444446 {"all" }, job_settings .upload_jobs [0 ].email_notification_types
@@ -448,6 +450,44 @@ def test_propagate_email_settings(self):
448450 job_settings .upload_jobs [1 ].email_notification_types ,
449451 )
450452
453+ def test_propagate_email_from_job (self ):
454+ """Tests that global email is set from first job if not provided."""
455+ example_job_configs = self .example_upload_config .model_dump (
456+ exclude = {"email_notification_types" }, round_trip = True
457+ )
458+ job_settings = SubmitJobRequestV2 (
459+ user_email = None ,
460+ email_notification_types = {"begin" , "fail" },
461+ upload_jobs = [
462+ UploadJobConfigsV2 (** example_job_configs ),
463+ ],
464+ )
465+ self .assertEqual (
466+ "test@example.com" , job_settings .upload_jobs [0 ].user_email
467+ )
468+
469+ def test_missing_email_validation (self ):
470+ """Tests that validation error is raised when no email is provided."""
471+ example_job_configs = self .example_upload_config .model_dump (
472+ exclude = {"user_email" , "email_notification_types" }, round_trip = True
473+ )
474+ with self .assertRaises (ValidationError ) as e :
475+ SubmitJobRequestV2 (
476+ user_email = None ,
477+ upload_jobs = [UploadJobConfigsV2 (** example_job_configs )],
478+ )
479+ errors = json .loads (e .exception .json ())
480+ self .assertEqual (1 , len (errors ))
481+ self .assertIn (
482+ "No user_email set for job" ,
483+ errors [0 ]["msg" ],
484+ )
485+ self .assertIn (
486+ "Either set user_email in the job config or in the "
487+ "SubmitJobRequestV2" ,
488+ errors [0 ]["msg" ],
489+ )
490+
451491 def test_check_duplicate_upload_jobs (self ):
452492 """Tests that duplicate upload jobs are not allowed."""
453493 job_configs = self .example_upload_config .model_dump (
@@ -459,8 +499,7 @@ def test_check_duplicate_upload_jobs(self):
459499 ]
460500 with self .assertRaises (ValidationError ) as e :
461501 SubmitJobRequestV2 (
462- upload_jobs = upload_jobs ,
463- user_email = "abc@example.com"
502+ upload_jobs = upload_jobs , user_email = "abc@example.com"
464503 )
465504 errors = json .loads (e .exception .json ())
466505 self .assertEqual (1 , len (errors ))
@@ -489,8 +528,7 @@ def test_check_duplicate_upload_jobs_same_prefix(self):
489528 }
490529 upload_jobs .append (UploadJobConfigsV2 (** job_configs , tasks = tasks ))
491530 submit_job_request = SubmitJobRequestV2 (
492- upload_jobs = upload_jobs ,
493- user_email = "abc@example.com"
531+ upload_jobs = upload_jobs , user_email = "abc@example.com"
494532 )
495533 self .assertEqual (10 , len (submit_job_request .upload_jobs ))
496534
@@ -504,7 +542,7 @@ def test_current_jobs_validation(self):
504542 UploadJobConfigsV2 (** job_configs , subject_id = subject_id )
505543 for subject_id in ["123456" , "123457" , "123458" ]
506544 ],
507- user_email = "abc@example.com"
545+ user_email = "abc@example.com" ,
508546 )
509547 current_jobs = [
510548 j .model_dump (mode = "json" , exclude_none = True )
@@ -513,8 +551,7 @@ def test_current_jobs_validation(self):
513551 new_job = UploadJobConfigsV2 (** job_configs , subject_id = "123459" )
514552 with validation_context ({"current_jobs" : current_jobs }):
515553 submit_job_request = SubmitJobRequestV2 (
516- upload_jobs = [new_job ],
517- user_email = "abc@example.com"
554+ upload_jobs = [new_job ], user_email = "abc@example.com"
518555 )
519556 self .assertEqual (1 , len (submit_job_request .upload_jobs ))
520557 self .assertEqual (
@@ -526,7 +563,7 @@ def test_current_jobs_validation_fail(self):
526563 """Tests job validation when an upload_job is already running."""
527564 submitted_job_request = SubmitJobRequestV2 (
528565 upload_jobs = [self .example_upload_config ],
529- user_email = "abc@example.com"
566+ user_email = "abc@example.com" ,
530567 )
531568 current_jobs_1 = [
532569 j .model_dump (mode = "json" , exclude_none = True )
@@ -540,7 +577,7 @@ def test_current_jobs_validation_fail(self):
540577 with validation_context ({"current_jobs" : current_jobs }):
541578 SubmitJobRequestV2 (
542579 upload_jobs = [self .example_upload_config ],
543- user_email = "abc@example.com"
580+ user_email = "abc@example.com" ,
544581 )
545582 err_msg = json .loads (err .exception .json ())[0 ]["msg" ]
546583 self .assertEqual (
0 commit comments