feat(z01): 낱값 값·설명 가름을 이름표 표시로 갈아끼움 — 잠정 잣대 뺌 · 이름표 role value 는 보임 · note 는 뺌 · 표시 없거나 모르는 낱말은 값으로 보이되 「미판정」 칸으로 드러냄(진짜 이름표 0 을 시험으로 못박음) · 줄 이름 열 @key 는 그 표 열 목록의 제 이름을 먼저 찾음(fx 통화 · masonry_slope 쌓기 방식)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BW6Jdsh18WPtYUR6THZJqn
This commit is contained in:
@@ -107,8 +107,10 @@ def test_묶음_표는_줄마다_이름_열(client: TestClient) -> None:
|
||||
assert slope["rows"][0]["성토"] == [0.3, 0.35, 0.4, 0.45, 0.5]
|
||||
cols = {c["key"]: c for c in slope["columns"]}
|
||||
assert cols["성토"]["label"] == "성토부 경사" and cols["성토"]["unit"] == "1:n"
|
||||
assert cols["@key"]["label"] == "쌓기 방식" # 줄 이름 열은 표마다 제 이름(이름표 표 열 목록)
|
||||
fx = {c["key"]: c for c in _rows(client, file="fx", table="variables")["columns"]}
|
||||
assert fx["value"]["label"] == "환율" and fx["value"]["unit"] == "원" # 「fx/value」 덮어쓰기
|
||||
assert fx["@key"]["label"] == "통화"
|
||||
|
||||
|
||||
def test_숨김은_이름표의_보임에서(client: TestClient) -> None:
|
||||
@@ -167,8 +169,8 @@ def test_찾는_차례와_없는_이름은_영문_key(
|
||||
)
|
||||
|
||||
|
||||
def test_낱값은_파일마다_표_하나_설명류는_뺌(client: TestClient) -> None:
|
||||
"""브레인 ④ — 표 아닌 마디(값 묶음)도 트리에 `@values` 한 마디로 · 설명·방침은 값이 아님."""
|
||||
def test_낱값은_파일마다_표_하나_설명은_뺌(client: TestClient) -> None:
|
||||
"""브레인 ④ — 표 아닌 마디(값 묶음)도 트리에 `@values` 한 마디로 · 값/설명 가름은 이름표 `role`."""
|
||||
files = _files(client)
|
||||
rates = files["rates"]["tables"]
|
||||
assert rates[-1]["id"] == "@values"
|
||||
@@ -183,20 +185,57 @@ def test_낱값은_파일마다_표_하나_설명류는_뺌(client: TestClient)
|
||||
"@value": False,
|
||||
"@path": True,
|
||||
}
|
||||
master = {r["@path"] for r in _rows(client, file="work_item_master", table="@values")["rows"]}
|
||||
assert master == {"stats"} # policy 는 방침
|
||||
assert "@values" not in {t["id"] for t in files["aliases"]["tables"]} # note 뿐
|
||||
assert "@values" not in {t["id"] for t in files["fx"]["tables"]} # 값 묶음 없음
|
||||
for f in files.values():
|
||||
if "@values" in {t["id"] for t in f["tables"]}:
|
||||
paths = [
|
||||
r["@path"] for r in _rows(client, file=f["id"], table="@values", size=500)["rows"]
|
||||
]
|
||||
assert not [p for p in paths if tables.is_description(p)], f["id"]
|
||||
assert "@values" not in {
|
||||
t["id"] for t in files["work_item_master"]["tables"]
|
||||
} # 방침·집계 = 설명
|
||||
assert "@values" not in {t["id"] for t in files["fx"]["tables"]} # 값 묶음 없음 — 줄이 곧 값
|
||||
for entry in LABELS["files"]: # 보이는 것 = 이름표가 「값」 이라 한 것 그대로
|
||||
want = [g["key"] for g in entry["value_groups"] if g["role"] == "value"]
|
||||
got = (
|
||||
_rows(client, file=entry["file_id"], table="@values", size=500)["rows"]
|
||||
if "@values" in {t["id"] for t in files[entry["file_id"]]["tables"]}
|
||||
else []
|
||||
)
|
||||
assert sorted(r["@path"] for r in got) == sorted(want), entry["file_id"]
|
||||
hit = _rows(client, file="rates", table="@values", q="산재")
|
||||
assert [r["@path"] for r in hit["rows"]] == ["variables/rate_sanjae"]
|
||||
|
||||
|
||||
def test_이름표가_값_설명을_안_가른_마디는_미판정으로_보임(
|
||||
client: TestClient, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""브레인 — 조용히 값으로 보이면 설명이 섞이고, 조용히 빼면 원가에 드는 값이 사라짐 → 값으로 보이되 드러나게."""
|
||||
entry = next(f for f in LABELS["files"] if f["file_id"] == "rates")
|
||||
lagging = [dict(g) for g in entry["value_groups"]]
|
||||
for g in lagging:
|
||||
if g["key"] in ("variables/rate_vat", "variables/rate_goyong/base"):
|
||||
del g["role"] # 이름표가 뒤처짐
|
||||
elif g["key"] == "variables/rate_care":
|
||||
g["role"] = "formula" # 코드가 모르는 낱말도 미판정
|
||||
(tmp_path / "labels_2026-01-01.json").write_text(
|
||||
json.dumps({**LABELS, "files": [{**entry, "value_groups": lagging}]}, ensure_ascii=False),
|
||||
encoding="utf-8",
|
||||
)
|
||||
monkeypatch.setattr(tables, "LABEL_DIR", tmp_path)
|
||||
values = _rows(client, file="rates", table="@values", size=500)
|
||||
marks = {r["@path"]: r.get(tables.UNDECIDED_COLUMN) for r in values["rows"]}
|
||||
undecided = {"variables/rate_vat", "variables/rate_goyong/base", "variables/rate_care"}
|
||||
assert {p for p, m in marks.items() if m} == undecided
|
||||
assert {marks[p] for p in undecided} == {tables.UNDECIDED}
|
||||
assert tables.UNDECIDED_COLUMN in {c["key"] for c in values["columns"]}
|
||||
assert not next(c for c in values["columns"] if c["key"] == tables.UNDECIDED_COLUMN)["hidden"]
|
||||
|
||||
|
||||
def test_진짜_이름표엔_미판정이_없음() -> None:
|
||||
undecided = [
|
||||
f"{entry['file_id']}::{r['@path']}"
|
||||
for entry in LABELS["files"]
|
||||
for r in tables._value_rows(entry, tables.ROOT / entry["path"], LABELS)
|
||||
if r.get(tables.UNDECIDED_COLUMN)
|
||||
]
|
||||
assert undecided == [], undecided
|
||||
|
||||
|
||||
def test_값_묶음_자리는_이름표와_양쪽으로_같음() -> None:
|
||||
not_labelled, label_only = [], []
|
||||
for entry in LABELS["files"]:
|
||||
@@ -207,7 +246,7 @@ def test_값_묶음_자리는_이름표와_양쪽으로_같음() -> None:
|
||||
assert not_labelled == [] and label_only == [], (not_labelled, label_only)
|
||||
for entry in LABELS["files"]: # 이름도 이름표가 푼 그대로(찾는 차례 「파일id::key」 → 끝 조각)
|
||||
named = {g["key"]: g["name_ko"] for g in entry["value_groups"]}
|
||||
rows = tables._value_rows(entry["file_id"], tables.ROOT / entry["path"], LABELS)
|
||||
rows = tables._value_rows(entry, tables.ROOT / entry["path"], LABELS)
|
||||
assert [r["@name"] for r in rows] == [named[r["@path"]] for r in rows], entry["file_id"]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user