- 조각 저장본 한 벌(_derived/plan_tile) — 처음 열 때 한 번 셈 · 받을 때 더함 · 넘치면 묵은 것부터 80 % 까지 · 하루 넘게 묵은 것만 본 때 찍음 - 한 장짜리 위성 그림 안 만듦(메타 = 지도 틀만) · vworld-map 위성 404 · 미리 받기 줄 걷음 - 옛 캔버스(D03 · B04 · B05 배수유역) = 위성 바탕 없이 + 알림 - 저장 떠 두기에서 조각 폴더 뺌 - 시험 590_2 새로 · 283 한 본문 손 고침 실패는 고치기 전부터(이 고침과 무관) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
102 lines
3.9 KiB
Python
102 lines
3.9 KiB
Python
"""590-2 위성 조각 정리 — 프로젝트당 한도 · 오래 안 본 것부터 · 한 장짜리 안 만듦 · B 저장 복사에서 뺌."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
import os
|
|
import re
|
|
import time
|
|
from pathlib import Path
|
|
from uuid import uuid4
|
|
|
|
from common_util import common_util_tile_cache as tile_cache
|
|
from common_util.common_util_save_guard import STORAGE_SCOPE, _files
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
|
|
|
|
def _tile(folder: Path, name: str, size: int, age_s: float) -> Path:
|
|
path = folder / "Satellite" / "18" / f"{name}.jpeg"
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
path.write_bytes(b"x" * size)
|
|
at = time.time() - age_s
|
|
os.utime(path, (at, at))
|
|
return path
|
|
|
|
|
|
def test_prune_oldest_first_down_to_keep_ratio(tmp_path: Path) -> None:
|
|
tiles = [_tile(tmp_path, f"t{i}", 100, age_s=1000 - i) for i in range(10)] # t0 = 가장 묵음
|
|
assert tile_cache.prune(tmp_path, limit=1000) == 0 # 한도 = 딱 맞음
|
|
assert tile_cache.prune(tmp_path, limit=900) == 3 # 1000 → 700(≤ 720)
|
|
assert [p.exists() for p in tiles] == [False] * 3 + [True] * 7
|
|
|
|
|
|
def test_note_counts_once_then_adds(tmp_path: Path) -> None:
|
|
for i in range(5):
|
|
_tile(tmp_path, f"t{i}", 100, age_s=100 - i)
|
|
tile_cache._SIZES.pop(tmp_path, None)
|
|
assert tile_cache.note(tmp_path, 0, limit=1000) == 0 # 처음 = 폴더 셈
|
|
assert tile_cache._SIZES[tmp_path] == 500
|
|
_tile(tmp_path, "new", 600, age_s=0)
|
|
assert tile_cache.note(tmp_path, 600, limit=1000) == 3 # 1100 → 800 · 묵은 셋
|
|
assert tile_cache._SIZES[tmp_path] == 800
|
|
assert (tmp_path / "Satellite" / "18" / "new.jpeg").exists()
|
|
|
|
|
|
def test_note_first_sight_prunes_overfull(tmp_path: Path) -> None:
|
|
for i in range(4):
|
|
_tile(tmp_path, f"t{i}", 100, age_s=100 - i)
|
|
tile_cache._SIZES.pop(tmp_path, None)
|
|
assert tile_cache.note(tmp_path, 0, limit=250) == 2 # 열 때 넘침 → 200
|
|
|
|
|
|
def test_seen_touches_only_stale(tmp_path: Path) -> None:
|
|
stale = _tile(tmp_path, "old", 1, age_s=tile_cache.TOUCH_AFTER_S + 60)
|
|
fresh = _tile(tmp_path, "new", 1, age_s=60)
|
|
fresh_at = fresh.stat().st_mtime
|
|
tile_cache.seen(stale)
|
|
tile_cache.seen(fresh)
|
|
assert time.time() - stale.stat().st_mtime < 60
|
|
assert fresh.stat().st_mtime == fresh_at
|
|
|
|
|
|
def test_save_snapshot_skips_tiles(tmp_path: Path) -> None:
|
|
_tile(tmp_path / "_derived" / "plan_tile", "t", 10, age_s=0)
|
|
keep = tmp_path / "_derived" / "plan_x" / "k.json"
|
|
keep.parent.mkdir(parents=True)
|
|
keep.write_text("{}", encoding="utf-8")
|
|
assert "_derived" in STORAGE_SCOPE
|
|
assert list(_files(tmp_path, STORAGE_SCOPE)) == ["_derived/plan_x/k.json"]
|
|
|
|
|
|
def test_satellite_writes_meta_only(tmp_path: Path) -> None:
|
|
from pyproj import CRS
|
|
|
|
from B04_PreProcess.B04_PreProcess_Engine_VWorld import download_vworld_satellite_map
|
|
|
|
prj = tmp_path / "plan.prj"
|
|
prj.write_text(CRS.from_epsg(5186).to_wkt("WKT1_ESRI"), encoding="utf-8")
|
|
bounds = {"x": [200000.0, 201000.0], "y": [500000.0, 501000.0]}
|
|
got = download_vworld_satellite_map(prj, bounds, tmp_path, layer_name="Satellite")
|
|
assert got == tmp_path / "vworld_satellite_meta.json" and got.is_file()
|
|
assert not (tmp_path / "vworld_satellite.png").exists()
|
|
|
|
|
|
def test_satellite_map_route_refuses() -> None:
|
|
from B04_PreProcess.B04_PreProcess_Router_GIS import get_vworld_map
|
|
|
|
reply = asyncio.run(get_vworld_map(uuid4(), None, "satellite")) # type: ignore[arg-type]
|
|
assert reply.status_code == 404
|
|
|
|
|
|
def test_screens_do_not_ask_satellite_image() -> None:
|
|
hits = []
|
|
for folder in ("A00_Common", "B04_PreProcess", "B05_Profile", "D03_PlanAnalysis"):
|
|
for path in (ROOT / folder).rglob("*.ts"):
|
|
text = path.read_text(encoding="utf-8")
|
|
if re.search(
|
|
r'getVWorldMapUrl\([^)]*"satellite"|vworld-map\?layer_name=satellite', text
|
|
):
|
|
hits.append(path.name)
|
|
assert hits == []
|