You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
PyDocument::render_png / render_all_png / export_png 3 #[pymethods] 신규 + 사적 render_png_internal 헬퍼. py.detach 안에서 SkiaLayerRenderer::new().render_png_with_options(&layer_tree, options) — owned PageLayerTree 가 closure 로 이동 (Send 보장). &self.inner 는 layer tree 빌드 단계 (GIL 유지) 에서만 사용 — unsendable 경계 위반 회피
src/document.rs:render_png_internal — owned PageLayerTree 를 closure 로 이동, SkiaLayerRenderer::new() 는 closure 안에서 인스턴스 생성 (Send + 'static 보장)
7 — 비동기 표면 (arender_png 모듈-level)
python/rhwp/document.py:arender_png — aparse 패턴 (file read 만 thread offload, render 는 호출 스레드 sync). Document 인스턴스 메서드 미제공 (unsendable 정합)
8 — max_pixels 가드 SSOT (상류 default wire-through)
RasterRenderOptions::default() 의 max_pixels: 67_108_864 (8192 × 8192) 그대로 사용. 사용자 명시 override 만 허용. 위반 시 상류 메시지 그대로 PyValueError (tests/test_render_png.py::TestRenderPng::test_max_pixels_guard_raises 가 회귀 가드)
3. 호환성
시나리오
결과
기존 사용자 (pip install rhwp-python 후 Document.render_pdf / render_svg / to_ir 호출)
변경 없음. v0.5.x 표면 모두 보존 (additive only)
새 사용자 (Document.render_png 호출)
extras 없이 즉시 사용 — wheel 에 native-skia binary 통합
wheel 크기
약 30 MB 추가 (skia-safe binary-cache + embed-icudtl). PyPI 단일 패키지 100 MB 한도 내 — abi3-py310 single wheel 정합 유지
abi3-py310 호환성
본 release 환경 (macOS arm64) 빌드 OK. CI 매트릭스 (Linux / macOS / Windows × x86_64 / aarch64) 검증은 publish.yml 트리거 시
CI test-without-extras job (skip count 5 → 6)
tests/test_render_png.py 가 file-level pytest.importorskip("PIL.Image") 게이트 — Pillow 미설치 환경에서 file 전체가 1 skip 으로 카운트. ci.yml + AGENTS.md 양쪽의 expected skip count 5 → 6 갱신. MCP TestMcpRenderPagePng 는 per-test importorskip("fastmcp") 라 fastmcp 미설치 시 한 테스트만 skip (file-level 카운트 영향 0)
tests/type_check_errors.py 의 4 intentional pyright errors
변경 없음
SemVer: MINOR (0.5.1 → 0.6.0). additive only — 외부 wire format / wheel 의존성 / schema ("1.1") / abi3-py310 정책 보존.
4. 검증
검사
결과
uv run pytest tests/test_render_png.py -v
7 passed — AC-1 ~ AC-7 모두 그린
uv run maturin develop --release
OK — abi3 wheel 빌드 (Apple silicon)
cargo clippy --all-targets -- -D warnings
exit 0 — clippy clean
uv run pyright python/ (autolint hook)
clean
uv run ruff check python/ tests/ (autolint hook)
clean
전체 회귀 (pytest -m "not slow" 등) 와 lint_docs.py 는 본 commit 후 별도 단계에서 실행.
기존 tests/test_pdf_rendering.py / tests/test_svg_rendering.py / tests/test_mcp_server.py 등 — 변경 없음
AC-9 (README PNG 섹션)
manual inspection — § "페이지 PNG 렌더링 (VLM 입력)" 신설
9/9 AC 모두 충족.
5. 작업 중 표면화된 spec 본문 단순화 (Draft → Draft 갱신)
본 PATCH 작업 중 spec 의 결정 1 + 4 + AC-1 + AC-8 이 내부 모순을 갖는 것이
표면화 — Draft 본문을 일관된 형태로 단순화. 주요 시행착오:
5.1 옵션 비교 (a/b/c)
원 spec 의 결정 1 (배포 형태) 옵션:
A: default features 통합 (모든 wheel 에 native-skia)
B: [png] extras 분리 (Python-side marker + Pillow 의존성) — 원 채택
C: 별도 PyPI 패키지 (rhwp-png)
원 채택 B 의 의도된 이점은 (1) skia-safe 빌드 비용을 모든 사용자에게 강제하지
않음, (2) 사용자가 PNG 사용 의도를 [png] extras 로 시그널화. 시행착오:
시점
발견
처리
α 채택 (extras + Pillow + marker 가드)
wheel 이 통합 빌드라 어차피 모든 사용자가 native skia binary 다운로드 — extras 의 비용 회피 효과 0. extras 가 추가하는 건 Pillow 만이고, render_png 자체는 Pillow 없이 작동 → marker import PIL 가드는 사용자에게 과도한 강제
결정 1 채택을 B → A (default 통합) 로 단순화
β 채택 (default 통합)
pip install rhwp-python 만으로 즉시 사용 가능. cli / mcp / langchain 의 런타임 Python 의존성 분리 extras 와 PNG 표면은 본질이 다름 (PNG 는 native binary 단독 동작) — 분리할 의미 없음. AC-1 ([png] extras 미설치 시 ImportError) / AC-8 (pytest.importorskip("rhwp._png_marker") skip count 5 → 6) 도 자연 제거
spec / ADR / 코드 / pyproject 모두 단순화 — _png_marker.py / _require_png_extras / [png] = [] 모두 삭제. testing 그룹의 Pillow 만 유지 (AC-3 dimension 검증)
5.2 가치 있는 학습
extras 패턴은 Python 런타임 의존성 분리에만 의미 있음 — native binary 단독으로 동작하는 표면은 default 통합이 정직. cli / mcp / langchain 처럼 extras 를 만들면 marker 가드는 사실상 dead code 가 됨
Draft 단계의 결정 변경은 spec 본문 직접 수정 — Frozen 후 결정 변경은 새 spec + Superseded 절차 (CONVENTIONS § Frozen 후 결정 변경) 가 필요하나, Draft 는 본문 갱신으로 충분. 본 release 에서 Draft 단계 시행착오를 본문에 흡수 → Frozen 전환 시 일관된 최종 결정 1 종만 보유
5.3 ADR row 1 갱신
ADR 의 결정 매트릭스 row 1 의 채택을 B → A 로 변경, 검증자 반박을 cli /
mcp / langchain 의 런타임 Python 의존성 분리 패턴과 PNG 의 native binary 단독
동작의 본질 차이 로 재작성. § 1.최종 결정 도 단순화 ([png] = ["pillow>=10"]
marker → default 통합 + extras 없음).
6. 알려진 한계 / 이월 사항
다음 항목은 v0.6.0 범위 밖. spec § 미확정 이슈 가 정확한 목록 — 본 절은
v0.6.0 작업 중 표면화된 항목 + 보류 결정 정리.
항목
상태
후속
skia-safe 빌드 시간 / wheel 크기 영향 (CI 매트릭스 측정)
본 release 미측정 — 사용자 GA 절차의 publish.yml 결과로 확인
임계 (wheel > 100 MB) 도달 시 별도 PyPI 패키지 (rhwp-png) 분리 검토
abi3-py310 호환성 (Linux / Windows × aarch64 빌드)
본 release 환경 (macOS arm64) 만 검증
publish.yml 의 cibuildwheel 결과로 확인
MCP ImageContent 의 LLM 클라이언트 호환성
미검증 (Claude Desktop / Cline 등 transport 별 base64 인코딩 안정성)
v0.5.0 클라이언트 호환성 표 (text-only 응답 기준) 의 image 컬럼 추가 — 별도 손 검증
stdio MCP transport 의 base64 페이로드 크기 (A4 페이지 약 100-500 KB → base64 약 130-660 KB)
미측정
임계 초과 시 README 에 streamable-http 권장 안내
tests/test_mcp_server.py 의 v0.5.0 7-tool 가드
v0.6.0 의 8-tool 등록 후 자연 회귀 — test_lists_exactly_seven_tools → test_lists_exactly_expected_tools 로 갱신 (set 기반 정확 매칭, render_page_png 추가). test_missing_extras_does_not_break_other_tools 의 len == 7 도 sentinel 기반 가드로 단순화 (카운트는 TestToolRegistry 가 책임)
본 release 의 후속 fix commit 에서 처리됨
Cargo.toml bump / CHANGELOG.md [0.6.0] 섹션 추가
본 release 의 commit 6 에 포함 (사용자 GA 절차 와 다른 패턴 — 본 release 는 사용자 요청대로 commit 분할 안에 포함)
—
7. v0.6.0 GA 절차 (인계)
본 step 이후 v0.6.0 GA 까지의 release 절차 (CONVENTIONS § GA 절차):
Cargo.toml version bump — 0.5.1 → 0.6.0 (commit 6 에서 완료)