def load(cls, fp: TextIO, args: Optional[ProgramArgs] = None): """ :param fp: .toml file's file pointer :param args: command line arguments :return: Config instance """ config_dic = toml.load(fp) # Root 'codestyle' is common code style common_code_style_config_dic = config_dic.get( _CODE_STYLE_CONFIG_KEY, {}) postprocess_config_dic = config_dic.get(_POST_PROCESS_CONFIG_KEY, {}) etc_config_dic = config_dic.get('etc', {}) run_config_dic = config_dic.get(_RUN_CONFIG_KEY, {}) code_style_config_dic = {**common_code_style_config_dic} # Handle config override strategy in the following code # (Most preferred) program arguments > lang-specific > common config (Least preferred) lang = (args and args.lang) or common_code_style_config_dic.get( "lang", DEFAULT_LANGUAGE) code_style_config_dic = _update_config_dict( code_style_config_dic, dict(lang=lang)) if lang in config_dic: lang_specific_config_dic = config_dic[lang] # e.g. [cpp.codestyle] if _CODE_STYLE_CONFIG_KEY in lang_specific_config_dic: lang_code_style = lang_specific_config_dic[_CODE_STYLE_CONFIG_KEY] if "lang" in lang_code_style: logger.warn( with_color("'lang' is only valid in common code style config, " "but detected in language-specific code style config. It will be ignored.", Fore.RED)) del lang_code_style["lang"] code_style_config_dic = _update_config_dict(code_style_config_dic, lang_code_style) # e.g. [cpp.postprocess] if _POST_PROCESS_CONFIG_KEY in lang_specific_config_dic: postprocess_config_dic = _update_config_dict(postprocess_config_dic, lang_specific_config_dic[_POST_PROCESS_CONFIG_KEY]) if _RUN_CONFIG_KEY in lang_specific_config_dic: # e.g. [cpp.run] run_config_dic = _update_config_dict(run_config_dic, lang_specific_config_dic[_RUN_CONFIG_KEY]) if args: code_style_config_dic = _update_config_dict( code_style_config_dic, dict(template_file=args.template, workspace_dir=args.workspace) ) etc_config_dic = _update_config_dict( etc_config_dic, dict( download_without_login=args.without_login, parallel_download=args.parallel, save_no_session_cache=args.save_no_session_cache, compile_before_testing=args.compile_before_testing, compile_only_when_diff_detected=args.compile_only_when_diff_detected ) ) return Config( code_style_config=CodeStyleConfig(**code_style_config_dic), postprocess_config=PostprocessConfig(**postprocess_config_dic), etc_config=EtcConfig(**etc_config_dic), run_config=RunConfig(**run_config_dic) )
def main(prog, args) -> None: if len(args) == 0: print("Usage: atcoder tools set [options]") return parser = argparse.ArgumentParser( prog=prog, formatter_class=argparse.RawTextHelpFormatter) parser.add_argument('--judge-type', '-j', help='error type' ' must be one of [{}]'.format( ', '.join(USER_FACING_JUDGE_TYPE_LIST)), type=str, default=None) parser.add_argument('--error-value', '-v', help='error value for decimal number judge:' ' [Default] ' + str(DEFAULT_EPS), type=float, default=None) parser.add_argument( "--lang", help="Programming language of your template code, {}.\n".format( " or ".join([lang.name for lang in ALL_LANGUAGES])), default=None) parser.add_argument( "--dir", '-d', help="Target directory to test. [Default] Current directory", default=".") args = parser.parse_args(args) old_metadata = Metadata.load_from(os.path.join(args.dir, "metadata.json")) # Use the old metadata as base metadata. output_metadata = Metadata.load_from( os.path.join(args.dir, "metadata.json")) if args.judge_type in ["absolute", "relative", "absolute_or_relative"]: new_metadata_judge_type = "decimal" else: new_metadata_judge_type = args.judge_type old_metadata_judge_type = old_metadata.judge_method.judge_type.value if new_metadata_judge_type is not None and new_metadata_judge_type != old_metadata_judge_type: if new_metadata_judge_type == JudgeType.Normal.value: output_metadata.judge_method = NormalJudge() elif new_metadata_judge_type == JudgeType.Decimal.value: output_metadata.judge_method = DecimalJudge() elif new_metadata_judge_type == JudgeType.MultiSolution.value: output_metadata.judge_method = MultiSolutionJudge() elif new_metadata_judge_type == JudgeType.Interactive.value: output_metadata.judge_method = InteractiveJudge() else: raise NoJudgeTypeException() judge_code_filename = os.path.join(args.dir, "judge.cpp") if new_metadata_judge_type == JudgeType.Decimal.value: if args.error_value is not None: output_metadata.judge_method.diff = args.error_value else: logger.warn( "Error-value is not specified. Default value will be set.") output_metadata.judge_method.error_type = ErrorType(args.judge_type) elif new_metadata_judge_type == JudgeType.MultiSolution.value: if not os.path.exists(judge_code_filename): print("Creating {} (multi-solution)".format(judge_code_filename)) judge_template_path = get_default_judge_template_path('cpp') shutil.copy(judge_template_path, judge_code_filename) else: print("Judge code exists. Skipping creating judge code...") elif new_metadata_judge_type == JudgeType.Interactive.value: if not os.path.exists(judge_code_filename): print("Creating {} (interactive)".format(judge_code_filename)) judge_template_path = get_default_judge_template_path('cpp') shutil.copy(judge_template_path, judge_code_filename) else: print("Judge code exists. Skipping creating judge code...") if args.lang is not None: if args.lang != output_metadata.lang.name: output_metadata.lang = Language.from_name(args.lang) output_metadata.code_filename = output_metadata.lang.get_code_filename( 'main') url = "https://atcoder.jp/contests/{}/tasks/{}".format( output_metadata.problem.contest.contest_id, output_metadata.problem.problem_id) main_code_filename = os.path.join(args.dir, output_metadata.code_filename) if not os.path.exists(main_code_filename): codegen_main("", ["--lang", output_metadata.lang.name, url], open(main_code_filename, 'w')) else: print("File exists: ", output_metadata.code_filename) else: print("Already set to {}. Skipping changing language...".format( args.lang)) output_metadata.save_to(os.path.join(args.dir, "metadata.json"))
def main(prog, args) -> bool: parser = argparse.ArgumentParser( prog=prog, formatter_class=argparse.RawTextHelpFormatter) parser.add_argument("--exec", '-e', help="File path to the execution target. [Default] Automatically detected exec file", default=None) parser.add_argument("--num", '-n', help="The case number to test (1-origin). All cases are tested if not specified.", type=int, default=None) parser.add_argument("--dir", '-d', help="Target directory to test. [Default] Current directory", default=".") parser.add_argument("--timeout", '-t', help="Timeout for each test cases (sec) [Default] 1", type=int, default=1) parser.add_argument("--knock-out", '-k', help="Stop execution immediately after any example's failure [Default] False", action="store_true", default=False) parser.add_argument('--skip-almost-ac-feedback', '-s', help='Hide inputs and expected/actual outputs if result is correct and there are error outputs' ' [Default] False,', action='store_true', default=False) parser.add_argument('--judge-type', '-j', help='error type' ' must be one of [{}]'.format( ', '.join(USER_FACING_JUDGE_TYPE_LIST)), type=str, default=None) parser.add_argument('--error-value', '-v', help='error value for decimal number judge:' ' [Default] ' + str(DEFAULT_EPS), type=float, default=None) parser.add_argument('--compile-before-testing', '-c', help='compile source before testing [true, false]: ' ' [Default]: false', type=bool, default=None) parser.add_argument('--compile-only-when-diff-detected', help='compile only when diff detected [true, false]' ' [Default]: true', type=bool, default=None) parser.add_argument("--config", help="File path to your config file\n{0}{1}".format("[Default (Primary)] {}\n".format( USER_CONFIG_PATH), "[Default (Secondary)] {}\n".format( get_default_config_path())) ) args = parser.parse_args(args) config = get_config(args) if config.etc_config.compile_before_testing is not None and args.compile_before_testing is None: args.compile_before_testing = config.etc_config.compile_before_testing if args.compile_before_testing: if config.etc_config.compile_only_when_diff_detected is not None and args.compile_only_when_diff_detected is None: args.compile_only_when_diff_detected = config.etc_config.compile_only_when_diff_detected metadata_file = os.path.join(args.dir, "metadata.json") metadata = get_metadata(metadata_file) judge_method = metadata.judge_method lang = metadata.lang in_sample_file_list = sorted( glob.glob(os.path.join(args.dir, metadata.sample_in_pattern))) out_sample_file_list = sorted( glob.glob(os.path.join(args.dir, metadata.sample_out_pattern))) user_input_decimal_error_type = None if args.judge_type is not None: if args.judge_type == "normal": judge_method = NormalJudge() elif args.judge_type in ["absolute", "relative", "absolute_or_relative"]: user_input_decimal_error_type = ErrorType(args.judge_type) elif args.judge_type == "multisolution": judge_method = MultiSolutionJudge(lang.name) elif args.judge_type == "interactive": judge_method = InteractiveJudge(lang.name) else: logger.error("Unknown judge type: {}. judge type must be one of [{}]".format( args.judge_type, ", ".join(USER_FACING_JUDGE_TYPE_LIST))) sys.exit(-1) user_input_error_value = args.error_value if isinstance(judge_method, DecimalJudge): judge_method = DecimalJudge(error_type=user_input_decimal_error_type or judge_method.error_type, diff=user_input_error_value or judge_method.diff) elif user_input_decimal_error_type is not None: judge_method = DecimalJudge(error_type=user_input_decimal_error_type, diff=user_input_error_value or DEFAULT_EPS) elif user_input_error_value is not None: assert judge_method.judge_type == JudgeType.Normal logger.warn("error_value {} is ignored because this is normal judge".format( user_input_error_value)) if isinstance(judge_method, DecimalJudge): logger.info("Decimal number judge is enabled. type={}, diff={}".format( judge_method.error_type.value, judge_method.diff)) if metadata.code_filename is None or not args.compile_before_testing: print("compile is skipped and infer exec file") exclude_exec_files = [] if hasattr(judge_method, "judge_exec_filename"): judge_method.judge_exec_filename = os.path.join( args.dir, judge_method.judge_exec_filename) exclude_exec_files.append(judge_method.judge_exec_filename) exec_file = args.exec or infer_exec_file( glob.glob(os.path.join(args.dir, '*')), exclude_exec_files) else: if args.compile_only_when_diff_detected: force_compile = True else: force_compile = False exec_file = lang.get_test_command('main', args.dir) print("command: ", exec_file) print("directory: ", args.dir) # Compile if not compile_main_and_judge_programs(metadata, args.dir, force_compile=force_compile): exit() if args.num is None: return run_all_tests(exec_file, in_sample_file_list, out_sample_file_list, args.timeout, args.knock_out, args.skip_almost_ac_feedback, judge_method, args.dir) else: return run_single_test(exec_file, in_sample_file_list, out_sample_file_list, args.timeout, args.num, judge_method, args.dir)
def main(prog, args) -> bool: parser = argparse.ArgumentParser( prog=prog, formatter_class=argparse.RawTextHelpFormatter) parser.add_argument( "--exec", '-e', help= "File path to the execution target. [Default] Automatically detected exec file", default=None) parser.add_argument( "--num", '-n', help= "The case number to test (1-origin). All cases are tested if not specified.", type=int, default=None) parser.add_argument( "--dir", '-d', help="Target directory to test. [Default] Current directory", default=".") parser.add_argument("--timeout", '-t', help="Timeout for each test cases (sec) [Default] 1", type=int, default=1) parser.add_argument( "--knock-out", '-k', help= "Stop execution immediately after any example's failure [Default] False", action="store_true", default=False) parser.add_argument( '--skip-almost-ac-feedback', '-s', help= 'Hide inputs and expected/actual outputs if result is correct and there are error outputs' ' [Default] False,', action='store_true', default=False) parser.add_argument('--judge-type', '-j', help='error type' ' must be one of [{}]'.format( ', '.join(USER_FACING_JUDGE_TYPE_LIST)), type=str, default=None) parser.add_argument('--error-value', '-v', help='error value for decimal number judge:' ' [Default] ' + str(DEFAULT_EPS), type=float, default=None) args = parser.parse_args(args) exec_file = args.exec or infer_exec_file( glob.glob(os.path.join(args.dir, '*'))) metadata_file = os.path.join(args.dir, "metadata.json") in_ex_pattern, out_ex_pattern, judge_method = get_sample_patterns_and_judge_method( metadata_file) in_sample_file_list = sorted( glob.glob(os.path.join(args.dir, in_ex_pattern))) out_sample_file_list = sorted( glob.glob(os.path.join(args.dir, out_ex_pattern))) user_input_decimal_error_type = None if args.judge_type is not None: if args.judge_type == "normal": judge_method = NormalJudge() elif args.judge_type in [ "absolute", "relative", "absolute_or_relative" ]: user_input_decimal_error_type = ErrorType(args.judge_type) else: logger.error( "Unknown judge type: {}. judge type must be one of [{}]". format(args.judge_type, ", ".join(USER_FACING_JUDGE_TYPE_LIST))) sys.exit(-1) user_input_error_value = args.error_value if isinstance(judge_method, DecimalJudge): judge_method = DecimalJudge(error_type=user_input_decimal_error_type or judge_method.error_type, diff=user_input_error_value or judge_method.diff) elif user_input_decimal_error_type is not None: judge_method = DecimalJudge(error_type=user_input_decimal_error_type, diff=user_input_error_value or DEFAULT_EPS) elif user_input_error_value is not None: assert judge_method.judge_type == JudgeType.Normal logger.warn( "error_value {} is ignored because this is normal judge".format( user_input_error_value)) if isinstance(judge_method, DecimalJudge): logger.info("Decimal number judge is enabled. type={}, diff={}".format( judge_method.error_type.value, judge_method.diff)) if args.num is None: return run_all_tests(exec_file, in_sample_file_list, out_sample_file_list, args.timeout, args.knock_out, args.skip_almost_ac_feedback, judge_method) else: return run_single_test(exec_file, in_sample_file_list, out_sample_file_list, args.timeout, args.num, judge_method)