changeset 26:5bbb68833868

Output text improvements Detailed error messages are now printed in more cases and have only their first letter forced into lowercase. The description of the --update option now describes properly what it does.
author Oleg Oshmyan <chortos@inbox.lv>
date Thu, 23 Sep 2010 23:50:45 +0000
parents b500e117080e
children dc4be35d17e0
files 2.00/problem.py 2.00/test-svn.py 2.00/testcases.py
diffstat 3 files changed, 18 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/2.00/problem.py	Thu Sep 23 23:05:58 2010 +0000
+++ b/2.00/problem.py	Thu Sep 23 23:50:45 2010 +0000
@@ -32,9 +32,10 @@
 
 __all__ = 'Problem',
 
-# This should no more be needed; pass all work on to the TestCase inheritance tree
-# LIBRARY and STDIO refer to interactive aka reactive problems
-#BATCH, OUTONLY, LIBRARY, STDIO, BESTOUT = xrange(5)
+def strerror(e):
+	s = getattr(e, 'strerror')
+	if not s: s = str(e)
+	return ' (%s%s)' % (s[0].lower(), s[1:]) if s else ''
 
 class Cache(object):
 	def __init__(self, mydict):
@@ -95,41 +96,19 @@
 					else:
 						verdict = 'non-zero return code %d' % e.exitcode
 				except testcases.CannotStartTestee:
-					e = sys.exc_info()[1]
-					if e.upstream.strerror:
-						verdict = 'cannot launch the program to test (%s)' % e.upstream.strerror.lower()
-					else:
-						verdict = 'cannot launch the program to test'
+					verdict = 'cannot launch the program to test%s' % strerror(sys.exc_info()[1].upstream)
 				except testcases.CannotStartValidator:
-					e = sys.exc_info()[1]
-					if e.upstream.strerror:
-						verdict = 'cannot launch the validator (%s)' % e.upstream.strerror.lower()
-					else:
-						verdict = 'cannot launch the validator'
+					verdict = 'cannot launch the validator%s' % strerror(sys.exc_info()[1].upstream)
 				except testcases.CannotReadOutputFile:
-					e = sys.exc_info()[1]
-					if e.upstream.strerror:
-						verdict = 'cannot read the output file (%s)' % e.upstream.strerror.lower()
-					else:
-						verdict = 'cannot read the output file'
+					verdict = 'cannot read the output file%s' % strerror(sys.exc_info()[1].upstream)
 				except testcases.CannotReadInputFile:
-					e = sys.exc_info()[1]
-					if e.upstream.strerror:
-						verdict = 'cannot read the input file (%s)' % e.upstream.strerror.lower()
-					else:
-						verdict = 'cannot read the input file'
+					verdict = 'cannot read the input file%s' % strerror(sys.exc_info()[1].upstream)
 				except testcases.CannotReadAnswerFile:
-					e = sys.exc_info()[1]
-					if e.upstream.strerror:
-						verdict = 'cannot read the reference output file (%s)' % e.upstream.strerror.lower()
-					else:
-						verdict = 'cannot read the reference output file'
+					verdict = 'cannot read the reference output file%s' % strerror(sys.exc_info()[1].upstream)
 				except testcases.TestCaseNotPassed:
-					e = sys.exc_info()[1]
-					verdict = 'unspecified reason [this may be a bug in test.py] (%s)' % e
+					verdict = 'unspecified reason [this may be a bug in test.py]%s' % strerror(sys.exc_info()[1])
 				#except Exception:
-				#	e = sys.exc_info()[1]
-				#	verdict = 'unknown error [this may be a bug in test.py] (%s)' % e
+				#	verdict = 'unknown error [this may be a bug in test.py]%s' % strerror(sys.exc_info()[1])
 				else:
 					if hasattr(granted, '__iter__'):
 						granted, comment = granted
@@ -145,7 +124,7 @@
 						verdict = 'wrong answer' + comment
 					else:
 						verdict = 'partly correct' + comment
-				granted *= case.points
+					granted *= case.points
 				say('%g/%g, %s' % (granted, case.points, verdict))
 				real += granted
 			weighted = real * prob.config.taskweight / max if max else 0
--- a/2.00/test-svn.py	Thu Sep 23 23:05:58 2010 +0000
+++ b/2.00/test-svn.py	Thu Sep 23 23:50:45 2010 +0000
@@ -12,9 +12,9 @@
 
 # $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 = optparse.OptionParser(version='test.py '+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='check for an updated version of test.py')
+parser.add_option('-u', '--update', dest='update', action='store_true', default=False, help='update the installed test.py 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')
--- a/2.00/testcases.py	Thu Sep 23 23:05:58 2010 +0000
+++ b/2.00/testcases.py	Thu Sep 23 23:50:45 2010 +0000
@@ -292,7 +292,6 @@
 		else:
 			case.validator = case.problem.config.tester
 	
-	# TODO
 	def validate(case, output):
 		if not case.validator:
 			# Compare the output with the reference output
@@ -317,7 +316,7 @@
 			except OSError:
 				raise CannotStartValidator(sys.exc_info()[1])
 			comment = case.process.communicate()[0].strip()
-			match = re.match(r'(?i)(ok|correct|wrong(?:(?:\s|_)*answer)?)(?:$|\s+|[.,!:]+\s*)', comment)
+			match = re.match(r'(?i)(ok|(?:correct|wrong)(?:(?:\s|_)*answer)?)(?:$|\s+|[.,!:]+\s*)', comment)
 			if match:
 				comment = comment[match.end():]
 			if not case.problem.config.maxexitcode:
@@ -374,6 +373,7 @@
 							except MemoryError:
 								# If there is not enough memory for the forked test.py,
 								# opt for silent dropping of the limit
+								# TODO: show a warning somewhere
 								case.process = Popen(case.problem.config.path, stdin=infile, stdout=outfile, stderr=devnull, universal_newlines=True, bufsize=-1)
 						except OSError:
 							raise CannotStartTestee(sys.exc_info()[1])
@@ -424,6 +424,7 @@
 				except MemoryError:
 					# If there is not enough memory for the forked test.py,
 					# opt for silent dropping of the limit
+					# TODO: show a warning somewhere
 					case.process = Popen(case.problem.config.path, stdin=devnull, stdout=devnull, stderr=STDOUT)
 			except OSError:
 				raise CannotStartTestee(sys.exc_info()[1])
@@ -480,7 +481,7 @@
 	# The basic idea is to launch the program to be tested and the grader
 	# and to pipe their standard I/O from and to each other,
 	# and then to capture the grader's exit code and use it
-	# like the exit code of a test validator is used.
+	# like the exit code of an output validator is used.
 
 
 def load_problem(prob, _types={'batch'   : BatchTestCase,