Mercurial > ~astiob > upreckon > hgweb
comparison upreckon/config.py @ 146:d5b6708c1955
Distutils support, reorganization and cleaning up
* Removed command-line options -t and -u.
* Reorganized code:
o all modules are now in package upreckon;
o TestCaseNotPassed and its descendants now live in a separate
module exceptions;
o load_problem now lives in module problem.
* Commented out mentions of command-line option -c in --help.
* Added a distutils-based setup.py.
author | Oleg Oshmyan <chortos@inbox.lv> |
---|---|
date | Sat, 28 May 2011 14:24:25 +0100 |
parents | config.py@6589511f5418 |
children | 006dce02752c |
comparison
equal
deleted
inserted
replaced
145:d2c266c8d820 | 146:d5b6708c1955 |
---|---|
1 # Copyright (c) 2010-2011 Chortos-2 <chortos@inbox.lv> | |
2 | |
3 from __future__ import division, with_statement | |
4 | |
5 from .compat import * | |
6 from . import files | |
7 from __main__ import options | |
8 | |
9 if files.ZipArchive: | |
10 try: | |
11 import zipimport | |
12 except ImportError: | |
13 zipimport = None | |
14 else: | |
15 zipimport = None | |
16 | |
17 import imp, os, sys, tempfile | |
18 | |
19 __all__ = 'load_problem', 'load_global', 'globalconf' | |
20 | |
21 defaults_problem = {'kind': 'batch', | |
22 'usegroups': False, | |
23 'maxcputime': None, | |
24 'maxwalltime': None, | |
25 'maxmemory': None, | |
26 'dummies': (), | |
27 'testsexcluded': (), | |
28 'padtests': 0, | |
29 'paddummies': 0, | |
30 'taskweight': 100, | |
31 'groupweight': {}, | |
32 'pointmap': {}, | |
33 'stdio': False, | |
34 'dummyinname': '', | |
35 'dummyoutname': '', | |
36 'tester': None, | |
37 'maxexitcode': 0, | |
38 'inname': '', | |
39 'ansname': ''} | |
40 defaults_global = {'problems': None, | |
41 'force_zero_exitcode': True} | |
42 defaults_noerase = {'inname': '%.in', | |
43 'outname': '%.out', | |
44 'ansname': '%.ans'} | |
45 patterns = ('inname', 'outname', 'ansname', 'testcaseinname', | |
46 'testcaseoutname', 'dummyinname', 'dummyoutname') | |
47 | |
48 class Config(object): | |
49 __slots__ = 'modules', '__dict__' | |
50 | |
51 def __init__(self, *modules): | |
52 self.modules = modules | |
53 | |
54 def __getattr__(self, name): | |
55 for module in self.modules: | |
56 try: | |
57 return getattr(module, name) | |
58 except AttributeError: | |
59 pass | |
60 # TODO: provide a message | |
61 raise AttributeError(name) | |
62 | |
63 # A helper context manager | |
64 class ReadDeleting(object): | |
65 __slots__ = 'name', 'file' | |
66 | |
67 def __init__(self, name): | |
68 self.name = name | |
69 | |
70 def __enter__(self): | |
71 try: | |
72 self.file = open(self.name, 'rU') | |
73 return self.file | |
74 except: | |
75 try: | |
76 self.__exit__(None, None, None) | |
77 except: | |
78 pass | |
79 raise | |
80 | |
81 def __exit__(self, exc_type, exc_val, exc_tb): | |
82 self.file.close() | |
83 os.remove(self.name) | |
84 | |
85 def load_problem(problem_name): | |
86 global builtins | |
87 try: | |
88 dwb = sys.dont_write_bytecode | |
89 sys.dont_write_bytecode = True | |
90 except AttributeError: | |
91 pass | |
92 metafile = files.File('/'.join((problem_name, 'testconf.py')), True, 'configuration') | |
93 module = None | |
94 with CompatBuiltins() as builtins: | |
95 if zipimport and isinstance(metafile.archive, files.ZipArchive): | |
96 try: | |
97 module = zipimport.zipimporter(os.path.dirname(metafile.full_real_path)).load_module('testconf') | |
98 except zipimport.ZipImportError: | |
99 pass | |
100 else: | |
101 del sys.modules['testconf'] | |
102 if not module: | |
103 try: | |
104 with metafile.open() as f: | |
105 module = imp.load_module('testconf', f, metafile.full_real_path, ('.py', 'r', imp.PY_SOURCE)) | |
106 # Handle the case when f is not a true file object but imp requires one | |
107 except ValueError: | |
108 # FIXME: 2.5 lacks the delete parameter | |
109 with tempfile.NamedTemporaryFile(delete=False) as f: | |
110 inputdatafname = f.name | |
111 metafile.copy(inputdatafname) | |
112 with ReadDeleting(inputdatafname) as f: | |
113 module = imp.load_module('testconf', f, metafile.full_real_path, ('.py', 'r', imp.PY_SOURCE)) | |
114 del sys.modules['testconf'] | |
115 module = Config(module, globalconf) | |
116 if hasattr(module, 'padwithzeroestolength'): | |
117 if not hasattr(module, 'padtests'): | |
118 try: | |
119 module.padtests = module.padwithzeroestolength[0] | |
120 except TypeError: | |
121 module.padtests = module.padwithzeroestolength | |
122 if not hasattr(module, 'paddummies'): | |
123 try: | |
124 module.paddummies = module.padwithzeroestolength[1] | |
125 except TypeError: | |
126 module.paddummies = module.padwithzeroestolength | |
127 if (not hasattr(module, 'maxcputime') and | |
128 not hasattr(module, 'maxwalltime') and | |
129 hasattr(module, 'maxtime')): | |
130 module.maxcputime = module.maxtime | |
131 for name in defaults_problem: | |
132 setattr(module, name, getattr(module, name, defaults_problem[name])) | |
133 if not module.dummyinname: | |
134 module.dummyinname = getattr(module, 'testcaseinname', module.dummyinname) | |
135 if not module.dummyoutname: | |
136 module.dummyoutname = getattr(module, 'testcaseoutname', module.dummyoutname) | |
137 if not hasattr(module, 'path'): | |
138 if hasattr(module, 'name'): | |
139 module.path = module.name | |
140 elif sys.platform != 'win32': | |
141 module.path = os.path.join(os.path.curdir, problem_name) | |
142 else: | |
143 module.path = problem_name | |
144 for name in 'pointmap', 'groupweight': | |
145 oldmap = getattr(module, name) | |
146 if isinstance(oldmap, dict): | |
147 newmap = {} | |
148 for key in oldmap: | |
149 if not options.legacy and isinstance(key, basestring): | |
150 newmap[key] = oldmap[key] | |
151 else: | |
152 try: | |
153 for k in key: | |
154 newmap[k] = oldmap[key] | |
155 except TypeError: | |
156 newmap[key] = oldmap[key] | |
157 setattr(module, name, newmap) | |
158 if options.no_maxtime: | |
159 module.maxcputime = module.maxwalltime = 0 | |
160 try: | |
161 sys.dont_write_bytecode = dwb | |
162 except NameError: | |
163 pass | |
164 for name in patterns: | |
165 if hasattr(module, name): | |
166 setattr(module, name, getattr(module, name).replace('%', problem_name)) | |
167 return module | |
168 | |
169 def load_global(): | |
170 global builtins | |
171 try: | |
172 dwb = sys.dont_write_bytecode | |
173 sys.dont_write_bytecode = True | |
174 except AttributeError: | |
175 pass | |
176 metafile = files.File('testconf.py', True, 'configuration') | |
177 module = None | |
178 with CompatBuiltins() as builtins: | |
179 if zipimport and isinstance(metafile.archive, files.ZipArchive): | |
180 try: | |
181 module = zipimport.zipimporter(os.path.dirname(metafile.full_real_path)).load_module('testconf') | |
182 except zipimport.ZipImportError: | |
183 pass | |
184 else: | |
185 del sys.modules['testconf'] | |
186 if not module: | |
187 try: | |
188 with metafile.open() as f: | |
189 module = imp.load_module('testconf', f, metafile.full_real_path, ('.py', 'r', imp.PY_SOURCE)) | |
190 # Handle the case when f is not a true file object but imp requires one | |
191 except ValueError: | |
192 # FIXME: 2.5 lacks the delete parameter | |
193 with tempfile.NamedTemporaryFile(delete=False) as f: | |
194 inputdatafname = f.name | |
195 metafile.copy(inputdatafname) | |
196 with ReadDeleting(inputdatafname) as f: | |
197 module = imp.load_module('testconf', f, metafile.full_real_path, ('.py', 'r', imp.PY_SOURCE)) | |
198 del sys.modules['testconf'] | |
199 for name in defaults_global: | |
200 setattr(module, name, getattr(module, name, defaults_global[name])) | |
201 if not options.erase: | |
202 for name in defaults_noerase: | |
203 setattr(module, name, getattr(module, name, defaults_noerase[name])) | |
204 if hasattr(module, 'tasknames'): | |
205 module.problems = module.tasknames | |
206 global globalconf | |
207 globalconf = module | |
208 try: | |
209 sys.dont_write_bytecode = dwb | |
210 except NameError: | |
211 pass | |
212 return module |