changeset 23:c1f52b5d80d6

Compatibility and bug fixes -1 command line option added (currently only detects the presence of test groups). The ansname configuration variable is now (again) optional when output validators are used. Bug fix: path realization only looked at paths beginning with tests/. Bug fix: non-reiterable values of the tests configuration variable are now handled correctly. Bug fix: an exceptions was raised if a problem had no test cases.
author Oleg Oshmyan <chortos@inbox.lv>
date Wed, 22 Sep 2010 23:34:51 +0000
parents f07b7a431ea6
children c23d81f4a1a3
files 2.00/files.py 2.00/problem.py 2.00/test-svn.py 2.00/testcases.py
diffstat 4 files changed, 45 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/2.00/files.py	Wed Sep 22 22:01:56 2010 +0000
+++ b/2.00/files.py	Wed Sep 22 23:34:51 2010 +0000
@@ -196,7 +196,7 @@
 					if os.path.exists(path):
 						if self.realize_path_archive(open_archive(path), '', virtpath, path):
 							return True
-			elif self.realize_path(root, virtpath[1:], allow_root, hastests):
+			if self.realize_path(root, virtpath[1:], allow_root, hastests):
 				return True
 		else:
 			if not hastests:
--- a/2.00/problem.py	Wed Sep 22 22:01:56 2010 +0000
+++ b/2.00/problem.py	Wed Sep 22 23:34:51 2010 +0000
@@ -58,6 +58,7 @@
 		raise NotImplementedError
 	
 	def test(prob):
+		case = None
 		try:
 			real = max = ntotal = nvalued = ncorrect = ncorrectvalued = 0
 			for case in prob.testcases:
@@ -153,7 +154,7 @@
 				say('Problem total: %d/%d tests; %g/%g points; weighted score: %g/%g' % (ncorrect, ntotal, real, max, weighted, prob.config.taskweight))
 			return weighted, prob.config.taskweight
 		finally:
-			if options.erase and (not prob.config.stdio or case.validator):
+			if options.erase and (not prob.config.stdio or case and case.validator):
 				for var in 'in', 'out':
 					name = getattr(prob.config, var + 'name')
 					if name:
--- a/2.00/test-svn.py	Wed Sep 22 22:01:56 2010 +0000
+++ b/2.00/test-svn.py	Wed Sep 22 23:34:51 2010 +0000
@@ -13,6 +13,7 @@
 # $Rev$
 version = '2.00.0 (SVN r$$REV$$)'
 parser = optparse.OptionParser(version='test.py '+version, epilog='Python 2.5 or newer is required, unless you have a custom build of Python.')
+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='check for an updated version of test.py')
 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')
--- a/2.00/testcases.py	Wed Sep 22 22:01:56 2010 +0000
+++ b/2.00/testcases.py	Wed Sep 22 23:34:51 2010 +0000
@@ -327,8 +327,9 @@
 		else:                 
 			# Call the validator program
 			output.close()
-			case.open_outfile()
-			case.outfile.copy(case.problem.config.ansname)
+			if case.problem.config.ansname:
+				case.open_outfile()
+				case.outfile.copy(case.problem.config.ansname)
 			case.process = Popen(case.validator, stdin=devnull, stdout=PIPE, stderr=STDOUT, universal_newlines=True, bufsize=-1)
 			comment = case.process.communicate()[0].strip()
 			lower = comment.lower()
@@ -381,6 +382,7 @@
 			with context:
 				with open(inputdatafname, 'rU') as infile:
 					with tempfile.TemporaryFile('w+') if options.erase and not case.validator else open(case.problem.config.outname, 'w+') as outfile:
+						# TODO: make sure outfile.file is passed to Popen if needed
 						try:
 							try:
 								case.process = Popen(case.problem.config.path, stdin=infile, stdout=outfile, stderr=devnull, universal_newlines=True, bufsize=-1, preexec_fn=preexec_fn)
@@ -476,6 +478,42 @@
                                'outonly' : OutputOnlyTestCase,
                                'bestout' : BestOutputTestCase,
                                'reactive': ReactiveTestCase}):
+	if options.legacy:
+		prob.config.usegroups = False
+		prob.config.tests = list(prob.config.tests)
+		for i, name in enumerate(prob.config.tests):
+			try:
+				if len(name) > 1:
+					prob.config.usegroups = True
+					break
+				elif len(name):
+					prob.config.tests[i] = name[0]
+			except Exception:
+				try:
+					# Try to retrieve the first two test case ID's and cache them on success
+					prob.config.tests[i] = name = iter(name)
+				except TypeError:
+					continue
+				try:
+					try:
+						first = next(name)
+					except NameError:
+						# Python 2.5 lacks the next() built-in
+						first = name.next()
+				except StopIteration:
+					prob.config.tests[i] = ()
+				else:
+					try:
+						try:
+							second = next(name)
+						except NameError:
+							second = name.next()
+					except StopIteration:
+						prob.config.tests[i] = first
+					else:
+						prob.config.tests[i] = itertools.chain((first, second), name)
+						prob.config.usegroups = True
+						break
 	if prob.config.usegroups:
 		# FIXME: test groups should again be supported!
 		pass
@@ -488,7 +526,7 @@
 		try:
 			len(prob.config.tests)
 		except Exception:
-			prob.config.dummies = tuple(prob.config.tests)
+			prob.config.tests = tuple(prob.config.tests)
 		# First get prob.cache.padoutput right
 		for i in prob.config.dummies:
 			s = 'sample ' + str(i).zfill(prob.config.paddummies)