Skip to content

Commit 7b8a5ef

Browse files
authored
Merge pull request #240 from JoelNiemela/add-type-annotations
Add python type annotations to `problem2{html,pdf}` and `verifyproblem`
2 parents 92dcbf3 + d5a3fa9 commit 7b8a5ef

File tree

4 files changed

+245
-290
lines changed

4 files changed

+245
-290
lines changed

problemtools/generatedata.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
ALL_EXTENSIONS = ['in', 'ans'] + Generators._VISUALIZER_EXTENSIONS
1515

16-
def argparser():
16+
def argparser() -> ArgumentParser:
1717
parser = ArgumentParser(description='Generate test data for a problem package in the Kattis problem format.')
1818
parser.add_argument('-g', '--generate',
1919
action='store_true',
@@ -31,7 +31,9 @@ def argparser():
3131
type=int,
3232
default=None,
3333
help='level of parallelism')
34+
3435
argparser_basic_arguments(parser)
36+
3537
parser.add_argument('problemdir', nargs='+')
3638
return parser
3739

@@ -41,10 +43,7 @@ def clean(prob, args):
4143
ProblemAspect.warnings = 0
4244
base_path = os.path.join(prob.probdir, 'data')
4345

44-
testcases = {
45-
case['path']: case
46-
for case in prob.generators._testcases
47-
}
46+
testcases = { case['path']: case for case in prob.generators._testcases }
4847

4948
def walk(name, path):
5049
case_count = 0
@@ -191,7 +190,6 @@ def generate_case(case_idx):
191190

192191

193192
def generate(prob, args):
194-
195193
# Create directory structure
196194
created = set()
197195
for case in prob.generators._testcases:

problemtools/problem2html.py

Lines changed: 26 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@
1414
from .ProblemPlasTeX import ProblemsetMacros
1515
from . import template
1616

17+
def convert(args: list[str]|None = None) -> None:
18+
options = parse_args(args)
1719

18-
def convert(problem, options=None):
19-
problem = os.path.realpath(problem)
20+
problem = os.path.realpath(options.problem)
2021

2122
problembase = os.path.splitext(os.path.basename(problem))[0]
2223
destdir = string.Template(options.destdir).safe_substitute(problem=problembase)
@@ -92,7 +93,7 @@ def convert(problem, options=None):
9293

9394
# identify any large generated files (especially images)
9495
if not options.quiet:
95-
for path, dirs, files in os.walk('.'):
96+
for path, _dirs, files in os.walk('.'):
9697
for f in files:
9798
file_size_kib = os.stat(os.path.join(path, f)).st_size // 1024
9899
if file_size_kib > 1024:
@@ -109,46 +110,31 @@ def convert(problem, options=None):
109110
# restore cwd
110111
os.chdir(origcwd)
111112

112-
return True
113-
114-
115-
class ConvertOptions:
116-
available = [
117-
['bodyonly', 'store_true', '-b', '--body-only',
118-
'only generate HTML body, no HTML headers', False],
119-
['css', 'store_false', '-c', '--no-css',
120-
"don't copy CSS file to output directory", True],
121-
['headers', 'store_false', '-H', '--headers',
122-
"don't generate problem headers (title, problem id, time limit)", True],
123-
['tidy', 'store_false', '-m', '--messy',
124-
"don't run tidy to postprocess the HTML", True],
125-
['destdir', 'store', '-d', '--dest-dir',
126-
"output directory", '${problem}_html'],
127-
['destfile', 'store', '-f', '--dest-file',
128-
"output file name", 'index.html'],
129-
['language', 'store', '-l', '--language',
130-
'choose alternate language (2-letter code)', None],
131-
['loglevel', 'store', '-L', '--log-level',
132-
'set log level (debug, info, warning, error, critical)', 'warning'],
133-
['quiet', 'store_true', '-q', '--quiet',
134-
"quiet", False],
135-
]
136-
137-
def __init__(self):
138-
for (dest, _, _, _, _, default) in ConvertOptions.available:
139-
setattr(self, dest, default)
140-
self.imgbasedir = ''
141-
142-
143-
def main():
144-
options = ConvertOptions()
113+
114+
def parse_args(args: list[str]|None) -> argparse.Namespace:
145115
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
146-
for (dest, action, short, _long, _help, default) in ConvertOptions.available:
147-
parser.add_argument(short, _long, dest=dest, help=_help, action=action, default=default)
116+
117+
parser.add_argument('-b', '--body-only', dest='bodyonly', action='store_true', help='only generate HTML body, no HTML headers', default=False)
118+
parser.add_argument('-c', '--no-css', dest='css', action='store_false', help="don't copy CSS file to output directory", default=True)
119+
parser.add_argument('-H', '--headers', dest='headers', action='store_false', help="don't generate problem headers (title, problem id, time limit)", default=True)
120+
parser.add_argument('-m', '--messy', dest='tidy', action='store_false', help="don't run tidy to postprocess the HTML", default=True)
121+
parser.add_argument('-d', '--dest-dir', dest='destdir', help="output directory", default='${problem}_html')
122+
parser.add_argument('-f', '--dest-file', dest='destfile', help="output file name", default='index.html')
123+
parser.add_argument('-l', '--language', dest='language', help='choose alternate language (2-letter code)', default=None)
124+
parser.add_argument('-L', '--log-level', dest='loglevel', help='set log level (debug, info, warning, error, critical)', default='warning')
125+
parser.add_argument('-q', '--quiet', dest='quiet', action='store_true', help="quiet", default=False)
148126
parser.add_argument('problem', help='the problem to convert')
149127

