This commit introduces a new key, `health-check.whitelisted-chars` for repo.toml. It allows TAs to configure repo-wide allowed non ASCII chars for the repo-health-checker binary. It results in a new command line switch, `-whitelisted-chars=X,Y,Z`, in the generated task.json. Co-Authored-By: GitHub Copilot <noreply@microsoft.com> <details> <summary>Copilot Prompt</summary> <br> This repository contains a Python app that does conversion from TOML config files to a complex, multistage JSON config file for an online judge system. For example, under `tests/convert/full`, input are the two TOML files `repo.toml` and `task.toml`, output is one JSON file `task,json`. Now, I want the repo-specific config (**repo.toml**) to accept an extra dotted key, "health-check.whitelisted-chars". This key shall accept an array of UTF-8 non-ASCII characters. To do so, I want you to - Model. Under `joj3_config_generator/models/repo.py`, add an extra field *whitelisted_chars* to class *HealthCheck*, identified by both "whitelisted-chars" and "whitelisted_chars"; - Transforming. Under `joj3_config_generator/transforers/repo.py`, translate the field to an additional command line switch `-whitelisted-chars`, comma-separated. - Other files you deem necessary, based on your understanding of this repo. IMPORTANT. Before you start, explore this repo to under the file structure and file-function relations. This repo uses the PDM package manager. After you finish your work, test your work appropriately. You should create new testcases under `tests/`. - Details: Read the output `task.json` after running the test, to verify whether the command line switch was added to the *Health Check* `stage` or not. </details> Reviewed-on: https://focs.ji.sjtu.edu.cn/git/JOJ/JOJ3-config-generator/pulls/29 Reviewed-by: 李衍志523370910113 <jon-lee@sjtu.edu.cn> Reviewed-by: 张泊明518370910136 <bomingzh@sjtu.edu.cn> Co-authored-by: Mack Wang <mac-wang@outlook.com> Co-committed-by: Mack Wang <mac-wang@outlook.com>
119 lines
3.6 KiB
Python
119 lines
3.6 KiB
Python
import os
|
|
from pathlib import Path
|
|
from typing import Any, List
|
|
|
|
from pydantic import AliasChoices, Field, field_validator, model_validator
|
|
|
|
from joj3_config_generator.models.common import Memory, StrictBaseModel
|
|
|
|
|
|
class Files(StrictBaseModel):
|
|
required: List[str] = []
|
|
immutable: List[str] = []
|
|
|
|
|
|
class Groups(StrictBaseModel):
|
|
name: List[str] = []
|
|
max_count: List[int] = Field(
|
|
[], validation_alias=AliasChoices("max-count", "max_count")
|
|
)
|
|
time_period_hour: List[int] = Field(
|
|
[], validation_alias=AliasChoices("time-period-hour", "time_period_hour")
|
|
)
|
|
ignore_submitter: bool = Field(
|
|
False, validation_alias=AliasChoices("ignore-submitter", "ignore_submitter")
|
|
)
|
|
|
|
|
|
class Label(StrictBaseModel):
|
|
name: str = "Kind/Testing"
|
|
color: str = "#795548"
|
|
exclusive: bool = False
|
|
|
|
|
|
class Issue(StrictBaseModel):
|
|
label: Label = Label()
|
|
show_submitter: bool = Field(
|
|
True, validation_alias=AliasChoices("show-submitter", "show_submitter")
|
|
)
|
|
|
|
|
|
class HealthCheck(StrictBaseModel):
|
|
score: int = 0
|
|
max_size: int = Field(
|
|
Memory("10m"), validation_alias=AliasChoices("max-size", "max_size")
|
|
)
|
|
immutable_path: Path = Field(
|
|
Path("immutable"),
|
|
validation_alias=AliasChoices("immutable-path", "immutable_path"),
|
|
)
|
|
required_files: List[str] = Field(
|
|
[], validation_alias=AliasChoices("required-files", "required_files")
|
|
)
|
|
whitelisted_chars: str = Field(
|
|
"", validation_alias=AliasChoices("whitelisted-chars", "whitelisted_chars")
|
|
)
|
|
|
|
@field_validator("max_size", mode="before")
|
|
@classmethod
|
|
def ensure_mem_type(cls, v: Any) -> Memory:
|
|
if isinstance(v, str):
|
|
return Memory(v)
|
|
raise ValueError(f'Must be a string, e.g., "256m" or "1g", but got {v}')
|
|
|
|
@field_validator("whitelisted_chars")
|
|
@classmethod
|
|
def ensure_non_ascii_chars(cls, chars: str) -> str:
|
|
for c in chars:
|
|
if c.isascii():
|
|
raise ValueError(
|
|
"Each whitelisted character must be a non-ASCII character"
|
|
)
|
|
return chars
|
|
|
|
|
|
class Config(StrictBaseModel):
|
|
root: Path = Field(Path("."), exclude=True)
|
|
path: Path = Field(Path("repo.toml"), exclude=True)
|
|
|
|
force_skip_health_check_on_test: bool = Field(
|
|
False,
|
|
validation_alias=AliasChoices(
|
|
"force-skip-health-check-on-test", "force_skip_health_check_on_test"
|
|
),
|
|
exclude=True,
|
|
)
|
|
force_skip_teapot_on_test: bool = Field(
|
|
False,
|
|
validation_alias=AliasChoices(
|
|
"force-skip-teapot-on-test", "force_skip_teapot_on_test"
|
|
),
|
|
exclude=True,
|
|
)
|
|
grading_repo_name: str = Field(
|
|
"",
|
|
validation_alias=AliasChoices("grading-repo-name", "grading_repo_name"),
|
|
)
|
|
sandbox_token: str = Field(
|
|
"", validation_alias=AliasChoices("sandbox-token", "sandbox_token")
|
|
)
|
|
max_total_score: int = Field(
|
|
100, validation_alias=AliasChoices("max-total-score", "max_total_score")
|
|
)
|
|
groups: Groups = Groups()
|
|
issue: Issue = Issue()
|
|
|
|
health_check: HealthCheck = Field(
|
|
HealthCheck(), validation_alias=AliasChoices("health-check", "health_check")
|
|
)
|
|
|
|
@model_validator(mode="after")
|
|
def set_grading_repo_name_from_cwd(self) -> "Config":
|
|
if not self.grading_repo_name:
|
|
course_env = os.getenv("COURSE")
|
|
if course_env:
|
|
self.grading_repo_name = f"{course_env}-joj"
|
|
else:
|
|
self.grading_repo_name = Path.cwd().name
|
|
return self
|