Skip to content

Commit 4ff100e

Browse files
committed
Move submit client closer to PEP 8
Fix all typing errors and style warnings reported by the `pycodestyle` tool. The max line length is not PEP 8, but limited to 120 characters. As working with mixed types such as `list | None` is annoying, the return value of `None` has been replaced with the empty lists and dictionaries for most functions, as this results in behavioural equivalent Python code in our case.
1 parent 91253db commit 4ff100e

File tree

1 file changed

+53
-38
lines changed

1 file changed

+53
-38
lines changed

submit/submit

Lines changed: 53 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import requests.utils
1717
import stat
1818
import sys
1919
import time
20+
from typing import NoReturn
2021
try:
2122
import magic
2223
except ModuleNotFoundError:
@@ -40,12 +41,14 @@ num_warnings = 0
4041

4142
headers = {'user-agent': f'domjudge-submit-client ({requests.utils.default_user_agent()})'}
4243

44+
4345
def confirm(message: str) -> bool:
4446
answer = ''
4547
while answer not in ['y', 'n']:
4648
answer = input(f'{message} (y/n) ').lower()
4749
return answer == 'y'
4850

51+
4952
def warn_user(msg: str):
5053
global num_warnings
5154
num_warnings += 1
@@ -54,18 +57,21 @@ def warn_user(msg: str):
5457
else:
5558
print(f'WARNING: {msg}!')
5659

57-
def usage(msg: str):
60+
61+
def usage(msg: str) -> NoReturn:
5862
logging.error(f'error: {msg}')
5963
print(f"Type '{sys.argv[0]} --help' to get help.")
6064
exit(1)
6165

62-
def error(msg: str):
66+
67+
def error(msg: str) -> NoReturn:
6368
logging.error(msg)
6469
exit(-1)
6570

71+
6672
def read_contests() -> list:
6773
'''Read all contests from the API.
68-
74+
6975
Returns:
7076
The contests or None if an error occurred.
7177
'''
@@ -74,28 +80,29 @@ def read_contests() -> list:
7480
data = do_api_request('contests')
7581
except RuntimeError as e:
7682
logging.warning(e)
77-
return None
83+
return []
7884

7985
if not isinstance(data, list):
8086
logging.warning("DOMjudge's API returned unexpected JSON data for endpoint 'contests'.")
81-
return None
87+
return []
8288

8389
contests = []
8490
for contest in data:
8591
if ('id' not in contest
86-
or 'shortname' not in contest
87-
or not contest['id']
88-
or not contest['shortname']):
92+
or 'shortname' not in contest
93+
or not contest['id']
94+
or not contest['shortname']):
8995
logging.warning("DOMjudge's API returned unexpected JSON data for 'contests'.")
90-
return None
96+
return []
9197
contests.append(contest)
9298

9399
logging.info(f'Read {len(contests)} contest(s) from the API.')
94100
return contests
95101

102+
96103
def read_languages() -> list:
97104
'''Read all languages for the current contest from the API.
98-
105+
99106
Returns:
100107
The languages or None if an error occurred.
101108
'''
@@ -105,22 +112,22 @@ def read_languages() -> list:
105112
data = do_api_request(endpoint)
106113
except RuntimeError as e:
107114
logging.warning(e)
108-
return None
115+
return []
109116

110117
if not isinstance(data, list):
111118
logging.warning("DOMjudge's API returned unexpected JSON data for endpoint 'languages'.")
112-
return None
119+
return []
113120

114121
languages = []
115122

116123
for item in data:
117124
if ('id' not in item
118-
or 'extensions' not in item
119-
or not item['id']
120-
or not isinstance(item['extensions'], list)
121-
or len(item['extensions']) == 0):
125+
or 'extensions' not in item
126+
or not item['id']
127+
or not isinstance(item['extensions'], list)
128+
or len(item['extensions']) == 0):
122129
logging.warning("DOMjudge's API returned unexpected JSON data for 'languages'.")
123-
return None
130+
return []
124131
language = {
125132
'id': item['id'],
126133
'name': item['name'],
@@ -134,9 +141,10 @@ def read_languages() -> list:
134141

135142
return languages
136143

144+
137145
def read_problems() -> list:
138146
'''Read all problems for the current contest from the API.
139-
147+
140148
Returns:
141149
The problems or None if an error occurred.
142150
'''
@@ -146,30 +154,31 @@ def read_problems() -> list:
146154
data = do_api_request(endpoint)
147155
except RuntimeError as e:
148156
logging.warning(e)
149-
return None
157+
return []
150158

151159
if not isinstance(data, list):
152160
logging.warning("DOMjudge's API returned unexpected JSON data for endpoint 'problems'.")
153-
return None
161+
return []
154162

155163
problems = []
156164

157165
for problem in data:
158166
if ('id' not in problem
159-
or 'label' not in problem
160-
or not problem['id']
161-
or not problem['label']):
167+
or 'label' not in problem
168+
or not problem['id']
169+
or not problem['label']):
162170
logging.warning("DOMjudge's API returned unexpected JSON data for 'problems'.")
163-
return None
171+
return []
164172
problems.append(problem)
165173

166174
logging.info(f'Read {len(problems)} problem(s) from the API.')
167175

168176
return problems
169177

