- common_util_spreadsheet_node.ts · common_util_spreadsheet.py · build:spreadsheet — [저장] 때 화면과 같은 TS 엔진을 Node 로 돌려 계산값 정본(브라우저 값 버림 · 못 풀면 503) - M02 새 종류 basis — resources/master_template/basis/<열 id>.json(구조물집계표 열마다) · 층 복사 · 뼈대 검사 · 옛 구조물 문서 산출근거 49 벌 옮김(migrate_basis) · 새 열도 같이 만듦 - 상세 산출근거 카드 = 새 스프레드시트(import() 로 늦게 받음) · basis 읽기 · 저장 - ⚠ 임시 [스프레드시트 시험] 단추 — 빈 통합문서(시트 셋) · 저장 자리 tmp/spreadsheet_trial.json · 1단계 검증 뒤 지움 - 시험 resources/tester/spreadsheet/ — 저장 · 서버 다리 · 크기 예산 · M02 만 늦게 불러옴 · 실무 구조도 xlsx 세 벌 수식 2,699 칸 엑셀 캐시값 대조(엔진 빈 몸이면 건너뜀) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0168FQuoV7vDh5nhnSowW5cp
75 lines
2.7 KiB
Python
75 lines
2.7 KiB
Python
"""F — 스프레드시트 크기 예산 · M02 만 늦게 불러옴(계약 `spreadsheet_types.ts` 머리).
|
|
|
|
예산(압축 gzip 뒤) — 엔진 A+B 22 KB · 화면 C+D+E 28 KB · css 4 KB · 합 54 KB.
|
|
엔진은 파일마다 따로 묶어 더하므로 실제보다 조금 크게 잼(넘치면 넘친 것).
|
|
"""
|
|
|
|
import json
|
|
import re
|
|
import shutil
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
ROOT = Path(__file__).resolve().parents[3]
|
|
SCRIPT = Path(__file__).with_name("spreadsheet_size.mjs")
|
|
KB = 1024
|
|
BUDGET = {"engine": 22 * KB, "view": 28 * KB, "css": 4 * KB, "total": 54 * KB}
|
|
|
|
pytestmark = pytest.mark.skipif(shutil.which("node") is None, reason="node 가 없음")
|
|
|
|
|
|
def test_크기_예산():
|
|
out = subprocess.run(
|
|
["node", str(SCRIPT), str(ROOT)],
|
|
cwd=ROOT,
|
|
capture_output=True,
|
|
text=True,
|
|
encoding="utf-8",
|
|
timeout=300,
|
|
check=True,
|
|
)
|
|
size = json.loads(out.stdout.strip().splitlines()[-1])
|
|
engine, total = size["engine"]["js"], size["total"]
|
|
view = max(0, total["js"] - engine)
|
|
print(
|
|
f"gzip — 엔진 {engine} · 화면 {view} · css {total['css']} · 합 {total['js'] + total['css']}"
|
|
)
|
|
assert engine <= BUDGET["engine"], f"엔진 {engine} B > {BUDGET['engine']}"
|
|
assert view <= BUDGET["view"], f"화면 {view} B > {BUDGET['view']}"
|
|
assert total["css"] <= BUDGET["css"], f"css {total['css']} B > {BUDGET['css']}"
|
|
assert total["js"] + total["css"] <= BUDGET["total"]
|
|
|
|
|
|
# 정적 import 금지 — 타입만(`import type`) · 늦게(`import(`) 는 됨
|
|
_STATIC = re.compile(
|
|
r"^\s*import\s+(?!type\b)[^;]*?from\s+[\"'][^\"']*spreadsheet/spreadsheet", re.M
|
|
)
|
|
_SIDE = re.compile(r"^\s*import\s+[\"'][^\"']*spreadsheet/spreadsheet", re.M)
|
|
|
|
|
|
def test_M02_만_늦게_불러옴():
|
|
offenders, users = [], []
|
|
listed = subprocess.run(
|
|
["git", "ls-files", "--cached", "--others", "--exclude-standard", "*.ts"],
|
|
cwd=ROOT,
|
|
capture_output=True,
|
|
text=True,
|
|
encoding="utf-8",
|
|
check=True,
|
|
).stdout.splitlines()
|
|
for rel in listed:
|
|
if rel.startswith("A00_Common/spreadsheet/") or not (ROOT / rel).is_file():
|
|
continue
|
|
text = (ROOT / rel).read_text(encoding="utf-8", errors="replace")
|
|
if "spreadsheet/spreadsheet" not in text:
|
|
continue
|
|
if _STATIC.search(text) or _SIDE.search(text):
|
|
offenders.append(rel)
|
|
if "import(" in text:
|
|
users.append(rel)
|
|
# 서버 Node 진입만 정적(브라우저 번들 밖)
|
|
assert offenders == ["common_util/common_util_spreadsheet_node.ts"], offenders
|
|
assert users and all(u.startswith("M02_MasterTemplete/") for u in users), users
|