view upreckon-vcs @ 92:17041a71bc02

maxtime is now auto-converted to maxcputime
author Oleg Oshmyan <chortos@inbox.lv>
date Mon, 28 Feb 2011 16:10:41 +0000
parents c62c9bfd614a
children 796eb7667fb0 c4dba6d44194
line wrap: on
line source

#! /usr/bin/env python
# Copyright (c) 2009-2011 Chortos-2 <chortos@inbox.lv>

from __future__ import division, with_statement
import optparse, sys, compat

from compat import *

version = '2.00.0 ($$REV$$)'
parser = optparse.OptionParser(version='Upreckon '+version, epilog='Python 2.5 or newer is required.')
parser.add_option('-1', dest='legacy', action='store_true', default=False, help='handle configuration files in a way more compatible with test.py 1.x')
parser.add_option('-u', '--update', dest='update', action='store_true', default=False, help='update the installed Upreckon to the latest publicly available version')
parser.add_option('-p', '--problem', dest='problems', metavar='PROBLEM', action='append', help='test only the PROBLEM (this option can be specified more than once with different problem names, all of which will be tested)')
parser.add_option('-m', '--copy-io', dest='copyonly', action='store_true', default=False, help='create a copy of the input/output files of the last test case for manual testing and exit')
parser.add_option('-x', '--auto-exit', dest='pause', action='store_false', default=True, help='do not wait for a key to be pressed after finishing testing')
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')
parser.add_option('-t', '--detect-time', dest='autotime', action='store_true', default=False, help='spend a second detecting the most precise time measurement function')
parser.add_option('-k', '--skim', action='store_true', default=False, help='skip test groups as soon as one test case is failed')
parser.add_option('--no-time-limits', dest='no_maxtime', action='store_true', default=False, help='disable all time limits')

options, args = parser.parse_args()
parser.destroy()
del parser

if options.update:
	try:
		urllib, urlread = compat.import_urllib()
	except ImportError:
		sys.exit('Error: the urllib Python module is missing. Without it, an automatic update is impossible.')
	
	latesttext = urlread('http://chortos.selfip.net/~astiob/test.py/version.txt')
	latest = latesttext.split('.')
	installed = version.split('.')
	update = None
	
	if latest[0] > installed[0]:
		update = 'major'
	elif latest[0] == installed[0]:
		if latest[1] > installed[1]:
			update = 'feature'
		elif latest[1] == installed[1]:
			if latest[2] > installed[2]:
				update = 'bug-fixing'
			elif latest[2] == installed[2]:
				say('You are using the latest publicly available version of Upreckon (%s).' % latesttext)
				sys.exit()
	
	if not update:
		say('Your copy of Upreckon is newer (%s) than the publicly available version (%s).' % (version, latesttext))
		sys.exit()
	
	say('A %s update to Upreckon is available (%s). Downloading...' % (update, latesttext))
	sys.stdout.flush()
	# FIXME: need to update all files!
	urllib.urlretrieve('http://chortos.selfip.net/~astiob/test.py/test.py', sys.argv[0])
	say('Downloaded and installed. Now you are using Upreckon %s.' % latesttext)
	sys.exit()

import config, itertools, os, subprocess, sys, time

if options.legacy:
	compat.pseudobuiltins += 'xrange',

import testcases

try:
	from testcases import pause
except ImportError:
	pause = None

try:
	globalconf = config.load_global()

	# Do this check here so that if we have to warn them, we do it as early as possible
	if options.pause and not pause and not hasattr(globalconf, 'pause'):
		if os.name == 'posix':
			globalconf.pause = 'read -s -n 1'
			say('Warning: configuration variable pause is not defined; it was devised automatically but the choice might be incorrect, so Upreckon might exit immediately after the testing is completed.', file=sys.stderr)
			sys.stderr.flush()
		elif os.name == 'nt':
			globalconf.pause = 'pause'
		else:
			sys.exit('Error: configuration variable pause is not defined and cannot be devised automatically.')

	from problem import *

	# Support single-problem configurations
	if globalconf.problems is None:
		shouldprintnames = False
		globalconf.multiproblem = False
		globalconf.problems = os.path.curdir,
	else:
		globalconf.multiproblem = True
		shouldprintnames = True

	ntasks = 0
	nfulltasks = 0
	maxscore = 0
	realscore = 0

	for taskname in (globalconf.problems if not options.problems else options.problems):
		problem = Problem(taskname)
		
		if ntasks and not options.copyonly: say()
		if shouldprintnames: say(taskname)
		
		if options.copyonly:
			problem.copytestdata()
		else:
			real, max = problem.test()
		
		ntasks += 1
		nfulltasks += real == max
		realscore += real
		maxscore += max

	if options.copyonly:
		sys.exit()

	if ntasks != 1:
		say()
		say('Grand total: %g/%g weighted points; %d/%d problems solved fully' % (realscore, maxscore, nfulltasks, ntasks))
except KeyboardInterrupt:
	sys.exit('Exiting due to a keyboard interrupt.')

if options.pause:
	say('Press any key to exit...')
	sys.stdout.flush()
	
	if pause:
		pause()
	elif callable(globalconf.pause):
		globalconf.pause()
	else:
		with open(os.devnull, 'w') as devnull:
			subprocess.call(globalconf.pause, shell=True, stdout=devnull, stderr=subprocess.STDOUT)