178+
170179
def do_api_request(name: str):
171180
'''Perform an API call to the given endpoint and return its data.
172-
181+
173182
Parameters:
174183
name (str): the endpoint to call
175184
@@ -184,7 +193,7 @@ def do_api_request(name: str):
184193
raise RuntimeError('No baseurl set')
185194

186195
url = f'{baseurl}api/{api_version}{name}'
187-
196+
188197
logging.info(f'Connecting to {url}')
189198

190199
try:
@@ -203,6 +212,7 @@ def do_api_request(name: str):
203212

204213
return json.loads(response.text)
205214

215+
206216
def kotlin_base_entry_point(filebase: str) -> str:
207217
if filebase == "":
208218
return "_"
@@ -219,6 +229,7 @@ def kotlin_base_entry_point(filebase: str) -> str:
219229

220230
return filebase
221231

232+
222233
def get_epilog():
223234
'''Get the epilog for the help text.'''
224235

@@ -248,7 +259,7 @@ drop-down box in the web interface.'''
248259
language_part = 'For LANGUAGE use the ID or a common extension.'
249260
else:
250261
language_part = 'For LANGUAGE use one of the following IDs or extensions:'
251-
max_length = max([len(l['name']) for l in languages])
262+
max_length = max([len(L['name']) for L in languages])
252263
for language in languages:
253264
sorted_exts = ', '.join(sorted(language['extensions']))
254265
language_part += f"\n {language['name']:<{max_length}} - {sorted_exts}"
@@ -287,6 +298,7 @@ Submit multiple files (the problem and language are taken from the first):
287298

288299
return "\n\n".join(part for part in epilog_parts if part)
289300

301+
290302
def do_api_submit():
291303
'''Submit to the API with the given data.'''
292304

@@ -323,15 +335,16 @@ def do_api_submit():
323335
error(f'Parsing DOMjudge\'s API output failed: {e}')
324336

325337
if (not isinstance(submission, dict)
326-
or not 'id' in submission
327-
or not isinstance(submission['id'], str)):
338+
or 'id' not in submission
339+
or not isinstance(submission['id'], str)):
328340
error('DOMjudge\'s API returned unexpected JSON data.')
329341

330342
time = datetime.datetime.fromisoformat(submission['time']).strftime('%H:%M:%S')
331343
sid = submission['id']
332344
print(f"Submission received: id = s{sid}, time = {time}")
333345
print(f"Check {baseurl}team/submission/{sid} for the result.")
334346

347+
335348
version_text = '''
336349
submit -- part of DOMjudge
337350
Written by the DOMjudge developers
@@ -364,7 +377,8 @@ parser.add_argument('-c', '--contest', help='''submit for contest with ID or sho
364377
parser.add_argument('-p', '--problem', help='submit for problem with ID or label PROBLEM', default='')
365378
parser.add_argument('-l', '--language', help='submit in language with ID LANGUAGE', default='')
366379
parser.add_argument('-e', '--entry_point', help='set an explicit entry_point, e.g. the java main class')
367-
parser.add_argument('-v', '--verbose', help='increase verbosity', choices=loglevels.keys(), nargs='?', const='INFO', default='WARNING')
380+
parser.add_argument('-v', '--verbose',
381+
help='increase verbosity', choices=loglevels.keys(), nargs='?', const='INFO', default='WARNING')
368382
parser.add_argument('-q', '--quiet', help='suppress warning/info messages', action='store_true')
369383
parser.add_argument('-y', '--assume-yes', help='suppress user input and assume yes', action='store_true')
370384
parser.add_argument('-u', '--url', help='''submit to server with base address URL
@@ -377,7 +391,7 @@ verbosity = args.verbose
377391
if args.quiet:
378392
verbosity = 'ERROR'
379393

380-
logging.basicConfig(format=f'%(message)s', level=loglevels[verbosity])
394+
logging.basicConfig(format='%(message)s', level=loglevels[verbosity])
381395
logging.info(f'set verbosity to {verbosity}')
382396

383397
problem_id = args.problem
@@ -403,9 +417,9 @@ contests = read_contests() if baseurl else None
403417
if not contests and not args.help:
404418
logging.warning('Could not obtain active contests.')
405419

406-
my_contest = None
407-
my_language = None
408-
my_problem = None
420+
my_contest: dict = {}
421+
my_language: dict = {}
422+
my_problem: dict = {}
409423

410424
if not contest_id:
411425
if not contests:
@@ -423,8 +437,8 @@ elif contests:
423437
my_contest = contest
424438
break
425439

426-
languages = None
427-
problems = None
440+
languages: list = []
441+
problems: list = []
428442
if my_contest and baseurl:
429443
if 'allow_submit' in my_contest and not my_contest['allow_submit']:
430444
warn_user('Submissions for contest (temporarily) disabled')
@@ -470,7 +484,7 @@ for index, filename in enumerate(args.filename, 1):
470484
st = os.stat(filename)
471485
except FileNotFoundError:
472486
usage(f"Cannot find file `{filename}'.")
473-
487+
474488
logging.debug(f"submission file {index}: `{filename}'")
475489

476490
# Do some checks on submission file and warn user
@@ -496,6 +510,7 @@ for index, filename in enumerate(args.filename, 1):
496510

497511
filebase = os.path.basename(filenames[0])
498512

513+
ext = ""
499514
if '.' in filebase:
500515
dot = filebase.rfind('.')
501516
ext = filebase[dot+1:]
@@ -527,7 +542,7 @@ for problem in problems:
527542
break
528543

529544
if not my_problem:
530-
usage('No known problem specified or detected.')
545+
usage('No known problem specified or detected.')
531546

532547
# Guess entry point if not already specified.
533548
if not entry_point and my_language['entry_point_required']:

0 commit comments

Comments
 (0)