feat: language specific create questions
All checks were successful
build / build (push) Successful in 1m48s

This commit is contained in:
张泊明518370910136 2025-03-17 18:35:47 -04:00
parent 80ba2f1451
commit df14ad801b
GPG Key ID: D47306D7062CDA9D
10 changed files with 211 additions and 33 deletions

View File

@ -9,17 +9,19 @@ from joj3_config_generator.models import answer, joj1, repo, task
def load_joj3_task_toml_answers() -> answer.Answers:
questions = [
inquirer.Text(name="name", message="What's the task name?"),
inquirer.Checkbox(
"stages",
message="What kind of stages do you need?",
choices=[member.value for member in answer.StageEnum],
default=[answer.StageEnum.COMPILATION],
),
]
answers = inquirer.prompt(questions)
return answer.Answers(**answers)
name = inquirer.text("What's the task name?", default="hw0")
language: answer.LanguageInterface = inquirer.list_input(
"What's the language?", choices=answer.LANGUAGES
)
stages = inquirer.checkbox(
"What's the stages?",
choices=[member.value for member in language.Stage],
default=[member.value for member in language.Stage],
)
language.set_stages(stages)
attribute = inquirer.prompt(language.get_attribute_questions())
language.set_attribute(attribute)
return answer.Answers(name=name, language=language)
def load_joj1_yaml(yaml_path: Path) -> joj1.Config:

View File

