Skip to content

Releases: JunDamin/hwpapi

v3.0.0 — Multi-document redesign + v3.1 ergonomics

29 Apr 06:57

Choose a tag to compare

🎯 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 / len
  • Document 풀 surface — text I/O / lifecycle / 7 컬렉션 / cursor / actions proxy
  • doc.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)

28 Apr 01:38

Choose a tag to compare

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

  • 이중 레이어 APIhwpapi.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 objectsParagraph, Run, Table, Cell
  • Context / IO / Errors 모듈hwpapi.context.*, hwpapi.io.*, hwpapi.errors (4단계 예외 + wrap_com_error())
  • Quarto 단일 문서 사이트 (43 페이지, 0 warnings)

🐛 Pre-publish fixes

  • #6from hwpapi.core import App failing on Linux/macOS: git index가 HwpApi/ (PascalCase) 로 트래킹되어 case-sensitive FS 에서 ModuleNotFoundError 발생. 디렉터리 케이싱을 hwpapi/ 로 정규화. Windows (case-insensitive FS) 에서는 표면화되지 않았던 이슈.
  • HTML 저장 1-line: _SAVE_FORMAT_MAP.htmlHTML+, .htmHTML 추가. 이제 app.save("report.html") 만으로 HTML 저장 가능.

⚠️ Removed (Breaking)

  • hwpapi/classes/ 전체 삭제 (~4,924 LOC)
  • App public 멤버 82 → ~12
  • 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.* 모두 제거
  • hwpapi.parametersets (top-level) → hwpapi.low.parametersets
  • nbs/ nbdev 파이프라인 폐기

전체 변경점: CHANGELOG.md.

Install

pip install hwpapi

v1 에 머무르려면: pip install "hwpapi<2"

v1.0.0 — Stable Release

22 Apr 06:19

Choose a tag to compare

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 objectsParagraph, 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 모두 제거
  • App public 멤버 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.pyhwpapi/low/actions.py
  • hwpapi/core/engine.pyhwpapi/low/engine.py
  • nbs/ nbdev 기반 문서 파이프라인 폐기 (아카이브)
  • docs/*.md (v1 계획 문서 10개) → docs/archive/ 이동

Added

  • hwpapi/collections/ 패키지 — fields, bookmarks, hyperlinks, images,
    paragraphs, styles, tables (각 Collection + Element value object)
  • hwpapi/document.pyDocument 퍼사드 (cached_property 로 lazy-wire)
  • hwpapi/low/ — raw actions / parametersets / engine escape hatch
  • hwpapi/errors.pyHwpApiError, ConnectionError, ActionFailedError,
    InvalidArgumentError, FileIOError + wrap_com_error()
  • hwpapi/context/scopes.pycharshape_scope, parashape_scope, styled_text
  • hwpapi/io/open_file, new_document, export_pdf, export_image, export_text
  • docs/ Quarto 사이트 (43 페이지, 0 warnings) — getting-started / guide /
    recipes / reference / design / adr
  • .github/workflows/deploy-docs.yaml — GitHub Pages 자동 배포
  • tests/conftest.pySetMessageBoxMode(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 의 dead from 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) — 문자열/정수 양방향 helper
  • hwpapi.units 모듈 — App 인스턴스 없이도 호출 가능한 단위 변환

Changed

  • version = 1.0.0 + Development Status :: 5 - Production/Stable
  • requires-python = ">=3.9" (이전 3.7 — EOL)
  • [project.optional-dependencies] 추가 — dev, test, docs
  • set_charshape(facename=...) — 단일 인자가 7개 facename 으로 자동 fan-out
  • find_text(facename=...) — 다국어 fan-out
  • set_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_font no-opapply_defaults() 메소드 추가
  • App.charshape() method vs charshape property 이름 충돌 — method 완전 제거
  • api.Run() None 반환 11곳 — cell_addr 추적 기반으로 전환
  • app.view.zoom()PictureScale 액션ZoomRate property 로 교체
  • 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_bookmarkapp.bookmarks.add
  • app.insert_hyperlinkapp.hyperlinks.add
  • app.replace_brackets_with_fieldsapp.fields.from_brackets
  • app.get_charshape / app.set_charshapeapp.charshape property
  • app.get_parashape / app.set_parashapeapp.parashape property

마이그레이션 가이드: 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 →...

Read more

v0.0.10 — 전면 dialog suppress + suppress_errors() + RegisterModule

15 Apr 08:37

Choose a tag to compare

🤫 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

15 Apr 08:18

Choose a tag to compare

🧭 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

15 Apr 07:58

Choose a tag to compare

🎯 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

15 Apr 07:40

Choose a tag to compare

🔍 내부 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.selectionapp.get_selected_text() alias 명시
  • app.visibleapp.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.pycore/ops/* delegate 분리

Full changelog: v0.0.6...v0.0.7

v0.0.6 — Phase C: convenience helpers

15 Apr 06:11

Choose a tag to compare

🎯 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.status property — 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()

15 Apr 05:10

Choose a tag to compare

🎯 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_field
  • fields · fields_dict (properties)
  • field_exists / move_to_field / delete_field / delete_all_fields / rename_field
  • replace_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 종료 시 원래 모드로 자동 복원.

📖 새 튜토리얼

호환성

  • 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)

15 Apr 04:31

Choose a tag to compare

🔧 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