Skip to content

Commit 482a729

Browse files
feat: [DEV-14864] add submission cancellation query support (#455)
1 parent dbaa1c7 commit 482a729

3 files changed

Lines changed: 100 additions & 1 deletion

File tree

indico/queries/submission.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@
77
from indico.errors import IndicoInputError, IndicoTimeoutError
88
from indico.filters import SubmissionFilter
99
from indico.queries import JobStatus
10-
from indico.types import Job, Submission, SubmissionReviewFull
10+
from indico.types import (
11+
Job,
12+
Submission,
13+
SubmissionCancellationResult,
14+
SubmissionReviewFull,
15+
)
1116
from indico.types.submission import VALID_SUBMISSION_STATUSES
1217
from indico.types.utils import Timer
1318

@@ -626,3 +631,36 @@ def process_response(self, response: "Payload") -> "List[Submission]":
626631
return [
627632
Submission(**s) for s in super().parse_payload(response)["retrySubmissions"]
628633
]
634+
635+
636+
class CancelSubmissions(GraphQLRequest["SubmissionCancellationResult"]):
637+
"""
638+
Given a list of submission ids, cancel those active submissions.
639+
640+
Args:
641+
submission_ids (List[int]): the given submission ids to cancel.
642+
"""
643+
644+
query = """
645+
mutation cancelSubmissions($submissionIds:[Int]!){
646+
cancelSubmissions(submissionIds: $submissionIds){
647+
cancelled
648+
skipped{
649+
submissionId
650+
reason
651+
}
652+
}
653+
}
654+
"""
655+
656+
def __init__(self, submission_ids: "List[int]"):
657+
if submission_ids is None or len(submission_ids) < 1:
658+
raise IndicoInputError("You must specify submission ids")
659+
if len(set(submission_ids)) != len(submission_ids):
660+
raise IndicoInputError("Cannot include duplicate submission ids")
661+
662+
super().__init__(self.query, variables={"submissionIds": submission_ids})
663+
664+
def process_response(self, response: "Payload") -> "SubmissionCancellationResult":
665+
payload = super().parse_payload(response)["cancelSubmissions"]
666+
return SubmissionCancellationResult(**payload)

indico/types/submission.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,32 @@ class SubmissionRetries(BaseType):
4242
submission_id: int
4343

4444

45+
class SubmissionCancellationSkipped(BaseType):
46+
"""
47+
Information about a submission that was skipped during cancellation.
48+
49+
Attributes:
50+
submission_id (int): The ID of the submission that was not cancelled.
51+
reason (str): The reason it was skipped.
52+
"""
53+
54+
submission_id: int
55+
reason: str
56+
57+
58+
class SubmissionCancellationResult(BaseType):
59+
"""
60+
Result payload from a submission cancellation request.
61+
62+
Attributes:
63+
cancelled (List[int]): Submission IDs that were successfully cancelled.
64+
skipped (List[SubmissionCancellationSkipped]): Submission IDs that were skipped.
65+
"""
66+
67+
cancelled: List[int]
68+
skipped: List[SubmissionCancellationSkipped]
69+
70+
4571
class SubmissionReview(BaseType):
4672
f"""
4773
Information about a submission's Reviews.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import pytest
2+
3+
from indico.errors import IndicoInputError
4+
from indico.queries import CancelSubmissions
5+
from indico.types import SubmissionCancellationResult
6+
7+
8+
def test_cancel_submissions_requires_ids() -> None:
9+
with pytest.raises(IndicoInputError, match="must specify submission ids"):
10+
CancelSubmissions([])
11+
12+
13+
def test_cancel_submissions_rejects_duplicate_ids() -> None:
14+
with pytest.raises(IndicoInputError, match="duplicate submission ids"):
15+
CancelSubmissions([1, 1])
16+
17+
18+
def test_cancel_submissions_process_response() -> None:
19+
request = CancelSubmissions([1, 2])
20+
result = request.process_response(
21+
{
22+
"data": {
23+
"cancelSubmissions": {
24+
"cancelled": [1],
25+
"skipped": [{"submissionId": 2, "reason": "already terminal"}],
26+
}
27+
}
28+
}
29+
)
30+
31+
assert isinstance(result, SubmissionCancellationResult)
32+
assert result.cancelled == [1]
33+
assert len(result.skipped) == 1
34+
assert result.skipped[0].submission_id == 2
35+
assert result.skipped[0].reason == "already terminal"

0 commit comments

Comments
 (0)