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 log_internal_error(self, exc: BaseException = None, message: str = None) -> None: if not message: # If exc exists, raise it so that sys.exc_info() is populated with its data. if exc: try: raise exc except KeyboardInterrupt: # Let KeyboardInterrupt bubble up. raise except: # noqa: E722, we want to catch everything pass message = ''.join(traceback.format_exception(*sys.exc_info())) logger.error(message) try: # Strip ANSI from the message, since this might be a checker's CompileError ...we don't want to see the raw # ANSI codes from GCC/Clang on the site. We could use format_ansi and send HTML to the site, but the site # doesn't presently support HTML internal error formatting. self.packet_manager.internal_error_packet(strip_ansi(message)) except Exception: # noqa E722: don't want `log_internal_error` to trigger `log_internal_error`, ever logger.exception( 'Error encountered while reporting error to site!')
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, 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 internal_error(self, exc=None): # If exc is exists, raise it so that sys.exc_info() is populated with its data if exc: try: raise exc except: pass exc = sys.exc_info() message = ''.join(traceback.format_exception(*exc)) # Strip ANSI from the message, since this might be a checker's CompileError # ...we don't want to see the raw ANSI codes from GCC/Clang on the site. # We could use format_ansi and send HTML to the site, but the site doesn't presently support HTML # internal error formatting. self.packet_manager.internal_error_packet(strip_ansi(message)) # Logs can contain ANSI, and it'll display fine print(message, file=sys.stderr)
def internal_error(self, exc=None): # If exc is exists, raise it so that sys.exc_info() is populated with its data if exc: try: raise exc except: pass exc = sys.exc_info() message = ''.join(traceback.format_exception(*exc)) # Strip ANSI from the message, since this might be a checker's CompileError # ...we don't want to see the raw ANSI codes from GCC/Clang on the site. # We could use format_ansi and send HTML to the site, but the site doesn't presently support HTML # internal error formatting. self.packet_manager.internal_error_packet(strip_ansi(message)) # Logs can contain ANSI, and it'll display fine print >>sys.stderr, message
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