@@ -55,8 +55,9 @@ def is_relative(url: str) -> bool:
55
55
(len(parsed.path)==0 or parsed.path[0]!='/'))
56
56
57
57
58
- def do_api_request(endpoint: str, method: str = 'GET', jsonData: dict = {},
59
- data: dict = {}, files: dict = {}, decode: bool = True):
58
+ def do_api_request(endpoint: str, method: str = 'GET', *,
59
+ data: dict = {}, files: dict = {}, jsonData: dict = {},
60
+ decode: bool = True, output_file: str = None):
60
61
'''Perform an API call to the given endpoint and return its data.
61
62
62
63
Based on whether `domjudge_api_url` is set, this will call the DOMjudge
@@ -69,9 +70,12 @@ def do_api_request(endpoint: str, method: str = 'GET', jsonData: dict = {},
69
70
jsonData (dict): the JSON data to PUT. Only used when method is PUT
70
71
data (dict): data to pass in a POST request
71
72
decode (bool): whether to decode the returned JSON data, default true
73
+ output_file (str): write API response to file, e.g. for binary content;
74
+ incompatible with decode=True.
72
75
73
76
Returns:
74
- The endpoint contents, either as raw bytes or JSON decoded.
77
+ The endpoint contents, either as raw bytes or JSON decoded, unless
78
+ output_file is specified.
75
79
76
80
Raises:
77
81
RuntimeError when the HTTP status code is non-2xx or the response
@@ -82,7 +86,7 @@ def do_api_request(endpoint: str, method: str = 'GET', jsonData: dict = {},
82
86
orig_kwargs = locals()
83
87
84
88
if domjudge_api_url is None and is_relative(endpoint):
85
- result = api_via_cli(endpoint, method, {}, {}, jsonData )
89
+ result = api_via_cli(endpoint, method, jsonData=jsonData, output_file=output_file )
86
90
else:
87
91
if not is_relative(endpoint):
88
92
raise RuntimeError(f'Cannot access non-relative URL {endpoint} without API base URL')
@@ -122,6 +126,10 @@ def do_api_request(endpoint: str, method: str = 'GET', jsonData: dict = {},
122
126
raise RuntimeError(e)
123
127
result = parse_api_response(endpoint, response)
124
128
129
+ if output_file is not None:
130
+ with open(output_file, 'wb') as f:
131
+ f.write(result)
132
+
125
133
if decode:
126
134
try:
127
135
result = json.loads(result)
@@ -141,7 +149,9 @@ def upload_file(endpoint: str, apifilename: str, file: str, data: dict = {}):
141
149
do_api_request(endpoint, 'POST', data=data, files={apifilename: file})
142
150
143
151
144
- def api_via_cli(endpoint: str, method: str = 'GET', data: dict = {}, files: dict = {}, jsonData: dict = {}):
152
+ def api_via_cli(endpoint: str, method: str = 'GET', *,
153
+ data: dict = {}, files: dict = {}, jsonData: dict = {},
154
+ output_file: str = None):
145
155
'''Perform the given API request using the CLI
146
156
147
157
Parameters:
@@ -150,6 +160,7 @@ def api_via_cli(endpoint: str, method: str = 'GET', data: dict = {}, files: dict
150
160
data (dict): the POST data to use. Only used when method is POST or PUT
151
161
files (dict): the files to use. Only used when method is POST or PUT
152
162
jsonData (dict): the JSON data to use. Only used when method is POST or PUT
163
+ output_file (str): write API response to file, e.g. for binary content
153
164
154
165
Returns:
155
166
The raw endpoint contents.
@@ -174,6 +185,9 @@ def api_via_cli(endpoint: str, method: str = 'GET', data: dict = {}, files: dict
174
185
if jsonData:
175
186
command.extend(['-j', json.dumps(jsonData)])
176
187
188
+ if output_file:
189
+ command.extend(['-o', output_file])
190
+
177
191
command.append(endpoint)
178
192
179
193
result = subprocess.run(command, capture_output=True)
0 commit comments