Skip to content

Commit 47797c0

Browse files
committed
update submissionBundle submissionstatus with evaluation_id
1 parent d5fac7e commit 47797c0

File tree

3 files changed

+59
-52
lines changed

3 files changed

+59
-52
lines changed

synapseclient/models/submission_bundle.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,8 @@ class SubmissionBundle(SubmissionBundleSynchronousProtocol):
179179
"""
180180

181181
def fill_from_dict(
182-
self, synapse_submission_bundle: Dict[str, Union[bool, str, int, Dict]]
182+
self,
183+
synapse_submission_bundle: Dict[str, Union[bool, str, int, Dict]],
183184
) -> "SubmissionBundle":
184185
"""
185186
Converts a response from the REST API into this dataclass.
@@ -201,9 +202,10 @@ def fill_from_dict(
201202

202203
submission_status_dict = synapse_submission_bundle.get("submissionStatus", None)
203204
if submission_status_dict:
204-
self.submission_status = SubmissionStatus().fill_from_dict(
205-
submission_status_dict
206-
)
205+
self.submission_status = SubmissionStatus().fill_from_dict(submission_status_dict)
206+
# Manually set evaluation_id from the submission data if available
207+
if self.submission_status and self.submission and self.submission.evaluation_id:
208+
self.submission_status.evaluation_id = self.submission.evaluation_id
207209
else:
208210
self.submission_status = None
209211

@@ -268,7 +270,8 @@ async def get_evaluation_submission_bundles_async(
268270

269271
bundles = []
270272
for bundle_dict in response.get("results", []):
271-
bundle = SubmissionBundle().fill_from_dict(bundle_dict)
273+
bundle = SubmissionBundle()
274+
bundle.fill_from_dict(bundle_dict)
272275
bundles.append(bundle)
273276

274277
return bundles
@@ -327,7 +330,8 @@ async def get_user_submission_bundles_async(
327330
# Convert response to list of SubmissionBundle objects
328331
bundles = []
329332
for bundle_dict in response.get("results", []):
330-
bundle = SubmissionBundle().fill_from_dict(bundle_dict)
333+
bundle = SubmissionBundle()
334+
bundle.fill_from_dict(bundle_dict)
331335
bundles.append(bundle)
332336

333337
return bundles

synapseclient/models/submission_status.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,8 @@ def _set_last_persistent_instance(self) -> None:
432432
self._last_persistent_instance = replace(self)
433433

434434
def fill_from_dict(
435-
self, synapse_submission_status: Dict[str, Union[bool, str, int, float, List]]
435+
self,
436+
synapse_submission_status: Dict[str, Union[bool, str, int, float, List]],
436437
) -> "SubmissionStatus":
437438
"""
438439
Converts a response from the REST API into this dataclass.
@@ -744,7 +745,7 @@ async def get_all_submission_statuses_async(
744745
for status_dict in response.get("results", []):
745746
submission_status = SubmissionStatus()
746747
submission_status.fill_from_dict(status_dict)
747-
# Manually set evaluation_id since it's not part of the response
748+
# Manually set evaluation_id since it's not in the SubmissionStatus response
748749
submission_status.evaluation_id = evaluation_id
749750
submission_status._set_last_persistent_instance()
750751
submission_statuses.append(submission_status)

tests/integration/synapseclient/models/synchronous/test_submission_status.py

Lines changed: 46 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,9 @@ async def test_get_submission_status_by_id(
9797
assert submission_status.id == test_submission.id
9898
assert submission_status.entity_id == test_submission.entity_id
9999
assert submission_status.evaluation_id == test_evaluation.id
100-
assert submission_status.status is not None # Should have some status (e.g., "RECEIVED")
100+
assert (
101+
submission_status.status is not None
102+
) # Should have some status (e.g., "RECEIVED")
101103
assert submission_status.etag is not None
102104
assert submission_status.status_version is not None
103105
assert submission_status.modified_on is not None
@@ -108,7 +110,9 @@ async def test_get_submission_status_without_id(self):
108110
submission_status = SubmissionStatus()
109111

110112
# THEN it should raise a ValueError
111-
with pytest.raises(ValueError, match="The submission status must have an ID to get"):
113+
with pytest.raises(
114+
ValueError, match="The submission status must have an ID to get"
115+
):
112116
submission_status.get(synapse_client=self.syn)
113117

114118
async def test_get_submission_status_with_invalid_id(self):
@@ -229,17 +233,17 @@ async def test_store_submission_status_with_submission_annotations(
229233
# WHEN I add submission annotations and store
230234
test_submission_status.submission_annotations = {
231235
"score": 85.5,
232-
"validation_passed": True,
236+
"validation_passed": [True],
233237
"feedback": "Good work!",
234238
}
235239
updated_status = test_submission_status.store(synapse_client=self.syn)
236240

237241
# THEN the submission annotations should be saved
238242
assert updated_status.submission_annotations is not None
239243
assert "score" in updated_status.submission_annotations
240-
assert updated_status.submission_annotations["score"] == 85.5
241-
assert updated_status.submission_annotations["validation_passed"] == True
242-
assert updated_status.submission_annotations["feedback"] == "Good work!"
244+
assert updated_status.submission_annotations["score"] == [85.5]
245+
assert updated_status.submission_annotations["validation_passed"] == [True]
246+
assert updated_status.submission_annotations["feedback"] == ["Good work!"]
243247

244248
async def test_store_submission_status_with_legacy_annotations(
245249
self, test_submission_status: SubmissionStatus
@@ -255,8 +259,8 @@ async def test_store_submission_status_with_legacy_annotations(
255259
# THEN the legacy annotations should be saved
256260
assert updated_status.annotations is not None
257261
assert "internal_score" in updated_status.annotations
258-
assert updated_status.annotations["internal_score"] == 92.3
259-
assert updated_status.annotations["reviewer_notes"] == "Excellent submission"
262+
assert updated_status.annotations["internal_score"] == [92.3]
263+
assert updated_status.annotations["reviewer_notes"] == ["Excellent submission"]
260264

261265
async def test_store_submission_status_with_combined_annotations(
262266
self, test_submission_status: SubmissionStatus
@@ -276,11 +280,11 @@ async def test_store_submission_status_with_combined_annotations(
276280
# THEN both types of annotations should be saved
277281
assert updated_status.submission_annotations is not None
278282
assert "public_score" in updated_status.submission_annotations
279-
assert updated_status.submission_annotations["public_score"] == 78.0
283+
assert updated_status.submission_annotations["public_score"] == [78.0]
280284

281285
assert updated_status.annotations is not None
282286
assert "internal_review" in updated_status.annotations
283-
assert updated_status.annotations["internal_review"] == True
287+
assert updated_status.annotations["internal_review"] == [True]
284288

285289
async def test_store_submission_status_with_private_annotations_false(
286290
self, test_submission_status: SubmissionStatus
@@ -292,10 +296,12 @@ async def test_store_submission_status_with_private_annotations_false(
292296
"public_notes": "This should be visible",
293297
}
294298
test_submission_status.private_status_annotations = False
295-
299+
296300
# AND I create the request body to inspect it
297-
request_body = test_submission_status.to_synapse_request(synapse_client=self.syn)
298-
301+
request_body = test_submission_status.to_synapse_request(
302+
synapse_client=self.syn
303+
)
304+
299305
# THEN the annotations should be marked as not private in the request
300306
assert "annotations" in request_body
301307
annotations_data = request_body["annotations"]
@@ -312,10 +318,12 @@ async def test_store_submission_status_with_private_annotations_true(
312318
"private_notes": "This should be private",
313319
}
314320
test_submission_status.private_status_annotations = True
315-
321+
316322
# AND I create the request body to inspect it
317-
request_body = test_submission_status.to_synapse_request(synapse_client=self.syn)
318-
323+
request_body = test_submission_status.to_synapse_request(
324+
synapse_client=self.syn
325+
)
326+
319327
# THEN the annotations should be marked as private in the request
320328
assert "annotations" in request_body
321329
annotations_data = request_body["annotations"]
@@ -328,7 +336,9 @@ async def test_store_submission_status_without_id(self):
328336
submission_status = SubmissionStatus(status="SCORED")
329337

330338
# THEN it should raise a ValueError
331-
with pytest.raises(ValueError, match="The submission status must have an ID to update"):
339+
with pytest.raises(
340+
ValueError, match="The submission status must have an ID to update"
341+
):
332342
submission_status.store(synapse_client=self.syn)
333343

334344
async def test_store_submission_status_without_changes(
@@ -405,7 +415,9 @@ async def test_files(
405415
with tempfile.NamedTemporaryFile(
406416
mode="w", delete=False, suffix=".txt"
407417
) as temp_file:
408-
temp_file.write(f"This is test content {i} for submission status testing.")
418+
temp_file.write(
419+
f"This is test content {i} for submission status testing."
420+
)
409421
temp_file_path = temp_file.name
410422

411423
try:
@@ -546,18 +558,18 @@ async def test_batch_update_submission_statuses(
546558
)
547559
assert updated_status.status == "VALIDATED"
548560
assert "batch_score" in updated_status.submission_annotations
549-
assert updated_status.submission_annotations["batch_processed"] == True
561+
assert updated_status.submission_annotations["batch_processed"] == [True]
550562

551563
async def test_batch_update_submission_statuses_large_batch(
552564
self, test_evaluation: Evaluation
553565
):
554566
"""Test batch update behavior with larger batch (approaching limits)."""
555567
# Note: This test demonstrates the pattern but doesn't create 500 submissions
556568
# as that would be too expensive for regular test runs
557-
569+
558570
# GIVEN I have a list of statuses (simulated for this test)
559571
statuses = []
560-
572+
561573
# WHEN I try to batch update (even with empty list)
562574
response = SubmissionStatus.batch_update_submission_statuses(
563575
evaluation_id=test_evaluation.id,
@@ -600,8 +612,10 @@ async def test_batch_update_submission_statuses_with_batch_tokens(
600612

601613
# IF there's a second batch and we got a batch token
602614
if len(batch2) > 0:
603-
batch_token = response1.get("batchToken") if isinstance(response1, dict) else None
604-
615+
batch_token = (
616+
response1.get("batchToken") if isinstance(response1, dict) else None
617+
)
618+
605619
# WHEN I update the second batch with the token
606620
response2 = SubmissionStatus.batch_update_submission_statuses(
607621
evaluation_id=test_evaluation.id,
@@ -644,10 +658,7 @@ async def test_to_synapse_request_with_annotations_missing_evaluation_id(self):
644658
"""Test that annotations require evaluation_id."""
645659
# WHEN I try to create a request with annotations but no evaluation_id
646660
submission_status = SubmissionStatus(
647-
id="123",
648-
etag="some-etag",
649-
status_version=1,
650-
annotations={"test": "value"}
661+
id="123", etag="some-etag", status_version=1, annotations={"test": "value"}
651662
)
652663

653664
# THEN it should raise a ValueError
@@ -663,7 +674,7 @@ async def test_to_synapse_request_valid_attributes(self):
663674
status_version=1,
664675
status="SCORED",
665676
evaluation_id="eval123",
666-
submission_annotations={"score": 85.5}
677+
submission_annotations={"score": 85.5},
667678
)
668679

669680
# THEN it should create a valid request body
@@ -690,21 +701,15 @@ async def test_fill_from_dict_with_complete_response(self):
690701
"canCancel": False,
691702
"cancelRequested": False,
692703
"annotations": {
693-
"stringAnnos": {
694-
"internal_note": ["This is internal"]
695-
},
704+
"stringAnnos": {"internal_note": ["This is internal"]},
696705
"doubleAnnos": {},
697-
"longAnnos": {}
706+
"longAnnos": {},
698707
},
699708
"submissionAnnotations": {
700-
"stringAnnos": {
701-
"feedback": ["Great work!"]
702-
},
703-
"doubleAnnos": {
704-
"score": [92.5]
705-
},
706-
"longAnnos": {}
707-
}
709+
"stringAnnos": {"feedback": ["Great work!"]},
710+
"doubleAnnos": {"score": [92.5]},
711+
"longAnnos": {},
712+
},
708713
}
709714

710715
# WHEN I fill a SubmissionStatus from the response
@@ -730,10 +735,7 @@ async def test_fill_from_dict_with_complete_response(self):
730735
async def test_fill_from_dict_with_minimal_response(self):
731736
"""Test filling a SubmissionStatus from a minimal API response."""
732737
# GIVEN a minimal API response
733-
api_response = {
734-
"id": "123456",
735-
"status": "RECEIVED"
736-
}
738+
api_response = {"id": "123456", "status": "RECEIVED"}
737739

738740
# WHEN I fill a SubmissionStatus from the response
739741
submission_status = SubmissionStatus()

0 commit comments

Comments
 (0)