Files
Aislo/resources/tester/test_800_5_copy_symbols.py
T
eomsangdonandClaude Sonnet 5.5 2a41b989a2 feat(800-5): 호표 줄 금액 참조 기호 — 정의 영역도 씌운 기호(C_합판) · M02 옛 사본 변수표 새로 쓰는 한 번 도구
- 정의 영역: 줄 참조 기호를 이름으로 덮던 줄 뺌 → 수식 영역과 같은 글(master_symbol 한 곳)
- M02_Copy_Symbols: 옛 사본 줄 변수표가 비었거나 열쇠 그대로면 지금 M01 줄 변수표로 채움 · 고친 기호 그대로 · 금액 대조 같을 때만 씀 · --backup
- test_800_5 새 4: 줄 참조 · M01 정의 한글(하위 로직 칩 빼고) 0 · 옛 사본 새로 씀 · 사용자 고침 보존 · 백업 되돌림

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 17:26:57 +09:00

141 lines
6.1 KiB
Python

# ruff: noqa: F811 — 임시 층 fixture(world)를 test_m02_labor_ref 에서 받아 씀
"""800-5 기호 남은 한글 — 임시 storage 에서만.
① 호표 줄 금액 참조(`줄.`) 기호 = 수식 영역 · 정의 영역 같은 글(한글 0) ② 새 사본 = 이미 새 기호
③ 옛 사본 변수표 새로 씀 = 사용자 고침 칸 그대로 · 금액 같음 · 백업 되돌림 ④ M01 전수 한글 기호(하위 로직 칩 제외) 0.
"""
from __future__ import annotations
import copy
import importlib
import json
import re
from M02_MasterTemplete import M02_Copy_Migrate as mig
from M02_MasterTemplete import M02_Copy_Symbols as sym
from M02_MasterTemplete import M02_Sangeun_Copy as skc
from M01_MasterData import M01_MasterData_Store as m01
from M02_MasterTemplete import M02_Labor_Ref as refs
from M02_MasterTemplete import M02_MasterTemplete_Store as store
from resources.tester.test_m02_labor_ref import world # noqa: F401 — 같은 임시 층
LINE = {"로직": "GC000211", "수량": {"손": 1}} # 변수 많은 합판거푸집
def _make(me):
with store.at(me):
sk = refs.create(
"sangeun",
{"이름": "sub2임시", "단위": "㎡", "바탕": {"로직": "GC000211"}, "더한줄": []},
)["이름"]
path = me / "sangeun" / f"{sk}.json"
raw = {k: v for k, v in json.loads(path.read_bytes()).items() if k != skc.KEY}
path.write_text(json.dumps(raw, ensure_ascii=False), encoding="utf-8")
return {path: raw}
def _mine(rows, olds):
keys = {p.stem for p in olds}
return {r["키"]: r for r in rows if r["어디"].startswith("개인") and r["키"] in keys}
meq = importlib.import_module("master_equation")
HAN = re.compile(r"[가-힣]")
def _walk(tree, out: list) -> None:
if isinstance(tree, dict):
if tree.get("꼴") == "변수":
out.append(tree)
for v in tree.values():
_walk(v, out)
elif isinstance(tree, list):
for v in tree:
_walk(v, out)
def test_줄_참조_기호_같은_글_한글_0():
eq = meq.export(m01.loaded()[1], "GC000211")
refs = []
_walk(eq["줄"], refs)
refs = [v for v in refs if str(v["열쇠"]).startswith("줄.")]
assert refs and all(not HAN.search(v["기호"]) and v["기호"] == "C" for v in refs)
defs = {(d["기호"], d["아래"]): d for d in eq["정의"]}
for v in refs:
d = defs[(v["기호"], v["아래"])]
assert d["갈래"] == "요소" and not HAN.search(d["기호"])
assert any("호표 줄 금액" in c for d in defs.values() for c in d["연결"])
def test_M01_전수_정의_한글_기호는_하위_로직_칩뿐():
whole = m01.loaded()[1]
keys = [r["키"] for d in m01.loaded()[0].values() if d.get("그룹") == "로직" for r in d["줄"]]
for code in keys[::25]:
for d in meq.export(whole, str(code))["정의"]:
assert d["갈래"] == "블록" or not HAN.search(d["기호"]), (code, d["이름"])
def _old(path):
"""사본 변수표를 걷어 옛 사본 흉내 → (옛 문서, 걷은 줄 수)."""
doc = json.loads(path.read_bytes())
cut = 0
for r in doc[skc.KEY]["로직"]:
cut += r.pop(sym.FIELD, None) is not None
doc[skc.KEY]["판"] = skc._fp(doc[skc.KEY]["로직"])
path.write_text(json.dumps(doc, ensure_ascii=False), encoding="utf-8")
return doc, cut
def test_새_사본은_이미_새_기호_옛_사본은_새로_씀(world, tmp_path):
olds = _make(world["personal"])
back = tmp_path / "stamp"
mig.migrate(True, back) # 새 사본 찍음
paths = list(olds)
for p in paths:
rows = json.loads(p.read_bytes())[skc.KEY]["로직"]
assert any(r.get(sym.FIELD) for r in rows) # ② 새 사본 = 변수표 있음
assert {r["상태"] for r in _mine(sym.run(), olds).values()} == {"채울것없음"}
stripped = {p: _old(p) for p in paths}
assert all(cut for _, cut in stripped.values())
# 사용자 고침 칸 하나 — 영문 기호 Z 는 그대로
sk = next(p for p in paths if p.parent.name == "sangeun")
doc = json.loads(sk.read_bytes())
row = next(r for r in doc[skc.KEY]["로직"] if r.get("입력"))
name = str(row["입력"][0]["이름"])
row[sym.FIELD] = {name: {"기호": "Z", "아래": "내것"}}
sk.write_text(json.dumps(doc, ensure_ascii=False), encoding="utf-8")
before = {p: p.read_bytes() for p in paths}
rows = _mine(sym.run(), olds) # 보기만 = 안 씀
assert {r["상태"] for r in rows.values()} == {"같음"} and not any(
r["씀"] for r in rows.values()
)
assert all(p.read_bytes() == b for p, b in before.items())
back = tmp_path / "back"
rows = _mine(sym.run(True, back), olds)
assert all(r["씀"] and r["채움"] > 0 and r["못닿음"] == 0 for r in rows.values())
for p in paths:
for r in json.loads(p.read_bytes())[skc.KEY]["로직"]:
for part in ("입력", "중간"):
for spec in r.get(part) or []:
look = (r.get(sym.FIELD) or {})[str(spec["이름"])]
assert look.get("기호")
if not (r is row and spec["이름"] == name):
assert not HAN.search(look["기호"]), (r["키"], spec["이름"])
now = next(r for r in json.loads(sk.read_bytes())[skc.KEY]["로직"] if r["키"] == row["키"])
assert now[sym.FIELD][name] == {"기호": "Z", "아래": "내것"}
assert {r["상태"] for r in _mine(sym.run(), olds).values()} == {"채울것없음"} # 다시 돌림
mig.restore(back)
assert all(p.read_bytes() == before[p] for p in paths)
def test_채운_줄은_M01_줄_변수표_그대로():
live = m01.loaded()[1]
row = copy.deepcopy(live.logic("GC000211"))
src = row[sym.FIELD]
stripped = {k: v for k, v in row.items() if k != sym.FIELD}
got, done, lost = sym.fill({"로직": [json.loads(json.dumps(stripped, default=str))]}, live)
names = {str(s["이름"]) for k in ("입력", "중간") for s in row[k]}
assert done == len(names & set(src)) and lost == len(names - set(src))
assert all(got["로직"][0][sym.FIELD][n]["기호"] == src[n]["기호"] for n in names & set(src))