dev #10
|  | @ -1,4 +1,6 @@ | |||
| import os | ||||
| from datetime import datetime | ||||
| from pathlib import Path | ||||
| from typing import List | ||||
| 
 | ||||
| from joj3_config_generator.models import joj1, repo, result, task | ||||
|  | @ -29,6 +31,11 @@ def convert(repo_conf: repo.Config, task_conf: task.Config) -> result.Config: | |||
|             if task_conf.release.end_time | ||||
|             else -1 | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 | ||||
|         ), | ||||
|         effective_unix_timestamp=( | ||||
|             int(task_conf.release.begin_time.timestamp()) | ||||
|             if task_conf.release.begin_time | ||||
|             else -1 | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  where is it used? where is it used? 
				
					
						李衍志523370910113
						commented  this should be storing all the files that are about to be copy in or out this should be storing all the files that are about to be copy in or out 
				
					
						李衍志523370910113
						commented  It is as the input and output for the following functions about parsers It is as the input and output for the following functions about parsers 
				
					
						张泊明518370910136
						commented  so this feature is not implemented? so this feature is not implemented? 
				
					
						李衍志523370910113
						commented  it is this is a loop, so this  ```python
    if not repo_conf.force_skip_health_check_on_test or not current_test:
        result_conf.stage.stages.append(get_health_check_config(repo_conf))
    cached: List[str] = []
    # Convert each stage in the task configuration
    for task_stage in task_conf.stages:
        executor_with_config, cached = get_executor_with_config(task_stage, cached)
        conf_stage = get_conf_stage(task_stage, executor_with_config)
        conf_stage = fix_result_detail(task_stage, conf_stage)
        conf_stage = fix_dummy(task_stage, conf_stage)
        conf_stage = fix_keyword(task_stage, conf_stage)
        conf_stage = fix_file(task_stage, conf_stage)
        conf_stage = fix_diff(task_stage, conf_stage, task_conf)
        result_conf.stage.stages.append(conf_stage)
```
it is
```python
    for task_stage in task_conf.stages:
        executor_with_config, cached = get_executor_with_config(task_stage, cached)
```
this is a loop, so this `cached` will be updated in every round of stage 
				
					
						张泊明518370910136
						commented  The return value is unnecessary. The return value is unnecessary. 
				
					
						李衍志523370910113
						commented  I have a lazing coding style here, everything has get imported would get exported, so should maintain this until the end of the loop. Everything is exported in previous stage would be imported in the next stage. I have a lazing coding style here, everything has get imported would get exported, so should maintain this until the end of the loop. Everything is exported in previous stage would be imported in the next stage. 
				
					
						张泊明518370910136
						commented  
 1. The return value is unnecessary
2. It should be a `set` 
				
					
						张泊明518370910136
						commented  try it yourself try it yourself 
				
					
						李衍志523370910113
						commented  I see why I see why 
				
					
						李衍志523370910113
						commented  resolved. resolved. | ||||
|         ), | ||||
|         actor_csv_path="/home/tt/.config/joj/students.csv",  # students.csv position | ||||
|         max_total_score=repo_conf.max_total_score, | ||||
|         stage=result.Stage( | ||||
|  | @ -62,9 +69,11 @@ def convert(repo_conf: repo.Config, task_conf: task.Config) -> result.Config: | |||
| def convert_joj1(joj1_conf: joj1.Config) -> task.Config: | ||||
|     stages = [get_joj1_run_stage(joj1_conf)] | ||||
|     return task.Config( | ||||
|         root=Path(""), | ||||
|         path=Path(""), | ||||
|         task=task.Task( | ||||
|             name=(""), | ||||
|         ), | ||||
|         release=task.Release(end_time=None, begin_time=None), | ||||
|         release=task.Release(end_time=datetime.now(), begin_time=datetime.now()), | ||||
|         stages=stages, | ||||
|     ) | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| from datetime import datetime | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  every field in this file should not be optional. we give an default value here if any field does not exist every field in this file should not be optional. we give an default value here if any field does not exist 
				
					
						张泊明518370910136
						commented  and use underscore naming in this file and use underscore naming in this file 
				
					
						李衍志523370910113
						commented  
 fixed > every field in this file should not be optional. we give an default value here if any field does not exist
fixed 
				
					
						李衍志523370910113
						commented  
 fixed. > and use underscore naming in this file
fixed. | ||||
| from pathlib import Path | ||||
| from typing import Any, Dict, List, Optional, Type | ||||
| from typing import Any, Dict, List, Type | ||||
| 
 | ||||
| from pydantic import BaseModel, Field, field_validator, model_validator | ||||
| 
 | ||||
|  | @ -13,48 +13,48 @@ from joj3_config_generator.models.const import ( | |||
| 
 | ||||
| 
 | ||||
| class ParserResultDetail(BaseModel): | ||||
|     time: Optional[bool] = True  # Display run time | ||||
|     mem: Optional[bool] = True  # Display memory usage | ||||
|     stdout: Optional[bool] = False  # Display stdout messages | ||||
|     stderr: Optional[bool] = False  # Display stderr messages | ||||
|     exitstatus: Optional[bool] = False | ||||
|     time: bool = True  # Display run time | ||||
|     mem: bool = True  # Display memory usage | ||||
|     stdout: bool = False  # Display stdout messages | ||||
|     stderr: bool = False  # Display stderr messages | ||||
|     exitstatus: bool = False | ||||
| 
 | ||||
| 
 | ||||
| class ParserFile(BaseModel): | ||||
|     name: Optional[str] = None | ||||
|     name: str = "" | ||||
| 
 | ||||
| 
 | ||||
| class ParserLog(BaseModel): | ||||
|     fileName: Optional[str] = None | ||||
|     msg: Optional[str] = None | ||||
|     level: Optional[str] = None | ||||
|     file_name: str = Field("", alias="fileName") | ||||
|     msg: str = "" | ||||
|     level: str = "" | ||||
| 
 | ||||
| 
 | ||||
| class ParserDummy(BaseModel): | ||||
|     comment: Optional[str] = "" | ||||
|     score: Optional[int] = 0 | ||||
|     forcequit: Optional[bool] = False | ||||
|     comment: str = "" | ||||
|     score: int = 0 | ||||
|     forcequit: bool = False | ||||
| 
 | ||||
| 
 | ||||
| class ParserKeyword(BaseModel): | ||||
|     keyword: Optional[List[str]] = [] | ||||
|     weight: Optional[List[int]] = [] | ||||
|     keyword: List[str] = [] | ||||
|     weight: List[int] = [] | ||||
| 
 | ||||
| 
 | ||||
| class Outputs(BaseModel): | ||||
|     score: Optional[int] = 0 | ||||
|     ignorespaces: Optional[bool] = True | ||||
|     hide: Optional[bool] = False | ||||
|     forcequit: Optional[bool] = False | ||||
|     score: int = 0 | ||||
|     ignorespaces: bool = True | ||||
|     hide: bool = False | ||||
|     forcequit: bool = False | ||||
| 
 | ||||
| 
 | ||||
| class ParserDiff(BaseModel): | ||||
|     output: Optional[Outputs] = Outputs() | ||||
|     output: Outputs = Outputs() | ||||
| 
 | ||||
| 
 | ||||
| class Files(BaseModel): | ||||
|     import_: Optional[List[str]] = Field([], alias="import") | ||||
|     export: Optional[List[str]] = [] | ||||
|     import_: List[str] = Field([], alias="import") | ||||
|     export: List[str] = [] | ||||
| 
 | ||||
| 
 | ||||
| class Limit(BaseModel): | ||||
|  | @ -75,30 +75,30 @@ class Limit(BaseModel): | |||
| 
 | ||||
| 
 | ||||
| class Stage(BaseModel): | ||||
|     name: Optional[str] = None  # Stage name | ||||
|     env: Optional[List[str]] = None | ||||
|     command: Optional[str] = None  # Command to run | ||||
|     files: Optional[Files] = None | ||||
|     in_: Optional[str] = Field(None, alias="in") | ||||
|     out_: Optional[str] = Field(None, alias="out") | ||||
|     score: Optional[int] = 0 | ||||
|     parsers: Optional[List[str]] = []  # list of parsers | ||||
|     name: str = ""  # Stage name | ||||
|     env: List[str] = [] | ||||
|     command: str = ""  # Command to run | ||||
|     files: Files = Files() | ||||
|     in_: str = Field("", alias="in") | ||||
|     out_: str = Field("", alias="out") | ||||
|     score: int = 0 | ||||
|     parsers: List[str] = []  # list of parsers | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  deprecated deprecated 
				
					
						李衍志523370910113
						commented  @bomingzh any suggestions on the structure? @bomingzh any suggestions on the structure? 
				
					
						张泊明518370910136
						commented  ```
PydanticDeprecatedSince20: Support for class-based `config` is deprecated, use ConfigDict instead. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.9/migration/
``` 
				
					
						李衍志523370910113
						commented  fixed with  fixed with `model_config` 
				
					
						张泊明518370910136
						commented  str here need to be a  str here need to be a `StrEnum` now. 
				
					
						李衍志523370910113
						commented  But I guess we don't know the set of case in advance, making it dynamic  But I guess we don't know the set of case in advance, making it dynamic `StrEnum` is meaningless 
				
					
						张泊明518370910136
						commented  line changed, the comment is for  line changed, the comment is for `parsers` | ||||
|     limit: Limit = Limit() | ||||
|     dummy: Optional[ParserDummy] = ParserDummy() | ||||
|     result_status: Optional[ParserDummy] = Field(ParserDummy(), alias="result-status") | ||||
|     keyword: Optional[ParserKeyword] = ParserKeyword() | ||||
|     clangtidy: Optional[ParserKeyword] = ParserKeyword() | ||||
|     cppcheck: Optional[ParserKeyword] = ParserKeyword() | ||||
|     cpplint: Optional[ParserKeyword] = ParserKeyword() | ||||
|     result_detail: Optional[ParserResultDetail] = Field( | ||||
|     dummy: ParserDummy = ParserDummy() | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						李衍志523370910113
						commented  this should be the  this should be the `StrEnum` 
				
					
						张泊明518370910136
						commented  yes yes 
				
					
						李衍志523370910113
						commented  It is supported now. It is supported now. | ||||
|     result_status: ParserDummy = Field(ParserDummy(), alias="result-status") | ||||
|     keyword: ParserKeyword = ParserKeyword() | ||||
|     clangtidy: ParserKeyword = ParserKeyword() | ||||
|     cppcheck: ParserKeyword = ParserKeyword() | ||||
|     cpplint: ParserKeyword = ParserKeyword() | ||||
|     result_detail: ParserResultDetail = Field( | ||||
|         ParserResultDetail(), alias="result-detail" | ||||
|     ) | ||||
|     file: Optional[ParserFile] = ParserFile() | ||||
|     skip: Optional[List[str]] = [] | ||||
|     file: ParserFile = ParserFile() | ||||
|     skip: List[str] = [] | ||||
| 
 | ||||
|     # cases related | ||||
|     cases: Optional[Dict[str, "Stage"]] = None | ||||
|     diff: Optional[ParserDiff] = ParserDiff() | ||||
|     cases: Dict[str, "Stage"] = {} | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  
 `begin_time` and `end_time` to make them match 
				
					
						李衍志523370910113
						commented  resolved resolved | ||||
|     diff: ParserDiff = ParserDiff() | ||||
| 
 | ||||
|     model_config = {"extra": "allow"} | ||||
| 
 | ||||
|  | @ -113,20 +113,18 @@ class Stage(BaseModel): | |||
| 
 | ||||
| 
 | ||||
| class Release(BaseModel): | ||||
|     end_time: Optional[datetime] = None  # RFC 3339 formatted date-time with offset | ||||
|     begin_time: Optional[datetime] = None | ||||
|     end_time: datetime = datetime.now()  # RFC 3339 formatted date-time with offset | ||||
|     begin_time: datetime = datetime.now()  # RFC 3339 formatted date-time with offset | ||||
| 
 | ||||
| 
 | ||||
| class Task(BaseModel): | ||||
|     type_: Optional[str] = Field( | ||||
|         "", serialization_alias="type", validation_alias="type" | ||||
|     ) | ||||
|     type_: str = Field("", serialization_alias="type", validation_alias="type") | ||||
|     name: str | ||||
| 
 | ||||
| 
 | ||||
| class Config(BaseModel): | ||||
|     root: Optional[Path] = None | ||||
|     path: Optional[Path] = None | ||||
|     root: Path = Path(".") | ||||
|     path: Path = Path("task.toml") | ||||
|     task: Task  # Task name (e.g., hw3 ex5) | ||||
|     release: Release  # Release configuration | ||||
|     stages: List[Stage]  # list of stage configurations | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ def get_joj1_run_stage(joj1_config: joj1.Config) -> task.Stage: | |||
|         cases_conf.append( | ||||
|             task.Stage( | ||||
|                 score=case.score, | ||||
|                 command=case.execute_args if case.execute_args else None, | ||||
|                 command=case.execute_args if case.execute_args else "", | ||||
|                 limit=task.Limit( | ||||
|                     cpu=Time(case.time) if case.time else DEFAULT_CPU_LIMIT, | ||||
|                     mem=(Memory(case.memory) if case.memory else DEFAULT_MEMORY_LIMIT), | ||||
|  |  | |||
|  | @ -207,8 +207,8 @@ def fix_diff( | |||
|             clock_limit = 2 * case_stage.limit.cpu | ||||
|             memory_limit = case_stage.limit.mem | ||||
|             command = case_stage.command if case_stage.command is not None else None | ||||
|             stdin = case_stage.in_ if case_stage.in_ is not None else f"{case}.in" | ||||
|             stdout = case_stage.out_ if case_stage.out_ is not None else f"{case}.out" | ||||
|             stdin = case_stage.in_ if case_stage.in_ != "" else f"{case}.in" | ||||
|             stdout = case_stage.out_ if case_stage.out_ != "" else f"{case}.out" | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  Create models for these dicts, then update them with the dict from  Create models for these dicts, then update them with the dict from `model_dump` 
				
					
						李衍志523370910113
						commented  @bomingzh I don't think we can change it. This is to make proper alias so that we can get the content of  @bomingzh I don't think we can change it. This is to make proper alias so that we can get the content of `result-status`. 
				
					
						张泊明518370910136
						commented  Then  ```
class DummyConfig(BaseModel):
    score: int
    comment: str
```
Then `dummy_parser_.with_.update(dummy_config(...).model_dump())`.
 
				
					
						李衍志523370910113
						commented  fixed fixed | ||||
| 
 | ||||
|             stage_cases.append( | ||||
|                 result.OptionalCmd( | ||||
|  |  | |||
|  | @ -1,8 +1,8 @@ | |||
| { | ||||
|     "name": "hw7 ex2", | ||||
|     "logPath": "/home/tt/.cache/joj3/homework/h7/e2.log", | ||||
|     "expireUnixTimestamp": -1, | ||||
|     "effectiveUnixTimestamp": -1, | ||||
|     "expireUnixTimestamp": 1735574399, | ||||
|     "effectiveUnixTimestamp": 1735487999, | ||||
|     "actorCsvPath": "/home/tt/.config/joj/students.csv", | ||||
|     "maxTotalScore": 100, | ||||
|     "stage": { | ||||
|  | @ -660,6 +660,7 @@ | |||
|                         }, | ||||
|                         "cases": [ | ||||
|                             { | ||||
|                                 "args": [], | ||||
|                                 "stdin": { | ||||
|                                     "src": "/home/tt/.config/joj/homework/h7/e2/case0.in" | ||||
|                                 }, | ||||
|  | @ -669,6 +670,7 @@ | |||
|                                 "procLimit": 50 | ||||
|                             }, | ||||
|                             { | ||||
|                                 "args": [], | ||||
|                                 "stdin": { | ||||
|                                     "src": "/home/tt/.config/joj/homework/h7/e2/case1.in" | ||||
|                                 }, | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
| task.name = "hw7 ex2" # task name | ||||
| task.type = "homework/h7/e2" # remove this task type later | ||||
| 
 | ||||
| release.deadline = 2024-12-30 23:59:59+08:00 | ||||
| release.end_time = 2024-12-30 23:59:59+08:00 | ||||
| release.begin_time = 2024-12-29 23:59:59+08:00 | ||||
| 
 | ||||
| [[stages]] | ||||
|  |  | |||
|  | @ -1,8 +1,8 @@ | |||
| { | ||||
|     "name": "hw7 ex2", | ||||
|     "logPath": "/home/tt/.cache/joj3/homework/h7/e2.log", | ||||
|     "expireUnixTimestamp": -1, | ||||
|     "effectiveUnixTimestamp": -1, | ||||
|     "expireUnixTimestamp": 1735574399, | ||||
|     "effectiveUnixTimestamp": 1735487999, | ||||
|     "actorCsvPath": "/home/tt/.config/joj/students.csv", | ||||
|     "maxTotalScore": 100, | ||||
|     "stage": { | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
| task.name = "hw7 ex2" # task name | ||||
| task.type = "homework/h7/e2" # remove this task type later | ||||
| 
 | ||||
| release.deadline = 2024-12-30 23:59:59+08:00 | ||||
| release.end_time = 2024-12-30 23:59:59+08:00 | ||||
| release.begin_time = 2024-12-29 23:59:59+08:00 | ||||
| 
 | ||||
| [[stages]] | ||||
|  |  | |||
|  | @ -1,8 +1,8 @@ | |||
| { | ||||
|     "name": "hw7 ex2", | ||||
|     "logPath": "/home/tt/.cache/joj3/homework/h7/e2.log", | ||||
|     "expireUnixTimestamp": -1, | ||||
|     "effectiveUnixTimestamp": -1, | ||||
|     "expireUnixTimestamp": 1735574399, | ||||
|     "effectiveUnixTimestamp": 1735487999, | ||||
|     "actorCsvPath": "/home/tt/.config/joj/students.csv", | ||||
|     "maxTotalScore": 100, | ||||
|     "stage": { | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
| task.name = "hw7 ex2" # task name | ||||
| task.type = "homework/h7/e2" # remove this task type later | ||||
| 
 | ||||
| release.deadline = 2024-12-30 23:59:59+08:00 | ||||
| release.end_time = 2024-12-30 23:59:59+08:00 | ||||
| release.begin_time = 2024-12-29 23:59:59+08:00 | ||||
| 
 | ||||
| [[stages]] | ||||
|  |  | |||
|  | @ -1,8 +1,8 @@ | |||
| { | ||||
|     "name": "hw7 ex2", | ||||
|     "logPath": "/home/tt/.cache/joj3/homework/h7/e2.log", | ||||
|     "expireUnixTimestamp": -1, | ||||
|     "effectiveUnixTimestamp": -1, | ||||
|     "expireUnixTimestamp": 1735574399, | ||||
|     "effectiveUnixTimestamp": 1735487999, | ||||
|     "actorCsvPath": "/home/tt/.config/joj/students.csv", | ||||
|     "maxTotalScore": 100, | ||||
|     "stage": { | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
| task.name = "hw7 ex2" # task name | ||||
| task.type = "homework/h7/e2" # remove this task type later | ||||
| 
 | ||||
| release.deadline = 2024-12-30 23:59:59+08:00 | ||||
| release.end_time = 2024-12-30 23:59:59+08:00 | ||||
| release.begin_time = 2024-12-29 23:59:59+08:00 | ||||
| 
 | ||||
| [[stages]] | ||||
|  |  | |||
|  | @ -1,8 +1,8 @@ | |||
| { | ||||
|     "name": "hw7 ex2", | ||||
|     "logPath": "/home/tt/.cache/joj3/homework/h7/e2.log", | ||||
|     "expireUnixTimestamp": -1, | ||||
|     "effectiveUnixTimestamp": -1, | ||||
|     "expireUnixTimestamp": 1735574399, | ||||
|     "effectiveUnixTimestamp": 1735487999, | ||||
|     "actorCsvPath": "/home/tt/.config/joj/students.csv", | ||||
|     "maxTotalScore": 100, | ||||
|     "stage": { | ||||
|  | @ -63,6 +63,7 @@ | |||
|                         }, | ||||
|                         "cases": [ | ||||
|                             { | ||||
|                                 "args": [], | ||||
|                                 "stdin": { | ||||
|                                     "src": "/home/tt/.config/joj/homework/h7/e2/case0.in" | ||||
|                                 }, | ||||
|  | @ -72,6 +73,7 @@ | |||
|                                 "procLimit": 50 | ||||
|                             }, | ||||
|                             { | ||||
|                                 "args": [], | ||||
|                                 "stdin": { | ||||
|                                     "src": "/home/tt/.config/joj/homework/h7/e2/case1.in" | ||||
|                                 }, | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
| task.name = "hw7 ex2" # task name | ||||
| task.type = "homework/h7/e2" # remove this task type later | ||||
| 
 | ||||
| release.deadline = 2024-12-30 23:59:59+08:00 | ||||
| release.end_time = 2024-12-30 23:59:59+08:00 | ||||
| release.begin_time = 2024-12-29 23:59:59+08:00 | ||||
| 
 | ||||
| [[stages]] | ||||
|  |  | |||
|  | @ -1,8 +1,8 @@ | |||
| { | ||||
|     "name": "hw7 ex2", | ||||
|     "logPath": "/home/tt/.cache/joj3/homework/h7/e2.log", | ||||
|     "expireUnixTimestamp": -1, | ||||
|     "effectiveUnixTimestamp": -1, | ||||
|     "expireUnixTimestamp": 1735574399, | ||||
|     "effectiveUnixTimestamp": 1735487999, | ||||
|     "actorCsvPath": "/home/tt/.config/joj/students.csv", | ||||
|     "maxTotalScore": 100, | ||||
|     "stage": { | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
| task.name = "hw7 ex2" # task name | ||||
| task.type = "homework/h7/e2" # remove this task type later | ||||
| 
 | ||||
| release.deadline = 2024-12-30 23:59:59+08:00 | ||||
| release.end_time = 2024-12-30 23:59:59+08:00 | ||||
| release.begin_time = 2024-12-29 23:59:59+08:00 | ||||
| 
 | ||||
| [[stages]] | ||||
|  |  | |||
Make this
Path.home()default to/home/tt. For now, create a const for this dir.fixed