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:
65
harness/seed_manager.py
Normal file
65
harness/seed_manager.py
Normal file
@@ -0,0 +1,65 @@
|
||||
"""Seed 관리자 - 작업별 Seed 고정 및 추적."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import random
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from harness.logger import JobRecord
|
||||
|
||||
|
||||
class SeedManager:
|
||||
"""DXF 파일 해시 기반 결정론적 seed를 생성하고 이력을 관리한다."""
|
||||
|
||||
MAX_SEED = 2**32 - 1
|
||||
|
||||
def get_seed(
|
||||
self,
|
||||
file_hash: str,
|
||||
fixed_seed: int | None = None,
|
||||
deterministic: bool = True,
|
||||
) -> int:
|
||||
"""
|
||||
Args:
|
||||
file_hash: DXF 파일의 SHA256 해시 앞 16자
|
||||
fixed_seed: 사용자가 직접 지정한 seed (None이면 자동)
|
||||
deterministic: True면 파일 해시 기반, False면 랜덤
|
||||
"""
|
||||
if fixed_seed is not None:
|
||||
return int(fixed_seed) % (self.MAX_SEED + 1)
|
||||
|
||||
if deterministic:
|
||||
return self._hash_to_seed(file_hash)
|
||||
|
||||
return random.randint(0, self.MAX_SEED)
|
||||
|
||||
def get_or_create_seed(
|
||||
self,
|
||||
db: Session,
|
||||
job_id: int,
|
||||
file_hash: str,
|
||||
fixed_seed: int | None = None,
|
||||
deterministic: bool = True,
|
||||
) -> int:
|
||||
"""DB에서 기존 seed를 조회하거나 새로 생성한다."""
|
||||
existing = db.query(JobRecord).filter_by(id=job_id).first()
|
||||
if existing and existing.seed is not None:
|
||||
return existing.seed
|
||||
|
||||
seed = self.get_seed(file_hash, fixed_seed, deterministic)
|
||||
if existing:
|
||||
existing.seed = seed
|
||||
db.commit()
|
||||
return seed
|
||||
|
||||
@staticmethod
|
||||
def _hash_to_seed(file_hash: str) -> int:
|
||||
"""파일 해시를 정수 seed로 변환한다."""
|
||||
digest = hashlib.sha256(file_hash.encode()).digest()
|
||||
return int.from_bytes(digest[:4], "big")
|
||||
|
||||
@staticmethod
|
||||
def describe(seed: int) -> str:
|
||||
return f"seed={seed} (0x{seed:08X})"
|
||||
Reference in New Issue
Block a user