def compile_with_auxiliary_files(filenames, flags=[], lang=None, compiler_time_limit=None, should_cache=True): from dmoj.executors import executors from dmoj.executors.compiled_executor import CompiledExecutor sources = {} for filename in filenames: with open(filename, 'rb') as f: sources[os.path.basename(filename)] = f.read() def find_runtime(languages): for grader in languages: if grader in executors: return grader return None use_cpp = any( map(lambda name: os.path.splitext(name)[1] in ['.cpp', '.cc'], filenames)) use_c = any( map(lambda name: os.path.splitext(name)[1] in ['.c'], filenames)) if lang is None: best_choices = ('CPP20', 'CPP17', 'CPP14', 'CPP11', 'CPP03') if use_cpp else ('C11', 'C') lang = find_runtime(best_choices) executor = executors.get(lang) if not executor: raise IOError('could not find an appropriate C++ executor') executor = executor.Executor kwargs = {'fs': executor.fs + [tempfile.gettempdir()]} if issubclass(executor, CompiledExecutor): kwargs['compiler_time_limit'] = compiler_time_limit if hasattr(executor, 'flags'): kwargs['flags'] = flags + list(executor.flags) # Optimize the common case. if use_cpp or use_c: # Some auxiliary files (like those using testlib.h) take an extremely long time to compile, so we cache them. executor = executor('_aux_file', None, aux_sources=sources, cached=should_cache, **kwargs) else: if len(sources) > 1: raise InternalError( 'non-C/C++ auxilary programs cannot be multi-file') executor = executor('_aux_file', list(sources.values())[0], **kwargs) return executor
def get_generator(self, filenames, flags, lang=None, compiler_time_limit=None): from dmoj.executors import executors from dmoj.executors.compiled_executor import CompiledExecutor filenames = list(map(os.path.abspath, filenames)) sources = {} try: for filename in filenames: with open(filename, 'rb') as f: sources[os.path.basename(filename)] = f.read() except Exception: traceback.print_exc() raise IOError('could not read generator source') def find_runtime(languages): for grader in languages: if grader in executors: return grader return None use_cpp = any( map(lambda name: os.path.splitext(name)[1] == '.cpp', filenames)) if lang is None: best_choices = ('CPP17', 'CPP14', 'CPP11', 'CPP03') if use_cpp else ('C11', 'C') lang = find_runtime(best_choices) clazz = executors.get(lang) if not clazz: raise IOError('could not find a C++ executor for generator') clazz = clazz.Executor if issubclass(clazz, CompiledExecutor): compiler_time_limit = compiler_time_limit or clazz.compiler_time_limit clazz = type('Executor', (clazz, ), {'compiler_time_limit': compiler_time_limit}) # Optimize the common case. if use_cpp: # Some generators (like those using testlib.h) take an extremely long time to compile, so we cache them. executor = clazz('_generator', None, aux_sources=sources, cached=True) else: if len(sources) > 1: raise InternalError('non-C/C++ generator cannot be multi-file') executor = clazz('_generator', list(sources.values())[0]) return executor
def get_generator(self, filenames, flags, lang=None): from dmoj.executors import executors filenames = map(os.path.abspath, filenames) sources = {} try: for filename in filenames: with open(filename, 'r') as f: sources[os.path.basename(filename)] = f.read() except: traceback.print_exc() raise IOError('could not read generator source') def find_runtime(languages): for grader in languages: if grader in executors: return grader return None use_cpp = any(map(lambda name: os.path.splitext(name)[1] == '.cpp', filenames)) if lang is None: best_choices = ('CPP17', 'CPP14', 'CPP11', 'CPP0X', 'CPP03') if use_cpp else ('C11', 'C') lang = find_runtime(best_choices) clazz = executors.get(lang) if not clazz: raise IOError('could not find a C++ executor for generator') clazz = clazz.Executor if hasattr(clazz, 'flags'): flags += ['-DWINDOWS_JUDGE', '-DWIN32'] if os.name == 'nt' else ['-DLINUX_JUDGE'] # We shouldn't be mutating the base class flags. # See <https://github.com/DMOJ/judge/issues/174>. clazz = type('FlaggedExecutor', (clazz,), {'flags': flags + list(clazz.flags)}) try: # Optimize the common case. if use_cpp: # Some generators (like those using testlib.h) take an extremely long time # to compile, so we cache them. executor = clazz('_generator', None, aux_sources=sources, cached=True) else: if len(sources) > 1: raise InternalError('non-C/C++ generator cannot be multi-file') executor = clazz('_generator', list(sources.values())[0]) except CompileError as err: # Strip ANSI codes from CompileError message so we don't get wacky displays on the site like # 01m[K_generator.cpp:26:23:[m[K [01;31m[Kerror: [m[K'[01m[Kgets[m[K' was not declared in this scope raise CompileError(ansi.strip_ansi(err.args[0])) return executor
def get_generator(self, filename, flags): from dmoj.executors import executors from dmoj.config import InvalidInitException filename = os.path.abspath(filename) cache_key = filename, tuple(flags) if cache_key in self._cache: return self._cache[cache_key] try: with open(filename) as file: source = file.read() except: traceback.print_exc() raise IOError('could not read generator source') def find_cpp(): for grader in ('CPP14', 'CPP11', 'CPP0X', 'CPP'): if grader in executors: return grader raise InvalidInitException( "can't grade with generator; why did I get this submission?") lookup = { '.py': executors.get('PY2', None), '.py3': executors.get('PY3', None), '.c': executors.get('C', None), '.cpp': executors.get(find_cpp(), None), '.java': executors.get('JAVA', None), '.rb': executors.get('RUBY', None) } ext = os.path.splitext(filename)[1] pass_platform_flags = ['.c', '.cpp'] if pass_platform_flags: flags += ['-DWINDOWS_JUDGE', '-DWIN32' ] if os.name == 'nt' else ['-DLINUX_JUDGE'] clazz = lookup.get(ext, None) if not clazz: raise IOError('could not identify generator extension') clazz = clazz.Executor if hasattr(clazz, 'flags'): # We shouldn't be mutating the base class flags # See https://github.com/DMOJ/judge/issues/174 clazz = type('FlaggedExecutor', (clazz, ), {'flags': flags + list(clazz.flags)}) try: # _ so we can't possibly conflict with submission source file name (e.g. /problem/generator submitted in C++) # _ is not a valid char in problem codes executor = clazz('_generator', source) except CompileError as err: # Strip ansi codes from CompileError message so we don't get wacky displays on the site like # 01m[K_generator.cpp:26:23:[m[K [01;31m[Kerror: [m[K'[01m[Kgets[m[K' was not declared in this scope raise CompileError(ansi.strip_ansi(err.message)) self._cache[cache_key] = executor return executor
def get_generator(self, filename, flags): from dmoj.executors import executors from dmoj.config import InvalidInitException filename = os.path.abspath(filename) cache_key = filename, tuple(flags) if cache_key in self._cache: return self._cache[cache_key] try: with open(filename) as file: source = file.read() except: traceback.print_exc() raise IOError('could not read generator source') def find_cpp(): for grader in ('CPP14', 'CPP11', 'CPP0X', 'CPP'): if grader in executors: return grader raise InvalidInitException( "can't grade with generator; why did I get this submission?") lookup = { '.py': executors.get('PY2', None), '.py3': executors.get('PY3', None), '.c': executors.get('C', None), '.cpp': executors.get(find_cpp(), None), '.java': executors.get('JAVA', None), '.rb': executors.get('RUBY', None) } ext = os.path.splitext(filename)[1] pass_platform_flags = ['.c', '.cpp'] if pass_platform_flags: flags += ['-DWINDOWS_JUDGE', '-DWIN32' ] if os.name == 'nt' else ['-DLINUX_JUDGE'] clazz = lookup.get(ext, None) if not clazz: raise IOError('could not identify generator extension') try: executor = clazz.Executor('_generator', source) except CompileError as err: # Strip ansi codes from CompileError message so we don't get wacky displays on the site like # 01m[K_generator.cpp:26:23:[m[K [01;31m[Kerror: [m[K'[01m[Kgets[m[K' was not declared in this scope raise CompileError(ansi.strip_ansi(err.message)) if hasattr(executor, 'flags'): executor.flags += flags self._cache[cache_key] = executor return executor
def get_generator(self, filename, flags): from dmoj.executors import executors filename = os.path.abspath(filename) cache_key = filename, tuple(flags) if cache_key in self._cache: return self._cache[cache_key] try: with open(filename) as file: source = file.read() except: traceback.print_exc() raise IOError('could not read generator source') def find_runtime(languages): for grader in languages: if grader in executors: return grader return None lookup = { '.py': executors.get('PY2', None), '.py3': executors.get('PY3', None), '.c': executors.get('C', None), '.cpp': executors.get(find_runtime(('CPP14', 'CPP11', 'CPP0X', 'CPP03')), None), '.java': executors.get(find_runtime(('JAVA9', 'JAVA8', 'JAVA7')), None), '.rb': executors.get(find_runtime(('RUBY21', 'RUBY19', 'RUBY18')), None) } ext = os.path.splitext(filename)[1] pass_platform_flags = ['.c', '.cpp'] if pass_platform_flags: flags += ['-DWINDOWS_JUDGE', '-DWIN32' ] if os.name == 'nt' else ['-DLINUX_JUDGE'] clazz = lookup.get(ext, None) if not clazz: raise IOError('could not identify generator extension') clazz = clazz.Executor if hasattr(clazz, 'flags'): # We shouldn't be mutating the base class flags # See https://github.com/DMOJ/judge/issues/174 clazz = type('FlaggedExecutor', (clazz, ), {'flags': flags + list(clazz.flags)}) try: executor = clazz('_generator', source) except CompileError as err: # Strip ansi codes from CompileError message so we don't get wacky displays on the site like # 01m[K_generator.cpp:26:23:[m[K [01;31m[Kerror: [m[K'[01m[Kgets[m[K' was not declared in this scope raise CompileError(ansi.strip_ansi(err.message)) self._cache[cache_key] = executor return executor