From d7852163961470ef9b9fdfbb8a4849a978d60ba0 Mon Sep 17 00:00:00 2001 From: Boming Zhang Date: Sun, 22 Jun 2025 01:59:20 +0800 Subject: [PATCH] feat: diff.output.xxx -> diff.xxx (#26) Reviewed-on: https://focs.ji.sjtu.edu.cn/git/JOJ/JOJ3-config-generator/pulls/26 Co-authored-by: Boming Zhang Co-committed-by: Boming Zhang --- joj3_config_generator/models/task.py | 44 +++++++++++++++------- joj3_config_generator/transformers/task.py | 42 +++++++++++---------- tests/convert/basic/task.toml | 10 ++--- tests/convert/diff/task.toml | 18 ++++----- 4 files changed, 68 insertions(+), 46 deletions(-) diff --git a/joj3_config_generator/models/task.py b/joj3_config_generator/models/task.py index 5944a6e..6fca240 100644 --- a/joj3_config_generator/models/task.py +++ b/joj3_config_generator/models/task.py @@ -98,15 +98,39 @@ class ParserDiffOutputs(BaseModel): class ParserDiff(BaseModel): + score: int = DEFAULT_CASE_SCORE + ignore_spaces: bool = Field( + True, validation_alias=AliasChoices("ignore-spaces", "ignore_spaces") + ) + hide: bool = False + force_quit: bool = Field( + False, validation_alias=AliasChoices("force-quit", "force_quit") + ) + max_length: int = Field( + 2048, validation_alias=AliasChoices("max-length", "max_length") + ) + max_lines: int = Field(50, validation_alias=AliasChoices("max-lines", "max_lines")) + hide_common_prefix: bool = Field( + False, validation_alias=AliasChoices("hide-common-prefix", "hide_common_prefix") + ) + # remove below codes when migration is complete output: ParserDiffOutputs = ParserDiffOutputs() - - -class ParserDiffFull(ParserDiff): default_score: int = Field( DEFAULT_CASE_SCORE, validation_alias=AliasChoices("default-score", "default_score"), ) + @model_validator(mode="after") + def copy_output_fields(self) -> "ParserDiff": + if "default_score" in self.model_fields_set: + self.score = self.default_score + if not isinstance(self.output, ParserDiffOutputs): + return self + for field_name, field_value in self.output.model_dump().items(): + if field_name in self.output.model_fields_set and hasattr(self, field_name): + setattr(self, field_name, field_value) + return self + class StageFiles(BaseModel): import_: List[str] = Field([], validation_alias="import") @@ -150,7 +174,7 @@ class Parser(str, Enum): ELF = "elf" -class CaseBase(BaseModel): +class Case(BaseModel): env: List[str] = [] command: str = "" # Command to run files: StageFiles = StageFiles() @@ -160,17 +184,10 @@ class CaseBase(BaseModel): True, validation_alias=AliasChoices("copy-in-cwd", "copy_in_cwd") ) limit: Limit = Limit() - - -class StageCase(CaseBase): - diff: ParserDiffFull = ParserDiffFull() - - -class DictCase(CaseBase): diff: ParserDiff = ParserDiff() -class Stage(StageCase): +class Stage(Case): name: str = "" # stage name skip: List[str] = [] @@ -190,8 +207,9 @@ class Stage(StageCase): validation_alias=AliasChoices("result-detail", "result_detail"), ) file: ParserFile = ParserFile() + # diff: ParserDiff = ParserDiff() # inherited from Case - cases: Dict[str, DictCase] = {} + cases: Dict[str, Case] = {} model_config = ConfigDict(extra="allow") diff --git a/joj3_config_generator/transformers/task.py b/joj3_config_generator/transformers/task.py index 5e6c70f..b3530a8 100644 --- a/joj3_config_generator/transformers/task.py +++ b/joj3_config_generator/transformers/task.py @@ -182,7 +182,7 @@ def fix_file(file_parser_config: task.ParserFile, file_parser: result.Parser) -> def fix_diff( - _: task.ParserDiffFull, + _: task.ParserDiff, diff_parser: result.Parser, task_stage: task.Stage, executor: result.Executor, @@ -228,22 +228,24 @@ def fix_diff( if cmd.proc_limit == executor.with_.default.proc_limit: cmd.proc_limit = None stage_cases.append(cmd) + + def get_diff_attribute(attribute_name: str) -> Any: + if case.diff and attribute_name in case.diff.model_fields_set: + return getattr(case.diff, attribute_name) + return getattr(task_stage.diff, attribute_name) + parser_case = result.DiffCasesConfig( outputs=[ result.DiffOutputConfig( - score=( - case.diff.output.score - if "score" in case.diff.output.model_fields_set - else task_stage.diff.default_score - ), + score=get_diff_attribute("score"), filename="stdout", answer_path=stdout, - force_quit_on_diff=case.diff.output.force_quit, - always_hide=case.diff.output.hide, - compare_space=not case.diff.output.ignore_spaces, - max_diff_length=case.diff.output.max_length, - max_diff_lines=case.diff.output.max_lines, - hide_common_prefix=case.diff.output.hide_common_prefix, + compare_space=not get_diff_attribute("ignore_spaces"), + always_hide=get_diff_attribute("hide"), + force_quit_on_diff=get_diff_attribute("force_quit"), + max_diff_length=get_diff_attribute("max_length"), + max_diff_lines=get_diff_attribute("max_lines"), + hide_common_prefix=get_diff_attribute("hide_common_prefix"), ) ] ) @@ -251,18 +253,20 @@ def fix_diff( for case_name in unspecified_cases: cmd = result.OptionalCmd( stdin=result.LocalFile(src=str(base_dir / f"{case_name}.in")), - cpu_limit=None, - clock_limit=None, - memory_limit=None, - proc_limit=None, ) stage_cases.append(cmd) parser_case = result.DiffCasesConfig( outputs=[ result.DiffOutputConfig( - score=task_stage.diff.default_score, + score=task_stage.diff.score, filename="stdout", answer_path=str(base_dir / f"{case_name}.out"), + compare_space=not task_stage.diff.ignore_spaces, + always_hide=task_stage.diff.hide, + force_quit_on_diff=task_stage.diff.force_quit, + max_diff_length=task_stage.diff.max_length, + max_diff_lines=task_stage.diff.max_lines, + hide_common_prefix=task_stage.diff.hide_common_prefix, ) ] ) @@ -272,7 +276,7 @@ def fix_diff( def get_unspecified_cases( - task_root: Path, task_path: Path, cases: Dict[str, task.DictCase] + task_root: Path, task_path: Path, cases: Dict[str, task.Case] ) -> List[str]: testcases = set() for testcases_path in (task_root / task_path).parent.glob("**/*.in"): @@ -302,7 +306,7 @@ def get_unspecified_cases( def get_stdin_stdout( - task_root: Path, task_path: Path, case_name: str, case: task.DictCase + task_root: Path, task_path: Path, case_name: str, case: task.Case ) -> Tuple[result.Stdin, Optional[str]]: case_stdout_name = case.out_ if case.out_ else f"{case_name}.out" stdin: result.Stdin = result.MemoryFile(content="") diff --git a/tests/convert/basic/task.toml b/tests/convert/basic/task.toml index 2768650..cfbdacd 100644 --- a/tests/convert/basic/task.toml +++ b/tests/convert/basic/task.toml @@ -92,7 +92,7 @@ copy-in-cwd = false files.import = [ "h7/build/ex2-asan" ] limit.mem = "128m" -diff.default-score = 10 +diff.score = 10 parsers = [ "diff", "result-detail" ] result-detail.exit-status = true @@ -101,17 +101,17 @@ result-detail.stderr = true # will be removed as long as the name is fixed case0.limit.cpu = "0.5s" case0.limit.mem = "5m" -case0.diff.output.ignore-spaces = true +case0.diff.ignore-spaces = true #case0.limit.stdout = 8 #case0.command = "./h7/build/ex2" case0.in = "case0.in" -case1.diff.output.score = 5 +case1.diff.score = 5 case1.limit.cpu = "1s" case1.limit.mem = "5m" -case1.diff.output.ignore-spaces = true +case1.diff.ignore-spaces = true #case1.limit.stdout = 8 #case1.command = "./h7/build/ex2" case1.in = "case1.in" -case2.diff.output.hide = true +case2.diff.hide = true diff --git a/tests/convert/diff/task.toml b/tests/convert/diff/task.toml index ea3d0de..61236e1 100644 --- a/tests/convert/diff/task.toml +++ b/tests/convert/diff/task.toml @@ -17,26 +17,26 @@ parsers = [ "diff", "result-detail" ] result-detail.exit-status = true result-detail.stderr = true -diff.default-score = 100 +diff.score = 100 -case0.diff.output.score = 5 +case0.diff.score = 5 case0.limit.cpu = "1s" case0.limit.mem = "2m" -case0.diff.output.ignore-spaces = true +case0.diff.ignore-spaces = true case0.command = "./h7/build/ex2" case0.in = "case0.in" -case1.diff.output.score = 123214122421 +case1.diff.score = 123214122421 case1.limit.cpu = "2s" case1.limit.mem = "4m" -case1.diff.output.ignore-spaces = true +case1.diff.ignore-spaces = true case1.command = "./h7/build/ex2" -case9.diff.output.score = 1232131 +case9.diff.score = 1232131 case9.limit.mem = "10m" -case11.diff.output.score = 92321 +case11.diff.score = 92321 -case10.diff.output.score = 823131 +case10.diff.score = 823131 -case5.diff.output.score = 2590 +case5.diff.score = 2590