117 lines
3.4 KiB
Python
117 lines
3.4 KiB
Python
from datetime import datetime
|
|
from pathlib import Path
|
|
from typing import Any, Dict, List, Optional, Type
|
|
|
|
import humanfriendly
|
|
from pydantic import BaseModel, Field, model_validator
|
|
|
|
|
|
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
|
|
|
|
|
|
class ParserFile(BaseModel):
|
|
name: Optional[str] = None
|
|
|
|
|
|
class ParserLog(BaseModel):
|
|
fileName: Optional[str] = None
|
|
msg: Optional[str] = None
|
|
level: Optional[str] = None
|
|
|
|
|
|
class ParserDummy(BaseModel):
|
|
comment: Optional[str] = ""
|
|
score: Optional[int] = 0
|
|
forcequit: Optional[bool] = False
|
|
|
|
|
|
class ParserKeyword(BaseModel):
|
|
keyword: Optional[list[str]] = []
|
|
weight: Optional[list[int]] = []
|
|
|
|
|
|
class Outputs(BaseModel):
|
|
score: Optional[int] = 0
|
|
ignorespaces: Optional[bool] = True
|
|
hide: Optional[bool] = False
|
|
forcequit: Optional[bool] = False
|
|
|
|
|
|
class ParserDiff(BaseModel):
|
|
output: Optional[Outputs] = Outputs()
|
|
|
|
|
|
class Files(BaseModel):
|
|
import_: Optional[list[str]] = Field([], alias="import")
|
|
export: Optional[list[str]] = []
|
|
|
|
|
|
class Limit(BaseModel):
|
|
mem: int = humanfriendly.parse_size("128M")
|
|
cpu: int = 1_000_000_000
|
|
stderr: int = humanfriendly.parse_size("128M")
|
|
stdout: int = humanfriendly.parse_size("128M")
|
|
|
|
|
|
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
|
|
limit: Optional[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(
|
|
ParserResultDetail(), alias="result-detail"
|
|
)
|
|
file: Optional[ParserFile] = ParserFile()
|
|
skip: Optional[list[str]] = []
|
|
|
|
# cases related
|
|
cases: Optional[Dict[str, "Stage"]] = None
|
|
diff: Optional[ParserDiff] = ParserDiff()
|
|
|
|
model_config = {"extra": "allow"}
|
|
|
|
@model_validator(mode="before")
|
|
@classmethod
|
|
def gather_cases(cls: Type["Stage"], values: Dict[str, Any]) -> Dict[str, Any]:
|
|
cases = {k: v for k, v in values.items() if k.startswith("case")}
|
|
for key in cases:
|
|
values.pop(key)
|
|
values["cases"] = {k: v for k, v in cases.items()}
|
|
return values
|
|
|
|
|
|
class Release(BaseModel):
|
|
end_time: Optional[datetime] = None # RFC 3339 formatted date-time with offset
|
|
begin_time: Optional[datetime] = None
|
|
|
|
|
|
class Task(BaseModel):
|
|
type_: Optional[str] = Field(
|
|
"", serialization_alias="type", validation_alias="type"
|
|
)
|
|
name: str
|
|
|
|
|
|
class Config(BaseModel):
|
|
root: Optional[Path] = None
|
|
path: Optional[Path] = None
|
|
task: Task # Task name (e.g., hw3 ex5)
|
|
release: Release # Release configuration
|
|
stages: List[Stage] # list of stage configurations
|