Files
Aislo/resources/tester/test_505_2_terrain_sheet.py
T
eomsangdonandClaude Opus 5.5 7ae7515773 fix(505-1 덧 · 505-2 5d B05): 추천 접근 = 엔진 지문 달라도 저장본 읽음 · 모델 없는 sheet 고르기 숨김 · 409 사유
- 추천 저장본: 프로젝트 접근(화면 기본 갈래)은 같은 판 · 같은 입력이면 그 파일 소스 지문으로 키를 다시 내 찾음(read_stored_any) · 지문 견줌 · 다시 셈은 전처리 체인만
- 초기 종단 저장본: 접근은 코드 지문 빼고 입력만 견줌 · 파일에 코드 지문 칸 · 지문 칸 없는 옛 파일은 그대로 읽음
- 분석 지형 고르기 목록: 설계 지형 아닌 쪽은 DB 완료 모델도 있어야 둠(없으면 숨김)
- 노선 [저장] 설계 지형 바꿈에 모델 없음(LookupError) = 되돌림 + 409 사유 한 줄
- 시험 test_309_3 둘 더함 · test_505_2_terrain_sheet 새로 · test_133_1 DB 모델 맞춤

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 13:28:06 +09:00

102 lines
3.7 KiB
Python

"""PLAN 505-2 5d — 수치지형도 sheet 고르기 = DB 모델 있을 때만 · 없으면 [확인] 409 사유 한 줄.
./venv/Scripts/python.exe -m pytest resources/tester/test_505_2_terrain_sheet.py -q
고르기 목록(`/route/terrain-sources`)은 npz 파일 + DB 완료 모델을 함께 봄 — 모델 없는 sheet 는 숨김
(화면은 고르기가 숨으면 분석 지형을 안 실음). 바꿈(`switch_design_terrain`)이 모델을 못 찾으면
`_recompute` 가 `{error}` → 노선 되돌리고 409(전엔 LookupError 가 저장 통째 되돌림).
"""
from __future__ import annotations
import asyncio
import sys
from contextlib import asynccontextmanager
from pathlib import Path
from uuid import uuid4
import pytest
ROOT = Path(__file__).resolve().parents[2]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
import B04_PreProcess.B04_PreProcess_Service as service # noqa: E402
import B05_Profile.B05_Profile_Router_Replan as replan # noqa: E402
import B05_Profile.B05_Profile_Router_Terrain as terrain # noqa: E402
from common_util.common_util_surface_confirmation import SHEET_ANALYSIS_FILTER # noqa: E402
LAS = {"source_filter": "classification", "method": "dtm", "smooth": True}
class _Pool:
@asynccontextmanager
async def acquire(self):
yield _Connection()
class _Connection:
async def begin(self):
pass
async def rollback(self):
_Connection.rolled = True
async def commit(self):
raise AssertionError("모델 없으면 확정하지 않음")
def _async(value):
async def inner(*args, **kwargs):
return value
return inner
def _model(source_filter: str) -> dict:
return {
"id": 7,
"status": "COMPLETE",
"model_type": "DTM",
"generation_params": {"source_filter": source_filter},
}
@pytest.fixture
def sources(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
models = tmp_path / terrain._MODELS_SUBDIR
models.mkdir(parents=True)
(models / f"dtm_{SHEET_ANALYSIS_FILTER}.npz").write_bytes(b"") # sheet 파일은 있음
monkeypatch.setattr(terrain, "get_db_pool", lambda: _Pool())
monkeypatch.setattr(terrain, "get_project_storage_relative_path", _async("p"))
monkeypatch.setattr(terrain, "get_surface_confirmation_params", _async(dict(LAS)))
monkeypatch.setattr(terrain, "_confirmed_model", _async(None))
monkeypatch.setattr(terrain, "resolve_stored_project_path", lambda stored: tmp_path)
monkeypatch.setattr(terrain, "_design_grid", lambda *args: None)
def run(models_in_db: list[dict]) -> list[str]:
monkeypatch.setattr(service, "list_surface_models", _async(models_in_db))
return asyncio.run(terrain.read_terrain_sources(uuid4()))["sources"]
return run
def test_모델_없는_sheet_고르기_숨김(sources) -> None:
assert sources([_model("classification")]) == ["las"]
def test_모델_있는_sheet_고르기_보임(sources) -> None:
assert sources([_model(SHEET_ANALYSIS_FILTER)]) == ["las", "sheet"]
def test_모델_없으면_재계산_409_사유(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
import common_util.common_util_surface_confirmation as surface
_Connection.rolled = False
monkeypatch.setattr(replan, "get_db_pool", lambda: _Pool())
monkeypatch.setattr(service, "get_surface_confirmation_params", _async(dict(LAS)))
monkeypatch.setattr(service, "list_surface_models", _async([_model("classification")]))
monkeypatch.setattr(surface, "get_surface_confirmation_params", _async(dict(LAS)))
got = asyncio.run(replan._recompute(uuid4(), tmp_path, "p", terrain="sheet"))
assert got == {"error": replan.TERRAIN_MODEL_MISSING} and _Connection.rolled