- build_detail auto — 없음 = 세류선 교차만 · all = 세류선 + 100 m 보충으로 다시 · add = 지금 목록 + 빈 구간 보충 · 후보는 늘 셈 - 배수유역 라우터 — 요청 auto 칸(틀리면 400) · 같은 자리(0.05 m) 관만 속성 · id · 사유 이어받음 · 나머지 새 관 = 등록부 기본값 · 저장본 열쇠에 auto - 노선 [저장] · 추천 [적용] — 오목 지점 보충 지움(응답 concave 칸 · 화면 한 줄 같이) - 시험 — test_369_drainage_auto 세 모드 · test_346_3 · 312 · 342_3 고쳐 씀 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VmC34fsxxbweEG3RUjs3Mn
76 lines
3.0 KiB
Python
76 lines
3.0 KiB
Python
"""342-3 세부 유역 저장본(부록 4 R15) — 열쇠가 같으면 다시 나누지 않음.
|
|
|
|
- 열쇠 = 관 목록 · 노선(평면 · 종단 Z) · 분석 산출물 · 강우표 · 구조물 정의 자국.
|
|
- 같은 열쇠 = _build 안 부름 · 관 목록은 사본 · 무엇이든 바뀌면 다시 셈.
|
|
- [저장] 뒤 파일 한 벌 — 서버를 다시 켜도(메모리 비움) GET 열쇠로 읽힘.
|
|
"""
|
|
|
|
import os
|
|
from pathlib import Path
|
|
from types import SimpleNamespace
|
|
|
|
import pytest
|
|
|
|
from B04_PreProcess import B04_PreProcess_Router_Basins as basins
|
|
from common_util.common_util_drainage_context import DrainageContext
|
|
from common_util.common_util_drainage_detail import DrainageDetail
|
|
from common_util.common_util_drainage_pipes import PipePoint
|
|
from common_util.common_util_route_geometry import RouteVertex
|
|
|
|
|
|
@pytest.fixture
|
|
def setup(tmp_path, monkeypatch):
|
|
monkeypatch.setattr(basins, "drainage_dir", lambda stored: tmp_path)
|
|
basins._DETAIL_CACHE.clear()
|
|
calls = SimpleNamespace(count=0)
|
|
|
|
def build(stored_path, context, points, auto=None):
|
|
calls.count += 1
|
|
chainages = [p.chainage_m for p in points] if points else [50.0]
|
|
return DrainageDetail(), [PipePoint(chainage_m=c, source="stream") for c in chainages]
|
|
|
|
monkeypatch.setattr(basins, "_build", build)
|
|
(tmp_path / "03_road_routing.npz").write_bytes(b"grid")
|
|
context = DrainageContext(
|
|
stored_path="x",
|
|
project_root=Path("."),
|
|
vertices=[RouteVertex(0.0, 0.0, 100.0, 0.0), RouteVertex(300.0, 0.0, 90.0, 300.0)],
|
|
)
|
|
return tmp_path, context, calls
|
|
|
|
|
|
def test_same_key_reuses_and_copies(setup):
|
|
_, context, calls = setup
|
|
points = [PipePoint(chainage_m=120.0, source="user")]
|
|
_, first = basins._build_cached(context, points)
|
|
first[0].x = 999.0 # 저장이 좌표를 채워도 저장본은 그대로
|
|
_, second = basins._build_cached(context, points)
|
|
assert calls.count == 1
|
|
assert second[0].x is None
|
|
|
|
|
|
def test_any_input_change_recomputes(setup):
|
|
tmp_path, context, calls = setup
|
|
points = [PipePoint(chainage_m=120.0, source="user")]
|
|
basins._build_cached(context, points)
|
|
basins._build_cached(context, [PipePoint(chainage_m=121.0, source="user")]) # 관 자리
|
|
context.vertices[1].z = 91.0 # 계획고(종단 Z) → 관 깊이
|
|
basins._build_cached(context, points)
|
|
routing = tmp_path / "03_road_routing.npz"
|
|
routing.write_bytes(b"grid-2") # 분석 다시 돎
|
|
os.utime(routing, ns=(1, 1))
|
|
basins._build_cached(context, points)
|
|
assert calls.count == 4
|
|
|
|
|
|
def test_saved_file_survives_restart(setup):
|
|
tmp_path, context, calls = setup
|
|
stored = [PipePoint(chainage_m=120.0, source="stream")]
|
|
detail, carried = basins._build(context.stored_path, context, stored)
|
|
basins._save_detail_cache(context, stored, detail, carried)
|
|
assert (tmp_path / basins.DETAIL_CACHE_FILENAME).exists()
|
|
basins._DETAIL_CACHE.clear() # 서버 다시 켬
|
|
_, again = basins._build_cached(context, stored)
|
|
assert calls.count == 1
|
|
assert [p.chainage_m for p in again] == [120.0]
|