Releases: JunDamin/hwpapi
v3.0.0 — Multi-document redesign + v3.1 ergonomics
🎯 Multi-document redesign (xlwings 모델)
ADR-003 의 결정대로 v3 부터 App 은 process lifecycle 만 책임지고
모든 문서 작업은 app.docs.open(path) / add() 가 반환하는
Document 인스턴스에서 직접 수행합니다 (xlwings 의 app.books[i]
와 동형).
💔 BREAKING
App.open / save / save_as / close / doc모두 제거 (clean cut, no shim)- v2 사용자:
pip install hwpapi==2.*로 동결 - 마이그레이션: v2→v3 가이드
➕ 신규
app.docs.open(path)/add()/active/[i]/["name"]/iter/lenDocument풀 surface — text I/O / lifecycle / 7 컬렉션 / cursor / actions proxydoc.set_charshape(**fmt)/set_parashape(**fmt)—with없이 즉시 적용 (v3.1)doc.selection(Selection) /doc.range(p1, p2)(Range)doc.find_all(query)/doc.replace_brackets({...})
📚 문서
- ADR-003 (accepted) — Multi-document redesign 결정
- ADR-004/005/006 (proposed) — Element API / API ergonomics / python-docx 패턴
- 양언어 (en + ko) 47+47 페이지
🧪 테스트
- 1,341 mock-based passes (windows-latest × Python 3.9~3.12)
자세한 변경사항은 CHANGELOG.md 참조.
v2.0.0 — Major redesign (dual-layer API + Quarto docs)
v2.0.0 — clean-cut major redesign. Dual-layer API + Quarto docs site.
This is a public API break vs v1.x. v1 사용자는 Migration Guide 를 참고하세요.
🎯 Highlights
- 이중 레이어 API —
hwpapi.App슬림 퍼사드 +app.doc.*컬렉션 /hwpapi.low.*(actions, parametersets, engine) escape hatch - Collection 일관성 —
app.doc.fields / bookmarks / hyperlinks / images / paragraphs / styles / tables, 모두 dict-like + iterable + filterable - Element value objects —
Paragraph,Run,Table,Cell - Context / IO / Errors 모듈 —
hwpapi.context.*,hwpapi.io.*,hwpapi.errors(4단계 예외 +wrap_com_error()) - Quarto 단일 문서 사이트 (43 페이지, 0 warnings)
🐛 Pre-publish fixes
- #6 —
from hwpapi.core import Appfailing on Linux/macOS: git index가HwpApi/(PascalCase) 로 트래킹되어 case-sensitive FS 에서ModuleNotFoundError발생. 디렉터리 케이싱을hwpapi/로 정규화. Windows (case-insensitive FS) 에서는 표면화되지 않았던 이슈. - HTML 저장 1-line:
_SAVE_FORMAT_MAP에.html→HTML+,.htm→HTML추가. 이제app.save("report.html")만으로 HTML 저장 가능.
⚠️ Removed (Breaking)
hwpapi/classes/전체 삭제 (~4,924 LOC)Apppublic 멤버 82 → ~12app.charshape = {...}→charshape_scope(app, **fmt)컨텍스트app.preset.*,app.template.*,app.config.*,app.lint(),app.view.*,app.debug.*,app.convert.*,app.sel.*,app.move.*,app.table.*,app.cell.*,app.page.*모두 제거hwpapi.parametersets(top-level) →hwpapi.low.parametersetsnbs/nbdev 파이프라인 폐기
전체 변경점: CHANGELOG.md.
Install
pip install hwpapiv1 에 머무르려면: pip install "hwpapi<2"
v1.0.0 — Stable Release
Changelog
모든 주요 변경사항이 이 문서에 기록됩니다.
포맷은 Keep a Changelog, 버전은
Semantic Versioning 을 따릅니다.
[Unreleased]
[2.0.0] — 2026-04-19 — 🚀 Major redesign (dual-layer API + Quarto docs)
v1.0 이후 약 4일간 진행한 전면 재설계. public API break 을 허용한 클린컷
릴리즈로, 구조/퍼사드/문서 파이프라인을 한꺼번에 갈아엎었습니다.
🎯 핵심 변경
- 이중 레이어 API
- 고수준:
hwpapi.App(슬림 퍼사드) +app.doc(Document 모듈) - 저수준:
hwpapi.low.*—actions,parametersets,engine이 공식 escape hatch - 같은 작업에 두 개의 공식 진입점을 남기지 않음 (Principle #1)
- 고수준:
- Collection 일관성 —
Protocol[T]기반 공통 인터페이스app.doc.fields / bookmarks / hyperlinks / images / paragraphs / styles / tables- 모두 dict-like + iterable + filterable 로 동일 멘탈 모델
- Element value objects —
Paragraph,Run,Table,Cell경량 객체
(.style,.charshape,.parashape,.runs,.cell(r, c).text, ...) - Context / IO / Errors 모듈 신설
hwpapi.context.{charshape_scope, parashape_scope, styled_text}hwpapi.io.{open_file, new_document, export_pdf, export_image, export_text}hwpapi.errors— 4단계 예외 계층 +wrap_com_error()컨텍스트 매니저
- Quarto 단일 문서 사이트 —
docs/43페이지, quartodoc 기반 자동 API 레퍼런스- Home / Getting Started / Guide / Recipes / Reference / Design 6-섹션
- 사이트 IA == import tree 1:1 매핑 (Principle #5)
Removed (Breaking)
hwpapi/classes/전체 삭제 (~4,924 LOC) — accessors/controls/convert/debug/
fields/images/lint/selection/shapes/styles/view 모두 제거Apppublic 멤버 82 → ~12 로 축소 (v1 accessor/preset/template/config/... 전면 제거)app.charshape = {...}프로퍼티 →charshape_scope(app, **fmt)컨텍스트로 이전app.preset.*,app.template.*,app.config.*,app.lint(),app.view.*,
app.debug.*,app.convert.*,app.sel.*,app.move.*,app.table.*,
app.cell.*,app.page.*— 모두 제거 (필요 시 Recipes 에서 재조립)hwpapi.parametersets(top-level) →hwpapi.low.parametersets로 이동hwpapi/actions.py→hwpapi/low/actions.pyhwpapi/core/engine.py→hwpapi/low/engine.pynbs/nbdev 기반 문서 파이프라인 폐기 (아카이브)docs/*.md(v1 계획 문서 10개) →docs/archive/이동
Added
hwpapi/collections/패키지 — fields, bookmarks, hyperlinks, images,
paragraphs, styles, tables (각 Collection + Element value object)hwpapi/document.py—Document퍼사드 (cached_property 로 lazy-wire)hwpapi/low/— raw actions / parametersets / engine escape hatchhwpapi/errors.py—HwpApiError,ConnectionError,ActionFailedError,
InvalidArgumentError,FileIOError+wrap_com_error()hwpapi/context/scopes.py—charshape_scope,parashape_scope,styled_texthwpapi/io/—open_file,new_document,export_pdf,export_image,export_textdocs/Quarto 사이트 (43 페이지, 0 warnings) — getting-started / guide /
recipes / reference / design / adr.github/workflows/deploy-docs.yaml— GitHub Pages 자동 배포tests/conftest.py—SetMessageBoxMode(0x111111)로 HWP 다이얼로그 전부 자동 Yes- v1→v2 Migration guide (80+ 매핑 행)
Fixed / Hardened
- pytest 전체 세션에서 HWP 다이얼로그가 더 이상 블로킹하지 않음
- griffe 2.x API drift 대응 —
griffe<1.0핀 ([project.optional-dependencies].docs) - 순환 import 제거 (
low/engine.py의 deadfrom hwpapi.classes import ...제거)
Tests
- 단위 테스트: 1,388 (v1.0) → 1,373 (v2.0, -15: v1 classes/ 테스트 사라짐, +30 새
Element 테스트, +29 새 context/io/errors 테스트). 전체 녹색.
Migration
클린컷이므로 코드 변경 필수입니다.
- 빠른 점검:
https://JunDamin.github.io/hwpapi/getting-started/migration-v1-to-v2.html - v1 에 머무르려면
pip install "hwpapi<2"또는git checkout v1.x.
[1.0.0] — 2026-04-15 — 🎉 Production / Stable release
v0.0.11 부터 v0.0.26 까지 16개의 마이너 릴리즈를 거쳐 도달한 v1.0 Stable.
주요 API 는 안정화되었으며, 버그/매직넘버/문서 블로커가 모두 해결되었습니다.
🎯 v1.0 성취
- 18개 accessor (move, sel, documents, fields, bookmarks, hyperlinks, images,
styles, controls, cell, table, page, convert, view, lint, template, config,
preset, debug) 로 도메인별 API 그룹핑 - 8개 context manager (silenced, suppress_errors, batch_mode, undo_group,
charshape_scope, parashape_scope, use_document, debug.trace) - 11개 preset (striped_rows, title_box, subtitle_bar, summary_box,
table_header, table_footer, toc, page_numbers, page_border, highlight_yellow) - ENUM 시스템 — BORDER_TYPE_MAP, HATCH_STYLE_MAP, CELL_APPLY_TO_MAP,
DIAGONAL_FLAG_MAP + Color 클래스 상수 16개 hwpapi.units모듈 — mm/cm/inch/pt ↔ HWPUNIT 변환- 25개 객체별 API 문서 (
nbs/02_api/디렉토리) - 13개 튜토리얼 — 9개 사용 사례 + 4개 신규 (Accessors, Presets Gallery,
Batch Workflow, Debug Tools) - 1388/1388 단위 테스트 통과
Added (v0.0.26 이후)
hwpapi.functions.cell_addr(app)/navigate_until(app, action)—
HWP 12 의Run()None 반환 회피용 공유 헬퍼Config.apply_defaults()—default_font/default_size실제 적용
메소드 (이전엔 dict 저장만)Color.RED,Color.BLUE, ...,Color.NAVY— 16 색상 클래스 상수resolve_enum(map, value)— 문자열/정수 양방향 helperhwpapi.units모듈 — App 인스턴스 없이도 호출 가능한 단위 변환
Changed
version = 1.0.0+Development Status :: 5 - Production/Stablerequires-python = ">=3.9"(이전 3.7 — EOL)[project.optional-dependencies]추가 —dev,test,docsset_charshape(facename=...)— 단일 인자가 7개 facename 으로 자동 fan-outfind_text(facename=...)— 다국어 fan-outset_cell_border(top="solid", bottom="double")— 문자열 enum 지원set_cell_color(hatch_style="diagonal_cross")— 문자열 지원
Fixed
replace_font(old, new)가old를 무시하던 버그 — HFindReplace pset
으로 재작성,old폰트만 정확히 교체 (replace_all=True로 legacy 동작 opt-in)app.config.default_fontno-op —apply_defaults()메소드 추가App.charshape()method vscharshapeproperty 이름 충돌 — method 완전 제거api.Run()None 반환 11곳 — cell_addr 추적 기반으로 전환app.view.zoom()의PictureScale액션 —ZoomRateproperty 로 교체- CellBorderFill 의 FillAttr 경로 —
SelCellsBorderFill.FillAttr로 수정 _apply_cell_bg가 작동 안 하던 버그 — HParameterSet chain 정확한 경로
Deprecated (v1.1 에서 제거 예정)
Field 관련 10개 — app.fields accessor 로 대체:
| 레거시 | 신규 |
|---|---|
app.create_field(name) |
app.fields.add(name) |
app.set_field(n, v) |
app.fields[n] = v |
app.get_field(n) |
app.fields[n].value |
app.field_exists(n) |
n in app.fields |
app.move_to_field(n) |
app.fields[n].goto() |
app.delete_field(n) |
app.fields.remove(n) |
app.delete_all_fields() |
app.fields.remove_all() |
app.rename_field(o, n) |
app.fields.rename(o, n) |
app.field_names |
list(app.fields) |
app.fields_dict |
app.fields.to_dict() |
Soft deprecation 7개 (docstring 안내만):
app.insert_bookmark→app.bookmarks.addapp.insert_hyperlink→app.hyperlinks.addapp.replace_brackets_with_fields→app.fields.from_bracketsapp.get_charshape/app.set_charshape→app.charshapepropertyapp.get_parashape/app.set_parashape→app.parashapeproperty
마이그레이션 가이드: docs/MIGRATION_v1.md
Removed
App.charshape()deprecated builder method (property 와 이름 충돌, v0.0.7 부터 호출 불가였음)
v1.1 로드맵 (예정)
- legacy field method 10개 완전 제거
- App 클래스 분할 (103 methods → 5 mixins in
core/ops/) HwpError예외 계열 (HwpFieldNotFound, HwpFileLocked 등)python -m hwpapi.migrate <file.py>AST 자동 변환 도구- Context manager 명명 통일 (
using_X패턴) - mypy + ruff + pre-commit
[0.0.26] — 2026-04-15 — v1.0 Phase 4: 객체별 API 문서 페이지
사용자 지적 ("Unit 같은 것도 홈페이지에 설명이 잘 있어야 하지 않을까?
모든 객체를 설명해주는 거지") 반영.
Added
nbs/02_api/ — 객체별 .qmd 페이지 25개 자동 생성:
core/(app, engine, document)navigation/(move, selection)collections/(fields, bookmarks, hyperlinks, images, controls, styles)structure/(cell, table, page)transform/(convert, view)quality/(lint, template, config)presets/(presets — 11 메소드)debug/(debug)data/(shapes — CharShape/ParaShape/PageShape)utilities/(units, enums, functions)index.qmd— 전체 매트릭스
각 페이지: import + 한 줄 요약 + docstring + 메소드/속성 표 (시그니처 + 한 줄 설명) + cross-link.
utilities/units.qmd — 사용자 친화적으로 보강:
- Quick Start 코드 6개 형태
- 함수 매트릭스 (mm/cm/inch/pt + parse)
- 변환표 (1mm = 283 HWPUNIT 등)
- 페이지 크기/폰트/테두리 사용 예
utilities/enums.qmd — Phase 3 ENUM 종합 가이드:
- BORDER_TYPE_MAP 16종 표
- HATCH_STYLE_MAP 13종 표
- CELL_APPLY_TO_MAP, DIAGONAL_FLAG_MAP
- Color 클래스 상수 16개
- resolve_enum 사용법
- 기존 35개 MAP 목록
Changed
nbs/_quarto.yml sidebar 확장: 기존 4 섹션에 "📖 API 레퍼런스" 트리
신설 — 카테고리별 8개 sub-section, 25개 페이지 직접 navigate 가능.
nbs/index.qmd 카드 변경: '익숙한 단위' 카드를 '익숙한 단위 / Enum'
으로 확장 — units, Color 상수, set_cell_border 예제 + 링크 2개.
v1.0 release 준비도
- 모든 P0 bug fix (v0.0.24)
- silent fail 가시화 (v0.0.24)
- BorderType / HatchStyle / Color 등 매직 넘버 enum 전환 (v0.0.25)
- 모든 18 accessor + dataclass + units + presets 02_api/ 페이지 보유 (v0.0.26)
- sidebar 에 "API 레퍼런스" 트리 노출 (v0.0.26)
- units.qmd / enums.qmd 가 homepage 카드에서 1-click 도달 (v0.0.26)
- tests/generate_doc_artifacts.py demo 13+개 실제 HWP 재생성
- CHANGELOG 정리 + v1.0.0 tag
[0.0.25] — 2026-04-15 — v1.0 Phase 3: ENUM 통일 + Color 상수
사용자 지적 ("선 모양도 enum 같은 걸로 되어야 할 거 같은데?") 반영.
매직 넘버 (BorderType=8, hatch_style=6) → 사용자 친화 이름 ("double", "diagonal_cross").
Added
hwpapi/parametersets/mappings.py — 4개 신규 enum/MAP:
BORDER_TYPE_MAP— 16종 선 종류 ("none","solid","dash","dot",
"dash_dot","long_dash","double","wave","thick_3d"등)HATCH_STYLE_MAP— 13종 빗금 패턴 ("horizontal","diagonal_cross",
"dense_horizontal"등)CELL_APPLY_TO_MAP— 셀 적용 범위 ("current"/"selected"/"all")DIAGONAL_FLAG_MAP— 대각선 비트플래그 ("top"/"middle"/"bottom"/"all")resolve_enum(map, value)헬퍼 — 문자열/정수 양방향 해석 (case-insensitive)
Color 클래스 상수 16개 (properties.py):
Color.RED, Color.GREEN, Color.BLUE, Color.BLACK, Color.WHITE,
Color.YELLOW, Color.CYAN, Color.MAGENTA, Color.ORANGE, Color.PURPLE,
Color.PINK, Color.BROWN, Color.GRAY, Color.LIGHT_GRAY,
Color.DARK_GRAY, Color.NAVY**get_rgb_tuple named-color 5 →...
v0.0.10 — 전면 dialog suppress + suppress_errors() + RegisterModule
🤫 v0.0.10 — Dialog 전면 suppression
사용자 요청: "확인하는 메시지를 정지시키는 그런 기능을 추가할 수 있을까? 에러메시지 미표시던가?"
이전 `silenced()` 는 단일 dialog 카테고리만 처리. 이제 HWP 의 6개 dialog 카테고리 전부를 한 번에 suppress 가능.
향상된 `silenced()`
```python
String preset (권장)
with app.silenced(): # = "yes"
with app.silenced("yes"): # 모든 dialog → 첫 버튼 (OK/Yes/Abort/...)
with app.silenced("no"): # 모든 dialog → 둘째 버튼 (No/Cancel/...)
with app.silenced("reset"): # 자동 응답 해제
직접 bitfield
with app.silenced(0x020001): # 예/아니오→NO + 확인→OK
```
새 클래스 상수:
| 상수 | 값 | 동작 |
|---|---|---|
| `App.SILENCE_ALL_YES` | `0x111111` | 모든 dialog 첫 버튼 |
| `App.SILENCE_ALL_NO` | `0x222222` | 모든 dialog 둘째 버튼 |
| `App.SILENCE_RESET` | `0xFFFFFF` | 자동 응답 해제 |
| `App.SILENCE_SAVE_NO` | `0x00020000` | 저장 dialog → NO |
| `App.SILENCE_OK_AUTO` | `0x00000001` | 확인 dialog → OK |
🆕 `suppress_errors()` — Python 예외 + dialog 동시
대량 처리에서 일부 파일 실패해도 루프 계속:
```python
for path in many_paths:
with app.suppress_errors():
app.open(path) # 깨진 파일이어도 silently 무시
app.save(path + ".out")
```
블록 내부 Python Exception 은 `logger.warning` 으로 기록만 하고 진행. dialog 도 자동 abort.
🆕 `register_security_module()` — hwp-mcp 식 명시 helper
App.init 에서 자동 호출되긴 하지만 명시적 (재)등록 가능:
```python
app.register_security_module() # 기본 DLL
app.register_security_module( # 커스텀
module_name="MyChecker",
dll_path=r"C:\my\custom.dll",
)
```
📊 6개 Dialog 카테고리 비트 레이아웃
| Bits | Dialog Type | 첫/둘째/셋째 버튼 |
|---|---|---|
| 0xF | 확인 | 1=OK |
| 0xF0 | 확인/취소 | 1=OK, 2=Cancel |
| 0xF00 | 종료/재시도/무시 | 1=Abort, 2=Retry, 4=Ignore |
| 0xF000 | 예/아니오/취소 | 1=Yes, 2=No, 4=Cancel |
| 0xF0000 | 예/아니오 | 1=Yes, 2=No |
| 0xF00000 | 재시도/취소 | 1=Retry, 2=Cancel |
호환성
100% backward compatible. 1,059 unit tests 통과.
Full changelog: v0.0.9...v0.0.10
v0.0.9 — Move sub-groups + Styles parser fix
🧭 v0.0.9 — 다듬기 릴리즈
🗂 MoveAccessor 재그룹화
38개의 flat 메소드를 의미 단위 sub-accessor 로 묶어 IDE 탐색성 향상.
```python
기존 (계속 지원됨)
app.move.top_of_file()
app.move.end_of_line()
app.move.next_word()
신규 — 계층적
app.move.doc.top()
app.move.line.end()
app.move.word.next()
새로 추가된 그룹들:
app.move.page.next() # 페이지 이동 (신규)
app.move.cell.right() # 표 셀 이동
```
7개 sub-group: `doc` · `line` · `word` · `para` · `char` · `page` · `cell`
🔧 `app.styles` 완전 수리
v0.0.8 에서 도입했으나 빈 리스트 반환하던 문제 해결. HWP COM 에 `SaveBlockAs` 가 없음을 파악하여 pyhwpx 의 `FileSaveBlock_S` + `HFileOpenSave` 패턴으로 교체.
```python
app.styles.names
→ ['바탕글', '본문', '개요 1', '개요 2', ..., '표준', '머리말', '꼬리말'] — 22개
app.styles['제목 1'].apply()
app.styles.current
→ Style(index=0, name='바탕글')
```
📝 CHANGELOG 갱신
Keep-a-Changelog 포맷으로 v0.0.4 ~ v0.0.9 전체 릴리즈 노트 정리.
✅ 호환성
100% backward compatible — flat 메소드는 계속 동작. 1,059 unit tests 통과.
Full changelog: v0.0.8...v0.0.9
v0.0.8 — Phase D/E: Styles · Controls accessors
🎯 Phase D + E 접근자 추가
pyhwpx 비교 분석에서 도출한 마지막 2개 Phase 완료.
🎛 Phase E — `app.controls` (완전 작동)
문서 내 모든 컨트롤 (표 · 그림 · 구역 · 하이퍼링크 · 북마크 등) 을 linked list 로 순회.
```python
전체 순회
for c in app.controls:
print(c.ctrl_id, c.user_desc)
[0] 'secd' '구역 정의'
[1] 'cold' '단 정의'
[2] 'tbl ' '표'
[3] '%hlk' '하이퍼링크'
검색
tbl = app.controls.find(desc="표")
all_tables = app.controls.find_all(ctrl_id="tbl")
그룹
groups = app.controls.by_ctrl_id() # {'tbl ': [...], '%hlk': [...]}
인스턴스 조작
tbl.select()
tbl.delete()
tbl.move_to()
```
🎨 Phase D — `app.styles` (구조 작동, HWPML parser best-effort)
문단 스타일 관리.
```python
app.styles.names # ['바탕글', '본문', ...]
app.styles["제목 1"].apply() # 이름으로 조회 + 적용
app.styles.apply("본문") # 단축 적용
app.styles.current # 현재 문단 스타일
app.styles.delete("unused", replace_with="본문")
app.styles.export("house.sty")
app.styles.import_from("house.sty")
app.styles.remove_unused()
```
::: {.callout-note}
Styles 는 HWP COM 이 스타일 목록을 직접 노출하지 않아 HWPML 블록 export → XML 파싱으로 구현. 일부 커서 상태에서 SaveBlockAs 가 실패할 수 있음. v0.0.9 에서 fallback 보강 예정.
:::
📊 현황
App 클래스 멤버 : 82 → 85 (+3 새 접근자)
Document 프록시를 통해 `doc.styles`, `doc.controls` 도 자동 지원.
✅ 호환성
100% backward compatible. 1,059 unit tests 통과.
🛣 다음 단계
- v0.0.9: Styles HWPML parser 튜닝 + MoveAccessor sub-grouping (REFACTORING_PLAN P1-3)
- v0.1.0: `app.charshape()` 완전 제거 + CharShape 중복 해소
Full changelog: v0.0.7...v0.0.8
v0.0.7 — 내부 중복 감사 + charshape() deprecation
🔍 내부 API 중복·겹침 감사 릴리즈
Phase A/B/C 확장 이후 App 클래스 82개 멤버의 중복/겹침/기능 분산 을 체계적으로 정리.
🔴 Deprecated
App.charshape(...)— legacy 빌더 (unbound pset 반환 후 다시set_charshape에 넘기는 간접 API). DeprecationWarning 발생. v0.1.0 에서 제거.# ❌ Old cs = app.charshape(bold=True) app.set_charshape(cs) # ✅ New app.set_charshape(bold=True)
📝 Docstring 개선 (cross-reference 추가)
app.selection↔app.get_selected_text()alias 명시app.visible↔app.set_visible()— property form 권장app.new_document()↔app.documents.add()alias 명시app.rgb_color()↔Color.from_rgb()— 반환 타입 차이 설명- 단위 변환 섹션 주석 — App method (COM) vs functions.py (pure Python)
📄 신규 문서
docs/DUPLICATION_AUDIT.md — 210줄 전체 감사 리포트:
- 9개 중복 패턴 분류 (P0/P1/P2)
- 각 케이스의 정체 vs 의도 판정
- 통합 권장 vs 유지 판정
- v0.0.7 ~ v0.1.x 실행 로드맵
✅ 호환성
100% backward compatible. 경고만 추가되고 실제 동작은 그대로.
- 1,059 unit tests 통과
- 기존 사용자 코드 수정 불필요
🛣 남은 로드맵
- v0.0.8: Phase D/E (
app.styles,app.controls접근자) - v0.1.0:
app.charshape()제거 + CharShape 중복 해소 - v0.1.x:
app.py→core/ops/*delegate 분리
Full changelog: v0.0.6...v0.0.7
v0.0.6 — Phase C: convenience helpers
🎯 Phase C — 편의 헬퍼
pyhwpx 비교 분석에서 도출된 편의 메소드들 추가.
신규 API (10개)
페이지 탐색
app.goto_page(n)— N번째 페이지로 이동
형광펜
app.highlight(color)— 선택 영역에 markpen (shade_color 와 다름)- 문자열
'#FFFF00'/ Color /(r,g,b)튜플 모두 지원
- 문자열
이미지 export
app.save_page_image(n, path)— 페이지 → 이미지 파일app.save_all_page_images(dir)— 전체 페이지 일괄 export
단위 변환 (instance methods)
app.mm_to_hwpunit(mm)/hwpunit_to_mm(hu)app.point_to_hwpunit(pt)/hwpunit_to_point(hu)app.rgb_color(r, g, b)— RGB → HWP BBGGRR
상태 조회
app.statusproperty — KeyIndicator + PageCount 를 dict 로:{'page': 1, 'total_pages': 4, 'section': 1, 'column': 1, 'line': 4, 'print_page': 1, 'char_index': 0, 'insert_mode': ...}
Color 클래스 확장
Color.from_rgb(r, g, b)— RGB 튜플로 생성Color.from_hex(hex_str)— 명시적 hex 생성자
버그 수정
app.current_page가 section 번호 반환하던 문제 → KeyIndicator[5] 사용
호환성
100% backward compatible. 1,059 unit tests 통과.
Full changelog: v0.0.5...v0.0.6
v0.0.5 — Mail Merge + pandas + silenced()
🎯 Mail Merge · Pandas · 대화상자 자동응답
pyhwpx 비교 분석 에서 도출한 고가치 기능들을 도입한 릴리즈.
📝 Field API (Mail Merge) — 핵심 신규 기능
HWP 필드(누름틀) 를 통한 템플릿 → 대량 문서 생성.
# 1. 템플릿 준비 ({{name}}, {{date}} 등의 브래킷)
app.open(\"contract_template.hwp\")
app.replace_brackets_with_fields() # 브래킷 → 실제 HWP 필드
# 2. 값 주입
app.set_field(\"name\", \"홍길동\")
app.set_field(\"date\", \"2026-04-15\")
# 3. 확인
print(app.fields_dict) # {'name': '홍길동', 'date': '2026-04-15'}
# 4. 저장
app.save(\"out/홍길동.hwp\")신규 API 14개:
create_field / set_field / get_fieldfields·fields_dict(properties)field_exists / move_to_field / delete_field / delete_all_fields / rename_fieldreplace_brackets_with_fields()— 핵심 헬퍼
🐼 pandas 연동
# DataFrame → HWP 표
df = pd.DataFrame({...})
app.insert_table(data=df) # columns 자동으로 header
# HWP 표 → DataFrame
df = app.read_table() # DataFrame
rows = app.read_table(to=\"list\") # 2D list
csv = app.read_table(to=\"csv\") # CSV 문자열🤫 대화상자 자동응답 — app.silenced()
with app.silenced(): # YES 자동 (기본)
for path in paths:
app.open(path) # '저장하시겠습니까?' → 자동 YES
app.replace_all(\"2025\", \"2026\")
app.save(path)
with app.silenced(mode=0x00200000): # NO 자동
app.close()Context manager 종료 시 원래 모드로 자동 복원.
📖 새 튜토리얼
- Mail Merge 사용 사례: https://jundamin.github.io/hwpapi/01_tutorials/usecase_mail_merge.html
- 100개 급여명세서 일괄 생성 예제
- pandas DataFrame 연동
- 다중 문서 병렬 편집
호환성
- 100% backward compatible — 모든 기존 코드 수정 없이 동작
- 1,059 unit tests 통과
- pandas 는 optional (설치 없어도 다른 기능 정상)
Full changelog: v0.0.4...v0.0.5
v0.0.4 — Phase 1 refactor (_Action + Color/UNSET)
🔧 Phase 1 리팩토링 릴리즈
리팩토링 계획 에 따른 첫 번째 릴리즈. P0 긴급 버그 수정.
P0-1: _Action 문서 바인딩 버그 수정 🔴
증상: _Action.__init__ 에서 CreateAction() 을 한 번만 호출해 캐싱 → 초기 활성 문서에 고정 → 이후 다른 문서 전환 시에도 원본 문서에 쓰기 발생
수정: act, pset 을 @property 로 재설계, 활성 문서 ID 별 lazy-cache
# Before: 버그 — 모두 doc1 에 쓰임
doc2.activate()
app.actions.CharShape.run() # ⚠️ doc1 에 적용
# After: 정상 동작
doc2.activate()
app.actions.CharShape.run() # ✅ doc2 에 적용P0-2: Color 래퍼 + UNSET 센티넬 🟠
증상: shade_color="#FFFFFF" 가 "제거" 인지 "흰색 shade 적용" 인지 모호 → 의도치 않은 shade 누수
수정: 새 타입 2개 도입
from hwpapi.parametersets import Color, UNSET
# 명시적 의미론
prop = UNSET # 변경 없음 (no-op)
prop = None # 필드 제거
prop = "#FF0000" / Color / int # 정규화 후 저장
# 28개 색상 필드 자동 변환 (TextColor, ShadeColor, Border*Color 등)P1-1 부분 진행
hwpapi/core/app.py(2,322줄) → Document/Documents 를document.py로 분리 (1,930줄로 감소)- 남은 app.py 분할은 다음 릴리즈에서 진행
기타
- 21개 새 단위 테스트 (
test_color_semantics.py) → 총 1,194 unit tests 통과 CHANGELOG.md도입- API 레퍼런스 재생성 (277K chars, 6,703줄)
호환성
- 100% backward compatible — 모든 기존 코드가 수정 없이 동작
- 신규 객체
Color,UNSET는 opt-in
Full changelog
https://github.com/JunDamin/hwpapi/blob/main/CHANGELOG.md
전체 변경: v0.0.3...v0.0.4