refactoring stage 5

- fix export command
This commit is contained in:
2026-05-05 20:04:07 +09:00
parent 97f1636c57
commit df8fb68a1d

140
run.py
View File

@@ -207,6 +207,17 @@ class Language(Enum):
case _:
return Language.UNDEFINED
@staticmethod
def languages() -> list["Language"]:
return [
Language.PYTHON,
Language.C,
Language.CPP,
Language.RUST,
Language.KOTLIN,
Language.LUA,
]
def _dispatch_target(target: str) -> tuple[str, str, Language]:
splited = target.split("/")
@@ -341,7 +352,12 @@ class StorageManager:
return None
def save_file(
self, location: str, lang: Language, filename: str, content: bytes, completed: bool
self,
location: str,
lang: Language,
filename: str,
content: bytes,
completed: bool,
) -> None:
path = STORAGE_DIR / location / lang.value / ("completed" if completed else "")
os.makedirs(path, exist_ok=True)
@@ -392,6 +408,18 @@ class StorageManager:
if os.path.isfile(completed_file):
os.rename(completed_file, uncompleted_file)
@staticmethod
def construct_target_path(
location: str, lang: Language, filename: str, completed: bool
) -> pathlib.Path:
return (
STORAGE_DIR
/ location
/ lang.value
/ ("completed" if completed else "")
/ f"{filename}.{lang.value}"
)
# =======================
# MAIN CLI LOGIC
@@ -482,7 +510,7 @@ def create(target: str, completed: bool, template: bool, force: bool):
@click.argument("lang", type=str, nargs=1, required=True)
@click.option("--testcase", "-t", default=["1"], multiple=True)
@click.option("--verbose/--no-verbose", "-v/-nv", default=True)
def run(lang: str, testcase: list[str], verbose: bool):
def run(lang: str, testcase: tuple[str, ...], verbose: bool):
"""
지정된 언어로 빌드 및 실행하는 명령어
"""
@@ -500,6 +528,7 @@ def run(lang: str, testcase: list[str], verbose: bool):
)
# 테케 분석
testcase: list[str] = list(testcase)
tcs: list[int] = _parse_range_string_list(testcase)
# build
@@ -608,73 +637,72 @@ def load(target: str, force: bool):
@click.command(name="export")
@click.option("--from", "from_", type=str, required=True)
@click.argument("from", "from_", type=str, nargs=-1)
@click.option(
"--completed/--no-completed", "-c/-nc", is_flag=True, flag_value=False, default=None
"--all", "all_", default=False, is_flag=True, help="Export all files in the space"
)
@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_)
@click.option(
"--force",
"-f",
is_flag=True,
help="Overwrite existing file in storage if it already exists",
)
def export(from_: tuple[str, ...], all_: bool, force: bool):
"""
space에 있는 파일을 storage의 각 location으로 이동시키는 명령.
"""
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)
def _export_sub_command(from_language: Language):
space = StateManager().get_space(from_language)
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"] = {}
s_file, s_loc, s_is_completed = (
space["file"],
space["location"],
space["is_completed"],
)
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]
path = StorageManager.construct_target_path(
s_loc, from_language, s_file, s_is_completed
)
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:
if path.is_file() and not force:
raise click.ClickException(
f"Export Exception: There is no file in {from_language.value} space"
f"File '{path.name}' already exists in location '{s_loc}'. Use --force to overwrite."
)
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}"
src_path = (
SRC_SPACE_DIR
/ f"src-{from_language.value}"
/ "src"
/ f"main.{from_language.value}"
)
os.makedirs(os.path.dirname(dest_path), exist_ok=True)
with open(src_path, "rb") as f_src:
content = f_src.read()
with open(source_path, "rb") as f_src, open(dest_path, "wb") as f_dst:
f_dst.write(f_src.read())
StorageManager().save_file(
s_loc, from_language, s_file, content, s_is_completed
)
click.secho(
f"Exported '{s_file}.{from_language.value}' to location '{s_loc}'",
fg="cyan",
bold=True,
)
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)
if all_:
for l in Language.languages():
if StateManager().check_space(l):
_export_sub_command(l)
else:
froms = map(lambda x: Language.convert_name(x), from_)
for l in froms:
if not StateManager().check_space(l):
click.secho(
f"No loaded file for language '{l.value}' in space. Skipping export for this language.",
fg="yellow",
)
continue
_export_sub_command(l)
@click.command(name="state")