ctfy.sdk.admin_resources.series
client.admin.series — recurring contests.
1"""``client.admin.series`` — recurring contests.""" 2 3from __future__ import annotations 4 5import builtins 6 7from ctfy.sdk._helpers import _raise_for_status 8from ctfy.sdk.base import BaseHttpClient 9from ctfy.server.models import ( 10 CompetitionSeriesConfig, 11 CompetitionSeriesInfo, 12 SeriesPreview, 13) 14 15 16class AdminSeriesResource: 17 """A schedule that creates competitions on its own. 18 19 The thing to know before enabling one: it publishes onto a public 20 listing without anybody pressing a button, so the two reads matter 21 more than the writes. :meth:`preview` is how you check a cadence 22 without waiting a week, and ``spawn_job_enabled`` on every read is 23 how you notice that the job which does the work is paused. 24 """ 25 26 def __init__(self, http: BaseHttpClient) -> None: 27 self._http = http 28 29 def list(self) -> builtins.list[CompetitionSeriesInfo]: 30 resp = self._http.request("GET", "/admin/series") 31 _raise_for_status(resp) 32 return [CompetitionSeriesInfo.model_validate(r) for r in resp.json()] 33 34 def get(self, series_id: str) -> CompetitionSeriesInfo: 35 resp = self._http.request("GET", f"/admin/series/{series_id}") 36 _raise_for_status(resp) 37 return CompetitionSeriesInfo.model_validate(resp.json()) 38 39 def create(self, config: CompetitionSeriesConfig) -> CompetitionSeriesInfo: 40 resp = self._http.request("POST", "/admin/series", json=config.model_dump(mode="json")) 41 _raise_for_status(resp) 42 return CompetitionSeriesInfo.model_validate(resp.json()) 43 44 def update(self, series_id: str, config: CompetitionSeriesConfig) -> CompetitionSeriesInfo: 45 """Full replace of the editable half. 46 47 The creation audit is not part of ``config`` and cannot be 48 rewritten — a schedule that then acts on its own must keep an 49 honest record of who set it up. 50 """ 51 resp = self._http.request( 52 "PUT", f"/admin/series/{series_id}", json=config.model_dump(mode="json") 53 ) 54 _raise_for_status(resp) 55 return CompetitionSeriesInfo.model_validate(resp.json()) 56 57 def delete(self, series_id: str) -> None: 58 """Retire a schedule. **Its competitions are kept.** 59 60 They are ordinary competitions with teams, solves and boards; 61 deleting a schedule cannot reasonably mean deleting the finished 62 events it produced. 63 """ 64 resp = self._http.request("DELETE", f"/admin/series/{series_id}") 65 _raise_for_status(resp) 66 67 def preview(self, series_id: str) -> SeriesPreview: 68 """What this series would do, without doing it. 69 70 Projects past the spawn lead window on purpose: the mistake worth 71 catching is a pool that covers three weeks of a schedule meant to 72 run indefinitely, and that is only visible at the fourth. 73 """ 74 resp = self._http.request("GET", f"/admin/series/{series_id}/preview") 75 _raise_for_status(resp) 76 return SeriesPreview.model_validate(resp.json())
17class AdminSeriesResource: 18 """A schedule that creates competitions on its own. 19 20 The thing to know before enabling one: it publishes onto a public 21 listing without anybody pressing a button, so the two reads matter 22 more than the writes. :meth:`preview` is how you check a cadence 23 without waiting a week, and ``spawn_job_enabled`` on every read is 24 how you notice that the job which does the work is paused. 25 """ 26 27 def __init__(self, http: BaseHttpClient) -> None: 28 self._http = http 29 30 def list(self) -> builtins.list[CompetitionSeriesInfo]: 31 resp = self._http.request("GET", "/admin/series") 32 _raise_for_status(resp) 33 return [CompetitionSeriesInfo.model_validate(r) for r in resp.json()] 34 35 def get(self, series_id: str) -> CompetitionSeriesInfo: 36 resp = self._http.request("GET", f"/admin/series/{series_id}") 37 _raise_for_status(resp) 38 return CompetitionSeriesInfo.model_validate(resp.json()) 39 40 def create(self, config: CompetitionSeriesConfig) -> CompetitionSeriesInfo: 41 resp = self._http.request("POST", "/admin/series", json=config.model_dump(mode="json")) 42 _raise_for_status(resp) 43 return CompetitionSeriesInfo.model_validate(resp.json()) 44 45 def update(self, series_id: str, config: CompetitionSeriesConfig) -> CompetitionSeriesInfo: 46 """Full replace of the editable half. 47 48 The creation audit is not part of ``config`` and cannot be 49 rewritten — a schedule that then acts on its own must keep an 50 honest record of who set it up. 51 """ 52 resp = self._http.request( 53 "PUT", f"/admin/series/{series_id}", json=config.model_dump(mode="json") 54 ) 55 _raise_for_status(resp) 56 return CompetitionSeriesInfo.model_validate(resp.json()) 57 58 def delete(self, series_id: str) -> None: 59 """Retire a schedule. **Its competitions are kept.** 60 61 They are ordinary competitions with teams, solves and boards; 62 deleting a schedule cannot reasonably mean deleting the finished 63 events it produced. 64 """ 65 resp = self._http.request("DELETE", f"/admin/series/{series_id}") 66 _raise_for_status(resp) 67 68 def preview(self, series_id: str) -> SeriesPreview: 69 """What this series would do, without doing it. 70 71 Projects past the spawn lead window on purpose: the mistake worth 72 catching is a pool that covers three weeks of a schedule meant to 73 run indefinitely, and that is only visible at the fourth. 74 """ 75 resp = self._http.request("GET", f"/admin/series/{series_id}/preview") 76 _raise_for_status(resp) 77 return SeriesPreview.model_validate(resp.json())
A schedule that creates competitions on its own.
The thing to know before enabling one: it publishes onto a public
listing without anybody pressing a button, so the two reads matter
more than the writes. preview() is how you check a cadence
without waiting a week, and spawn_job_enabled on every read is
how you notice that the job which does the work is paused.
45 def update(self, series_id: str, config: CompetitionSeriesConfig) -> CompetitionSeriesInfo: 46 """Full replace of the editable half. 47 48 The creation audit is not part of ``config`` and cannot be 49 rewritten — a schedule that then acts on its own must keep an 50 honest record of who set it up. 51 """ 52 resp = self._http.request( 53 "PUT", f"/admin/series/{series_id}", json=config.model_dump(mode="json") 54 ) 55 _raise_for_status(resp) 56 return CompetitionSeriesInfo.model_validate(resp.json())
Full replace of the editable half.
The creation audit is not part of config and cannot be
rewritten — a schedule that then acts on its own must keep an
honest record of who set it up.
58 def delete(self, series_id: str) -> None: 59 """Retire a schedule. **Its competitions are kept.** 60 61 They are ordinary competitions with teams, solves and boards; 62 deleting a schedule cannot reasonably mean deleting the finished 63 events it produced. 64 """ 65 resp = self._http.request("DELETE", f"/admin/series/{series_id}") 66 _raise_for_status(resp)
Retire a schedule. Its competitions are kept.
They are ordinary competitions with teams, solves and boards; deleting a schedule cannot reasonably mean deleting the finished events it produced.
68 def preview(self, series_id: str) -> SeriesPreview: 69 """What this series would do, without doing it. 70 71 Projects past the spawn lead window on purpose: the mistake worth 72 catching is a pool that covers three weeks of a schedule meant to 73 run indefinitely, and that is only visible at the fourth. 74 """ 75 resp = self._http.request("GET", f"/admin/series/{series_id}/preview") 76 _raise_for_status(resp) 77 return SeriesPreview.model_validate(resp.json())
What this series would do, without doing it.
Projects past the spawn lead window on purpose: the mistake worth catching is a pool that covers three weeks of a schedule meant to run indefinitely, and that is only visible at the fourth.