Skip to content

Commit 3593bff

Browse files
committed
add submission status retrieval and update methods; remove empty submissionstatus file
1 parent 460f257 commit 3593bff

File tree

4 files changed

+687
-40
lines changed

4 files changed

+687
-40
lines changed

synapseclient/api/submission_services.py

Lines changed: 257 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# TODO: The functions here should be moved into the `evaluation_services.py` file, once this branch is rebased onto those changes.
22

33
import json
4-
from typing import TYPE_CHECKING, List, Optional
4+
from typing import TYPE_CHECKING, Optional
55

66
if TYPE_CHECKING:
77
from synapseclient import Synapse
@@ -222,3 +222,259 @@ async def cancel_submission(
222222
response = await client.rest_put_async(uri)
223223

224224
return response
225+
226+
227+
async def get_submission_status(
228+
submission_id: str, synapse_client: Optional["Synapse"] = None
229+
) -> dict:
230+
"""
231+
Gets the SubmissionStatus object associated with a specified Submission.
232+
233+
<https://rest-docs.synapse.org/rest/GET/evaluation/submission/subId/status.html>
234+
235+
Arguments:
236+
submission_id: The ID of the submission to get the status for.
237+
synapse_client: If not passed in and caching was not disabled by
238+
`Synapse.allow_client_caching(False)` this will use the last created
239+
instance from the Synapse class constructor.
240+
241+
Returns:
242+
The SubmissionStatus object as a JSON dict.
243+
244+
Note:
245+
The caller must be granted the ACCESS_TYPE.READ on the specified Evaluation.
246+
Furthermore, the caller must be granted the ACCESS_TYPE.READ_PRIVATE_SUBMISSION
247+
to see all data marked as "private" in the SubmissionStatus.
248+
"""
249+
from synapseclient import Synapse
250+
251+
client = Synapse.get_client(synapse_client=synapse_client)
252+
253+
uri = f"/evaluation/submission/{submission_id}/status"
254+
255+
response = await client.rest_get_async(uri)
256+
257+
return response
258+
259+
260+
async def update_submission_status(
261+
submission_id: str, request_body: dict, synapse_client: Optional["Synapse"] = None
262+
) -> dict:
263+
"""
264+
Updates a SubmissionStatus object.
265+
266+
<https://rest-docs.synapse.org/rest/PUT/evaluation/submission/subId/status.html>
267+
268+
Arguments:
269+
submission_id: The ID of the SubmissionStatus being updated.
270+
request_body: The SubmissionStatus object to update as a dictionary.
271+
synapse_client: If not passed in and caching was not disabled by
272+
`Synapse.allow_client_caching(False)` this will use the last created
273+
instance from the Synapse class constructor.
274+
275+
Returns:
276+
The updated SubmissionStatus object as a JSON dict.
277+
278+
Note:
279+
Synapse employs an Optimistic Concurrency Control (OCC) scheme to handle
280+
concurrent updates. Each time a SubmissionStatus is updated a new etag will be
281+
issued to the SubmissionStatus. When an update is requested, Synapse will compare
282+
the etag of the passed SubmissionStatus with the current etag of the SubmissionStatus.
283+
If the etags do not match, then the update will be rejected with a PRECONDITION_FAILED
284+
(412) response. When this occurs, the caller should fetch the latest copy of the
285+
SubmissionStatus and re-apply any changes, then re-attempt the SubmissionStatus update.
286+
287+
The caller must be granted the ACCESS_TYPE.UPDATE_SUBMISSION on the specified Evaluation.
288+
"""
289+
from synapseclient import Synapse
290+
291+
client = Synapse.get_client(synapse_client=synapse_client)
292+
293+
uri = f"/evaluation/submission/{submission_id}/status"
294+
295+
response = await client.rest_put_async(uri, body=json.dumps(request_body))
296+
297+
return response
298+
299+
300+
async def get_all_submission_statuses(
301+
evaluation_id: str,
302+
status: Optional[str] = None,
303+
limit: int = 10,
304+
offset: int = 0,
305+
synapse_client: Optional["Synapse"] = None,
306+
) -> dict:
307+
"""
308+
Gets a collection of SubmissionStatuses to a specified Evaluation.
309+
310+
<https://rest-docs.synapse.org/rest/GET/evaluation/evalId/submission/status/all.html>
311+
312+
Arguments:
313+
evaluation_id: The ID of the specified Evaluation.
314+
status: Optionally filter submission statuses by status.
315+
limit: Limits the number of entities that will be fetched for this page.
316+
When null it will default to 10, max value 100. Default to 10.
317+
offset: The offset index determines where this page will start from.
318+
An index of 0 is the first entity. Default to 0.
319+
synapse_client: If not passed in and caching was not disabled by
320+
`Synapse.allow_client_caching(False)` this will use the last created
321+
instance from the Synapse class constructor.
322+
323+
Returns:
324+
A PaginatedResults<SubmissionStatus> object as a JSON dict containing
325+
a paginated list of submission statuses for the evaluation queue.
326+
327+
Note:
328+
The caller must be granted the ACCESS_TYPE.READ on the specified Evaluation.
329+
Furthermore, the caller must be granted the ACCESS_TYPE.READ_PRIVATE_SUBMISSION
330+
to see all data marked as "private" in the SubmissionStatuses.
331+
"""
332+
from synapseclient import Synapse
333+
334+
client = Synapse.get_client(synapse_client=synapse_client)
335+
336+
uri = f"/evaluation/{evaluation_id}/submission/status/all"
337+
query_params = {"limit": limit, "offset": offset}
338+
339+
if status:
340+
query_params["status"] = status
341+
342+
response = await client.rest_get_async(uri, **query_params)
343+
344+
return response
345+
346+
347+
async def batch_update_submission_statuses(
348+
evaluation_id: str, request_body: dict, synapse_client: Optional["Synapse"] = None
349+
) -> dict:
350+
"""
351+
Update multiple SubmissionStatuses. The maximum batch size is 500.
352+
353+
<https://rest-docs.synapse.org/rest/PUT/evaluation/evalId/statusBatch.html>
354+
355+
Arguments:
356+
evaluation_id: The ID of the Evaluation to which the SubmissionStatus objects belong.
357+
request_body: The SubmissionStatusBatch object as a dictionary containing:
358+
- statuses: List of SubmissionStatus objects to update
359+
- isFirstBatch: Boolean indicating if this is the first batch in the series
360+
- isLastBatch: Boolean indicating if this is the last batch in the series
361+
- batchToken: Token from previous batch response (required for all but first batch)
362+
synapse_client: If not passed in and caching was not disabled by
363+
`Synapse.allow_client_caching(False)` this will use the last created
364+
instance from the Synapse class constructor.
365+
366+
Returns:
367+
A BatchUploadResponse object as a JSON dict containing the batch token
368+
and other response information.
369+
370+
Note:
371+
To allow upload of more than the maximum batch size (500), the system supports
372+
uploading a series of batches. Synapse employs optimistic concurrency on the
373+
series in the form of a batch token. Each request (except the first) must include
374+
the 'batch token' returned in the response to the previous batch. If another client
375+
begins batch upload simultaneously, a PRECONDITION_FAILED (412) response will be
376+
generated and upload must restart from the first batch.
377+
378+
After the final batch is uploaded, the data for the Evaluation queue will be
379+
mirrored to the tables which support querying. Therefore uploaded data will not
380+
appear in Evaluation queries until after the final batch is successfully uploaded.
381+
382+
It is the client's responsibility to note in each batch request:
383+
1. Whether it is the first batch in the series (isFirstBatch)
384+
2. Whether it is the last batch (isLastBatch)
385+
386+
For a single batch both flags are set to 'true'.
387+
388+
The caller must be granted the ACCESS_TYPE.UPDATE_SUBMISSION on the specified Evaluation.
389+
"""
390+
from synapseclient import Synapse
391+
392+
client = Synapse.get_client(synapse_client=synapse_client)
393+
394+
uri = f"/evaluation/{evaluation_id}/statusBatch"
395+
396+
response = await client.rest_put_async(uri, body=json.dumps(request_body))
397+
398+
return response
399+
400+
401+
async def get_evaluation_submission_bundles(
402+
evaluation_id: str,
403+
status: Optional[str] = None,
404+
limit: int = 10,
405+
offset: int = 0,
406+
synapse_client: Optional["Synapse"] = None,
407+
) -> dict:
408+
"""
409+
Gets a collection of bundled Submissions and SubmissionStatuses to a given Evaluation.
410+
411+
<https://rest-docs.synapse.org/rest/GET/evaluation/evalId/submission/bundle/all.html>
412+
413+
Arguments:
414+
evaluation_id: The ID of the specified Evaluation.
415+
status: Optionally filter submission bundles by status.
416+
limit: Limits the number of entities that will be fetched for this page.
417+
When null it will default to 10, max value 100. Default to 10.
418+
offset: The offset index determines where this page will start from.
419+
An index of 0 is the first entity. Default to 0.
420+
synapse_client: If not passed in and caching was not disabled by
421+
`Synapse.allow_client_caching(False)` this will use the last created
422+
instance from the Synapse class constructor.
423+
424+
Returns:
425+
A PaginatedResults<SubmissionBundle> object as a JSON dict containing
426+
a paginated list of submission bundles for the evaluation queue.
427+
428+
Note:
429+
The caller must be granted the ACCESS_TYPE.READ_PRIVATE_SUBMISSION on the specified Evaluation.
430+
"""
431+
from synapseclient import Synapse
432+
433+
client = Synapse.get_client(synapse_client=synapse_client)
434+
435+
uri = f"/evaluation/{evaluation_id}/submission/bundle/all"
436+
query_params = {"limit": limit, "offset": offset}
437+
438+
if status:
439+
query_params["status"] = status
440+
441+
response = await client.rest_get_async(uri, **query_params)
442+
443+
return response
444+
445+
446+
async def get_user_submission_bundles(
447+
evaluation_id: str,
448+
limit: int = 10,
449+
offset: int = 0,
450+
synapse_client: Optional["Synapse"] = None,
451+
) -> dict:
452+
"""
453+
Gets the requesting user's bundled Submissions and SubmissionStatuses to a specified Evaluation.
454+
455+
<https://rest-docs.synapse.org/rest/GET/evaluation/evalId/submission/bundle.html>
456+
457+
Arguments:
458+
evaluation_id: The ID of the specified Evaluation.
459+
limit: Limits the number of entities that will be fetched for this page.
460+
When null it will default to 10. Default to 10.
461+
offset: The offset index determines where this page will start from.
462+
An index of 0 is the first entity. Default to 0.
463+
synapse_client: If not passed in and caching was not disabled by
464+
`Synapse.allow_client_caching(False)` this will use the last created
465+
instance from the Synapse class constructor.
466+
467+
Returns:
468+
A PaginatedResults<SubmissionBundle> object as a JSON dict containing
469+
a paginated list of the requesting user's submission bundles for the evaluation queue.
470+
"""
471+
from synapseclient import Synapse
472+
473+
client = Synapse.get_client(synapse_client=synapse_client)
474+
475+
uri = f"/evaluation/{evaluation_id}/submission/bundle"
476+
query_params = {"limit": limit, "offset": offset}
477+
478+
response = await client.rest_get_async(uri, **query_params)
479+
480+
return response

0 commit comments

Comments
 (0)