Example #1
0
    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)
        )
Example #2
0
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"))
Example #3
0
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)
Example #4
0
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)