요구 651 · 653 — 계산 공식 참고용 흐름도(① M01 로직 상세 오른쪽 접는 패널)를 걷음. ② M02 일위대가 다이어그램은 그대로.
지움(64 파일 · 18,666 줄 · 되돌릴 길 = git 이력)
- M01 6 파일 1,064 줄 — Store_Flow.py · UI_LogicLab_Flow.ts/.css · FlowRows.ts · FlowView.ts/.css
- M02_MasterTemplete/DataFlow 43 파일 12,799 줄 — 흐름도 화면 · 셈(Compute · Convert · Lookup · Model · Eval …)
- 시험 15 파일 4,803 줄 — test_m01_logic_flow{view,_engine,_project,_save} · test_m02_df_*(값 찾기 values_old 뺌) — 지운 흐름 코드만 지키던 것
남김(바닥) — DataFlow M02_DF_UnitPick(일위대가 셋) · M02_DF_Values(M02_Item_Prices) · M02_DF_Round · _standard 표 ·
M02_DF_Router = GET /api/m02/df/standards 하나 · M02_DF_Api = cfStandards 하나 · CfRound 꼴은 Round 안으로
고침
- M01 Router — /save = Store_Make.save(개정 확인 · 자체 파일 새 줄 GX · added 그대로) · /calc /text /logic/auto = 옛 셈만 · /logic/flow 둘 지움
- master_formula — 흐름 훅 지움 · 줄에 「흐름」 이 남으면 「흐름도 로직은 걷음」 까닭 오류(저장된 흐름 로직 0 — 마스터 · storage 다시 확인)
- Sangeun_Calc._defaults = 옛 자동값 · M02_Logic_Lib_Read /logic/flow 지움 · main.py 주석
- 화면 — LogicLab(startFlow · scheduleFlow · 예시값 잇기 지움 · [신규 로직] 줄 = 입력 · 중간 · 호표 빈 목록 + 끝수 null) ·
Side(원문 패널 하나) · Source(머리 칸 이름 m01lab-src__top/__title · DF_Panel.css 안 씀) · Detail · View(nowInputs 지움) · Sheet(흐름 갈래 지움) · 글
- 시험 — 지운 파일을 가리키던 목록 넷(spreadsheet_size · 208_1 · 588 · input_prefs) · 717_1 흐름 길 두 줄 · values_old 흐름 셈 부분 지움
- test_713_3_list 기대 — 로직 1,461 → 1,515 · 묶음 307 → 335 · 작업량 21 → 65 · 부르는 506 → 512(782-1 · 2 · 3 건설 기초 로직 54 더함 ·
옛 키만 세면 307 · 21 · 506 그대로)
- 새 지킴 test_794_1b_flow_gone — 흐름 길 404 · 표준 표 남음 · 신규 로직 자체 GX · 흐름 남은 줄 까닭 오류
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
87 lines
3.3 KiB
Python
87 lines
3.3 KiB
Python
"""F — 스프레드시트 크기 예산 · M02 · E05 만 늦게 불러옴(계약 `spreadsheet_types.ts` 머리).
|
|
|
|
예산(압축 gzip 뒤) — 엔진 A+B 48 KB · 화면 C+D+E 72 KB · css 8 KB · 합 128 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": 48 * KB, "view": 72 * KB, "css": 8 * KB, "total": 128 * 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 size["static"] == [], f"스프레드시트 조각을 정적으로 끌어옴 — {size['static']}"
|
|
assert size["first"] == [], f"M02 첫 조각에 스프레드시트 모듈 — {size['first']}"
|
|
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:
|
|
# 시험용 진입(`resources/tester/`)은 앱 번들 밖
|
|
if rel.startswith(("A00_Common/spreadsheet/", "resources/tester/")):
|
|
continue
|
|
if 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
|
|
# M02 화면 + 고르기 모달 편집 화면 + E05 보고서(내장 엑셀 · 열 때만 `import(`)
|
|
later = (
|
|
"M02_MasterTemplete/",
|
|
"ui_template/ui_template_item_picker_edit.ts",
|
|
"E05_StabReport/",
|
|
)
|
|
assert users and all(u.startswith(later) for u in users), users
|