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
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add option to save API output to file
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.
  • Loading branch information
eldering committed Jul 15, 2025
commit d8db6cd5cbc122cb0c2643a5a7630fdb778998c4
2 changes: 1 addition & 1 deletion misc-tools/configure-domjudge.in
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ if os.path.exists('config.json'):
print(f' - missing keys from new config = {missing_keys}')
if diffs or new_keys or missing_keys:
if dj_utils.confirm(' - Upload these configuration changes?', True):
actual_config = dj_utils.do_api_request('config', 'PUT', expected_config)
actual_config = dj_utils.do_api_request('config', 'PUT', jsonData=expected_config)
diffs, new_keys, missing_keys = compare_configs(
actual_config=actual_config,
expected_config=expected_config
Expand Down
24 changes: 19 additions & 5 deletions misc-tools/dj_utils.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,9 @@ def is_relative(url: str) -> bool:
(len(parsed.path)==0 or parsed.path[0]!='/'))


def do_api_request(endpoint: str, method: str = 'GET', jsonData: dict = {},
data: dict = {}, files: dict = {}, decode: bool = True):
def do_api_request(endpoint: str, method: str = 'GET', *,
data: dict = {}, files: dict = {}, jsonData: dict = {},
decode: bool = True, output_file: str = None):
'''Perform an API call to the given endpoint and return its data.

Based on whether `domjudge_api_url` is set, this will call the DOMjudge
Expand All @@ -69,9 +70,12 @@ def do_api_request(endpoint: str, method: str = 'GET', jsonData: dict = {},
jsonData (dict): the JSON data to PUT. Only used when method is PUT
data (dict): data to pass in a POST request
decode (bool): whether to decode the returned JSON data, default true
output_file (str): write API response to file, e.g. for binary content;
incompatible with decode=True.

Returns:
The endpoint contents, either as raw bytes or JSON decoded.
The endpoint contents, either as raw bytes or JSON decoded, unless
output_file is specified.

Raises:
RuntimeError when the HTTP status code is non-2xx or the response
Expand All @@ -82,7 +86,7 @@ def do_api_request(endpoint: str, method: str = 'GET', jsonData: dict = {},
orig_kwargs = locals()

if domjudge_api_url is None and is_relative(endpoint):
result = api_via_cli(endpoint, method, {}, {}, jsonData)
result = api_via_cli(endpoint, method, jsonData=jsonData, output_file=output_file)
else:
if not is_relative(endpoint):
raise RuntimeError(f'Cannot access non-relative URL {endpoint} without API base URL')
Expand Down Expand Up @@ -122,6 +126,10 @@ def do_api_request(endpoint: str, method: str = 'GET', jsonData: dict = {},
raise RuntimeError(e)
result = parse_api_response(endpoint, response)

if output_file is not None:
with open(output_file, 'wb') as f:
f.write(result)

if decode:
try:
result = json.loads(result)
Expand All @@ -141,7 +149,9 @@ def upload_file(endpoint: str, apifilename: str, file: str, data: dict = {}):
do_api_request(endpoint, 'POST', data=data, files={apifilename: file})


def api_via_cli(endpoint: str, method: str = 'GET', data: dict = {}, files: dict = {}, jsonData: dict = {}):
def api_via_cli(endpoint: str, method: str = 'GET', *,
data: dict = {}, files: dict = {}, jsonData: dict = {},
output_file: str = None):
'''Perform the given API request using the CLI

Parameters:
Expand All @@ -150,6 +160,7 @@ def api_via_cli(endpoint: str, method: str = 'GET', data: dict = {}, files: dict
data (dict): the POST data to use. Only used when method is POST or PUT
files (dict): the files to use. Only used when method is POST or PUT
jsonData (dict): the JSON data to use. Only used when method is POST or PUT
output_file (str): write API response to file, e.g. for binary content

Returns:
The raw endpoint contents.
Expand All @@ -174,6 +185,9 @@ def api_via_cli(endpoint: str, method: str = 'GET', data: dict = {}, files: dict
if jsonData:
command.extend(['-j', json.dumps(jsonData)])

if output_file:
command.extend(['-o', output_file])

command.append(endpoint)

result = subprocess.run(command, capture_output=True)
Expand Down
14 changes: 13 additions & 1 deletion webapp/src/Command/CallApiActionCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ protected function configure(): void
'u',
InputOption::VALUE_REQUIRED,
'User to use for API requests. If not given, the first admin user will be used'
)
->addOption(
'output',
'o',
InputOption::VALUE_REQUIRED,
'Filename to write output to. Useful for binary content'
);
}

Expand Down Expand Up @@ -154,7 +160,13 @@ protected function execute(InputInterface $input, OutputInterface $output): int
return Command::FAILURE;
}

$output->writeln($response);
if ($filename = $input->getOption('output')) {
$fd = fopen($filename, 'w');
fwrite($fd, $response);
fclose($fd);
} else {
$output->write($response);
}
return Command::SUCCESS;
}
}
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