feat: strict mode toml loader
All checks were successful
build / build (push) Successful in 2m16s
build / trigger-build-image (push) Successful in 9s

This commit is contained in:
张泊明518370910136 2025-09-17 01:13:51 -07:00
parent 1a1d74a058
commit 3f0fdd816b
GPG Key ID: D47306D7062CDA9D
3 changed files with 19 additions and 14 deletions

View File

@ -1,6 +1,7 @@
from typing import Union from typing import Union
import humanfriendly import humanfriendly
from pydantic import BaseModel, ConfigDict
class Memory(int): class Memory(int):
@ -17,3 +18,7 @@ class Time(int):
parsed = humanfriendly.parse_timespan(value) * 1_000_000_000 # ns parsed = humanfriendly.parse_timespan(value) * 1_000_000_000 # ns
return super().__new__(cls, round(parsed)) return super().__new__(cls, round(parsed))
return super().__new__(cls, value) return super().__new__(cls, value)
class StrictBaseModel(BaseModel):
model_config = ConfigDict(extra="forbid")

View File

@ -2,17 +2,17 @@ import os
from pathlib import Path from pathlib import Path
from typing import Any, List from typing import Any, List
from pydantic import AliasChoices, BaseModel, Field, field_validator, model_validator from pydantic import AliasChoices, Field, field_validator, model_validator
from joj3_config_generator.models.common import Memory from joj3_config_generator.models.common import Memory, StrictBaseModel
class Files(BaseModel): class Files(StrictBaseModel):
required: List[str] = [] required: List[str] = []
immutable: List[str] = [] immutable: List[str] = []
class Groups(BaseModel): class Groups(StrictBaseModel):
name: List[str] = [] name: List[str] = []
max_count: List[int] = Field( max_count: List[int] = Field(
[], validation_alias=AliasChoices("max-count", "max_count") [], validation_alias=AliasChoices("max-count", "max_count")
@ -22,20 +22,20 @@ class Groups(BaseModel):
) )
class Label(BaseModel): class Label(StrictBaseModel):
name: str = "Kind/Testing" name: str = "Kind/Testing"
color: str = "#795548" color: str = "#795548"
exclusive: bool = False exclusive: bool = False
class Issue(BaseModel): class Issue(StrictBaseModel):
label: Label = Label() label: Label = Label()
show_submitter: bool = Field( show_submitter: bool = Field(
True, validation_alias=AliasChoices("show-submitter", "show_submitter") True, validation_alias=AliasChoices("show-submitter", "show_submitter")
) )
class HealthCheck(BaseModel): class HealthCheck(StrictBaseModel):
score: int = 0 score: int = 0
max_size: int = Field( max_size: int = Field(
Memory("10m"), validation_alias=AliasChoices("max-size", "max_size") Memory("10m"), validation_alias=AliasChoices("max-size", "max_size")
@ -56,7 +56,7 @@ class HealthCheck(BaseModel):
raise ValueError(f'Must be a string, e.g., "256m" or "1g", but got {v}') raise ValueError(f'Must be a string, e.g., "256m" or "1g", but got {v}')
class Config(BaseModel): class Config(StrictBaseModel):
root: Path = Field(Path("."), exclude=True) root: Path = Field(Path("."), exclude=True)
path: Path = Field(Path("repo.toml"), exclude=True) path: Path = Field(Path("repo.toml"), exclude=True)

View File

@ -13,7 +13,7 @@ from pydantic import (
model_validator, model_validator,
) )
from joj3_config_generator.models.common import Memory, Time from joj3_config_generator.models.common import Memory, StrictBaseModel, Time
from joj3_config_generator.models.const import ( from joj3_config_generator.models.const import (
DEFAULT_CASE_SCORE, DEFAULT_CASE_SCORE,
DEFAULT_CLOCK_LIMIT_MULTIPLIER, DEFAULT_CLOCK_LIMIT_MULTIPLIER,
@ -183,7 +183,7 @@ class Parser(str, Enum):
ELF = "elf" ELF = "elf"
class Case(BaseModel): class Case(StrictBaseModel):
env: List[str] = [] env: List[str] = []
command: str = "" # Command to run command: str = "" # Command to run
files: StageFiles = StageFiles() files: StageFiles = StageFiles()
@ -236,7 +236,7 @@ class Stage(Case):
return values return values
class Release(BaseModel): class Release(StrictBaseModel):
end_time: datetime = Field( end_time: datetime = Field(
datetime(1970, 1, 1, 0, 0, 0, tzinfo=timezone.utc), datetime(1970, 1, 1, 0, 0, 0, tzinfo=timezone.utc),
validation_alias=AliasChoices("end-time", "end_time"), validation_alias=AliasChoices("end-time", "end_time"),
@ -247,17 +247,17 @@ class Release(BaseModel):
) # timestamp = 0, no begin time ) # timestamp = 0, no begin time
class SubmissionTime(BaseModel): class SubmissionTime(StrictBaseModel):
begin: Optional[datetime] = None begin: Optional[datetime] = None
end: Optional[datetime] = None end: Optional[datetime] = None
class Penalties(BaseModel): class Penalties(StrictBaseModel):
hours: List[float] = [] hours: List[float] = []
factors: List[float] = [] factors: List[float] = []
class Config(BaseModel): class Config(StrictBaseModel):
root: Path = Field(Path("."), exclude=True) root: Path = Field(Path("."), exclude=True)
path: Path = Field(Path("task.toml"), exclude=True) path: Path = Field(Path("task.toml"), exclude=True)
suffix: str = Field("", exclude=True) suffix: str = Field("", exclude=True)