Import S-CANVAS source + iter=1~7 lint cleanup

S-CANVAS (Saman Corp.) — DXF + DEM + AI 기반 3D 조감도 생성 엔진.
~24k LOC Python (scanvas_maker.py 7072 LOC GUI + 구조물 파서/빌더 다수).

이 커밋은 7-iter cleanup이 적용된 상태로 import:
- F821 8 + B023 6: 비동기 lambda + except/loop 변수 캡처 NameError
  (Py3.13에서 reproduce 확인된 진짜 버그)
- RUF012 4 + RUF013 1: ClassVar / implicit Optional 명시화
- F811/B905/B904/F401/F841/W293/F541/UP/SIM/RUF/PLR 700+ cleanup/modernization

신규 파일:
- ruff.toml: target=py313, Korean unicode/저자 스타일/도메인 복잡도 무력화
- requirements-py313.txt: pyproj>=3.7, scipy>=1.14, numpy>=2.0.2 (Py3.13 wheel)
- .gitignore: gcp-key.json, 캐시, 백업, 생성 이미지 제외

검증: ruff 0 errors, py_compile 0 errors, import 33/33 OK on Py3.13.13.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-08 10:29:08 +09:00
parent 53d8b53c2f
commit b9342f6726
92 changed files with 3413501 additions and 0 deletions

99
fix_bpy_import.py Normal file
View File

@@ -0,0 +1,99 @@
"""fix_bpy_import.py — scanvas_maker.py 의 bpy import 오류 핫픽스.
증상:
[모듈 없음] Blender 렌더 모듈을 찾을 수 없습니다: No module named 'bpy'
원인:
apply_blender_patch.py v1 의 P1 콜백 안에서 dump_params_to_json 을
gate_3d_builder_bpy 에서 import 하도록 되어 있는데, 이 모듈은 첫 줄에
`import bpy` 가 있어 S-CANVAS conda env(GUI 측)에서는 import 불가.
수정:
동일 함수의 bpy-무의존 버전인 params_to_json.dump_dataclass_to_json 으로 교체.
(params_to_json.py 는 이미 D:\\에 있음)
이 스크립트는 idempotent: 이미 수정돼있으면 변경 없음.
백업: 실행 전 scanvas_maker.py.bak_bpyfix 자동 생성.
사용법:
cd D:\\2026\\PROGRAM\\1_S-CANVAS
python fix_bpy_import.py
"""
from __future__ import annotations
import ast
import shutil
import sys
from pathlib import Path
TARGET = Path("scanvas_maker.py")
BACKUP = Path("scanvas_maker.py.bak_bpyfix")
# 정확한 한 줄을 교체 (CRLF/LF 무관 — bytes로 처리)
OLD_LINE = b"from gate_3d_builder_bpy import dump_params_to_json as _dump_gate"
NEW_LINE = b"from params_to_json import dump_dataclass_to_json as _dump_gate"
def main():
if not TARGET.is_file():
sys.exit(f"[ERR] {TARGET} 가 현재 폴더에 없습니다. "
f"D:\\2026\\PROGRAM\\1_S-CANVAS 에서 실행하세요.")
raw = TARGET.read_bytes()
print(f"파일: {TARGET} ({len(raw):,} bytes)")
if NEW_LINE in raw:
print("\n→ 이미 수정됨. 추가 작업 없음.")
# 그래도 import 실제로 동작하는지 확인
if not Path("params_to_json.py").is_file():
print("\n ⚠ 경고: params_to_json.py 가 현재 폴더에 없습니다.")
print(" S-CANVAS 폴더에 이 모듈이 있어야 import 가 성공합니다.")
return 0
if OLD_LINE not in raw:
print("\n[INFO] OLD 패턴을 찾지 못했습니다.")
print(" apply_blender_patch.py 를 먼저 실행했는지 확인하세요.")
# 진단 — 어떤 import가 있는지
for keyword in [b"gate_3d_builder_bpy", b"_dump_gate", b"dump_params_to_json"]:
n = raw.count(keyword)
print(f" '{keyword.decode()}' 발생: {n}")
sys.exit(1)
# params_to_json.py 가 실제로 있는지 미리 확인
if not Path("params_to_json.py").is_file():
sys.exit("[ERR] params_to_json.py 가 현재 폴더에 없습니다. "
"이 모듈이 import 대상입니다.")
# 단일 라인 치환
new_raw = raw.replace(OLD_LINE, NEW_LINE, 1)
n_replaced = raw.count(OLD_LINE) - new_raw.count(OLD_LINE)
print(f" 교체 라인 수: {n_replaced}")
# AST parse 검증 (utf-8 디코드 후)
try:
text = new_raw.decode("utf-8")
# CRLF면 그대로, AST는 양쪽 다 받음
ast.parse(text)
print(f" AST parse: OK ({len(text.splitlines()):,} lines)")
except SyntaxError as e:
sys.exit(f"\n[ERR] 수정 후 syntax error: {e}\n파일 변경 안 함.")
# 백업
shutil.copy2(TARGET, BACKUP)
print(f"\n 백업: {BACKUP}")
# 저장
TARGET.write_bytes(new_raw)
print(f"\n✓ 핫픽스 적용 완료: {TARGET} ({len(new_raw):,} bytes)")
print("\n변경 내용:")
print(f" - {OLD_LINE.decode()}")
print(f" + {NEW_LINE.decode()}")
print("\n다음 단계:")
print(" 1) S-CANVAS 재시작 (또는 그냥 다이얼로그를 다시 열어 다시 시도)")
print(" 2) '🎨 Blender 렌더' 버튼 클릭")
if __name__ == "__main__":
sys.exit(main() or 0)