Skip to content

Add contest export script #3039

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open

Add contest export script #3039

wants to merge 12 commits into from

Conversation

eldering
Copy link
Member

Closes #2726

eldering added 11 commits July 9, 2025 00:39
…via CLI

Fetching the event feed from the API via `internalApiRequest` wasn't
working since it returns a StreamedResponse. Fix this by only using
an output buffer in `internalApiRequest` and only calling `ob_flush`
from `getEventFeedAction` if the top-level output buffer allows it.

Also return contents from `internalApiRequest` without JSON decoding
it, since the event feed endpoint is NDJSON, *not* JSON. Explicitly
decode the JSON at the other places calling internalApiRequest`.
This will be used by the contest export script for downloading
the event feed (NDJSON) and other files.

Also improve error reporting when an internal API call fails.
Also initialize `domjudge_api_url = None` and simply call the
API via CLI if `domjudge_api_url` is unset.
Capture all function parameters and pass these as is
to the function itself again, just now with the global
`ca_check = False`.
This follows the specifications correctly, but beware that
specifying a base URL that doesn't end with a `/` leads to
strange results, see #2378

Replace `exit(1)` by an exception so this can be caught also if this
code runs asynchronously in a thread or separate process.
This is needed for binary content that otherwise gets mangled
when fetched through the CLI.

Also force all but the `endpoint` and `method` parameters to
`do_api_request` to be named parameters to prevent mistakes.
This gives more flexibility for extension in the future and
leaves the default usage without arguments unchanged.
@eldering eldering force-pushed the add-contest-export branch from f55ed07 to d13e643 Compare July 15, 2025 19:39
Copy link
Member

@nickygerritsen nickygerritsen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some small comments but I like it

recurse_find_files(data[0], store_path, default_name)
else:
for i, item in enumerate(data):
recurse_find_files(item, store_path, f"{default_name}.{i}")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initially we pass '' in default_name, so this becomes .{i}? (same with .{key} below)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I think you're right. The idea is that this builds up a default file name while recursively descending into the object's structure. So at the base level you always find the object itself as a dict, and that means that at line 94 default_name is set to the property key, but as you say with a prefix .. So for example for multiple JPEG files in the array under contest.logo, their default names would become .logo.0.jpg, .logo.1.jpg. So that first . must indeed be stripped.


if ext == '.json':
data = json.loads(data)
store_path = name
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why use store_path here? Can't we just use name below?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think so. I guess this is a left-over of previous refactoring. It's a bit annoying that there's too many similar concepts floating around: name of the endpoint, endpoint path in the URL, path to store the downloaded endpoint data to on disk, and filename on disk.


parser = ArgumentParser(description='Import a contest archive to DOMjudge via the API.')
parser.add_argument('-d', '--dir', help="directory containing the contest archive, defaults to current directory")
parser.add_argument('-u', '--url', help="DOMjudge API URL to use, if not specified use the CLI interface")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might mean some of our automation scripts need to change. I do like it though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hadn't checked in ansible, but note that I added the dir argument and the default behaviour is as before. Did we ever explicitly pass the API base URL instead of using the CLI directly?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also see I forgot to change this in configure-contest too.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure actually. But if we do it's an easy change.

Co-authored-by: Nicky Gerritsen <nickygerritsen@me.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add export-contest script
2 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy