remake run.py: run load init export state
This commit is contained in:
579
run.py
579
run.py
@@ -6,82 +6,154 @@ from enum import Enum, unique, auto
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import yaml
|
||||||
|
|
||||||
import click
|
import click
|
||||||
|
|
||||||
TC_TARGET_DIR = "./_testcases"
|
CFG_PATH = "./config.yml"
|
||||||
|
STATE_PATH = "./state.yml"
|
||||||
|
|
||||||
|
TC_DIR = "./_testcases"
|
||||||
|
|
||||||
|
SRC_SPACE_DIR = "./space"
|
||||||
|
|
||||||
|
STORAGE_DIR = "./storage"
|
||||||
|
|
||||||
|
BUILD_DIR = "./build"
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@unique
|
||||||
class ProblemRunType:
|
class Language(Enum):
|
||||||
name: str
|
PYTHON = "py"
|
||||||
dir: str
|
C = "c"
|
||||||
runner: str
|
CPP = "cpp"
|
||||||
prefix: str
|
RUST = "rs"
|
||||||
prerunner: str = ""
|
KOTLIN = "kt"
|
||||||
|
LUA = "lua"
|
||||||
|
|
||||||
|
UNDEFINED = "undefined"
|
||||||
|
|
||||||
class ProblemRunEnum:
|
@property
|
||||||
zeta_python: ProblemRunType = ProblemRunType(
|
def build_command(self):
|
||||||
name="zeta_python",
|
return {
|
||||||
dir="./zeta_python",
|
Language.PYTHON: [
|
||||||
runner="python {source}",
|
"python",
|
||||||
prefix="py",
|
"./make.py",
|
||||||
)
|
"build",
|
||||||
zeta_C: ProblemRunType = ProblemRunType(
|
],
|
||||||
name="zeta_C",
|
Language.C: [
|
||||||
dir="./zeta_C",
|
"make",
|
||||||
runner="./a.out",
|
"build",
|
||||||
prefix="c",
|
],
|
||||||
prerunner="gcc {source} -std=gnu11 -lm -Wall",
|
Language.CPP: [
|
||||||
)
|
"make",
|
||||||
zeta_cpp: ProblemRunType = ProblemRunType(
|
"build",
|
||||||
name="zeta_cpp",
|
],
|
||||||
dir="./zeta_cpp",
|
Language.RUST: [
|
||||||
runner="./a.out",
|
"cargo",
|
||||||
prefix="cpp",
|
"build",
|
||||||
prerunner="g++ {source} -std=c++17 -lm -Wall",
|
],
|
||||||
)
|
Language.KOTLIN: [
|
||||||
zeta_kotlin: ProblemRunType = ProblemRunType(
|
"./gradlew",
|
||||||
name="zeta_kotlin",
|
"jar",
|
||||||
dir="./zeta_kotlin",
|
],
|
||||||
runner="java -Xms2G -Xmx4G -Xss1G -Dfile.encoding=UTF-8 -jar a.jar",
|
Language.LUA: [
|
||||||
prefix="kt",
|
"make",
|
||||||
prerunner="kotlinc-jvm {source} -J-Xms2G -J-Xmx4G -J-Xss1G -include-runtime -d a.jar",
|
"build",
|
||||||
)
|
],
|
||||||
# WIP
|
}[self]
|
||||||
zeta_lua: ProblemRunType = ProblemRunType(
|
|
||||||
name="zeta_lua", dir="./zeta_lua", runner="", prefix="lua"
|
|
||||||
)
|
|
||||||
|
|
||||||
zeta_rust: ProblemRunType = ProblemRunType(
|
@property
|
||||||
name="zeta_rust",
|
def working_dir(self):
|
||||||
dir="./zeta_rust",
|
return f"{SRC_SPACE_DIR}/src-{self.value}"
|
||||||
runner="./a.out",
|
|
||||||
prefix="rs",
|
|
||||||
prerunner="rustc --edition 2021 -O -o a.out {source}",
|
|
||||||
)
|
|
||||||
|
|
||||||
# ExceptionType
|
@property
|
||||||
err: ProblemRunType = ProblemRunType(name="err", dir="", runner="", prefix="")
|
def build_executable(self):
|
||||||
|
return {
|
||||||
|
Language.PYTHON: "py.pyc",
|
||||||
|
Language.C: "c.out",
|
||||||
|
Language.CPP: "cpp.out",
|
||||||
|
Language.RUST: "rs.out",
|
||||||
|
Language.KOTLIN: "kt.jar",
|
||||||
|
Language.LUA: "lua.luac",
|
||||||
|
}[self]
|
||||||
|
|
||||||
|
def run_executable_command(self, executable_loc):
|
||||||
|
return {
|
||||||
|
Language.PYTHON: ["python", f"{executable_loc}"],
|
||||||
|
Language.C: [f"{executable_loc}"],
|
||||||
|
Language.CPP: [f"{executable_loc}"],
|
||||||
|
Language.RUST: [f"{executable_loc}"],
|
||||||
|
Language.KOTLIN: ["java", "-jar", f"{executable_loc}"],
|
||||||
|
Language.LUA: ["lua", f"{executable_loc}"],
|
||||||
|
}[self]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def quicklink(link: str) -> ProblemRunType:
|
def convert_ext(ext: str):
|
||||||
match link.lower().replace("-", "").replace("_", ""):
|
match (ext):
|
||||||
case "zetapython" | "bojpython" | "bojpy" | "zetapy" | "zpy":
|
case "py":
|
||||||
return ProblemRunEnum.zeta_python
|
return Language.PYTHON
|
||||||
case "zetac" | "bojc" | "zc":
|
case "c":
|
||||||
return ProblemRunEnum.zeta_C
|
return Language.C
|
||||||
case "zetacpp" | "bojcpp" | "zcpp":
|
case "cpp":
|
||||||
return ProblemRunEnum.zeta_cpp
|
return Language.CPP
|
||||||
case "zetalua" | "bojlua" | "zlua":
|
case "rs":
|
||||||
return ProblemRunEnum.zeta_lua
|
return Language.RUST
|
||||||
case "zetakotlin" | "zetakt" | "bojkotlin" | "bojkt" | "zkt" | "zkotlin":
|
case "kt":
|
||||||
return ProblemRunEnum.zeta_kotlin
|
return Language.KOTLIN
|
||||||
case "zetarust" | "zetars" | "zrs" | "zrust" | "bojrs" | "bojrust":
|
case "lua":
|
||||||
return ProblemRunEnum.zeta_rust
|
return Language.LUA
|
||||||
case _:
|
case _:
|
||||||
return ProblemRunEnum.err
|
return Language.UNDEFINED
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def convert_name(name: str):
|
||||||
|
match (name.lower()):
|
||||||
|
case "py" | "py3" | "python" | "python3":
|
||||||
|
return Language.PYTHON
|
||||||
|
case "c":
|
||||||
|
return Language.C
|
||||||
|
case "cpp" | "c++":
|
||||||
|
return Language.CPP
|
||||||
|
case "rust" | "rs":
|
||||||
|
return Language.RUST
|
||||||
|
case "kt" | "kotlin":
|
||||||
|
return Language.KOTLIN
|
||||||
|
case "lua":
|
||||||
|
return Language.LUA
|
||||||
|
case _:
|
||||||
|
return Language.UNDEFINED
|
||||||
|
|
||||||
|
|
||||||
|
def parse_range_string(range_str):
|
||||||
|
try:
|
||||||
|
if range_str.startswith(".."):
|
||||||
|
# 형식: "..N" → 1부터 N까지
|
||||||
|
end = int(range_str[2:])
|
||||||
|
return list(range(1, end + 1))
|
||||||
|
else:
|
||||||
|
# 형식: "M..N" → M부터 N까지
|
||||||
|
parts = range_str.split("..")
|
||||||
|
if len(parts) == 1:
|
||||||
|
# 단일 숫자 (예: "1")
|
||||||
|
return [int(parts[0])]
|
||||||
|
elif len(parts) == 2:
|
||||||
|
# 범위 (예: "3..5")
|
||||||
|
start = int(parts[0])
|
||||||
|
end = int(parts[1])
|
||||||
|
return list(range(start, end + 1))
|
||||||
|
else:
|
||||||
|
raise ValueError("Invalid range format")
|
||||||
|
except ValueError as e:
|
||||||
|
print(f"Error: {e}")
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
def parse_range_string_list(str_list):
|
||||||
|
result = []
|
||||||
|
for s in str_list:
|
||||||
|
result.extend(parse_range_string(s))
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
@click.group()
|
@click.group()
|
||||||
@@ -89,121 +161,348 @@ def cli():
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
@click.command(name="run")
|
||||||
@click.argument("runtype_string", type=str, nargs=1, required=True)
|
@click.option("--from", "from_", type=str, required=True)
|
||||||
@click.argument("problem_code", type=str, nargs=1, required=True)
|
@click.option("--target", "-t", default=["1"], multiple=True)
|
||||||
@click.argument("count", type=int, nargs=1, required=False, default=1)
|
@click.option("--verbose/--no-verbose", "-v/-nv", default=True)
|
||||||
@click.option("--verbose", "-v", is_flag=True)
|
def run(from_: str, target: str, verbose: bool):
|
||||||
@click.option("--profile", "-p", is_flag=True)
|
# Language 확인
|
||||||
def run(
|
from_language: Language = Language.convert_name(from_)
|
||||||
runtype_string: str, problem_code: str, count: int, verbose: bool, profile: bool
|
|
||||||
):
|
|
||||||
runtype: ProblemRunType = ProblemRunEnum.quicklink(runtype_string)
|
|
||||||
if runtype is ProblemRunEnum.err:
|
|
||||||
raise click.UsageError("Error RUNTYPE.")
|
|
||||||
|
|
||||||
if count < 1:
|
if from_language is Language.UNDEFINED:
|
||||||
raise click.UsageError("COUNT must be greater than 1.")
|
raise click.ClickException("Undefined Language Exception")
|
||||||
|
|
||||||
problem_code_path = f"{runtype.dir}/{problem_code}.{runtype.prefix}"
|
|
||||||
|
|
||||||
if not os.path.exists(problem_code_path):
|
|
||||||
raise click.UsageError("Problem does not exist.")
|
|
||||||
|
|
||||||
tc_files: list[str] = [
|
|
||||||
fpath
|
|
||||||
for fpath in os.listdir(TC_TARGET_DIR)
|
|
||||||
if os.path.isfile(os.path.join(TC_TARGET_DIR, fpath))
|
|
||||||
]
|
|
||||||
|
|
||||||
for c in range(1, count + 1):
|
|
||||||
inpf = None
|
|
||||||
outputfs = []
|
|
||||||
for name in tc_files:
|
|
||||||
ix = re.match(f"{c}.in", name)
|
|
||||||
ox = re.match(f"{c}.out[0-9]*", name)
|
|
||||||
if ix:
|
|
||||||
inpf = name
|
|
||||||
elif ox:
|
|
||||||
outputfs.append(name)
|
|
||||||
|
|
||||||
if (not inpf) or (not outputfs):
|
|
||||||
click.echo(f"{c:02d}: {None}")
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
# check
|
|
||||||
with open(os.path.join(TC_TARGET_DIR, inpf), "r", encoding="utf-8") as f:
|
|
||||||
if runtype.prerunner:
|
|
||||||
try:
|
try:
|
||||||
_ = subprocess.run(
|
with open("state.yml", "r", encoding="utf-8") as f:
|
||||||
runtype.prerunner.format(
|
state = yaml.safe_load(f)
|
||||||
source=problem_code_path,
|
except FileNotFoundError as e:
|
||||||
).split(),
|
raise click.ClickException(e)
|
||||||
|
except yaml.YAMLError as e:
|
||||||
|
raise click.ClickException(e)
|
||||||
|
|
||||||
|
if "space" not in state:
|
||||||
|
raise click.ClickException("State(state.yml) Exception")
|
||||||
|
elif not state["space"]:
|
||||||
|
click.secho("state.space has no member", fg="yellow", bold=True)
|
||||||
|
state["space"] = {}
|
||||||
|
|
||||||
|
lang_space_state: dict | None
|
||||||
|
if from_language.value not in state["space"]:
|
||||||
|
lang_space_state = None
|
||||||
|
else:
|
||||||
|
lang_space_state = state["space"][from_language.value]
|
||||||
|
|
||||||
|
if lang_space_state is None or not lang_space_state:
|
||||||
|
raise click.ClickException("Run Exception: There are no pre-defined state")
|
||||||
|
|
||||||
|
# 테케 분석
|
||||||
|
try:
|
||||||
|
tcs: list[int] = parse_range_string_list(target)
|
||||||
|
except ValueError as e:
|
||||||
|
raise click.ClickException(e)
|
||||||
|
|
||||||
|
# build
|
||||||
|
|
||||||
|
try:
|
||||||
|
subprocess.run(
|
||||||
|
from_language.build_command,
|
||||||
check=True,
|
check=True,
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
text=True,
|
||||||
|
cwd=from_language.working_dir,
|
||||||
)
|
)
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
click.echo(">>>>>> [Error while PRERUNNER process] >>>>>>")
|
click.echo(">>>>>> [Error while BUILD process] >>>>>>")
|
||||||
click.echo(f"{e.stderr}")
|
raise click.ClickException(e.stderr)
|
||||||
click.echo(">>>>>> [Error while PRERUNNER process] >>>>>>")
|
|
||||||
continue
|
build_executable = from_language.build_executable
|
||||||
|
|
||||||
|
for tc in tcs:
|
||||||
|
if not (
|
||||||
|
os.path.isfile(f"{TC_DIR}/{tc}.in") and os.path.isfile(f"{TC_DIR}/{tc}.out")
|
||||||
|
):
|
||||||
|
click.echo(f"{tc:02d}: {None}")
|
||||||
|
else:
|
||||||
|
f_in_path = f"{TC_DIR}/{tc}.in"
|
||||||
|
f_out_path = f"{TC_DIR}/{tc}.out"
|
||||||
|
with open(f_in_path, "r", encoding="utf-8") as f_in:
|
||||||
try:
|
try:
|
||||||
stdout = subprocess.run(
|
stdout = subprocess.run(
|
||||||
runtype.runner.format(
|
from_language.run_executable_command(
|
||||||
source=problem_code_path,
|
f"{BUILD_DIR}/{build_executable}"
|
||||||
).split(),
|
),
|
||||||
check=True,
|
check=True,
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
text=True,
|
||||||
stdin=f,
|
stdin=f_in,
|
||||||
).stdout
|
).stdout
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
click.echo(">>>>>> [Error while RUNNER process] >>>>>>")
|
click.echo(">>>>>> [Error while RUNNING process] >>>>>>")
|
||||||
click.echo(f"{e.stderr}")
|
click.echo(f"{e.stderr}")
|
||||||
click.echo(f"returncode: {e.returncode}")
|
click.echo(f"returncode: {e.returncode}")
|
||||||
click.echo(">>>>>> [Error while RUNNER process] >>>>>>")
|
|
||||||
stdout = ""
|
stdout = ""
|
||||||
continue
|
continue
|
||||||
|
flag: bool = False
|
||||||
|
with open(f_out_path, "r", encoding="utf-8") as f_out:
|
||||||
|
flag = stdout.strip() == f_out.read().strip()
|
||||||
|
click.echo(f"{tc:02d}: {flag}")
|
||||||
|
|
||||||
flag = False
|
|
||||||
for outputpath in outputfs:
|
|
||||||
with open(
|
|
||||||
os.path.join(TC_TARGET_DIR, outputpath), "r", encoding="utf-8"
|
|
||||||
) as f:
|
|
||||||
if stdout.strip() == f.read().strip():
|
|
||||||
flag = True
|
|
||||||
break
|
|
||||||
|
|
||||||
click.echo(f"{c:02d}: {flag}")
|
|
||||||
if verbose:
|
if verbose:
|
||||||
click.echo("===" * 3)
|
click.echo("===" * 3)
|
||||||
click.echo(stdout)
|
click.echo(stdout)
|
||||||
click.echo("===" * 3)
|
click.echo("===" * 3)
|
||||||
|
|
||||||
|
|
||||||
|
@click.command(name="load")
|
||||||
|
@click.argument("file", type=str, nargs=1, required=True)
|
||||||
|
@click.option("--to", type=str, default="") # language value
|
||||||
|
@click.option("--from", "from_", type=str, required=True)
|
||||||
|
@click.option("--force", "-f", is_flag=True)
|
||||||
|
def load(file: str, to: str, from_: str, force: bool):
|
||||||
|
"""
|
||||||
|
load specific file into corresponding src-space
|
||||||
|
"""
|
||||||
|
|
||||||
|
# 파일의 src-space가 어딘지 확인
|
||||||
|
to_language: Language
|
||||||
|
file_name: str
|
||||||
|
file_sep_ext = file.split(".")
|
||||||
|
if len(file_sep_ext) == 1:
|
||||||
|
file_name = file_sep_ext[0]
|
||||||
|
to_language = Language.convert_name(to) # if blank, undefined
|
||||||
|
elif len(file_sep_ext) == 2:
|
||||||
|
file_name = file_sep_ext[0]
|
||||||
|
to_language = Language.convert_name(file_sep_ext[1])
|
||||||
|
else:
|
||||||
|
file_name = ""
|
||||||
|
to_language = Language.UNDEFINED
|
||||||
|
|
||||||
|
if to_language is Language.UNDEFINED:
|
||||||
|
raise click.UsageError("LoadError: `to` or `file` argument is wrong")
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(STATE_PATH, "r", encoding="utf-8") as f_state:
|
||||||
|
state = yaml.safe_load(f_state)
|
||||||
|
except FileNotFoundError as e:
|
||||||
|
raise click.ClickException(e)
|
||||||
|
except yaml.YAMLError as e:
|
||||||
|
raise click.ClickException(e)
|
||||||
|
|
||||||
|
if "space" not in state:
|
||||||
|
raise click.ClickException("state.yml is wrong")
|
||||||
|
elif not state["space"]:
|
||||||
|
click.secho("state.space has no member", fg="yellow", bold=True)
|
||||||
|
state["space"] = {}
|
||||||
|
|
||||||
|
lang_space_state: dict | None
|
||||||
|
if to_language.value not in state["space"]:
|
||||||
|
lang_space_state = None
|
||||||
|
else:
|
||||||
|
lang_space_state = state["space"][to_language.value]
|
||||||
|
|
||||||
|
if not force:
|
||||||
|
if lang_space_state is None or not lang_space_state:
|
||||||
|
pass
|
||||||
|
elif lang_space_state["file"] is None:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise click.ClickException(
|
||||||
|
f"File {lang_space_state['file']}.{to_language.value} already in source space {to_language.value}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 파일이 존재하는지 확인
|
||||||
|
# uncompleted
|
||||||
|
file_is_exist: bool = False
|
||||||
|
file_is_completed: bool = False
|
||||||
|
file_loc: str = None
|
||||||
|
if os.path.isfile(
|
||||||
|
f"{STORAGE_DIR}/{from_}/{to_language.value}/{file_name}.{to_language.value}"
|
||||||
|
):
|
||||||
|
file_is_exist = True
|
||||||
|
file_is_completed = False
|
||||||
|
file_loc = (
|
||||||
|
f"{STORAGE_DIR}/{from_}/{to_language.value}/{file_name}.{to_language.value}"
|
||||||
|
)
|
||||||
|
elif os.path.isfile(
|
||||||
|
f"{STORAGE_DIR}/{from_}/{to_language.value}/completed/{file_name}.{to_language.value}"
|
||||||
|
):
|
||||||
|
file_is_exist = True
|
||||||
|
file_is_completed = True
|
||||||
|
file_loc = f"{STORAGE_DIR}/{from_}/{to_language.value}/completed/{file_name}.{to_language.value}"
|
||||||
|
# 존재하면 move
|
||||||
|
# 존재하지 않으면 빈 파일을 생성하고
|
||||||
|
# state에 기록함
|
||||||
|
if file_is_exist:
|
||||||
|
with (
|
||||||
|
open(file_loc, "rb") as f_src,
|
||||||
|
open(
|
||||||
|
f"{SRC_SPACE_DIR}/src-{to_language.value}/src/main.{to_language.value}",
|
||||||
|
"wb",
|
||||||
|
) as f_dst,
|
||||||
|
):
|
||||||
|
f_dst.write(f_src.read())
|
||||||
|
os.remove(file_loc)
|
||||||
|
else:
|
||||||
|
with open(
|
||||||
|
f"{SRC_SPACE_DIR}/src-{to_language.value}/src/main.{to_language.value}",
|
||||||
|
"wb",
|
||||||
|
) as f_dst:
|
||||||
|
pass
|
||||||
|
|
||||||
|
with open("state.yml", "w", encoding="utf-8") as f:
|
||||||
|
if lang_space_state is None:
|
||||||
|
state["space"][to_language.value] = {}
|
||||||
|
state["space"][to_language.value]["file"] = file_name
|
||||||
|
state["space"][to_language.value]["location"] = from_
|
||||||
|
state["space"][to_language.value]["is_completed"] = file_is_completed
|
||||||
|
|
||||||
|
yaml.safe_dump(state, f)
|
||||||
|
if file_is_exist:
|
||||||
|
click.echo(
|
||||||
|
f"File {file_name}.{to_language.value} from {from_}{'/completed' if file_is_completed else ''} is successfully loaded"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
click.echo(f"File {file_name}.{to_language.value} is successfully created")
|
||||||
|
|
||||||
|
|
||||||
|
@click.command(name="export")
|
||||||
|
@click.option("--from", "from_", type=str, required=True)
|
||||||
|
@click.option(
|
||||||
|
"--completed/--no-completed", "-c/-nc", is_flag=True, flag_value=False, default=None
|
||||||
|
)
|
||||||
|
@click.option("--copy", is_flag=True, help="is copy from state or move")
|
||||||
|
def export(from_: str, completed: bool, copy: bool):
|
||||||
|
# Language 알기
|
||||||
|
from_language = Language.convert_name(from_)
|
||||||
|
|
||||||
|
if from_language is Language.UNDEFINED:
|
||||||
|
raise click.ClickException("Undefined Language Exception")
|
||||||
|
try:
|
||||||
|
with open("state.yml", "r", encoding="utf-8") as f:
|
||||||
|
state = yaml.safe_load(f)
|
||||||
|
except FileNotFoundError as e:
|
||||||
|
raise click.ClickException(e)
|
||||||
|
except yaml.YAMLError as e:
|
||||||
|
raise click.ClickException(e)
|
||||||
|
|
||||||
|
if "space" not in state:
|
||||||
|
raise click.ClickException("State(state.yml) Exception")
|
||||||
|
elif not state["space"]:
|
||||||
|
click.secho("state.space has no member", fg="yellow", bold=True)
|
||||||
|
state["space"] = {}
|
||||||
|
|
||||||
|
lang_space_state: dict | None
|
||||||
|
if from_language.value not in state["space"]:
|
||||||
|
lang_space_state = None
|
||||||
|
else:
|
||||||
|
lang_space_state = state["space"][from_language.value]
|
||||||
|
|
||||||
|
if lang_space_state is None or not lang_space_state:
|
||||||
|
raise click.ClickException("Export Exception: There are no pre-defined state")
|
||||||
|
|
||||||
|
s_file = lang_space_state["file"]
|
||||||
|
s_loc = lang_space_state["location"]
|
||||||
|
s_is_completed = lang_space_state["is_completed"]
|
||||||
|
|
||||||
|
if not s_file:
|
||||||
|
raise click.ClickException(
|
||||||
|
f"Export Exception: There is no file in {from_language.value} space"
|
||||||
|
)
|
||||||
|
|
||||||
|
if not s_loc:
|
||||||
|
raise click.ClickException(f"Export Exception: Location {s_loc} is not defined")
|
||||||
|
|
||||||
|
if completed:
|
||||||
|
s_is_completed = True
|
||||||
|
|
||||||
|
dest_path: str = (
|
||||||
|
f"{STORAGE_DIR}/{s_loc}/{from_language.value}{'/completed' if s_is_completed else ''}/{s_file}.{from_language.value}"
|
||||||
|
)
|
||||||
|
source_path: str = (
|
||||||
|
f"{SRC_SPACE_DIR}/src-{from_language.value}/src/main.{from_language.value}"
|
||||||
|
)
|
||||||
|
|
||||||
|
with open(source_path, "rb") as f_src, open(dest_path, "wb") as f_dst:
|
||||||
|
f_dst.write(f_src.read())
|
||||||
|
|
||||||
|
click.echo(f"File {s_file}.{from_language.value} successfully ")
|
||||||
|
|
||||||
|
if not copy:
|
||||||
|
with open("state.yml", "w", encoding="utf-8") as f:
|
||||||
|
state["space"][from_language.value] = {}
|
||||||
|
yaml.safe_dump(state, f)
|
||||||
|
|
||||||
|
os.remove(source_path)
|
||||||
|
|
||||||
|
|
||||||
|
@click.command(name="state")
|
||||||
|
def state():
|
||||||
|
try:
|
||||||
|
with open(STATE_PATH, "r", encoding="utf-8") as f_state:
|
||||||
|
state = yaml.safe_load(f_state)
|
||||||
|
except FileNotFoundError as e:
|
||||||
|
raise click.ClickException(e)
|
||||||
|
except yaml.YAMLError as e:
|
||||||
|
raise click.ClickException(e)
|
||||||
|
|
||||||
|
if "space" not in state:
|
||||||
|
raise click.ClickException("state.yml is wrong")
|
||||||
|
elif not state["space"]:
|
||||||
|
click.secho("state.space has no member", fg="yellow", bold=True)
|
||||||
|
state["space"] = {}
|
||||||
|
|
||||||
|
for k, v in state["space"].items():
|
||||||
|
if not v:
|
||||||
|
print(f"{k}: _")
|
||||||
|
else:
|
||||||
|
print(
|
||||||
|
f"{k}: {v['file']}.{k} @ {v['location']}{'/completed' if v['is_completed'] else ''}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@click.command(name="init")
|
@click.command(name="init")
|
||||||
@click.argument("count", type=int)
|
@click.argument("count", type=int)
|
||||||
def init(count: int):
|
def init(count: int):
|
||||||
|
"""
|
||||||
|
init testcases with initial count and state.yml and config.yml
|
||||||
|
"""
|
||||||
if count < 1:
|
if count < 1:
|
||||||
raise click.UsageError("COUNT must be greater than 1.")
|
raise click.UsageError("var count should be greater than 1.")
|
||||||
else:
|
|
||||||
if not os.path.exists("./" + TC_TARGET_DIR):
|
if not os.path.exists("./" + TC_DIR):
|
||||||
os.mkdir(TC_TARGET_DIR)
|
os.mkdir(TC_DIR)
|
||||||
for i in range(1, count + 1):
|
for i in range(1, count + 1):
|
||||||
default_in_path = "./" + TC_TARGET_DIR + f"/{i}.in"
|
default_in_path = "./" + TC_DIR + f"/{i}.in"
|
||||||
default_out_path = "./" + TC_TARGET_DIR + f"/{i}.out"
|
default_out_path = "./" + TC_DIR + f"/{i}.out"
|
||||||
|
if not os.path.exists(default_in_path):
|
||||||
with open(default_in_path, "w", encoding="utf-8") as _:
|
with open(default_in_path, "w", encoding="utf-8") as _:
|
||||||
pass
|
pass
|
||||||
|
if not os.path.exists(default_out_path):
|
||||||
with open(default_out_path, "w", encoding="utf-8") as _:
|
with open(default_out_path, "w", encoding="utf-8") as _:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
click.echo("Testcases was made successfully!")
|
click.echo(f"1. Testcases was made with count {count} successfully!")
|
||||||
|
|
||||||
|
if not os.path.isfile("./state.yml"):
|
||||||
|
click.echo("2-1. state.yml does not exist, creating...")
|
||||||
|
with open("state.yml", "w", encoding="utf-8") as f:
|
||||||
|
f.write("space:\n")
|
||||||
|
click.echo("2-1. state.yml is created successfully!")
|
||||||
|
else:
|
||||||
|
click.echo("2-1. state.yml exists")
|
||||||
|
if not os.path.isfile("./config.yml"):
|
||||||
|
click.echo("2-2. config.yml does not exist, creating...")
|
||||||
|
with open("config.yml", "w", encoding="utf-8") as f:
|
||||||
|
f.write("space:\n")
|
||||||
|
click.echo("2-2. config.yml is created successfully!")
|
||||||
|
else:
|
||||||
|
click.echo("2-2. config.yml exists")
|
||||||
|
|
||||||
|
|
||||||
cli.add_command(run)
|
cli.add_command(run)
|
||||||
|
cli.add_command(load)
|
||||||
cli.add_command(init)
|
cli.add_command(init)
|
||||||
|
cli.add_command(export)
|
||||||
|
cli.add_command(state)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
cli()
|
cli()
|
||||||
|
|||||||
Reference in New Issue
Block a user