150-
options = parser.parse_args(namespace=options)
151-
convert(options.problem, options)
128+
if args is not None:
129+
options = parser.parse_args(args)
130+
else:
131+
options = parser.parse_args()
132+
133+
options.imgbasedir = ''
134+
return options
135+
136+
def main() -> None:
137+
convert()
152138

153139

154140
if __name__ == '__main__':

problemtools/problem2pdf.py

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,10 @@
88
from . import template
99

1010

11-
def convert(problem, options=None):
12-
if options is None:
13-
options = ConvertOptions()
11+
def convert(args: list[str]|None = None) -> bool:
12+
options = parse_args(args)
1413

15-
problem = os.path.realpath(problem)
14+
problem = os.path.realpath(options.problem)
1615
problembase = os.path.splitext(os.path.basename(problem))[0]
1716
destfile = string.Template(options.destfile).safe_substitute(problem=problembase)
1817

@@ -47,33 +46,23 @@ def convert(problem, options=None):
4746

4847
return status == 0
4948

49+
def parse_args(args: list[str]|None) -> argparse.Namespace:
50+
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
5051

51-
class ConvertOptions:
52-
available = [
53-
['destfile', 'store', '-o', '--output',
54-
"output file name", '${problem}.pdf'],
55-
['quiet', 'store_true', '-q', '--quiet',
56-
"quiet", False],
57-
['language', 'store', '-l', '--language',
58-
'choose alternate language (2-letter code)', None],
59-
['nopdf', 'store_true', '-n', '--no-pdf',
60-
'run pdflatex in -draftmode', False],
61-
]
52+
parser.add_argument('-o', '--output', dest='destfile', help="output file name", default='${problem}.pdf')
53+
parser.add_argument('-q', '--quiet', dest='quiet', action='store_true', help="quiet", default=False)
54+
parser.add_argument('-l', '--language', dest='language', help='choose alternate language (2-letter code)', default=None)
55+
parser.add_argument('-n', '--no-pdf', dest='nopdf', action='store_true', help='run pdflatex in -draftmode', default=False)
56+
parser.add_argument('problem', help='the problem to convert')
6257

63-
def __init__(self):
64-
for (dest, _, _, _, _, default) in ConvertOptions.available:
65-
setattr(self, dest, default)
58+
if args is not None:
59+
return parser.parse_args(args)
6660

61+
return parser.parse_args()
6762

68-
def main():
69-
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
70-
71-
for (dest, action, short, _long, _help, default) in ConvertOptions.available:
72-
parser.add_argument(short, _long, dest=dest, help=_help, action=action, default=default)
73-
parser.add_argument('problem', help='the problem to convert')
7463

75-
options = parser.parse_args()
76-
convert(options.problem, options)
64+
def main() -> None:
65+
convert()
7766

7867

7968
if __name__ == '__main__':

0 commit comments

Comments
 (0)