Mercurial > ~astiob > upreckon > hgweb
view upreckon/config.py @ 164:b375daa74371
The first/only item of testconf.tester is now passed through nativize_path
author | Oleg Oshmyan <chortos@inbox.lv> |
---|---|
date | Fri, 10 Jun 2011 21:25:38 +0100 |
parents | 2db236d25ecd |
children | 161d78f52cc3 e0b2fbd7ebe0 |
line wrap: on
line source
# Copyright (c) 2010-2011 Chortos-2 <chortos@inbox.lv> from __future__ import division, with_statement from .compat import * from . import files from __main__ import options, args if files.ZipArchive: try: import zipimport except ImportError: zipimport = None else: zipimport = None import imp, os, posixpath, sys, tempfile __all__ = 'load_problem', 'load_global', 'globalconf', 'nativize_path' defaults_problem = {'kind': 'batch', 'usegroups': False, 'maxcputime': None, 'maxwalltime': None, 'maxmemory': None, 'dummies': (), 'testsexcluded': (), 'padtests': 0, 'paddummies': 0, 'taskweight': 100, 'groupweight': {}, 'pointmap': {}, 'stdio': False, 'dummyinname': '', 'dummyoutname': '', 'tester': None, 'maxexitcode': 0, 'inname': '', 'ansname': ''} defaults_global = {'problems': None, 'force_zero_exitcode': True} defaults_noerase = {'inname': '%.in', 'outname': '%.out', 'ansname': '%.ans'} patterns = ('inname', 'outname', 'ansname', 'testcaseinname', 'testcaseoutname', 'dummyinname', 'dummyoutname') class Config(object): __slots__ = 'modules', '__dict__' def __init__(self, *modules): self.modules = modules def __getattr__(self, name): for module in self.modules: try: return getattr(module, name) except AttributeError: pass # TODO: provide a message raise AttributeError(name) # A helper context manager class ReadDeleting(object): __slots__ = 'name', 'file' def __init__(self, name): self.name = name def __enter__(self): try: self.file = open(self.name, 'rU') return self.file except: try: self.__exit__(None, None, None) except: pass raise def __exit__(self, exc_type, exc_val, exc_tb): self.file.close() os.remove(self.name) def nativize_path(portable_path): if portable_path.startswith('//:'): return portable_path[3:] comps = portable_path.split('/') for i, comp in enumerate(comps): if comp == '..': comps[i] = os.path.pardir elif comp == '.': comps[i] = os.path.curdir native_path = os.path.join(*comps) if posixpath.isabs(portable_path) and not os.path.isabs(native_path): abspath = os.path.abspath(native_path) parent = os.path.dirname(abspath) while parent != abspath: abspath, parent = parent, os.path.dirname(parent) native_path = os.path.join(parent, native_path) elif not posixpath.isabs(portable_path) and os.path.isabs(native_path): native_path = os.path.sep + native_path if posixpath.isabs(portable_path) != os.path.isabs(native_path): raise ValueError('cannot make native path relative/absolute') return native_path def load_problem(problem_name): global builtins try: dwb = sys.dont_write_bytecode sys.dont_write_bytecode = True except AttributeError: pass metafile = files.File(problem_name + '/testconf.py', True, 'configuration') module = None with CompatBuiltins() as builtins: if zipimport and isinstance(metafile.archive, files.ZipArchive): try: module = zipimport.zipimporter(os.path.dirname(metafile.full_real_path)).load_module('testconf') except zipimport.ZipImportError: pass else: del sys.modules['testconf'] if not module: try: with metafile.open() as f: module = imp.load_module('testconf', f, metafile.full_real_path, ('.py', 'r', imp.PY_SOURCE)) # Handle the case when f is not a true file object but imp requires one except ValueError: # FIXME: 2.5 lacks the delete parameter with tempfile.NamedTemporaryFile(delete=False) as f: inputdatafname = f.name metafile.copy(inputdatafname) with ReadDeleting(inputdatafname) as f: module = imp.load_module('testconf', f, metafile.full_real_path, ('.py', 'r', imp.PY_SOURCE)) del sys.modules['testconf'] module = Config(module, globalconf) if hasattr(module, 'padwithzeroestolength'): if not hasattr(module, 'padtests'): try: module.padtests = module.padwithzeroestolength[0] except TypeError: module.padtests = module.padwithzeroestolength if not hasattr(module, 'paddummies'): try: module.paddummies = module.padwithzeroestolength[1] except TypeError: module.paddummies = module.padwithzeroestolength if (not hasattr(module, 'maxcputime') and not hasattr(module, 'maxwalltime') and hasattr(module, 'maxtime')): module.maxcputime = module.maxtime for name in defaults_problem: setattr(module, name, getattr(module, name, defaults_problem[name])) if not module.dummyinname: module.dummyinname = getattr(module, 'testcaseinname', module.dummyinname) if not module.dummyoutname: module.dummyoutname = getattr(module, 'testcaseoutname', module.dummyoutname) if hasattr(module, 'testee'): if isinstance(module.testee, basestring): module.path = nativize_path(module.testee) else: testee = tuple(module.testee) module.path = (nativize_path(testee[0]),) + testee[1:] elif not hasattr(module, 'path'): if hasattr(module, 'name'): module.path = module.name elif sys.platform != 'win32': module.path = os.path.join(os.path.curdir, problem_name) else: module.path = problem_name if module.tester: if isinstance(module.tester, basestring): module.tester = nativize_path(module.tester) else: tester = tuple(module.tester) module.tester = (nativize_path(tester[0]),) + tester[1:] for name in 'pointmap', 'groupweight': oldmap = getattr(module, name) if isinstance(oldmap, dict): newmap = {} for key in oldmap: if not options.legacy and isinstance(key, basestring): newmap[key] = oldmap[key] else: try: for k in key: newmap[k] = oldmap[key] except TypeError: newmap[key] = oldmap[key] setattr(module, name, newmap) if options.no_maxtime: module.maxcputime = module.maxwalltime = 0 if args: module.usegroups = False module.tests = args module.dummies = () try: sys.dont_write_bytecode = dwb except NameError: pass for name in patterns: if hasattr(module, name): setattr(module, name, getattr(module, name).replace('%', problem_name)) return module def load_global(): global builtins try: dwb = sys.dont_write_bytecode sys.dont_write_bytecode = True except AttributeError: pass metafile = files.File('testconf.py', True, 'configuration') module = None with CompatBuiltins() as builtins: if zipimport and isinstance(metafile.archive, files.ZipArchive): try: module = zipimport.zipimporter(os.path.dirname(metafile.full_real_path)).load_module('testconf') except zipimport.ZipImportError: pass else: del sys.modules['testconf'] if not module: try: with metafile.open() as f: module = imp.load_module('testconf', f, metafile.full_real_path, ('.py', 'r', imp.PY_SOURCE)) # Handle the case when f is not a true file object but imp requires one except ValueError: # FIXME: 2.5 lacks the delete parameter with tempfile.NamedTemporaryFile(delete=False) as f: inputdatafname = f.name metafile.copy(inputdatafname) with ReadDeleting(inputdatafname) as f: module = imp.load_module('testconf', f, metafile.full_real_path, ('.py', 'r', imp.PY_SOURCE)) del sys.modules['testconf'] for name in defaults_global: setattr(module, name, getattr(module, name, defaults_global[name])) if not options.erase: for name in defaults_noerase: setattr(module, name, getattr(module, name, defaults_noerase[name])) if hasattr(module, 'tasknames'): module.problems = module.tasknames global globalconf globalconf = module try: sys.dont_write_bytecode = dwb except NameError: pass return module