codabench-client 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Abderrahmane Moujar [Scarface]
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,258 @@
1
+ Metadata-Version: 2.4
2
+ Name: codabench-client
3
+ Version: 0.1.0
4
+ Summary: A small, readable Python client and CLI for the Codabench API.
5
+ License: MIT
6
+ Project-URL: Homepage, https://github.com/amoujar/codabench-client
7
+ Project-URL: Issues, https://github.com/amoujar/codabench-client/issues
8
+ Keywords: codabench,codalab,benchmark,competition,machine-learning
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Environment :: Console
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
15
+ Requires-Python: >=3.9
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: requests>=2.25
19
+ Dynamic: license-file
20
+
21
+ # codabench-client
22
+
23
+ A small, readable Python client and CLI for the [Codabench](https://www.codabench.org/) API.
24
+
25
+ Codabench is a great benchmark platform, but a lot of what you can do in its web UI —
26
+ grabbing a starting kit, submitting a zip, pulling the scoring logs of a failed run —
27
+ is tedious to click through and awkward to automate. This package does all of it from
28
+ the terminal or from Python.
29
+
30
+ ```bash
31
+ codabench show 17363 # everything about a competition
32
+ codabench files 16161 # download the starting kit & public data
33
+ codabench submit 17525 -z run.zip --wait # submit and watch the score come back
34
+ codabench outputs 17525 # fetch the prediction & scoring output
35
+ ```
36
+
37
+ ---
38
+
39
+ ## Install
40
+
41
+ ```bash
42
+ git clone https://github.com/<you>/api-codabench.git
43
+ cd api-codabench
44
+ pip install -e .
45
+ ```
46
+
47
+ Python 3.9+ and `requests` are the only requirements. Without installing, everything
48
+ also works as `python -m codabench ...` and `python examples/01_show_competition.py`.
49
+
50
+ ## Credentials
51
+
52
+ Copy the template and fill it in:
53
+
54
+ ```bash
55
+ cp .env.example .env
56
+ ```
57
+
58
+ ```ini
59
+ CODABENCH_USERNAME=your_username
60
+ CODABENCH_PASSWORD=your_password
61
+ # CODABENCH_URL=https://dev.codabench.org/ # optional; default is www.codabench.org
62
+ ```
63
+
64
+ `.env` is gitignored. Environment variables win over the file, so CI can just set
65
+ `CODABENCH_USERNAME` / `CODABENCH_PASSWORD`. Reading a **public** competition needs no
66
+ credentials at all.
67
+
68
+ > **Accounts are per-instance.** A `www.codabench.org` login does not work on
69
+ > `dev.codabench.org`, and vice versa.
70
+
71
+ ## Commands
72
+
73
+
74
+ | Command | What it does |
75
+ | ---------------------------------------------- | ---------------------------------------------------------- |
76
+ | `codabench competitions [--search TEXT]` | List competitions |
77
+ | `codabench show <id|url>` | Pages, phases, tasks, files, leaderboard |
78
+ | `codabench files <id|url>` | List / download the "Files" tab |
79
+ | `codabench submit <id|url> -z FILE` | Upload a submission, optionally wait for the score |
80
+ | `codabench outputs <id|url>` | Download a submission's zip, prediction & scoring output |
81
+ | `codabench rerun --submission ID --task KEY` | Re-run a submission on another task (robot accounts) |
82
+ | `codabench create -b bundle.zip` | Create a competition from a bundle |
83
+
84
+
85
+ | Command | What it does |
86
+ | ------------------------------------------------ | ---------------------------------------------------------- |
87
+ | `codabench competitions [--search TEXT]` | List competitions |
88
+ | `codabench show &lt;id&#124;url&gt;` | Pages, phases, tasks, files, leaderboard |
89
+ | `codabench files &lt;id&#124;url&gt;` | List / download the "Files" tab |
90
+ | `codabench submit &lt;id&#124;url&gt; -z FILE` | Upload a submission, optionally wait for the score |
91
+ | `codabench outputs &lt;id&#124;url&gt;` | Download a submission's zip, prediction & scoring output |
92
+ | `codabench rerun --submission ID --task KEY` | Re-run a submission on another task (robot accounts) |
93
+ | `codabench create -b bundle.zip` | Create a competition from a bundle |
94
+
95
+ Every command takes `--url`, `--username`, `--password`, `--env`, and `--help`.
96
+
97
+ ### Inspect a competition
98
+
99
+ ```bash
100
+ codabench show 17363 # or the full https://www.codabench.org/competitions/17363/ URL
101
+ codabench show 17363 --pages # full text of every page
102
+ codabench show 17363 --json # raw API payload
103
+ ```
104
+
105
+ Save the whole thing — description, one markdown file per page, and every file you are
106
+ allowed to download:
107
+
108
+ ```bash
109
+ codabench show 17363 --save-dir workdir/17363
110
+ ```
111
+
112
+ ```
113
+ workdir/17363/
114
+ ├── description.md
115
+ ├── pages/
116
+ │ ├── 00-overview.md
117
+ │ ├── 01-data.md
118
+ │ └── ...
119
+ └── input/
120
+ └── Track 1 Starting Kit V5/
121
+ ```
122
+
123
+ Add `--no-download` for the text only.
124
+
125
+ ### Download competition files
126
+
127
+ ```bash
128
+ codabench files 16161 --list # see what exists first
129
+ codabench files 16161 # download into files/16161/
130
+ codabench files 16161 --only starting_kit # filter by type or name
131
+ codabench files 16161 --no-extract # keep the zips
132
+ ```
133
+
134
+ ### Submit and get scored
135
+
136
+ ```bash
137
+ codabench submit 17525 -z submission.zip --wait
138
+ codabench submit 17525 -z submission.zip --wait \
139
+ --results-json results.json --download-dir outputs
140
+ ```
141
+
142
+ The phase is resolved automatically (the only one, or the currently open one); pass
143
+ `--phase <id>` or `--phase-index <n>` when a competition has several open at once.
144
+ Submitting **consumes your daily quota** — the command checks eligibility first and
145
+ tells you if you are out.
146
+
147
+ ### Get a submission's output
148
+
149
+ ```bash
150
+ codabench outputs 17525 --list # your submissions on the phase
151
+ codabench outputs 17525 # newest submission
152
+ codabench outputs 17525 --last 2 # the one before it
153
+ codabench outputs --submission 856524 # a specific id
154
+ codabench outputs 17525 --only scoring # just the scoring step
155
+ ```
156
+
157
+ Everything lands in `outputs/<submission id>/` with the zips extracted, plus a
158
+ `details.json` holding the scores, logs and exit statuses — which is usually where the
159
+ answer is when a submission fails.
160
+
161
+ ## Python API
162
+
163
+ ```python
164
+ from codabench import CodabenchClient, collect_files, find_phase
165
+
166
+ client = CodabenchClient() # reads .env / environment
167
+
168
+ competition = client.competition(17363) # id or URL
169
+ phase = find_phase(competition) # the open phase
170
+
171
+ for entry in collect_files(competition):
172
+ path = client.download_dataset(entry.key, "input/", entry.filename)
173
+ print(entry.name, "->", path or "not authorized")
174
+
175
+ submission = client.submit(phase["id"], "run.zip")
176
+ client.wait_for_submission(submission["id"])
177
+ print(client.results(submission["id"])["metrics"])
178
+ ```
179
+
180
+ The client raises `CodabenchError` (with `AuthError` and `ApiError` subclasses) and
181
+ never calls `sys.exit`, so it is safe to use inside a notebook or a larger program.
182
+
183
+ ## What you can actually download
184
+
185
+ This trips everyone up, so it is worth stating plainly. Codabench decides per file, and
186
+ this tool cannot widen what your account is allowed to see:
187
+
188
+
189
+ | File | Who can download it |
190
+ | --------------------------------- | ----------------------------------------------------------------------- |
191
+ | Starting kit, public data | Any approved participant |
192
+ | Ingestion / scoring program | Participants**only if** the organizer set `make_programs_available` |
193
+ | Input data | Participants**only if** the organizer set `make_input_data_available` |
194
+ | Reference data (the answer key) | Organizers only, always |
195
+ | Competition bundle | Organizers only |
196
+
197
+ Files your account may not fetch are skipped, not treated as an error. `codabench show`
198
+ prints the organizer's two flags so you can see why something is missing.
199
+
200
+ ## How authentication works
201
+
202
+ Codabench uses **two** mechanisms and you need both — the reason `CodabenchClient` holds
203
+ a token *and* a session:
204
+
205
+
206
+ | Endpoint | Auth |
207
+ | ----------------------------- | ------------------------------------------------------- |
208
+ | `/api/...` | Token from`POST /api/api-token-auth/` |
209
+ | `/datasets/download/<key>/` | Django**session cookie** from `POST /accounts/login/` |
210
+
211
+ The download route behind the "Files" tab is a plain Django view that ignores the API
212
+ token, which is why a token-only client gets 403s on files a participant can plainly
213
+ download in the browser. Both schemes read the same credentials, so callers never have
214
+ to think about it.
215
+
216
+ (There is also `GET /api/competitions/{id}/get_files/`, but it is organizer-only and
217
+ returns 403 for participants — this package does not rely on it.)
218
+
219
+ ## Repository layout
220
+
221
+ ```
222
+ codabench/ the library
223
+ ├── auth.py credentials, token auth, session login
224
+ ├── client.py CodabenchClient — every API call
225
+ ├── competitions.py pure helpers over a competition payload
226
+ ├── downloads.py saving & extracting artifacts
227
+ ├── text.py HTML→text, slugs, sizes
228
+ ├── errors.py CodabenchError / AuthError / ApiError
229
+ └── cli.py the `codabench` command
230
+
231
+ examples/ the same flows as standalone scripts
232
+ ├── 01_show_competition.py
233
+ ├── 02_download_competition_files.py
234
+ ├── 03_submit_and_wait.py
235
+ ├── 04_download_submission_outputs.py
236
+ ├── 05_create_competition.py
237
+ └── 06_rerun_submission.py
238
+
239
+ assets/ a sample submission zip and competition bundle
240
+ ```
241
+
242
+ Run any example directly — no install needed:
243
+
244
+ ```bash
245
+ python examples/01_show_competition.py 17363
246
+ ```
247
+
248
+ ## Notes
249
+
250
+ * **Organizers**: `codabench create -b bundle.zip` uploads a competition bundle and polls
251
+ until it is unpacked. Try it on `https://dev.codabench.org/` first.
252
+ * **Robot accounts**: `codabench rerun` re-runs an existing submission against another
253
+ task, reusing the uploaded data. It needs an account flagged `is_bot`, or the API
254
+ answers 403.
255
+
256
+ ## License
257
+
258
+ MIT.
@@ -0,0 +1,238 @@
1
+ # codabench-client
2
+
3
+ A small, readable Python client and CLI for the [Codabench](https://www.codabench.org/) API.
4
+
5
+ Codabench is a great benchmark platform, but a lot of what you can do in its web UI —
6
+ grabbing a starting kit, submitting a zip, pulling the scoring logs of a failed run —
7
+ is tedious to click through and awkward to automate. This package does all of it from
8
+ the terminal or from Python.
9
+
10
+ ```bash
11
+ codabench show 17363 # everything about a competition
12
+ codabench files 16161 # download the starting kit & public data
13
+ codabench submit 17525 -z run.zip --wait # submit and watch the score come back
14
+ codabench outputs 17525 # fetch the prediction & scoring output
15
+ ```
16
+
17
+ ---
18
+
19
+ ## Install
20
+
21
+ ```bash
22
+ git clone https://github.com/<you>/api-codabench.git
23
+ cd api-codabench
24
+ pip install -e .
25
+ ```
26
+
27
+ Python 3.9+ and `requests` are the only requirements. Without installing, everything
28
+ also works as `python -m codabench ...` and `python examples/01_show_competition.py`.
29
+
30
+ ## Credentials
31
+
32
+ Copy the template and fill it in:
33
+
34
+ ```bash
35
+ cp .env.example .env
36
+ ```
37
+
38
+ ```ini
39
+ CODABENCH_USERNAME=your_username
40
+ CODABENCH_PASSWORD=your_password
41
+ # CODABENCH_URL=https://dev.codabench.org/ # optional; default is www.codabench.org
42
+ ```
43
+
44
+ `.env` is gitignored. Environment variables win over the file, so CI can just set
45
+ `CODABENCH_USERNAME` / `CODABENCH_PASSWORD`. Reading a **public** competition needs no
46
+ credentials at all.
47
+
48
+ > **Accounts are per-instance.** A `www.codabench.org` login does not work on
49
+ > `dev.codabench.org`, and vice versa.
50
+
51
+ ## Commands
52
+
53
+
54
+ | Command | What it does |
55
+ | ---------------------------------------------- | ---------------------------------------------------------- |
56
+ | `codabench competitions [--search TEXT]` | List competitions |
57
+ | `codabench show <id|url>` | Pages, phases, tasks, files, leaderboard |
58
+ | `codabench files <id|url>` | List / download the "Files" tab |
59
+ | `codabench submit <id|url> -z FILE` | Upload a submission, optionally wait for the score |
60
+ | `codabench outputs <id|url>` | Download a submission's zip, prediction & scoring output |
61
+ | `codabench rerun --submission ID --task KEY` | Re-run a submission on another task (robot accounts) |
62
+ | `codabench create -b bundle.zip` | Create a competition from a bundle |
63
+
64
+
65
+ | Command | What it does |
66
+ | ------------------------------------------------ | ---------------------------------------------------------- |
67
+ | `codabench competitions [--search TEXT]` | List competitions |
68
+ | `codabench show &lt;id&#124;url&gt;` | Pages, phases, tasks, files, leaderboard |
69
+ | `codabench files &lt;id&#124;url&gt;` | List / download the "Files" tab |
70
+ | `codabench submit &lt;id&#124;url&gt; -z FILE` | Upload a submission, optionally wait for the score |
71
+ | `codabench outputs &lt;id&#124;url&gt;` | Download a submission's zip, prediction & scoring output |
72
+ | `codabench rerun --submission ID --task KEY` | Re-run a submission on another task (robot accounts) |
73
+ | `codabench create -b bundle.zip` | Create a competition from a bundle |
74
+
75
+ Every command takes `--url`, `--username`, `--password`, `--env`, and `--help`.
76
+
77
+ ### Inspect a competition
78
+
79
+ ```bash
80
+ codabench show 17363 # or the full https://www.codabench.org/competitions/17363/ URL
81
+ codabench show 17363 --pages # full text of every page
82
+ codabench show 17363 --json # raw API payload
83
+ ```
84
+
85
+ Save the whole thing — description, one markdown file per page, and every file you are
86
+ allowed to download:
87
+
88
+ ```bash
89
+ codabench show 17363 --save-dir workdir/17363
90
+ ```
91
+
92
+ ```
93
+ workdir/17363/
94
+ ├── description.md
95
+ ├── pages/
96
+ │ ├── 00-overview.md
97
+ │ ├── 01-data.md
98
+ │ └── ...
99
+ └── input/
100
+ └── Track 1 Starting Kit V5/
101
+ ```
102
+
103
+ Add `--no-download` for the text only.
104
+
105
+ ### Download competition files
106
+
107
+ ```bash
108
+ codabench files 16161 --list # see what exists first
109
+ codabench files 16161 # download into files/16161/
110
+ codabench files 16161 --only starting_kit # filter by type or name
111
+ codabench files 16161 --no-extract # keep the zips
112
+ ```
113
+
114
+ ### Submit and get scored
115
+
116
+ ```bash
117
+ codabench submit 17525 -z submission.zip --wait
118
+ codabench submit 17525 -z submission.zip --wait \
119
+ --results-json results.json --download-dir outputs
120
+ ```
121
+
122
+ The phase is resolved automatically (the only one, or the currently open one); pass
123
+ `--phase <id>` or `--phase-index <n>` when a competition has several open at once.
124
+ Submitting **consumes your daily quota** — the command checks eligibility first and
125
+ tells you if you are out.
126
+
127
+ ### Get a submission's output
128
+
129
+ ```bash
130
+ codabench outputs 17525 --list # your submissions on the phase
131
+ codabench outputs 17525 # newest submission
132
+ codabench outputs 17525 --last 2 # the one before it
133
+ codabench outputs --submission 856524 # a specific id
134
+ codabench outputs 17525 --only scoring # just the scoring step
135
+ ```
136
+
137
+ Everything lands in `outputs/<submission id>/` with the zips extracted, plus a
138
+ `details.json` holding the scores, logs and exit statuses — which is usually where the
139
+ answer is when a submission fails.
140
+
141
+ ## Python API
142
+
143
+ ```python
144
+ from codabench import CodabenchClient, collect_files, find_phase
145
+
146
+ client = CodabenchClient() # reads .env / environment
147
+
148
+ competition = client.competition(17363) # id or URL
149
+ phase = find_phase(competition) # the open phase
150
+
151
+ for entry in collect_files(competition):
152
+ path = client.download_dataset(entry.key, "input/", entry.filename)
153
+ print(entry.name, "->", path or "not authorized")
154
+
155
+ submission = client.submit(phase["id"], "run.zip")
156
+ client.wait_for_submission(submission["id"])
157
+ print(client.results(submission["id"])["metrics"])
158
+ ```
159
+
160
+ The client raises `CodabenchError` (with `AuthError` and `ApiError` subclasses) and
161
+ never calls `sys.exit`, so it is safe to use inside a notebook or a larger program.
162
+
163
+ ## What you can actually download
164
+
165
+ This trips everyone up, so it is worth stating plainly. Codabench decides per file, and
166
+ this tool cannot widen what your account is allowed to see:
167
+
168
+
169
+ | File | Who can download it |
170
+ | --------------------------------- | ----------------------------------------------------------------------- |
171
+ | Starting kit, public data | Any approved participant |
172
+ | Ingestion / scoring program | Participants**only if** the organizer set `make_programs_available` |
173
+ | Input data | Participants**only if** the organizer set `make_input_data_available` |
174
+ | Reference data (the answer key) | Organizers only, always |
175
+ | Competition bundle | Organizers only |
176
+
177
+ Files your account may not fetch are skipped, not treated as an error. `codabench show`
178
+ prints the organizer's two flags so you can see why something is missing.
179
+
180
+ ## How authentication works
181
+
182
+ Codabench uses **two** mechanisms and you need both — the reason `CodabenchClient` holds
183
+ a token *and* a session:
184
+
185
+
186
+ | Endpoint | Auth |
187
+ | ----------------------------- | ------------------------------------------------------- |
188
+ | `/api/...` | Token from`POST /api/api-token-auth/` |
189
+ | `/datasets/download/<key>/` | Django**session cookie** from `POST /accounts/login/` |
190
+
191
+ The download route behind the "Files" tab is a plain Django view that ignores the API
192
+ token, which is why a token-only client gets 403s on files a participant can plainly
193
+ download in the browser. Both schemes read the same credentials, so callers never have
194
+ to think about it.
195
+
196
+ (There is also `GET /api/competitions/{id}/get_files/`, but it is organizer-only and
197
+ returns 403 for participants — this package does not rely on it.)
198
+
199
+ ## Repository layout
200
+
201
+ ```
202
+ codabench/ the library
203
+ ├── auth.py credentials, token auth, session login
204
+ ├── client.py CodabenchClient — every API call
205
+ ├── competitions.py pure helpers over a competition payload
206
+ ├── downloads.py saving & extracting artifacts
207
+ ├── text.py HTML→text, slugs, sizes
208
+ ├── errors.py CodabenchError / AuthError / ApiError
209
+ └── cli.py the `codabench` command
210
+
211
+ examples/ the same flows as standalone scripts
212
+ ├── 01_show_competition.py
213
+ ├── 02_download_competition_files.py
214
+ ├── 03_submit_and_wait.py
215
+ ├── 04_download_submission_outputs.py
216
+ ├── 05_create_competition.py
217
+ └── 06_rerun_submission.py
218
+
219
+ assets/ a sample submission zip and competition bundle
220
+ ```
221
+
222
+ Run any example directly — no install needed:
223
+
224
+ ```bash
225
+ python examples/01_show_competition.py 17363
226
+ ```
227
+
228
+ ## Notes
229
+
230
+ * **Organizers**: `codabench create -b bundle.zip` uploads a competition bundle and polls
231
+ until it is unpacked. Try it on `https://dev.codabench.org/` first.
232
+ * **Robot accounts**: `codabench rerun` re-runs an existing submission against another
233
+ task, reusing the uploaded data. It needs an account flagged `is_bot`, or the API
234
+ answers 403.
235
+
236
+ ## License
237
+
238
+ MIT.
@@ -0,0 +1,56 @@
1
+ """A small, readable Python client for the `Codabench <https://www.codabench.org/>`_ API.
2
+
3
+ Typical use::
4
+
5
+ from codabench import CodabenchClient
6
+
7
+ client = CodabenchClient() # reads .env / environment
8
+ competition = client.competition(17363) # URL or id both work
9
+ for f in collect_files(competition):
10
+ client.download_dataset(f.key, "input/", f.filename)
11
+
12
+ Every command in the ``codabench`` CLI is a thin wrapper over these methods —
13
+ see ``examples/`` for the same flows written as standalone scripts.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ from .auth import Credentials, DEFAULT_URL, load_dotenv
19
+ from .client import ARTIFACTS, CodabenchClient, TERMINAL_STATES, default_env_path
20
+ from .competitions import (
21
+ CompetitionFile,
22
+ collect_files,
23
+ description_markdown,
24
+ find_phase,
25
+ pages,
26
+ parse_competition_id,
27
+ phases,
28
+ primary_metric,
29
+ save_description,
30
+ )
31
+ from .errors import ApiError, AuthError, CodabenchError
32
+
33
+ __version__ = "0.1.0"
34
+
35
+ __all__ = [
36
+ "ARTIFACTS",
37
+ "ApiError",
38
+ "AuthError",
39
+ "CodabenchClient",
40
+ "CodabenchError",
41
+ "CompetitionFile",
42
+ "Credentials",
43
+ "DEFAULT_URL",
44
+ "TERMINAL_STATES",
45
+ "__version__",
46
+ "collect_files",
47
+ "default_env_path",
48
+ "description_markdown",
49
+ "find_phase",
50
+ "load_dotenv",
51
+ "pages",
52
+ "parse_competition_id",
53
+ "phases",
54
+ "primary_metric",
55
+ "save_description",
56
+ ]
@@ -0,0 +1,8 @@
1
+ """Allow ``python -m codabench ...`` next to the installed ``codabench`` script."""
2
+
3
+ import sys
4
+
5
+ from .cli import main
6
+
7
+ if __name__ == "__main__":
8
+ sys.exit(main())