feat: LLM generated convert function
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				build / build (push) Successful in 1m3s
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	build / build (push) Successful in 1m3s
				
			This commit is contained in:
		
							parent
							
								
									228488cbf2
								
							
						
					
					
						commit
						8bf0f7cfff
					
				
							
								
								
									
										61
									
								
								joj3_config_generator/convert.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								joj3_config_generator/convert.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,61 @@ | ||||||
|  | from joj3_config_generator.models import ( | ||||||
|  |     Cmd, | ||||||
|  |     CmdFile, | ||||||
|  |     ExecutorConfig, | ||||||
|  |     ExecutorWithConfig, | ||||||
|  |     ParserConfig, | ||||||
|  |     Repo, | ||||||
|  |     ResultConfig, | ||||||
|  |     Stage, | ||||||
|  |     StageConfig, | ||||||
|  |     Task, | ||||||
|  |     TeapotConfig, | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # FIXME: LLM generated convert function, only for demostration | ||||||
|  | def convert(repo_conf: Repo, task_conf: Task) -> ResultConfig: | ||||||
|  |     # Create the base ResultConf object | ||||||
|  |     result_conf = ResultConfig( | ||||||
|  |         name=task_conf.task, | ||||||
|  |         log_path=f"{task_conf.task.replace(' ', '_')}.log", | ||||||
|  |         expire_unix_timestamp=( | ||||||
|  |             int(task_conf.release.deadline.timestamp()) | ||||||
|  |             if task_conf.release.deadline | ||||||
|  |             else -1 | ||||||
|  |         ), | ||||||
|  |         stage=StageConfig(stages=[], sandbox_token=repo_conf.sandbox_token), | ||||||
|  |         teapot=TeapotConfig(), | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     # Convert each stage in the task configuration | ||||||
|  |     for task_stage in task_conf.stages: | ||||||
|  |         executor_with_config = ExecutorWithConfig( | ||||||
|  |             default=Cmd( | ||||||
|  |                 args=task_stage.command.split(), | ||||||
|  |                 copy_in={file: CmdFile(src=file) for file in task_stage.files.import_}, | ||||||
|  |                 copy_out_cached=task_stage.files.export, | ||||||
|  |             ), | ||||||
|  |             cases=[],  # You can add cases if needed | ||||||
|  |         ) | ||||||
|  |         conf_stage = Stage( | ||||||
|  |             name=task_stage.name, | ||||||
|  |             group=task_conf.task, | ||||||
|  |             executor=ExecutorConfig( | ||||||
|  |                 name="sandbox", | ||||||
|  |                 with_=executor_with_config, | ||||||
|  |             ), | ||||||
|  |             parsers=[ | ||||||
|  |                 ParserConfig(name=parser, with_={}) for parser in task_stage.parsers | ||||||
|  |             ], | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         if "result-detail" in task_stage.parsers: | ||||||
|  |             result_detail_parser = next( | ||||||
|  |                 p for p in conf_stage.parsers if p.name == "result-detail" | ||||||
|  |             ) | ||||||
|  |             result_detail_parser.with_.update(task_stage.result_detail) | ||||||
|  | 
 | ||||||
|  |         result_conf.stage.stages.append(conf_stage) | ||||||
|  | 
 | ||||||
|  |     return result_conf | ||||||
|  | @ -1,3 +1,5 @@ | ||||||
|  | from pathlib import Path | ||||||
|  | 
 | ||||||
| import inquirer | import inquirer | ||||||
| import typer | import typer | ||||||
| 
 | 
 | ||||||
|  | @ -7,9 +9,9 @@ app = typer.Typer(add_completion=False) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @app.command() | @app.command() | ||||||
| def create() -> None: | def create(toml: typer.FileTextWrite) -> None: | ||||||
|     """ |     """ | ||||||
|     Create a new JOJ3 config file |     Create a new JOJ3 toml config file | ||||||
|     """ |     """ | ||||||
|     logger.info("Creating") |     logger.info("Creating") | ||||||
|     questions = [ |     questions = [ | ||||||
|  | @ -24,8 +26,16 @@ def create() -> None: | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @app.command() | @app.command() | ||||||
| def convert() -> None: | def convert_joj1(yaml: typer.FileText, toml: typer.FileTextWrite) -> None: | ||||||
|     """ |     """ | ||||||
|     Convert a JOJ1 config file to JOJ3 config file |     Convert a JOJ1 yaml config file to JOJ3 toml config file | ||||||
|     """ |     """ | ||||||
|     logger.info("Converting") |     logger.info("Converting") | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @app.command() | ||||||
|  | def convert(root_path: Path = Path(".")) -> None: | ||||||
|  |     """ | ||||||
|  |     Convert given dir of JOJ3 toml config files to JOJ3 json config files | ||||||
|  |     """ | ||||||
|  |     logger.info(f"Converting {root_path.absolute()}") | ||||||
|  |  | ||||||
|  | @ -1,101 +0,0 @@ | ||||||
| from datetime import datetime |  | ||||||
| from typing import List, Optional |  | ||||||
| 
 |  | ||||||
| import rtoml |  | ||||||
| from pydantic import BaseModel, Field |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class RepoFiles(BaseModel): |  | ||||||
|     whitelist_patterns: List[str] |  | ||||||
|     whitelist_file: Optional[str] |  | ||||||
|     required: List[str] |  | ||||||
|     immutable: List[str] |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class Repo(BaseModel): |  | ||||||
|     teaching_team: List[str] |  | ||||||
|     max_size: float = Field(..., ge=0) |  | ||||||
|     release_tags: List[str] |  | ||||||
|     files: RepoFiles |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class ParserResultDetail(BaseModel): |  | ||||||
|     time: bool = True  # Display run time |  | ||||||
|     mem: bool = True  # Display memory usage |  | ||||||
|     stderr: bool = False  # Display stderr messages |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class Files(BaseModel): |  | ||||||
|     import_: List[str] = Field(alias="import") |  | ||||||
|     export: List[str] |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class Stage(BaseModel): |  | ||||||
|     name: str  # Stage name |  | ||||||
|     command: str  # Command to run |  | ||||||
|     files: Files  # Files to import and export |  | ||||||
|     score: int  # Score for the task |  | ||||||
|     parsers: List[str]  # List of parsers |  | ||||||
|     result_detail: ParserResultDetail = ( |  | ||||||
|         ParserResultDetail() |  | ||||||
|     )  #  for result-detail parser |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class Release(BaseModel): |  | ||||||
|     deadline: Optional[datetime]  # RFC 3339 formatted date-time with offset |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class Task(BaseModel): |  | ||||||
|     task: str  # Task name (e.g., hw3 ex5) |  | ||||||
|     release: Release  # Release configuration |  | ||||||
|     stages: List[Stage]  # List of stage configurations |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| if __name__ == "__main__": |  | ||||||
|     repo_toml = """ |  | ||||||
| teaching_team = [ "prof_john", "ta_alice", "ta_bob" ] |  | ||||||
| max_size = 50.5 |  | ||||||
| release_tags = [ "v1.0", "v2.0", "final" ] |  | ||||||
| 
 |  | ||||||
| [files] |  | ||||||
| whitelist_patterns = [ "*.py", "*.txt", "*.md" ] |  | ||||||
| whitelist_file = ".whitelist" |  | ||||||
| required = [ "main.py", "README.md" ] |  | ||||||
| immutable = [ "config.yaml", "setup.py" ] |  | ||||||
| """ |  | ||||||
|     task_toml = """ |  | ||||||
| task = "hw3 ex5" |  | ||||||
| 
 |  | ||||||
| [release] |  | ||||||
| deadline = "2024-10-18T23:59:00+08:00" |  | ||||||
| 
 |  | ||||||
| [[stages]] |  | ||||||
| name = "judge_base" |  | ||||||
| command = "./matlab-joj ./h3/ex5.m" |  | ||||||
| score = 100 |  | ||||||
| parsers = [ "diff", "result-detail" ] |  | ||||||
| 
 |  | ||||||
| files.import = [ "tools/matlab-joj", "tools/matlab_formatter.py" ] |  | ||||||
| files.export = [ "output/ex5_results.txt", "output/ex5_logs.txt" ] |  | ||||||
| 
 |  | ||||||
| result_detail.time = false |  | ||||||
| result_detail.mem = false |  | ||||||
| result_detail.stderr = true |  | ||||||
| 
 |  | ||||||
| [[stages]] |  | ||||||
| name = "judge_base2" |  | ||||||
| command = "./matlab-joj ./h3/ex5.m" |  | ||||||
| score = 80 |  | ||||||
| parsers = [ "diff", "result-detail" ] |  | ||||||
| 
 |  | ||||||
| files.import = [ "tools/matlab-joj", "tools/matlab_formatter.py" ] |  | ||||||
| files.export = [ "output/ex5_results2.txt", "output/ex5_logs2.txt" ] |  | ||||||
| 
 |  | ||||||
| result_detail.time = true |  | ||||||
| result_detail.mem = true |  | ||||||
| result_detail.stderr = false |  | ||||||
| """ |  | ||||||
|     repo_obj = rtoml.loads(repo_toml) |  | ||||||
|     task_obj = rtoml.loads(task_toml) |  | ||||||
|     print(Repo(**repo_obj)) |  | ||||||
|     print(Task(**task_obj)) |  | ||||||
							
								
								
									
										11
									
								
								joj3_config_generator/models/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								joj3_config_generator/models/__init__.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | ||||||
|  | from joj3_config_generator.models.repo import Repo as Repo | ||||||
|  | from joj3_config_generator.models.result import Cmd as Cmd | ||||||
|  | from joj3_config_generator.models.result import CmdFile as CmdFile | ||||||
|  | from joj3_config_generator.models.result import ExecutorConfig as ExecutorConfig | ||||||
|  | from joj3_config_generator.models.result import ExecutorWithConfig as ExecutorWithConfig | ||||||
|  | from joj3_config_generator.models.result import ParserConfig as ParserConfig | ||||||
|  | from joj3_config_generator.models.result import ResultConfig as ResultConfig | ||||||
|  | from joj3_config_generator.models.result import Stage as Stage | ||||||
|  | from joj3_config_generator.models.result import StageConfig as StageConfig | ||||||
|  | from joj3_config_generator.models.result import TeapotConfig as TeapotConfig | ||||||
|  | from joj3_config_generator.models.task import Task as Task | ||||||
							
								
								
									
										18
									
								
								joj3_config_generator/models/repo.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								joj3_config_generator/models/repo.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | ||||||
|  | from typing import Optional | ||||||
|  | 
 | ||||||
|  | from pydantic import BaseModel, Field | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class RepoFiles(BaseModel): | ||||||
|  |     whitelist_patterns: list[str] | ||||||
|  |     whitelist_file: Optional[str] | ||||||
|  |     required: list[str] | ||||||
|  |     immutable: list[str] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Repo(BaseModel): | ||||||
|  |     teaching_team: list[str] | ||||||
|  |     max_size: float = Field(..., ge=0) | ||||||
|  |     release_tags: list[str] | ||||||
|  |     files: RepoFiles | ||||||
|  |     sandbox_token: str | ||||||
							
								
								
									
										135
									
								
								joj3_config_generator/models/result.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								joj3_config_generator/models/result.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,135 @@ | ||||||
|  | from typing import Any, Optional | ||||||
|  | 
 | ||||||
|  | import rtoml | ||||||
|  | from pydantic import BaseModel, Field | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class CmdFile(BaseModel): | ||||||
|  |     src: Optional[str] = None | ||||||
|  |     content: Optional[str] = None | ||||||
|  |     file_id: Optional[str] = Field(None, serialization_alias="fileId") | ||||||
|  |     name: Optional[str] = None | ||||||
|  |     max: Optional[int] = None | ||||||
|  |     symlink: Optional[str] = None | ||||||
|  |     stream_in: bool = Field(False, serialization_alias="streamIn") | ||||||
|  |     stream_out: bool = Field(False, serialization_alias="streamOut") | ||||||
|  |     pipe: bool = False | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Cmd(BaseModel): | ||||||
|  |     args: list[str] | ||||||
|  |     env: list[str] = [] | ||||||
|  |     stdin: Optional[CmdFile] = None | ||||||
|  |     stdout: Optional[CmdFile] = None | ||||||
|  |     stderr: Optional[CmdFile] = None | ||||||
|  |     cpu_limit: int = Field(0, serialization_alias="cpuLimit") | ||||||
|  |     real_cpu_limit: int = Field(0, serialization_alias="realCpuLimit") | ||||||
|  |     clock_limit: int = Field(0, serialization_alias="clockLimit") | ||||||
|  |     memory_limit: int = Field(0, serialization_alias="memoryLimit") | ||||||
|  |     stack_limit: int = Field(0, serialization_alias="stackLimit") | ||||||
|  |     proc_limit: int = Field(0, serialization_alias="procLimit") | ||||||
|  |     cpu_rate_limit: int = Field(0, serialization_alias="cpuRateLimit") | ||||||
|  |     cpu_set_limit: str = Field("", serialization_alias="cpuSetLimit") | ||||||
|  |     copy_in: dict[str, CmdFile] = Field({}, serialization_alias="copyIn") | ||||||
|  |     copy_in_cached: dict[str, str] = Field({}, serialization_alias="copyInCached") | ||||||
|  |     copy_in_dir: str = Field("", serialization_alias="copyInDir") | ||||||
|  |     copy_out: list[str] = Field([], serialization_alias="copyOut") | ||||||
|  |     copy_out_cached: list[str] = Field([], serialization_alias="copyOutCached") | ||||||
|  |     copy_out_max: int = Field(0, serialization_alias="copyOutMax") | ||||||
|  |     copy_out_dir: str = Field("", serialization_alias="copyOutDir") | ||||||
|  |     tty: bool = False | ||||||
|  |     strict_memory_limit: bool = Field(False, serialization_alias="strictMemoryLimit") | ||||||
|  |     data_segment_limit: bool = Field(False, serialization_alias="dataSegmentLimit") | ||||||
|  |     address_space_limit: bool = Field(False, serialization_alias="addressSpaceLimit") | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class OptionalCmd(BaseModel): | ||||||
|  |     args: Optional[list[str]] = None | ||||||
|  |     env: Optional[list[str]] = None | ||||||
|  |     stdin: Optional[CmdFile] = None | ||||||
|  |     stdout: Optional[CmdFile] = None | ||||||
|  |     stderr: Optional[CmdFile] = None | ||||||
|  |     cpu_limit: Optional[int] = Field(None, serialization_alias="cpuLimit") | ||||||
|  |     real_cpu_limit: Optional[int] = Field(None, serialization_alias="realCpuLimit") | ||||||
|  |     clock_limit: Optional[int] = Field(None, serialization_alias="clockLimit") | ||||||
|  |     memory_limit: Optional[int] = Field(None, serialization_alias="memoryLimit") | ||||||
|  |     stack_limit: Optional[int] = Field(None, serialization_alias="stackLimit") | ||||||
|  |     proc_limit: Optional[int] = Field(None, serialization_alias="procLimit") | ||||||
|  |     cpu_rate_limit: Optional[int] = Field(None, serialization_alias="cpuRateLimit") | ||||||
|  |     cpu_set_limit: Optional[str] = Field(None, serialization_alias="cpuSetLimit") | ||||||
|  |     copy_in: Optional[dict[str, CmdFile]] = Field(None, serialization_alias="copyIn") | ||||||
|  |     copy_in_cached: Optional[dict[str, str]] = Field( | ||||||
|  |         None, serialization_alias="copyInCached" | ||||||
|  |     ) | ||||||
|  |     copy_in_dir: Optional[str] = Field(None, serialization_alias="copyInDir") | ||||||
|  |     copy_out: Optional[list[str]] = Field(None, serialization_alias="copyOut") | ||||||
|  |     copy_out_cached: Optional[list[str]] = Field( | ||||||
|  |         None, serialization_alias="copyOutCached" | ||||||
|  |     ) | ||||||
|  |     copy_out_max: Optional[int] = Field(None, serialization_alias="copyOutMax") | ||||||
|  |     copy_out_dir: Optional[str] = Field(None, serialization_alias="copyOutDir") | ||||||
|  |     tty: Optional[bool] = None | ||||||
|  |     strict_memory_limit: Optional[bool] = Field( | ||||||
|  |         None, serialization_alias="strictMemoryLimit" | ||||||
|  |     ) | ||||||
|  |     data_segment_limit: Optional[bool] = Field( | ||||||
|  |         None, serialization_alias="dataSegmentLimit" | ||||||
|  |     ) | ||||||
|  |     address_space_limit: Optional[bool] = Field( | ||||||
|  |         None, serialization_alias="addressSpaceLimit" | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Stage(BaseModel): | ||||||
|  |     name: str | ||||||
|  |     group: str | ||||||
|  |     executor: "ExecutorConfig" | ||||||
|  |     parsers: list["ParserConfig"] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class ExecutorWithConfig(BaseModel): | ||||||
|  |     default: Cmd | ||||||
|  |     cases: list[OptionalCmd] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class ExecutorConfig(BaseModel): | ||||||
|  |     name: str | ||||||
|  |     with_: ExecutorWithConfig = Field(..., serialization_alias="with") | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class ParserConfig(BaseModel): | ||||||
|  |     name: str | ||||||
|  |     with_: dict[str, Any] = Field(..., serialization_alias="with") | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class StageConfig(BaseModel): | ||||||
|  |     sandbox_exec_server: str = Field( | ||||||
|  |         "172.17.0.1:5051", serialization_alias="sandboxExecServer" | ||||||
|  |     ) | ||||||
|  |     sandbox_token: str = Field("", serialization_alias="sandboxToken") | ||||||
|  |     output_path: str = Field( | ||||||
|  |         "/tmp/joj3_result.json", serialization_alias="outputPath" | ||||||
|  |     )  # nosec: B108 | ||||||
|  |     stages: list[Stage] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class TeapotConfig(BaseModel): | ||||||
|  |     log_path: str = Field( | ||||||
|  |         "/home/tt/.cache/joint-teapot-debug.log", serialization_alias="logPath" | ||||||
|  |     ) | ||||||
|  |     scoreboard_path: str = Field("scoreboard.csv", serialization_alias="scoreboardPath") | ||||||
|  |     failed_table_path: str = Field( | ||||||
|  |         "failed-table.md", serialization_alias="failedTablePath" | ||||||
|  |     ) | ||||||
|  |     grading_repo_name: str = Field("", serialization_alias="gradingRepoName") | ||||||
|  |     skip_issue: bool = Field(False, serialization_alias="skipIssue") | ||||||
|  |     skip_scoreboard: bool = Field(False, serialization_alias="skipScoreboard") | ||||||
|  |     skip_failed_table: bool = Field(False, serialization_alias="skipFailedTable") | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class ResultConfig(BaseModel): | ||||||
|  |     name: str = "unknown" | ||||||
|  |     log_path: str = Field("", serialization_alias="logPath") | ||||||
|  |     expire_unix_timestamp: int = Field(-1, serialization_alias="expireUnixTimestamp") | ||||||
|  |     stage: StageConfig | ||||||
|  |     teapot: TeapotConfig | ||||||
							
								
								
									
										37
									
								
								joj3_config_generator/models/task.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								joj3_config_generator/models/task.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,37 @@ | ||||||
|  | from datetime import datetime | ||||||
|  | from typing import Optional | ||||||
|  | 
 | ||||||
|  | from pydantic import BaseModel, Field | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class ParserResultDetail(BaseModel): | ||||||
|  |     time: bool = True  # Display run time | ||||||
|  |     mem: bool = True  # Display memory usage | ||||||
|  |     stdout: bool = False  # Display stdout messages | ||||||
|  |     stderr: bool = False  # Display stderr messages | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Files(BaseModel): | ||||||
|  |     import_: list[str] = Field(alias="import") | ||||||
|  |     export: list[str] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Stage(BaseModel): | ||||||
|  |     name: str  # Stage name | ||||||
|  |     command: str  # Command to run | ||||||
|  |     files: Files  # Files to import and export | ||||||
|  |     score: int  # Score for the task | ||||||
|  |     parsers: list[str]  # list of parsers | ||||||
|  |     result_detail: ParserResultDetail = ( | ||||||
|  |         ParserResultDetail() | ||||||
|  |     )  #  for result-detail parser | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Release(BaseModel): | ||||||
|  |     deadline: Optional[datetime]  # RFC 3339 formatted date-time with offset | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Task(BaseModel): | ||||||
|  |     task: str  # Task name (e.g., hw3 ex5) | ||||||
|  |     release: Release  # Release configuration | ||||||
|  |     stages: list[Stage]  # list of stage configurations | ||||||
							
								
								
									
										10
									
								
								tests/basic/repo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								tests/basic/repo.toml
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | ||||||
|  | teaching_team = ["prof_john", "ta_alice", "ta_bob"] | ||||||
|  | max_size = 50.5 | ||||||
|  | release_tags = ["v1.0", "v2.0", "final"] | ||||||
|  | sandbox_token = "test" | ||||||
|  | 
 | ||||||
|  | [files] | ||||||
|  | whitelist_patterns = ["*.py", "*.txt", "*.md"] | ||||||
|  | whitelist_file = ".whitelist" | ||||||
|  | required = ["main.py", "README.md"] | ||||||
|  | immutable = ["config.yaml", "setup.py"] | ||||||
							
								
								
									
										181
									
								
								tests/basic/task.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										181
									
								
								tests/basic/task.json
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,181 @@ | ||||||
|  | { | ||||||
|  |     "name": "hw3 ex5", | ||||||
|  |     "logPath": "hw3_ex5.log", | ||||||
|  |     "expireUnixTimestamp": 1729267140, | ||||||
|  |     "stage": { | ||||||
|  |         "sandboxExecServer": "172.17.0.1:5051", | ||||||
|  |         "sandboxToken": "test", | ||||||
|  |         "outputPath": "/tmp/joj3_result.json", | ||||||
|  |         "stages": [ | ||||||
|  |             { | ||||||
|  |                 "name": "judge_base", | ||||||
|  |                 "group": "hw3 ex5", | ||||||
|  |                 "executor": { | ||||||
|  |                     "name": "sandbox", | ||||||
|  |                     "with": { | ||||||
|  |                         "default": { | ||||||
|  |                             "args": [ | ||||||
|  |                                 "./matlab-joj", | ||||||
|  |                                 "./h3/ex5.m" | ||||||
|  |                             ], | ||||||
|  |                             "env": [], | ||||||
|  |                             "stdin": null, | ||||||
|  |                             "stdout": null, | ||||||
|  |                             "stderr": null, | ||||||
|  |                             "cpuLimit": 0, | ||||||
|  |                             "realCpuLimit": 0, | ||||||
|  |                             "clockLimit": 0, | ||||||
|  |                             "memoryLimit": 0, | ||||||
|  |                             "stackLimit": 0, | ||||||
|  |                             "procLimit": 0, | ||||||
|  |                             "cpuRateLimit": 0, | ||||||
|  |                             "cpuSetLimit": "", | ||||||
|  |                             "copyIn": { | ||||||
|  |                                 "tools/matlab-joj": { | ||||||
|  |                                     "src": "tools/matlab-joj", | ||||||
|  |                                     "content": null, | ||||||
|  |                                     "fileId": null, | ||||||
|  |                                     "name": null, | ||||||
|  |                                     "max": null, | ||||||
|  |                                     "symlink": null, | ||||||
|  |                                     "streamIn": false, | ||||||
|  |                                     "streamOut": false, | ||||||
|  |                                     "pipe": false | ||||||
|  |                                 }, | ||||||
|  |                                 "tools/matlab_formatter.py": { | ||||||
|  |                                     "src": "tools/matlab_formatter.py", | ||||||
|  |                                     "content": null, | ||||||
|  |                                     "fileId": null, | ||||||
|  |                                     "name": null, | ||||||
|  |                                     "max": null, | ||||||
|  |                                     "symlink": null, | ||||||
|  |                                     "streamIn": false, | ||||||
|  |                                     "streamOut": false, | ||||||
|  |                                     "pipe": false | ||||||
|  |                                 } | ||||||
|  |                             }, | ||||||
|  |                             "copyInCached": {}, | ||||||
|  |                             "copyInDir": "", | ||||||
|  |                             "copyOut": [], | ||||||
|  |                             "copyOutCached": [ | ||||||
|  |                                 "output/ex5_results.txt", | ||||||
|  |                                 "output/ex5_logs.txt" | ||||||
|  |                             ], | ||||||
|  |                             "copyOutMax": 0, | ||||||
|  |                             "copyOutDir": "", | ||||||
|  |                             "tty": false, | ||||||
|  |                             "strictMemoryLimit": false, | ||||||
|  |                             "dataSegmentLimit": false, | ||||||
|  |                             "addressSpaceLimit": false | ||||||
|  |                         }, | ||||||
|  |                         "cases": [] | ||||||
|  |                     } | ||||||
|  |                 }, | ||||||
|  |                 "parsers": [ | ||||||
|  |                     { | ||||||
|  |                         "name": "diff", | ||||||
|  |                         "with": {} | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "name": "result-detail", | ||||||
|  |                         "with": { | ||||||
|  |                             "time": false, | ||||||
|  |                             "mem": false, | ||||||
|  |                             "stdout": false, | ||||||
|  |                             "stderr": true | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 ] | ||||||
|  |             }, | ||||||
|  |             { | ||||||
|  |                 "name": "judge_base2", | ||||||
|  |                 "group": "hw3 ex5", | ||||||
|  |                 "executor": { | ||||||
|  |                     "name": "sandbox", | ||||||
|  |                     "with": { | ||||||
|  |                         "default": { | ||||||
|  |                             "args": [ | ||||||
|  |                                 "./matlab-joj", | ||||||
|  |                                 "./h3/ex5.m" | ||||||
|  |                             ], | ||||||
|  |                             "env": [], | ||||||
|  |                             "stdin": null, | ||||||
|  |                             "stdout": null, | ||||||
|  |                             "stderr": null, | ||||||
|  |                             "cpuLimit": 0, | ||||||
|  |                             "realCpuLimit": 0, | ||||||
|  |                             "clockLimit": 0, | ||||||
|  |                             "memoryLimit": 0, | ||||||
|  |                             "stackLimit": 0, | ||||||
|  |                             "procLimit": 0, | ||||||
|  |                             "cpuRateLimit": 0, | ||||||
|  |                             "cpuSetLimit": "", | ||||||
|  |                             "copyIn": { | ||||||
|  |                                 "tools/matlab-joj": { | ||||||
|  |                                     "src": "tools/matlab-joj", | ||||||
|  |                                     "content": null, | ||||||
|  |                                     "fileId": null, | ||||||
|  |                                     "name": null, | ||||||
|  |                                     "max": null, | ||||||
|  |                                     "symlink": null, | ||||||
|  |                                     "streamIn": false, | ||||||
|  |                                     "streamOut": false, | ||||||
|  |                                     "pipe": false | ||||||
|  |                                 }, | ||||||
|  |                                 "tools/matlab_formatter.py": { | ||||||
|  |                                     "src": "tools/matlab_formatter.py", | ||||||
|  |                                     "content": null, | ||||||
|  |                                     "fileId": null, | ||||||
|  |                                     "name": null, | ||||||
|  |                                     "max": null, | ||||||
|  |                                     "symlink": null, | ||||||
|  |                                     "streamIn": false, | ||||||
|  |                                     "streamOut": false, | ||||||
|  |                                     "pipe": false | ||||||
|  |                                 } | ||||||
|  |                             }, | ||||||
|  |                             "copyInCached": {}, | ||||||
|  |                             "copyInDir": "", | ||||||
|  |                             "copyOut": [], | ||||||
|  |                             "copyOutCached": [ | ||||||
|  |                                 "output/ex5_results2.txt", | ||||||
|  |                                 "output/ex5_logs2.txt" | ||||||
|  |                             ], | ||||||
|  |                             "copyOutMax": 0, | ||||||
|  |                             "copyOutDir": "", | ||||||
|  |                             "tty": false, | ||||||
|  |                             "strictMemoryLimit": false, | ||||||
|  |                             "dataSegmentLimit": false, | ||||||
|  |                             "addressSpaceLimit": false | ||||||
|  |                         }, | ||||||
|  |                         "cases": [] | ||||||
|  |                     } | ||||||
|  |                 }, | ||||||
|  |                 "parsers": [ | ||||||
|  |                     { | ||||||
|  |                         "name": "diff", | ||||||
|  |                         "with": {} | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "name": "result-detail", | ||||||
|  |                         "with": { | ||||||
|  |                             "time": true, | ||||||
|  |                             "mem": true, | ||||||
|  |                             "stdout": false, | ||||||
|  |                             "stderr": false | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 ] | ||||||
|  |             } | ||||||
|  |         ] | ||||||
|  |     }, | ||||||
|  |     "teapot": { | ||||||
|  |         "logPath": "/home/tt/.cache/joint-teapot-debug.log", | ||||||
|  |         "scoreboardPath": "scoreboard.csv", | ||||||
|  |         "failedTablePath": "failed-table.md", | ||||||
|  |         "gradingRepoName": "", | ||||||
|  |         "skipIssue": false, | ||||||
|  |         "skipScoreboard": false, | ||||||
|  |         "skipFailedTable": false | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										30
									
								
								tests/basic/task.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								tests/basic/task.toml
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | ||||||
|  | task = "hw3 ex5" | ||||||
|  | 
 | ||||||
|  | [release] | ||||||
|  | deadline = "2024-10-18T23:59:00+08:00" | ||||||
|  | 
 | ||||||
|  | [[stages]] | ||||||
|  | name = "judge_base" | ||||||
|  | command = "./matlab-joj ./h3/ex5.m" | ||||||
|  | score = 100 | ||||||
|  | parsers = ["diff", "result-detail"] | ||||||
|  | 
 | ||||||
|  | files.import = ["tools/matlab-joj", "tools/matlab_formatter.py"] | ||||||
|  | files.export = ["output/ex5_results.txt", "output/ex5_logs.txt"] | ||||||
|  | 
 | ||||||
|  | result_detail.time = false | ||||||
|  | result_detail.mem = false | ||||||
|  | result_detail.stderr = true | ||||||
|  | 
 | ||||||
|  | [[stages]] | ||||||
|  | name = "judge_base2" | ||||||
|  | command = "./matlab-joj ./h3/ex5.m" | ||||||
|  | score = 80 | ||||||
|  | parsers = ["diff", "result-detail"] | ||||||
|  | 
 | ||||||
|  | files.import = ["tools/matlab-joj", "tools/matlab_formatter.py"] | ||||||
|  | files.export = ["output/ex5_results2.txt", "output/ex5_logs2.txt"] | ||||||
|  | 
 | ||||||
|  | result_detail.time = true | ||||||
|  | result_detail.mem = true | ||||||
|  | result_detail.stderr = false | ||||||
							
								
								
									
										23
									
								
								tests/conftest.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								tests/conftest.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,23 @@ | ||||||
|  | import os | ||||||
|  | from typing import Any | ||||||
|  | 
 | ||||||
|  | import pytest | ||||||
|  | 
 | ||||||
|  | from joj3_config_generator.models import Repo, Task | ||||||
|  | from tests.utils import read_convert_files | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def get_test_cases() -> list[tuple[str, Repo, Task, dict[str, Any]]]: | ||||||
|  |     test_cases = [] | ||||||
|  |     tests_dir = os.path.dirname(os.path.realpath(__file__)) | ||||||
|  |     for dir_name in os.listdir(tests_dir): | ||||||
|  |         dir_path = os.path.join(tests_dir, dir_name) | ||||||
|  |         if os.path.isdir(dir_path) and dir_name != "__pycache__": | ||||||
|  |             repo, task, expected_result = read_convert_files(dir_path) | ||||||
|  |             test_cases.append((dir_name, repo, task, expected_result)) | ||||||
|  |     return test_cases | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @pytest.fixture(params=get_test_cases(), ids=lambda x: x[0]) | ||||||
|  | def test_case(request: pytest.FixtureRequest) -> tuple[Repo, Task, dict[str, Any]]: | ||||||
|  |     return request.param[1:]  # return repo, task, expected_result | ||||||
|  | @ -1,17 +0,0 @@ | ||||||
| # from xxx import generate |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| from typing import Any |  | ||||||
| 
 |  | ||||||
| import pytest |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| @pytest.mark.xfail(strict=True) |  | ||||||
| def test_generate() -> None: |  | ||||||
|     generate = lambda x: x  # TODO: real generate function imported |  | ||||||
|     data_input: dict[Any, Any] = {}  # TODO: load real input from some file |  | ||||||
|     data_output: dict[Any, Any] = generate(data_input) |  | ||||||
|     expected_output: dict[Any, Any] = { |  | ||||||
|         "a": "b" |  | ||||||
|     }  # TODO: load real output from some file |  | ||||||
|     assert data_output == expected_output |  | ||||||
							
								
								
									
										10
									
								
								tests/test_all_cases.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								tests/test_all_cases.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | ||||||
|  | from typing import Any | ||||||
|  | 
 | ||||||
|  | from joj3_config_generator.convert import convert | ||||||
|  | from joj3_config_generator.models import Repo, Task | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def test_convert(test_case: tuple[Repo, Task, dict[str, Any]]) -> None: | ||||||
|  |     repo, task, expected_result = test_case | ||||||
|  |     result = convert(repo, task).model_dump(by_alias=True) | ||||||
|  |     assert result == expected_result | ||||||
							
								
								
									
										22
									
								
								tests/utils.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								tests/utils.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | ||||||
|  | import json | ||||||
|  | import os | ||||||
|  | from typing import Any | ||||||
|  | 
 | ||||||
|  | import rtoml | ||||||
|  | 
 | ||||||
|  | from joj3_config_generator.models import Repo, Task | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def read_convert_files(root: str) -> tuple[Repo, Task, dict[str, Any]]: | ||||||
|  |     repo_toml_path = os.path.join(root, "repo.toml") | ||||||
|  |     task_toml_path = os.path.join(root, "task.toml") | ||||||
|  |     result_json_path = os.path.join(root, "task.json") | ||||||
|  |     with open(repo_toml_path) as repo_file: | ||||||
|  |         repo_toml = repo_file.read() | ||||||
|  |     with open(task_toml_path) as task_file: | ||||||
|  |         task_toml = task_file.read() | ||||||
|  |     with open(result_json_path) as result_file: | ||||||
|  |         expected_result: dict[str, Any] = json.load(result_file) | ||||||
|  |     repo_obj = rtoml.loads(repo_toml) | ||||||
|  |     task_obj = rtoml.loads(task_toml) | ||||||
|  |     return Repo(**repo_obj), Task(**task_obj), expected_result | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user