@ -30,8 +30,6 @@ def create(
Create a new JOJ3 task toml config file
"""
answers = load_joj3_task_toml_answers()
answers_dict = answers.model_dump(mode="json", by_alias=True)
logger.debug(f"Got answers: {answers_dict}")
task_model = create_joj3_task_conf(answers)
result_dict = task_model.model_dump(
mode="json", by_alias=True, exclude_none=True, exclude_unset=True

View File

@ -1,16 +1,124 @@
from abc import ABC, abstractmethod
from enum import Enum
from typing import List
from typing import Any, ClassVar, Dict, List
from pydantic import BaseModel
import inquirer
from pydantic import BaseModel, ConfigDict
class StageEnum(str, Enum):
COMPILATION = "Compilation"
CPPCHECK = "Cppcheck"
CPPLINT = "Cpplint"
CLANG_TIDY = "Clang-Tidy"
class LanguageInterface(ABC):
@abstractmethod
def __str__(self) -> str: ...
@abstractmethod
class Stage(str, Enum): ...
@abstractmethod
class Attribute(BaseModel): ...
stages: ClassVar[List[Enum]]
attribute: ClassVar[BaseModel]
@classmethod
def set_stages(cls, stages: List[str]) -> None:
cls.stages = [cls.Stage(stage) for stage in stages]
@classmethod
def set_attribute(cls, attribute_dict: Dict[str, Any]) -> None:
cls.attribute = cls.Attribute(**attribute_dict)
@classmethod
@abstractmethod
def get_attribute_questions(cls) -> List[Any]: ...
class Cpp(LanguageInterface):
def __str__(self) -> str:
return "C++"
class Stage(str, Enum):
COMPILATION = "Compilation"
CPPCHECK = "Cppcheck"
CPPLINT = "Cpplint"
CLANG_TIDY = "Clang-Tidy"
RUN = "Run"
class Attribute(BaseModel):
compile_command: str = "make"
run_command: str = "./a.out"
stages = []
attribute = Attribute()
@classmethod
def get_attribute_questions(cls) -> List[Any]:
return [
inquirer.Text(
name="compile_command",
message="Compile command",
default=cls.attribute.compile_command,
),
inquirer.Text(
name="run_command",
message="Run command",
default=cls.attribute.run_command,
),
]
class Python(LanguageInterface):
def __str__(self) -> str:
return "Python"
class Stage(str, Enum):
RUN = "Run"
class Attribute(BaseModel):
run_command: str = "python3 main.py"
stages = []
attribute = Attribute()
@classmethod
def get_attribute_questions(cls) -> List[Any]:
return [
inquirer.Text(
name="run_command",
message="Run command",
default=cls.attribute.run_command,
),
]
class Rust(LanguageInterface):
def __str__(self) -> str:
return "Rust"
class Stage(str, Enum):
COMPILATION = "Compilation"
CLIPPY = "Clippy"
RUN = "Run"
class Attribute(BaseModel):
pass
stages = []
attribute = Attribute()
@classmethod
def get_attribute_questions(cls) -> List[Any]:
return []
LANGUAGES = [
Cpp(),
Python(),
Rust(),
]
class Answers(BaseModel):
name: str
stages: List[str]
language: LanguageInterface
model_config = ConfigDict(arbitrary_types_allowed=True)

View File

@ -1,6 +1,52 @@
from typing import Any, Callable, Dict, List, Type
from joj3_config_generator.models import answer, task
# TODO: implement
def get_task_conf_from_answers(answers: answer.Answers) -> task.Config:
return task.Config(task=task.Task(name=answers.name))
language = answers.language
transformer_dict = get_transformer_dict()
transformer = transformer_dict[type(language)]
stages = transformer(language)
return task.Config(task=task.Task(name=answers.name), stages=stages)
def get_transformer_dict() -> Dict[
Type[Any],
Callable[[Any], List[task.Stage]],
]:
return {
answer.Cpp: get_cpp_stages,
answer.Python: get_python_stages,
answer.Rust: get_rust_stages,
}
# TODO: implement
def get_cpp_stages(language: answer.Cpp) -> List[task.Stage]:
stages = language.stages
attribute: answer.Cpp.Attribute = language.attribute
task_stages = []
if answer.Cpp.Stage.CPPCHECK in stages:
task_stages.append(task.Stage(name=answer.Cpp.Stage.CPPCHECK))
if answer.Cpp.Stage.CPPLINT in stages:
task_stages.append(task.Stage(name=answer.Cpp.Stage.CPPLINT))
if answer.Cpp.Stage.CLANG_TIDY in stages:
task_stages.append(task.Stage(name=answer.Cpp.Stage.CLANG_TIDY))
if answer.Cpp.Stage.RUN in stages:
task_stages.append(task.Stage(name=answer.Cpp.Stage.RUN))
return task_stages
# TODO: implement
def get_python_stages(language: answer.Python) -> List[task.Stage]:
stages = language.stages
attribute: answer.Python.Attribute = language.attribute
return []
# TODO: implement
def get_rust_stages(language: answer.Rust) -> List[task.Stage]:
stages = language.stages
attribute: answer.Rust.Attribute = language.attribute
return []

View File

@ -1,4 +0,0 @@
{
"name": "hw7 ex2",
"stages": ["Compilation"]
}

View File

@ -1,2 +0,0 @@
[task]
name = "hw7 ex2"

View File

@ -0,0 +1,9 @@
{
"name": "hw7 ex2",
"language": "C++",
"stages": ["Compilation", "Cppcheck", "Cpplint", "Clang-Tidy", "Run"],
"attribute": {
"compile_command": "make",
"run_command": "./ex2"
}
}

View File

@ -0,0 +1,18 @@
[task]
name = "hw7 ex2"
[[stages]]
name = "Cppcheck"
cases = {}
[[stages]]
name = "Cpplint"
cases = {}
[[stages]]
name = "Clang-Tidy"
cases = {}
[[stages]]
name = "Run"
cases = {}

View File

@ -1,5 +1,5 @@
from tests.create.utils import load_case
def test_basic() -> None:
load_case("basic")
def test_cpp() -> None:
load_case("cpp")

View File

@ -11,8 +11,11 @@ def load_case(case_name: str) -> None:
root = Path(__file__).resolve().parent
answers_json_path = root / case_name / "answers.json"
task_toml_path = root / case_name / "task.toml"
answers = answer.Answers(**json.loads(answers_json_path.read_text()))
print(answers)
answers_dict = json.loads(answers_json_path.read_text())
language = next(x for x in answer.LANGUAGES if str(x) == answers_dict["language"])
language.set_stages(answers_dict["stages"])
language.set_attribute(answers_dict["attribute"])
answers = answer.Answers(name=answers_dict["name"], language=language)
expected_result = rtoml.loads(task_toml_path.read_text())
result = create_joj3_task_conf(answers).model_dump(
mode="json", by_alias=True, exclude_none=True, exclude_unset=True