Mercurial > ~astiob > upreckon > hgweb
annotate test-svn.py @ 14:28b1f4853968
Get the latest published version from /test.py/version.txt
author | Oleg Oshmyan <chortos@inbox.lv> |
---|---|
date | Sat, 13 Mar 2010 00:04:57 +0000 |
parents | 7c6f02865bf6 |
children | c0e925ae721e |
rev | line source |
---|---|
0 | 1 #! /usr/bin/python |
3 | 2 # Copyright (c) 2009-2010 Chortos-2 <chortos@inbox.lv> |
0 | 3 |
4 import os, sys, shutil, time, subprocess, filecmp, optparse, signal, tempfile, tarfile, zipfile | |
5 | |
12
7c6f02865bf6
$Rev$ substitution hopefully works
Oleg Oshmyan <chortos@inbox.lv>
parents:
11
diff
changeset
|
6 # $Rev$ |
10
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
7 version = '1.21.0 (SVN r$$REV$$)' |
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
8 parser = optparse.OptionParser(version='test.py '+version, usage='usage: %prog [options] [problem names] [[path' + os.path.sep + 'to' + os.path.sep + ']solution-app] [test case numbers]\n\nTest case numbers can be specified in plain text or as a Python expression\nif there is only one positional argument.\n\nOnly problem names listed in testconf.py are recognized.') |
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
9 parser.add_option('-u', '--update', dest='update', action='store_true', default=False, help='check for an updated version of test.py') |
0 | 10 parser.add_option('-e', '--exclude', dest='exclude', action='append', help='test case number(s) to exclude, as a Python expression; multiple -e options can be supplied') |
11 parser.add_option('-c', '--cleanup', dest='clean', action='store_true', default=False, help='delete the copies of input/output files and exit') | |
12 parser.add_option('-s', '--save-io', dest='erase', action='store_false', default=True, help='do not delete the copies of input/output files after the last test case; create copies of input files and store output in files even if the solution uses standard I/O; delete the stored input/output files if the solution uses standard I/O and the -c/--cleanup option is specified') | |
4 | 13 parser.add_option('-m', '--copy-io', dest='copyonly', action='store_true', default=False, help='only create a copy of the input/output files of the last test case for manual testing; to delete them, use options -cs or -cm') |
0 | 14 parser.add_option('-x', '--auto-exit', dest='pause', action='store_false', default=True, help='do not wait for a key to be pressed when finished testing') |
15 parser.add_option('-p', '--python', action='store_true', default=False, help='always parse all positional arguments as a single Python expression (including the first argument even if it names an executable file)') | |
16 parser.add_option('-t', '--detect-time', dest='autotime', action='store_true', default=False, help='spend a second detecting the most precise time measurement function') | |
17 | |
18 options, args = parser.parse_args() | |
19 parser.destroy() | |
20 del parser | |
21 | |
10
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
22 def update(): |
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
23 import urllib |
14
28b1f4853968
Get the latest published version from /test.py/version.txt
Oleg Oshmyan <chortos@inbox.lv>
parents:
12
diff
changeset
|
24 latesttext = urllib.urlopen('http://chortos.selfip.net/~astiob/test.py/version.txt').read() |
28b1f4853968
Get the latest published version from /test.py/version.txt
Oleg Oshmyan <chortos@inbox.lv>
parents:
12
diff
changeset
|
25 latest = latesttext.split('.') |
10
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
26 installed = version.split('.') |
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
27 update = '' |
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
28 if latest[0] > installed[0]: |
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
29 update = 'major' |
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
30 elif latest[0] == installed[0]: |
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
31 if latest[1] > installed[1]: |
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
32 update = 'feature' |
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
33 elif latest[1] == installed[1]: |
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
34 if latest[2] > installed[2]: |
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
35 update = 'bug-fixing' |
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
36 elif latest[2] == installed[2]: |
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
37 print 'You are using the latest publicly available version of test.py.' |
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
38 return |
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
39 if update == '': |
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
40 print 'Your copy of test.py is newer than the publicly available version.' |
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
41 return |
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
42 print 'A ' + update + ' update to test.py is available. Downloading...' |
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
43 urllib.urlretrieve('http://chortos.selfip.net/~astiob/test.py/test.py', 'test.py') |
14
28b1f4853968
Get the latest published version from /test.py/version.txt
Oleg Oshmyan <chortos@inbox.lv>
parents:
12
diff
changeset
|
44 print 'Downloaded and installed. Now you are using test.py ' + latesttext + '.' |
10
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
45 |
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
46 if options.update: |
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
47 update() |
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
48 sys.exit() |
c87ec78f1fae
Auto-update and revision number reporting added
Oleg Oshmyan <chortos@inbox.lv>
parents:
9
diff
changeset
|
49 |
0 | 50 globals1 = set(globals()) |
51 | |
52 # Initialize some configuration variables with default values | |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
53 tasknames = (os.path.curdir,) |
0 | 54 maxtime = 0 |
55 tests = () | |
56 dummies = () | |
57 testsexcluded = () | |
58 padwithzeroestolength = 0 | |
59 taskweight = 100 | |
60 pointmap = {} | |
61 stdio = False | |
62 dummyinname = '' | |
63 dummyoutname = '' | |
64 tester = '' | |
5
eb15a5a9b026
Output validators can now award partial scores
Oleg Oshmyan <chortos@inbox.lv>
parents:
4
diff
changeset
|
65 maxexitcode = 0 |
0 | 66 |
67 def exectestconf_helper(name): | |
68 if os.path.isfile('tests.tar'): | |
69 f = tarfile.open('tests.tar') | |
70 try: | |
71 exec f.extractfile(name).read() in globals() | |
72 f.close() | |
73 return True | |
74 except KeyError: | |
75 f.close() | |
76 if os.path.isfile('tests.zip'): | |
77 f = zipfile.ZipFile('tests.zip') | |
78 try: | |
79 exec f.open(name, 'rU').read() in globals() | |
80 f.close() | |
81 return True | |
82 except KeyError: | |
83 f.close() | |
84 if os.path.isfile('tests.tgz'): | |
85 f = tarfile.open('tests.tgz') | |
86 try: | |
87 exec f.extractfile(name).read() in globals() | |
88 f.close() | |
89 return True | |
90 except KeyError: | |
91 f.close() | |
92 if os.path.isfile('tests.tar.gz'): | |
93 f = tarfile.open('tests.tar.gz') | |
94 try: | |
95 exec f.extractfile(name).read() in globals() | |
96 f.close() | |
97 return True | |
98 except KeyError: | |
99 f.close() | |
100 if os.path.isfile('tests.tbz2'): | |
101 f = tarfile.open('tests.tbz2') | |
102 try: | |
103 exec f.extractfile(name).read() in globals() | |
104 f.close() | |
105 return True | |
106 except KeyError: | |
107 f.close() | |
108 if os.path.isfile('tests.tar.bz2'): | |
109 f = tarfile.open('tests.tar.bz2') | |
110 try: | |
111 exec f.extractfile(name).read() in globals() | |
112 f.close() | |
113 return True | |
114 except KeyError: | |
115 f.close() | |
116 return False | |
117 | |
118 try: | |
119 execfile('testconf.py') | |
120 except IOError, error: | |
121 exc_info = sys.exc_info()[2] | |
122 try: | |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
123 execfile(os.path.join('tests', 'testconf.py')) |
0 | 124 except IOError: |
125 if not exectestconf_helper('testconf.py'): | |
126 raise IOError, (error.errno, 'The configuration file is missing', error.filename), exc_info | |
127 del exc_info | |
128 | |
129 globals2 = set(globals()) | |
130 globals2.remove('globals1') | |
131 globals2 -= globals1 | |
132 del globals1 | |
133 | |
134 shared = {} | |
135 g = globals() | |
136 for k in globals2: | |
137 shared[k] = g[k] | |
138 | |
139 newtasknames = [] | |
140 while len(args) and args[0] in tasknames: | |
141 newtasknames.append(args[0]) | |
142 del args[0] | |
143 if len(newtasknames): | |
144 tasknames = newtasknames | |
145 | |
146 scoresumoveralltasks = 0 | |
147 scoremaxoveralltasks = 0 | |
148 ntasks = 0 | |
149 nfulltasks = 0 | |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
150 cwd = '' # At any time this is either '' or taskname |
0 | 151 |
152 if options.autotime: | |
153 c = time.clock() | |
154 time.sleep(1) | |
155 c = time.clock() - c | |
156 if int(c + .99999) == 1: | |
157 clock = time.clock | |
158 else: | |
159 clock = time.time | |
160 elif os.name == 'nt': | |
161 clock = time.clock | |
162 else: | |
163 clock = time.time | |
164 | |
165 if options.copyonly: | |
166 options.erase = False | |
167 | |
168 def existstestcase_helper(name): | |
169 if os.path.isfile('tests.tar'): | |
170 f = tarfile.open('tests.tar') | |
171 try: | |
172 f.getmember(name) | |
173 f.close() | |
174 return True | |
175 except KeyError: | |
176 f.close() | |
177 if os.path.isfile('tests.zip'): | |
178 f = zipfile.ZipFile('tests.zip') | |
179 try: | |
180 f.getinfo(name) | |
181 f.close() | |
182 return True | |
183 except KeyError: | |
184 f.close() | |
185 if os.path.isfile('tests.tgz'): | |
186 f = tarfile.open('tests.tgz') | |
187 try: | |
188 f.getmember(name) | |
189 f.close() | |
190 return True | |
191 except KeyError: | |
192 f.close() | |
193 if os.path.isfile('tests.tar.gz'): | |
194 f = tarfile.open('tests.tar.gz') | |
195 try: | |
196 f.getmember(name) | |
197 f.close() | |
198 return True | |
199 except KeyError: | |
200 f.close() | |
201 if os.path.isfile('tests.tbz2'): | |
202 f = tarfile.open('tests.tbz2') | |
203 try: | |
204 f.getmember(name) | |
205 f.close() | |
206 return True | |
207 except KeyError: | |
208 f.close() | |
209 if os.path.isfile('tests.tar.bz2'): | |
210 f = tarfile.open('tests.tar.bz2') | |
211 try: | |
212 f.getmember(name) | |
213 f.close() | |
214 return True | |
215 except KeyError: | |
216 f.close() | |
217 return False | |
218 | |
219 def existstestcase(name): | |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
220 if os.path.isfile(os.path.join('tests', taskname, name)) or os.path.isfile(os.path.join('tests', name)): |
0 | 221 return True |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
222 if cwd and (os.path.isfile(os.path.join(oldcwd, 'tests', cwd, name)) or os.path.isfile(os.path.join(oldcwd, 'tests', name))): |
0 | 223 return True |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
224 if existstestcase_helper(os.path.join(taskname, name)) or existstestcase_helper(name): |
0 | 225 return True |
226 if cwd: | |
227 os.chdir(oldcwd) | |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
228 if existstestcase_helper(os.path.join(cwd, name)) or existstestcase_helper(name): |
0 | 229 os.chdir(cwd) |
230 return True | |
231 os.chdir(cwd) | |
232 return False | |
233 | |
234 def opentestcase_helper(name): | |
235 if os.path.isfile('tests.tar'): | |
236 f = tarfile.open('tests.tar') | |
237 try: | |
238 c = f.extractfile(name) | |
239 return c | |
240 except KeyError: | |
241 f.close() | |
242 if os.path.isfile('tests.zip'): | |
243 f = zipfile.ZipFile('tests.zip') | |
244 try: | |
245 c = f.open(name, 'rU') | |
246 f.close() | |
247 return c | |
248 except KeyError: | |
249 f.close() | |
250 if os.path.isfile('tests.tgz'): | |
251 f = tarfile.open('tests.tgz') | |
252 try: | |
253 c = f.extractfile(name) | |
254 return c | |
255 except KeyError: | |
256 f.close() | |
257 if os.path.isfile('tests.tar.gz'): | |
258 f = tarfile.open('tests.tar.gz') | |
259 try: | |
260 c = f.extractfile(name) | |
261 return c | |
262 except KeyError: | |
263 f.close() | |
264 if os.path.isfile('tests.tbz2'): | |
265 f = tarfile.open('tests.tbz2') | |
266 try: | |
267 c = f.extractfile(name) | |
268 return c | |
269 except KeyError: | |
270 f.close() | |
271 if os.path.isfile('tests.tar.bz2'): | |
272 f = tarfile.open('tests.tar.bz2') | |
273 try: | |
274 c = f.extractfile(name) | |
275 return c | |
276 except KeyError: | |
277 f.close() | |
278 return None | |
279 | |
280 def opentestcase(name): | |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
281 if os.path.isfile(os.path.join('tests', taskname, name)): |
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
282 return open(os.path.join('tests', taskname, name), 'rU') |
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
283 elif os.path.isfile(os.path.join('tests', name)): |
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
284 return open(os.path.join('tests', name), 'rU') |
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
285 f = opentestcase_helper(os.path.join(taskname, name)) |
0 | 286 if not f: |
287 f = opentestcase_helper(name) | |
288 if f: | |
289 return f | |
290 if cwd: | |
3 | 291 if os.path.isfile(os.path.join(oldcwd, 'tests', cwd, name)): |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
292 return open(os.path.join(oldcwd, 'tests', cwd, name), 'rU') |
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
293 elif os.path.isfile(os.path.join(oldcwd, 'tests', name)): |
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
294 return open(os.path.join(oldcwd, 'tests', name), 'rU') |
0 | 295 os.chdir(oldcwd) |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
296 f = opentestcase_helper(os.path.join(cwd, name)) |
0 | 297 if not f: |
298 f = opentestcase_helper(name) | |
299 os.chdir(cwd) | |
300 if f: | |
301 return f | |
302 raise KeyError, 'The test-case-defining file \'' + name + '\' cannot be found' | |
303 | |
304 def copytestcase_helper(name, target): | |
305 if os.path.isfile('tests.tar'): | |
306 f = tarfile.open('tests.tar') | |
307 try: | |
308 m = f.getmember(name) | |
309 m.name = target | |
310 f.extract(m) | |
311 f.close() | |
312 return True | |
313 except KeyError: | |
314 f.close() | |
315 if os.path.isfile('tests.zip'): | |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
316 if not os.path.isabs(target): |
0 | 317 f = zipfile.ZipFile('tests.zip') |
318 m = f.getinfo(name) | |
319 try: | |
320 m.filename = target | |
321 f.extract(m) | |
322 f.close() | |
323 return True | |
324 except KeyError: | |
325 f.close() | |
326 else: | |
327 oldcwd = os.getcwdu() | |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
328 os.chdir('/') # FIXME: portability? |
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
329 f = zipfile.ZipFile(os.path.join(oldcwd, 'tests.zip')) |
0 | 330 try: |
331 m = f.getinfo(name) | |
332 m.filename = target[1:] | |
333 f.extract(m) | |
334 f.close() | |
335 os.chdir(oldcwd) | |
336 return True | |
337 except KeyError: | |
338 f.close() | |
339 os.chdir(oldwcd) | |
340 if os.path.isfile('tests.tgz'): | |
341 f = tarfile.open('tests.tgz') | |
342 try: | |
343 m = f.getmember(name) | |
344 m.name = target | |
345 f.extract(m) | |
346 f.close() | |
347 return True | |
348 except KeyError: | |
349 f.close() | |
350 if os.path.isfile('tests.tar.gz'): | |
351 f = tarfile.open('tests.tar.gz') | |
352 try: | |
353 m = f.getmember(name) | |
354 m.name = target | |
355 f.extract(m) | |
356 f.close() | |
357 return True | |
358 except KeyError: | |
359 f.close() | |
360 if os.path.isfile('tests.tbz2'): | |
361 f = tarfile.open('tests.tbz2') | |
362 try: | |
363 m = f.getmember(name) | |
364 m.name = target | |
365 f.extract(m) | |
366 f.close() | |
367 return True | |
368 except KeyError: | |
369 f.close() | |
370 if os.path.isfile('tests.tar.bz2'): | |
371 f = tarfile.open('tests.tar.bz2') | |
372 try: | |
373 m = f.getmember(name) | |
374 m.name = target | |
375 f.extract(m) | |
376 f.close() | |
377 return True | |
378 except KeyError: | |
379 f.close() | |
380 return False | |
381 | |
382 def copytestcase(name, target): | |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
383 if os.path.isfile(os.path.join('tests', taskname, name)): |
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
384 shutil.copyfile(os.path.join('tests', taskname, name), target) |
0 | 385 return |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
386 elif os.path.isfile(os.path.join('tests', name)): |
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
387 shutil.copyfile(os.path.join('tests', name), target) |
0 | 388 return |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
389 if copytestcase_helper(os.path.join(taskname, name), target) or copytestcase_helper(name, target): |
0 | 390 return |
391 if cwd: | |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
392 if os.path.isfile(os.path.join(oldcwd, 'tests', cwd, name)): |
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
393 shutil.copyfile(os.path.join(oldcwd, 'tests', cwd, name), target) |
0 | 394 return |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
395 elif os.path.isfile(os.path.join(oldcwd, 'tests', name)): |
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
396 shutil.copyfile(os.path.join(oldcwd, 'tests', name), target) |
0 | 397 return |
398 os.chdir(oldcwd) | |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
399 if copytestcase_helper(os.path.join(cwd, name), target) or copytestcase_helper(name, target): |
0 | 400 os.chdir(cwd) |
401 return | |
402 os.chdir(cwd) | |
403 raise KeyError, 'The test-case-defining file \'' + name + '\' cannot be found' | |
404 | |
405 # Always chdir if the directory exists but use any existing config | |
406 def chdir_and_exec_testconf(): | |
407 global cwd | |
408 cwd = '' | |
409 if os.path.isdir(taskname): | |
410 os.chdir(taskname) | |
3 | 411 if taskname != os.path.curdir: |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
412 cwd = taskname |
0 | 413 try: |
414 execfile('testconf.py', globals()) | |
415 return | |
416 except IOError: | |
417 pass | |
418 if not cwd: | |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
419 if os.path.isfile(os.path.join('tests', taskname, 'testconf.py')): |
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
420 execfile(os.path.join('tests', taskname, 'testconf.py'), globals()) |
0 | 421 return |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
422 if os.path.isfile(os.path.join('tests', 'testconf.py')): |
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
423 execfile(os.path.join('tests', 'testconf.py'), globals()) |
0 | 424 return |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
425 if exectestconf_helper(os.path.join(taskname, 'testconf.py')) or exectestconf_helper('testconf.py'): |
0 | 426 return |
427 if cwd: | |
428 os.chdir(oldcwd) | |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
429 if os.path.isfile(os.path.join('tests', cwd, 'testconf.py')): |
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
430 execfile(os.path.join('tests', cwd, 'testconf.py'), globals()) |
0 | 431 os.chdir(cwd) |
432 return | |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
433 if os.path.isfile(os.path.join('tests', 'testconf.py')): |
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
434 execfile(os.path.join('tests', 'testconf.py'), globals()) |
0 | 435 os.chdir(cwd) |
436 return | |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
437 if exectestconf_helper(os.path.join(cwd, 'testconf.py')) or exectestconf_helper('testconf.py'): |
0 | 438 os.chdir(cwd) |
439 return | |
440 if os.path.isfile('testconf.py'): | |
441 execfile('testconf.py', globals()) | |
442 os.chdir(cwd) | |
443 return | |
444 os.chdir(cwd) | |
445 elif os.path.isfile('testconf.py'): | |
446 execfile('testconf.py', globals()) | |
447 return | |
448 raise KeyError, 'The configuration file for task ' + taskname + ' is missing' | |
449 | |
450 try: | |
451 name | |
452 namedefined = True | |
453 except Exception: | |
454 namedefined = False | |
455 | |
456 for taskname in tasknames: | |
457 if ntasks: | |
458 print | |
459 | |
460 try: | |
461 if len(tasknames) > 1: | |
462 print taskname | |
463 except Exception: | |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
464 if taskname != os.path.curdir or ntasks: |
0 | 465 print taskname |
466 | |
467 try: del inname | |
468 except NameError: pass | |
469 try: del outname | |
470 except NameError: pass | |
471 try: del ansname | |
472 except NameError: pass | |
473 | |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
474 if not namedefined and taskname != os.path.curdir: |
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
475 name = os.path.join(os.path.curdir, taskname) |
0 | 476 for k in shared: |
477 g[k] = shared[k] | |
478 | |
479 oldcwd = os.getcwdu() | |
480 chdir_and_exec_testconf() | |
481 | |
482 if options.clean: | |
483 try: | |
484 if not stdio or tester: | |
485 if not tester: | |
486 inname | |
487 outname | |
488 if tester: | |
489 ansname | |
490 except NameError, error: | |
491 raise NameError, 'configuration ' + str(error).replace('name ', 'variable ', 1), sys.exc_info()[2] | |
492 if not options.erase: | |
493 try: | |
494 inname = inname.replace('%', taskname) | |
495 except NameError: | |
496 inname = taskname + '.in' | |
497 try: | |
498 outname = outname.replace('%', taskname) | |
499 except NameError: | |
500 outname = taskname + '.out' | |
501 try: | |
502 ansname = ansname.replace('%', taskname) | |
503 except NameError: | |
504 ansname = taskname + '.ans' | |
4 | 505 elif not stdio or tester or not options.erase: |
0 | 506 inname = inname.replace('%', taskname) |
507 outname = outname.replace('%', taskname) | |
508 if tester: | |
509 ansname = ansname.replace('%', taskname) | |
510 if not stdio or tester or not options.erase: | |
511 if os.path.exists(inname): os.remove(inname) | |
512 if os.path.exists(outname): os.remove(outname) | |
513 if (tester or not options.erase) and ansname: | |
514 if os.path.exists(ansname): os.remove(ansname) | |
515 continue | |
516 | |
517 try: | |
518 name | |
519 except NameError, error: | |
520 if str(error).count('name') == 1: | |
521 raise NameError, 'configuration ' + str(error), sys.exc_info()[2] | |
522 else: | |
523 raise NameError, 'configuration ' + str(error).replace('name ', 'variable ', 1), sys.exc_info()[2] | |
524 | |
525 try: | |
526 if not stdio: | |
527 inname | |
528 outname | |
529 testcaseinname | |
530 if tester: | |
531 outname | |
532 if ansname: | |
533 testcaseoutname | |
534 else: | |
535 testcaseoutname | |
536 except NameError, error: | |
537 raise NameError, 'configuration ' + str(error).replace('name ', 'variable ', 1), sys.exc_info()[2] | |
538 | |
539 if not options.erase: | |
540 try: | |
541 inname | |
542 except NameError: | |
543 inname = taskname + '.in' | |
544 try: | |
545 outname | |
546 except NameError: | |
547 outname = taskname + '.out' | |
548 try: | |
549 ansname | |
550 except NameError: | |
551 ansname = taskname + '.ans' | |
552 | |
553 if options.pause: | |
554 try: | |
555 pause | |
556 except NameError, error: | |
557 if os.name == 'posix': | |
558 pause = 'read -s -n 1' | |
3 | 559 print 'Configuration ' + str(error).replace('name ', 'variable ') + '; it was devised automatically but the choice might be incorrect, so test.py might exit immediately after the testing is completed.' |
0 | 560 elif os.name == 'nt': |
561 pause = 'pause' | |
562 else: | |
563 raise NameError, 'configuration ' + str(error).replace('name ', 'variable ') + ' and cannot be devised automatically', sys.exc_info()[2] | |
564 | |
565 if not dummyinname: | |
566 dummyinname = testcaseinname | |
567 if not dummyoutname and (not tester or ansname): | |
568 dummyoutname = testcaseoutname | |
569 | |
570 dummyinname = dummyinname.replace('%', taskname) | |
571 dummyoutname = dummyoutname.replace('%', taskname) | |
572 testcaseinname = testcaseinname.replace('%', taskname) | |
573 if not stdio or not options.erase: | |
574 inname = inname.replace('%', taskname) | |
575 outname = outname.replace('%', taskname) | |
576 try: | |
577 ansname = ansname.replace('%', taskname) | |
578 except NameError: | |
579 pass | |
580 if tester: | |
581 try: inname = inname.replace('%', taskname) | |
582 except NameError: pass | |
583 outname = outname.replace('%', taskname) | |
584 if ansname: | |
585 ansname = ansname.replace('%', taskname) | |
586 testcaseoutname = testcaseoutname.replace('%', taskname) | |
587 else: | |
588 testcaseoutname = testcaseoutname.replace('%', taskname) | |
589 | |
590 if isinstance(padwithzeroestolength, tuple): | |
591 padwithzeroestolength, paddummieswithzeroestolength = padwithzeroestolength | |
592 else: | |
593 paddummieswithzeroestolength = padwithzeroestolength | |
594 | |
595 if options.python: | |
596 dummies = () | |
597 s = ' '.join(args) | |
598 tests = eval(s) | |
599 try: | |
600 tests.__iter__ | |
601 except AttributeError: | |
602 tests = (tests,) | |
603 elif len(args): | |
604 if os.path.exists(args[0]): | |
605 name = args[0] | |
606 del args[0] | |
607 if len(args) > 1: | |
608 dummies = () | |
609 tests = args | |
610 elif len(args): | |
611 dummies = () | |
612 s = args[0] | |
613 if len(s) < padwithzeroestolength: | |
614 s = s.zfill(padwithzeroestolength) | |
615 if existstestcase(testcaseinname.replace('$', s)): | |
616 tests = (s,) | |
617 else: | |
618 try: | |
619 tests = eval(args[0]) | |
620 try: | |
621 tests.__iter__ | |
622 except AttributeError: | |
623 tests = (tests,) | |
624 except Exception: | |
625 tests = (s,) | |
626 | |
627 if options.exclude: | |
628 testsexcluded = [] | |
629 for i in options.exclude: | |
630 v = eval(i) | |
631 try: | |
632 testsexcluded.extend(v) | |
633 except TypeError: | |
634 testsexcluded.append(v) | |
635 | |
636 # Windows doesn't like paths beginning with .\ and not ending with an extension | |
637 name = os.path.normcase(name) | |
2
bddcc05aba59
Finished path portability improvements
Oleg Oshmyan <chortos@inbox.lv>
parents:
1
diff
changeset
|
638 if os.name == 'nt' and name.startswith('.\\'): |
0 | 639 name = name[2:] |
640 | |
641 newpointmap = {} | |
642 | |
643 for i in pointmap: | |
644 try: | |
645 for j in i: | |
646 newpointmap[j] = pointmap[i] | |
647 except TypeError: | |
648 newpointmap[i] = pointmap[i] | |
649 | |
650 pointmap = newpointmap | |
651 | |
9
ed90b375d197
Award maxexitcode points by default
Oleg Oshmyan <chortos@inbox.lv>
parents:
6
diff
changeset
|
652 if not tester: |
ed90b375d197
Award maxexitcode points by default
Oleg Oshmyan <chortos@inbox.lv>
parents:
6
diff
changeset
|
653 maxexitcode = 0 |
ed90b375d197
Award maxexitcode points by default
Oleg Oshmyan <chortos@inbox.lv>
parents:
6
diff
changeset
|
654 |
0 | 655 if maxtime > 0: |
656 strmaxtime = '/%.3f' % maxtime | |
657 else: | |
658 strmaxtime = '' | |
659 | |
660 padoutputtolength = 0 | |
661 ntests = [] | |
662 | |
663 for j in dummies: | |
664 try: | |
665 j.__iter__ | |
666 except AttributeError: | |
667 j = (j,) | |
668 ntests.append((j, True)) | |
669 for i in j: | |
670 s = str(i) | |
671 if len(s) < paddummieswithzeroestolength: | |
672 s = s.zfill(paddummieswithzeroestolength) | |
673 s = 'sample ' + s | |
674 if padoutputtolength < len(s): | |
675 padoutputtolength = len(s) | |
676 | |
677 for j in tests: | |
678 try: | |
679 j.__iter__ | |
680 except AttributeError: | |
681 j = (j,) | |
682 ntests.append((j, False)) | |
683 for i in j: | |
684 s = str(i) | |
685 if len(s) < padwithzeroestolength: | |
686 s = s.zfill(padwithzeroestolength) | |
687 if padoutputtolength < len(s): | |
688 padoutputtolength = len(s) | |
689 | |
690 tests = ntests | |
691 score = maxpoints = ncorrect = ntotal = ncorrectvalued = nvalued = 0 | |
692 | |
693 if options.copyonly: | |
694 j, isdummy = tests[-1] | |
695 if isdummy: | |
696 realinname = dummyinname | |
697 realoutname = dummyoutname | |
698 else: | |
699 realinname = testcaseinname | |
700 realoutname = testcaseoutname | |
701 for i in j: | |
702 if i in testsexcluded and not isdummy: | |
703 continue | |
704 s = str(i) | |
705 if isdummy: | |
706 if len(s) < paddummieswithzeroestolength: | |
707 s = s.zfill(paddummieswithzeroestolength) | |
708 else: | |
709 if len(s) < padwithzeroestolength: | |
710 s = s.zfill(padwithzeroestolength) | |
711 copytestcase(realinname.replace('$', s), inname) | |
712 if ansname: | |
713 copytestcase(realoutname.replace('$', s), ansname) | |
714 continue | |
715 | |
716 for j, isdummy in tests: | |
717 ncorrectgrp = 0 | |
718 ntotalgrp = 0 | |
719 scoregrp = 0 | |
720 maxpointsgrp = 0 | |
721 if isdummy: | |
722 realinname = dummyinname | |
723 realoutname = dummyoutname | |
724 else: | |
725 realinname = testcaseinname | |
726 realoutname = testcaseoutname | |
727 for i in j: | |
728 if i in testsexcluded and not isdummy: | |
729 continue | |
730 ntotalgrp += 1 | |
731 s = str(i) | |
732 if isdummy: | |
733 npoints = 0 | |
734 if len(s) < paddummieswithzeroestolength: | |
735 s = s.zfill(paddummieswithzeroestolength) | |
736 spref = 'sample ' | |
737 else: | |
9
ed90b375d197
Award maxexitcode points by default
Oleg Oshmyan <chortos@inbox.lv>
parents:
6
diff
changeset
|
738 npoints = pointmap.get(None, maxexitcode if maxexitcode and isinstance(maxexitcode, int) else 1) |
0 | 739 npoints = pointmap.get(i, npoints) |
740 maxpointsgrp += npoints | |
741 if npoints: | |
742 nvalued += 1 | |
743 if len(s) < padwithzeroestolength: | |
744 s = s.zfill(padwithzeroestolength) | |
745 spref = '' | |
746 print ' ' * (padoutputtolength - len(spref + s)) + spref + s + ':', | |
747 sys.stdout.flush() | |
748 outputdata = open(os.devnull, 'w') | |
749 if stdio: | |
750 f = tempfile.NamedTemporaryFile(delete=False) | |
751 inputdatafname = f.name | |
752 f.close() | |
753 copytestcase(realinname.replace('$', s), inputdatafname) | |
754 inputdata = open(inputdatafname, 'rU') | |
755 if options.erase: | |
756 tempoutput = tempfile.TemporaryFile('w+') | |
757 else: | |
758 tempoutput = open(outname, 'w+') | |
759 try: | |
760 proc = subprocess.Popen(name, stdin=inputdata, stdout=tempoutput, stderr=outputdata, universal_newlines=True) | |
761 except OSError, error: | |
762 raise OSError, 'The program to be tested cannot be launched: ' + str(error), sys.exc_info()[2] | |
763 else: | |
764 if os.path.exists(outname): | |
765 os.remove(outname) | |
766 copytestcase(realinname.replace('$', s), inname) | |
767 try: | |
768 proc = subprocess.Popen(name, stdin=outputdata, stdout=outputdata, stderr=outputdata, universal_newlines=True) | |
769 except OSError, error: | |
770 raise OSError, 'The program to be tested cannot be launched: ' + str(error), sys.exc_info()[2] | |
771 cl = clock() | |
772 if maxtime > 0: | |
773 while 1: | |
774 proc.poll() | |
775 elapsed = clock() - cl | |
776 if proc.returncode == None: | |
777 if elapsed >= maxtime: | |
778 print '%.3f%s s, 0/%d, time limit exceeded' % (elapsed, strmaxtime, npoints) | |
779 sys.stdout.flush() | |
780 while proc.returncode == None: | |
781 try: | |
782 proc.terminate() | |
783 except OSError: | |
784 pass | |
785 except AttributeError: | |
786 try: | |
787 os.kill(proc.pid, signal.SIGTERM) | |
788 except Exception: | |
789 pass | |
790 proc.poll() | |
791 outputdata.close() | |
792 if stdio: | |
793 tempoutput.close() | |
794 break | |
795 else: | |
796 print '%.3f%s s,' % (elapsed, strmaxtime), | |
797 sys.stdout.flush() | |
798 elapsed = 0 | |
799 if stdio: | |
800 tempoutput.seek(0) | |
801 lines = tempoutput.readlines() | |
802 tempoutput.close() | |
803 break | |
804 if elapsed >= maxtime: | |
805 continue | |
806 else: | |
807 data = proc.communicate() | |
808 elapsed = clock() - cl | |
809 print '%.3f%s s,' % (elapsed, strmaxtime), | |
810 sys.stdout.flush() | |
811 if stdio: | |
812 tempoutput.seek(0) | |
813 lines = tempoutput.readlines() | |
814 tempoutput.close() | |
815 outputdata.close() | |
816 if stdio: | |
817 inputdata.close() | |
818 try: | |
819 os.unlink(inputdatafname) | |
820 except Exception: | |
821 pass | |
822 if proc.returncode > 0: | |
823 print '0/%d, non-zero return code %d' % (npoints, proc.returncode) | |
824 sys.stdout.flush() | |
825 elif proc.returncode < 0: | |
826 print '0/%d, terminated by signal %d' % (npoints, -proc.returncode) | |
827 sys.stdout.flush() | |
828 else: | |
829 if not tester: | |
830 if stdio: | |
831 outputdata = opentestcase(realoutname.replace('$', s)) | |
832 r = 0 | |
833 data = outputdata.read().splitlines(True) | |
834 if len(lines) != len(data): | |
835 r = 1 | |
836 else: | |
837 for i in zip(lines, data): | |
838 if i[0] != i[1]: | |
839 r = 1 | |
840 break | |
841 outputdata.close() | |
842 else: | |
843 try: | |
844 inputdata = open(outname, 'rU') | |
845 except IOError: | |
846 print '0/%g, output file not created or not readable' % npoints | |
847 sys.stdout.flush() | |
848 r = None | |
849 else: | |
850 outputdata = opentestcase(realoutname.replace('$', s)) | |
851 r = 0 | |
852 lines = inputdata.readlines() | |
853 data = outputdata.read().splitlines(True) | |
854 if len(lines) != len(data): | |
855 r = 1 | |
856 else: | |
857 for i in zip(lines, data): | |
858 if i[0] != i[1]: | |
859 r = 1 | |
860 break | |
861 inputdata.close() | |
862 outputdata.close() | |
863 else: | |
864 if ansname: | |
865 copytestcase(realoutname.replace('$', s), ansname) | |
866 if stdio: | |
867 try: copytestcase(realinname.replace('$', s), inname) | |
868 except NameError: pass | |
869 outputdata = open(outname, 'w') | |
870 outputdata.writelines(lines) | |
871 outputdata.close() | |
872 try: | |
873 proc = subprocess.Popen(tester, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True) | |
874 except OSError, error: | |
875 raise OSError, 'The tester application cannot be launched: ' + str(error), sys.exc_info()[2] | |
876 data = proc.communicate() | |
877 r = proc.returncode | |
878 if tester and data[0]: | |
879 data = ''.join((' (', data[0].strip(), ')')) | |
880 else: | |
881 data = '' | |
5
eb15a5a9b026
Output validators can now award partial scores
Oleg Oshmyan <chortos@inbox.lv>
parents:
4
diff
changeset
|
882 if not maxexitcode and r or maxexitcode and not r: |
0 | 883 print '0/%g, wrong answer%s' % (npoints, data) |
884 sys.stdout.flush() | |
5
eb15a5a9b026
Output validators can now award partial scores
Oleg Oshmyan <chortos@inbox.lv>
parents:
4
diff
changeset
|
885 elif not maxexitcode and r == 0 or maxexitcode and r >= maxexitcode: |
0 | 886 print '%g/%g, OK%s' % (npoints, npoints, data) |
887 sys.stdout.flush() | |
888 scoregrp += npoints | |
889 ncorrectgrp += 1 | |
890 if npoints: | |
891 ncorrectvalued += 1 | |
5
eb15a5a9b026
Output validators can now award partial scores
Oleg Oshmyan <chortos@inbox.lv>
parents:
4
diff
changeset
|
892 elif maxexitcode and r != None: |
eb15a5a9b026
Output validators can now award partial scores
Oleg Oshmyan <chortos@inbox.lv>
parents:
4
diff
changeset
|
893 actualpoints = npoints*r/maxexitcode if not npoints*r%maxexitcode else float(npoints*r)/maxexitcode |
eb15a5a9b026
Output validators can now award partial scores
Oleg Oshmyan <chortos@inbox.lv>
parents:
4
diff
changeset
|
894 print '%g/%g, partly OK%s' % (actualpoints, npoints, data) |
eb15a5a9b026
Output validators can now award partial scores
Oleg Oshmyan <chortos@inbox.lv>
parents:
4
diff
changeset
|
895 sys.stdout.flush() |
eb15a5a9b026
Output validators can now award partial scores
Oleg Oshmyan <chortos@inbox.lv>
parents:
4
diff
changeset
|
896 scoregrp += actualpoints |
eb15a5a9b026
Output validators can now award partial scores
Oleg Oshmyan <chortos@inbox.lv>
parents:
4
diff
changeset
|
897 ncorrectgrp += 1 |
eb15a5a9b026
Output validators can now award partial scores
Oleg Oshmyan <chortos@inbox.lv>
parents:
4
diff
changeset
|
898 if npoints: |
eb15a5a9b026
Output validators can now award partial scores
Oleg Oshmyan <chortos@inbox.lv>
parents:
4
diff
changeset
|
899 ncorrectvalued += 1 |
0 | 900 if ntotalgrp: |
6
b0034b18f942
maxexitcode now gets on with test groups
Oleg Oshmyan <chortos@inbox.lv>
parents:
5
diff
changeset
|
901 if ncorrectgrp < ntotalgrp: |
0 | 902 scoregrp = 0 |
903 if ntotalgrp > 1: | |
904 print 'Group total: %d/%d tests; %g/%g points' % (ncorrectgrp, ntotalgrp, scoregrp, maxpointsgrp) | |
905 sys.stdout.flush() | |
906 ncorrect += ncorrectgrp | |
907 ntotal += ntotalgrp | |
908 score += scoregrp | |
909 maxpoints += maxpointsgrp | |
910 | |
911 if options.erase: | |
912 if not stdio or tester: | |
913 if os.path.exists(inname): os.remove(inname) | |
914 if os.path.exists(outname): os.remove(outname) | |
915 if tester and ansname: | |
916 if os.path.exists(ansname): os.remove(ansname) | |
917 elif stdio: | |
918 copytestcase(realinname.replace('$', s), inname) | |
919 copytestcase(realoutname.replace('$', s), ansname) | |
5
eb15a5a9b026
Output validators can now award partial scores
Oleg Oshmyan <chortos@inbox.lv>
parents:
4
diff
changeset
|
920 actualpoints = (score*taskweight/maxpoints if not score*taskweight%maxpoints else float(score*taskweight)/maxpoints) if maxpoints else 0 |
0 | 921 if nvalued != ntotal: |
5
eb15a5a9b026
Output validators can now award partial scores
Oleg Oshmyan <chortos@inbox.lv>
parents:
4
diff
changeset
|
922 print 'Grand total: %d/%d tests (%d/%d valued); %g/%g points; weighted score: %g/%g' % (ncorrect, ntotal, ncorrectvalued, nvalued, score, maxpoints, actualpoints, taskweight) |
0 | 923 else: |
5
eb15a5a9b026
Output validators can now award partial scores
Oleg Oshmyan <chortos@inbox.lv>
parents:
4
diff
changeset
|
924 print 'Grand total: %d/%d tests; %g/%g points; weighted score: %g/%g' % (ncorrect, ntotal, score, maxpoints, actualpoints, taskweight) |
0 | 925 |
5
eb15a5a9b026
Output validators can now award partial scores
Oleg Oshmyan <chortos@inbox.lv>
parents:
4
diff
changeset
|
926 scoresumoveralltasks += actualpoints |
0 | 927 scoremaxoveralltasks += taskweight |
928 ntasks += 1 | |
929 nfulltasks += int((score == maxpoints) if maxpoints else (taskweight == 0)) | |
930 | |
931 os.chdir(oldcwd) | |
932 | |
933 if options.clean or options.copyonly: | |
934 sys.exit() | |
935 | |
936 if ntasks != 1: | |
937 print | |
938 print 'Grand grand total: %g/%g weighted points; %d/%d problems solved fully' % (scoresumoveralltasks, scoremaxoveralltasks, nfulltasks, ntasks) | |
939 | |
940 if options.pause: | |
941 print 'Press any key to exit... ', | |
942 sys.stdout.flush() | |
943 os.system(pause + ' >' + os.devnull) |