comparison 2.00/config.py @ 25:b500e117080e

Bug fixes and overhead reduction Added the --problem/-p option. (WARNING: not the same as the -p option of test.py 1.x.) The problem names supplied are not validated. Added zip_longest to compat.py. Experimental: problem names are now _always_ printed for multi-problem sets. Overhead: Escape presses are now checked only once every .15 seconds (at least kbhit() on Windows is very slow). Overhead: sleep(0) is now called in the time-control-and-Escape-watching loop (at least on Windows, it immediately transfers control to some waiting thread). Bug fix: compat.py now overwrites built-ins only while including testconfs (--help was broken in Python 2). Bug fix: ReadDeleting in config.py now closes the file it opens (especially important on Windows, where open files cannot be deleted). Bug fix: added callable to compat.py (it is absent from Python 3). Bug fix: the default (built-in) output validator now properly handles unwanted trailing data. Bug fix: testconfs in custom archives no more raise NameError. Bug fix: if a validator program cannot be launched, CannotStartValidator is now raised instead of the fatal OSError.
author Oleg Oshmyan <chortos@inbox.lv>
date Thu, 23 Sep 2010 23:05:58 +0000
parents c23d81f4a1a3
children dc4be35d17e0
comparison
equal deleted inserted replaced
24:c23d81f4a1a3 25:b500e117080e
2 # Copyright (c) 2010 Chortos-2 <chortos@inbox.lv> 2 # Copyright (c) 2010 Chortos-2 <chortos@inbox.lv>
3 3
4 from __future__ import division, with_statement 4 from __future__ import division, with_statement
5 5
6 try: 6 try:
7 from compat import *
7 import files 8 import files
8 except ImportError: 9 except ImportError:
9 import __main__ 10 import __main__
10 __main__.import_error(sys.exc_info()[1]) 11 __main__.import_error(sys.exc_info()[1])
11 else: 12 else:
59 # TODO: provide a message 60 # TODO: provide a message
60 raise AttributeError(name) 61 raise AttributeError(name)
61 62
62 # A helper context manager 63 # A helper context manager
63 class ReadDeleting(object): 64 class ReadDeleting(object):
64 __slots__ = 'name' 65 __slots__ = 'name', 'file'
65 66
66 def __init__(self, name): 67 def __init__(self, name):
67 self.name = name 68 self.name = name
68 69
69 def __enter__(self): 70 def __enter__(self):
70 try: 71 try:
71 return open(self.name, 'rU') 72 self.file = open(self.name, 'rU')
73 return self.file
72 except: 74 except:
73 try: 75 try:
74 self.__exit__(None, None, None) 76 self.__exit__(None, None, None)
75 except: 77 except:
76 pass 78 pass
77 raise 79 raise
78 80
79 def __exit__(self, exc_type, exc_val, exc_tb): 81 def __exit__(self, exc_type, exc_val, exc_tb):
82 self.file.close()
80 os.remove(self.name) 83 os.remove(self.name)
81 84
82 def load_problem(problem_name): 85 def load_problem(problem_name):
83 dwb = sys.dont_write_bytecode 86 dwb = sys.dont_write_bytecode
84 sys.dont_write_bytecode = True 87 sys.dont_write_bytecode = True
85 metafile = files.File('/'.join((problem_name, 'testconf.py')), True, 'configuration') 88 metafile = files.File('/'.join((problem_name, 'testconf.py')), True, 'configuration')
86 module = None 89 module = None
87 if zipimport and isinstance(metafile.archive, files.ZipArchive): 90 with CompatBuiltins():
88 try: 91 if zipimport and isinstance(metafile.archive, files.ZipArchive):
89 module = zipimport.zipimporter(os.path.dirname(metafile.full_real_path)).load_module('testconf') 92 try:
90 except zipimport.ZipImportError: 93 module = zipimport.zipimporter(os.path.dirname(metafile.full_real_path)).load_module('testconf')
91 pass 94 except zipimport.ZipImportError:
92 else: 95 pass
96 else:
97 del sys.modules['testconf']
98 if not module:
99 try:
100 with metafile.open() as f:
101 module = imp.load_module('testconf', f, metafile.full_real_path, ('.py', 'r', imp.PY_SOURCE))
102 # Handle the case when f is not a true file object but imp requires one
103 except ValueError:
104 # FIXME: 2.5 lacks the delete parameter
105 with tempfile.NamedTemporaryFile(delete=False) as f:
106 inputdatafname = f.name
107 metafile.copy(inputdatafname)
108 with ReadDeleting(inputdatafname) as f:
109 module = imp.load_module('testconf', f, metafile.full_real_path, ('.py', 'r', imp.PY_SOURCE))
93 del sys.modules['testconf'] 110 del sys.modules['testconf']
94 if not module:
95 try:
96 with metafile.open() as f:
97 module = imp.load_module('testconf', f, metafile.full_real_path, ('.py', 'r', imp.PY_SOURCE))
98 # Handle the case when f is not a true file object but imp requires one
99 except ValueError:
100 # FIXME: 2.5 lacks the delete parameter
101 with tempfile.NamedTemporaryFile(delete=False) as f:
102 inputdatafname = f.name
103 metafile.extract(inputdatafname)
104 with ReadDeleting(inputdatafname) as f:
105 module = imp.load_module('testconf', f, metafile.full_real_path, ('.py', 'r', imp.PY_SOURCE))
106 del sys.modules['testconf']
107 if hasattr(module, 'padwithzeroestolength'): 111 if hasattr(module, 'padwithzeroestolength'):
108 if not hasattr(module, 'padtests'): 112 if not hasattr(module, 'padtests'):
109 try: 113 try:
110 module.padtests = module.padwithzeroestolength[0] 114 module.padtests = module.padwithzeroestolength[0]
111 except TypeError: 115 except TypeError:
137 def load_global(): 141 def load_global():
138 dwb = sys.dont_write_bytecode 142 dwb = sys.dont_write_bytecode
139 sys.dont_write_bytecode = True 143 sys.dont_write_bytecode = True
140 metafile = files.File('testconf.py', True, 'configuration') 144 metafile = files.File('testconf.py', True, 'configuration')
141 module = None 145 module = None
142 if zipimport and isinstance(metafile.archive, files.ZipArchive): 146 with CompatBuiltins():
143 try: 147 if zipimport and isinstance(metafile.archive, files.ZipArchive):
144 module = zipimport.zipimporter(os.path.dirname(metafile.full_real_path)).load_module('testconf') 148 try:
145 except zipimport.ZipImportError: 149 module = zipimport.zipimporter(os.path.dirname(metafile.full_real_path)).load_module('testconf')
146 pass 150 except zipimport.ZipImportError:
147 else: 151 pass
152 else:
153 del sys.modules['testconf']
154 if not module:
155 try:
156 with metafile.open() as f:
157 module = imp.load_module('testconf', f, metafile.full_real_path, ('.py', 'r', imp.PY_SOURCE))
158 # Handle the case when f is not a true file object but imp requires one
159 except ValueError:
160 # FIXME: 2.5 lacks the delete parameter
161 with tempfile.NamedTemporaryFile(delete=False) as f:
162 inputdatafname = f.name
163 metafile.copy(inputdatafname)
164 with ReadDeleting(inputdatafname) as f:
165 module = imp.load_module('testconf', f, metafile.full_real_path, ('.py', 'r', imp.PY_SOURCE))
148 del sys.modules['testconf'] 166 del sys.modules['testconf']
149 if not module:
150 try:
151 with metafile.open() as f:
152 module = imp.load_module('testconf', f, metafile.full_real_path, ('.py', 'r', imp.PY_SOURCE))
153 # Handle the case when f is not a true file object but imp requires one
154 except ValueError:
155 # FIXME: 2.5 lacks the delete parameter
156 with tempfile.NamedTemporaryFile(delete=False) as f:
157 inputdatafname = f.name
158 metafile.extract(inputdatafname)
159 with ReadDeleting(inputdatafname) as f:
160 module = imp.load_module('testconf', f, metafile.full_real_path, ('.py', 'r', imp.PY_SOURCE))
161 del sys.modules['testconf']
162 for name in defaults_global: 167 for name in defaults_global:
163 setattr(module, name, getattr(module, name, defaults_global[name])) 168 setattr(module, name, getattr(module, name, defaults_global[name]))
164 global globalconf 169 global globalconf
165 globalconf = module 170 globalconf = module
166 sys.dont_write_bytecode = dwb 171 sys.dont_write_bytecode = dwb