"""PLAN 561-1 — `.cpg` 없는 도엽 dbf = cp949 로 읽음 · 병합 열쇠에 파서 판 번호. ./venv/Scripts/python.exe -m pytest resources/tester/test_561_1_sheet_encoding.py -q `.cpg` 없는 dbf 를 그냥 읽으면 latin-1 → 칸 이름 「등고수치」가 깨져 등고 높이가 빔 (D 프로젝트 4250c7bc 「등고 라인 94단을 격자에 굽어 0셀」). """ from __future__ import annotations import sys import zipfile from pathlib import Path import geopandas as gpd from shapely.geometry import LineString ROOT = Path(__file__).resolve().parents[2] if str(ROOT) not in sys.path: sys.path.insert(0, str(ROOT)) import B04_PreProcess.B04_PreProcess_Engine_SheetParser as parser # noqa: E402 BASE = "N3L_F0010000" def _sheet_zip(tmp_path: Path, with_cpg: bool) -> Path: """등고선 두 줄짜리 도엽 zip — dbf 는 cp949 · `.cpg` 는 고름.""" shp_dir = tmp_path / ("cpg" if with_cpg else "nocpg") shp_dir.mkdir() gdf = gpd.GeoDataFrame( {"등고수치": [100.0, 105.0], "구분": ["주곡선", "주곡선"]}, geometry=[LineString([(0, 0), (10, 0)]), LineString([(0, 5), (10, 5)])], crs="EPSG:5186", ) gdf.to_file(shp_dir / f"{BASE}.shp", encoding="cp949") cpg = shp_dir / f"{BASE}.cpg" if with_cpg: cpg.write_text("CP949", encoding="ascii") else: cpg.unlink(missing_ok=True) zip_path = tmp_path / f"{shp_dir.name}.zip" with zipfile.ZipFile(zip_path, "w") as zf: for f in shp_dir.iterdir(): zf.write(f, f.name) return zip_path def _read(zip_path: Path) -> gpd.GeoDataFrame: gdf = parser._read_layer_from_zip(zip_path, "N3L", "F0010000", "EPSG:5186") assert gdf is not None return gdf def test_no_cpg_reads_cp949(tmp_path): gdf = _read(_sheet_zip(tmp_path, with_cpg=False)) assert "등고수치" in gdf.columns assert sorted(gdf["등고수치"].tolist()) == [100.0, 105.0] assert set(gdf["구분"]) == {"주곡선"} def test_with_cpg_unchanged(tmp_path): gdf = _read(_sheet_zip(tmp_path, with_cpg=True)) assert sorted(gdf["등고수치"].tolist()) == [100.0, 105.0] def test_merge_keys_carry_parser_version(): assert parser.PARSER_VERSION >= 2 for rel in ( "B04_PreProcess/B04_PreProcess_Engine.py", "D03_PlanAnalysis/D03_PlanAnalysis_Terrain.py", ): text = (ROOT / rel).read_text(encoding="utf-8") assert '"parser": PARSER_VERSION' in text, rel