- 233_4 다섯: 500-2 누름 잡는 단계(capture) 본문 찾기 - 0d: 410 좌표 낡음 판정 — 가짜 구조물 정수 측점 · 그 측점을 낳는 옆 좌표 - 0l · 0s · 0q · 0o 되돌리기: 472-5 덧 그리기 멈춤 풀림(pipelineHolding)까지 기다림 - pipeline_once:77be773c0상세 가게 칸 채움(keepSavedDetail) - 0u: 저장 곡선 반지름 초안 · 끈 꼭짓점 다음 꺾임점 기준 - 남은 xfail 둘(0o 끌기 · 횡단 보기 진입) = cross 군더더기 차례 제품 흠(a02367e61) - 309-2 화면: 표식 user_agent 로그 행 지움 · 포트 = OWNERS.md 이 폴더 줄(다른 폴더 사본이 8004 판을 고치던 흠) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
65 lines
2.8 KiB
Python
65 lines
2.8 KiB
Python
"""검증 프로젝트 찾기 — 읽기만 하는 시험이 필요한 파일을 가진 storage 프로젝트 하나를 고름(507-4).
|
|
|
|
옛 시험은 지워진 검증_sub7 의 uuid 를 박아 늘 건너뜀 → 지금 storage 에 있는 프로젝트 가운데
|
|
OWNERS.md 의 검증_subN 가운데 필요한 파일이 다 있고 가장 오래 안 바뀐 것을 씀(쓰는 중인 프로젝트 피함). `AISLO_TEST_PROJECT=<uuid>` 로 고정 가능. 없으면
|
|
`NONE` 경로(존재하지 않음) 를 돌려줘 시험이 `SKIP_REASON` 글로 건너뜀. 쓰는 시험 금지(읽기 전용).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import re
|
|
|
|
import pytest
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
NONE = ROOT / "storage" / "_no_verify_project"
|
|
SKIP_REASON = "검증 프로젝트 없음 — storage/*/*/ 에 필요한 파일(격자 · 종단 · 노선 · 관)을 다 가진 프로젝트가 없음"
|
|
|
|
#: B05 노선 · B06 상세 · 관 · 격자를 쓰는 349 계열 시험이 읽는 파일
|
|
ROUTE_SET = (
|
|
"B04_PreProcess/models/dtm_classification_smooth.npz",
|
|
"B06_Section/longitudinal/longitudinal.json",
|
|
"B05_Profile/route/planned_route_curves.json",
|
|
"B05_Profile/route/planned_route.csv",
|
|
"B05_Profile/route/planned_route_nodes.csv",
|
|
"B04_PreProcess/drainage/edits/pipe_points.json",
|
|
)
|
|
|
|
|
|
def _verify_ids() -> set[str]:
|
|
"""OWNERS.md 표의 검증_subN 프로젝트 uuid — 사용자 프로젝트(엄상준_검증 등)는 시험이 안 열음."""
|
|
text = (ROOT / "OWNERS.md").read_text(encoding="utf-8")
|
|
return set(re.findall(r"`검증_sub\d+`\s*\|\s*`([0-9a-f-]{36})`", text))
|
|
|
|
|
|
def _touched(project: Path, rels: tuple[str, ...]) -> float:
|
|
"""가장 늦게 바뀐 때 — 다른 창이 쓰는 중인 프로젝트(최근)는 뒤로."""
|
|
sections = project / "B06_Section" / "cross_sections"
|
|
stamps = [(project / rel).stat().st_mtime for rel in rels] + [sections.stat().st_mtime]
|
|
return max(stamps + [f.stat().st_mtime for f in sections.glob("*.json")])
|
|
|
|
|
|
def find_project(*rels: str) -> Path:
|
|
pinned = os.environ.get("AISLO_TEST_PROJECT")
|
|
candidates = (
|
|
list((ROOT / "storage").glob(f"*/*/{pinned}"))
|
|
if pinned
|
|
else [p for p in (ROOT / "storage").glob("*/*/*") if p.name in _verify_ids()]
|
|
)
|
|
found = [
|
|
project
|
|
for project in candidates
|
|
if all((project / rel).is_file() for rel in rels)
|
|
and (project / "B06_Section" / "cross_sections").is_dir()
|
|
]
|
|
return min(found, key=lambda project: _touched(project, rels), default=NONE)
|
|
|
|
|
|
#: 제품 흠으로 보고한 시험만(508-1a) — 고치면 그 시험에서 걷음
|
|
DRIFT = pytest.mark.xfail(
|
|
strict=False,
|
|
reason="508-1a 제품 흠: 노선 초안 자리 칸 넘김이 cross 입력을 바꿔 cross 군더더기 차례(a02367e61)",
|
|
)
|