Skip to main content

Python bindings for native rhwp HWP to PDF conversion

Project description

hwp-ingest

CI PyPI Python versions License

Rust-backed Python package for Korean HWP/HWPX ingestion.
Convert HWP documents to PDF or page-level SVG artifacts through a typed Python facade.

hwp-ingest uses a vendored rhwp subset as its current HWP parsing, layout, and rendering backend. The vendored backend can carry hwp-ingest-local compatibility patches, while product-facing conversion policy stays in the hwp-ingest Rust/Python layers.

Features

  • Convert HWP files to PDF bytes or PDF files.
  • Render page-level SVG artifacts for inspection and downstream pipelines.
  • Read basic document metadata such as renderable page count.
  • Keep conversion orchestration in Rust while Python handles paths, overwrite policy, and typed facade ergonomics.

Install from PyPI:

uv pip install hwp-ingest
# or
python -m pip install hwp-ingest

Runtime PDF dependency

PDF conversion requires the rsvg-convert executable from librsvg at runtime. The Python wheel does not bundle this executable. SVG output does not require rsvg-convert; that executable is only needed for PDF conversion.

Check availability:

rsvg-convert --version

Install examples:

# Debian/Ubuntu
sudo apt-get install librsvg2-bin

# Fedora/RHEL
sudo dnf install librsvg2-tools

# Arch Linux
sudo pacman -S librsvg

# macOS
brew install librsvg

On Windows, install librsvg/rsvg-convert and ensure rsvg-convert.exe is on PATH. If rsvg-convert is missing, PDF conversion raises hwp_ingest.HwpIngestError with a clear message. svg2pdf is not used as an automatic fallback because it is known to drop clipped table text in some HWP documents.

Font fallback and PUA glyphs

hwp-ingest does not bundle Hancom or Microsoft fonts. PDF conversion asks rsvg-convert/fontconfig to resolve the SVG font-family chain from fonts installed on the system. If a document contains visible Private Use Area (PUA) characters, such as Hancom symbol slots, a generic Unicode font is not enough: PUA codepoints do not define a standard glyph shape. They render correctly only when the owning document font is installed, or when the project adds a source-backed codepoint mapping for that specific symbol set.

The current renderer preserves the document font name first, then appends Korean-compatible fallback families:

Text family in the document Fallback order
Batang/Myeongjo/serif text Document font → Batang/바탕Nanum MyeongjoAppleMyungjoNoto Serif KR / Noto Serif CJK KRHCR Batang Ext-B / 함초롬바탕 확장BHCR Batang Ext / 함초롬바탕 확장HCR Batang / 함초롬바탕Source Han Serif K Old Hangulserif
Dotum/Gothic/Gulim/sans-serif text Document font → Malgun Gothic / 맑은 고딕Apple SD Gothic NeoNoto Sans KR ExtraLightNoto Sans KRPretendardHCR Batang Ext-B / 함초롬바탕 확장BHCR Batang Ext / 함초롬바탕 확장HCR Batang / 함초롬바탕Source Han Serif K Old Hangulsans-serif

For Hancom-origin documents with PUA symbols, install the matching licensed font on the machine running conversion:

Document/font origin Families to check first
Hancom/HCR body or PUA symbols HCR Batang / 함초롬바탕, HCR Dotum / 함초롬돋움
Windows-origin documents Batang, Dotum, Gulim, Gungsuh, Malgun Gothic
Older HY/Hanyang documents HY울릉도L, HY헤드라인M, HY견고딕, HY그래픽, HY견명조, HY신명조

Linux/fontconfig check:

fc-match "HCR Batang"
fc-match "함초롬바탕"
fc-match "HCR Dotum"

If these commands resolve to a fallback like Noto or DejaVu instead of the expected Hancom/HCR family, install the licensed TTF/OTF files into a system or user font directory and refresh fontconfig:

# user-local example
mkdir -p ~/.local/share/fonts/hancom
cp HCRBatang.ttf HCRBatang-Bold.ttf ~/.local/share/fonts/hancom/
fc-cache -f ~/.local/share/fonts/hancom

Do not commit restricted font files into this repository.

Quick start

Convert an HWP file to a PDF next to the input file:

from pathlib import Path

import hwp_ingest

input_path = Path("document.hwp")
output_path = hwp_ingest.to_pdf_file(input_path, overwrite=True)
print(output_path)

Convert one zero-based page to bytes:

from pathlib import Path

import hwp_ingest

pdf_bytes = hwp_ingest.to_pdf_bytes(
    Path("document.hwp").read_bytes(),
    page_index=0,
)
Path("page-1.pdf").write_bytes(pdf_bytes)

Render SVG page artifacts without the PDF backend:

from pathlib import Path

import hwp_ingest

svg_pages = hwp_ingest.to_svg_pages(Path("document.hwp").read_bytes())
Path("page-1.svg").write_bytes(svg_pages[0])

Read basic document metadata:

from pathlib import Path

import hwp_ingest

info = hwp_ingest.analyze_bytes(Path("document.hwp").read_bytes())
print(info.page_count)

Python API

The package is typed and ships py.typed plus checked-in .pyi stubs.

hwp_ingest.analyze_bytes(data: bytes) -> hwp_ingest.DocumentInfo

Returns a DocumentInfo object. DocumentInfo.page_count is the number of renderable pages discovered in the HWP bytes.

hwp_ingest.to_pdf_bytes(
    data: bytes,
    *,
    page_index: int | None = None,
) -> bytes

Returns PDF bytes. page_index is zero-based. Pass None to convert the full document.

hwp_ingest.to_svg_pages(
    data: bytes,
    *,
    page_index: int | None = None,
) -> list[bytes]

Returns one SVG document per selected page as bytes. page_index is zero-based. Pass None to render all pages in document order. SVG output does not require rsvg-convert.

hwp_ingest.to_pdf_file(
    input_path: str | os.PathLike[str],
    output_path: str | os.PathLike[str] | None = None,
    *,
    page_index: int | None = None,
    overwrite: bool = False,
) -> pathlib.Path

Writes a PDF and returns the output path. If output_path is None, the output uses the input path with a .pdf suffix. Existing output files are protected unless overwrite=True.

hwp_ingest.to_svg_files(
    input_path: str | os.PathLike[str],
    output_dir: str | os.PathLike[str] | None = None,
    *,
    page_index: int | None = None,
    overwrite: bool = False,
) -> list[pathlib.Path]

Writes one SVG file per selected page and returns paths in page order. If output_dir is None, SVG files are written beside the input file. Generated filenames are stable and use one-based visible page numbers: <stem>.page-0001.svg, <stem>.page-0002.svg, and so on. Existing output files are protected unless overwrite=True.

Errors

  • ValueError: negative page_index, empty documents, or out-of-range pages.
  • FileExistsError: output exists and overwrite=False.
  • FileNotFoundError: input file path does not exist.
  • hwp_ingest.HwpIngestError: parse, render, PDF backend, or output write failures.

Local development

cargo test --workspace
uv run maturin develop
uv run pytest

Build distributable artifacts locally:

uv run maturin sdist --out dist
uv run --with ziglang maturin build --release --locked --out dist --compatibility pypi --zig

Notices

This project includes vendored portions of rhwp.

본 제품은 한글과컴퓨터의 HWP 문서 파일(.hwp) 공개 문서를 참고하여 개발하였습니다.

"한글", "한컴", "HWP", and "HWPX" are registered trademarks of Hancom Inc. hwp-ingest is an independent open-source project and is not affiliated with, sponsored by, or endorsed by Hancom Inc.

See NOTICE, THIRD_PARTY_LICENSES.md, and vendor/rhwp-subset/NOTICE for vendored source attribution and license details.

Project direction

See docs/rhwp-python-binding-plan.md for batch engine, semantic output, vendor/upstream sync, and production pipeline direction.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hwp_ingest-0.1.1.tar.gz (2.5 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

hwp_ingest-0.1.1-cp310-abi3-win_amd64.whl (2.8 MB view details)

Uploaded CPython 3.10+Windows x86-64

hwp_ingest-0.1.1-cp310-abi3-manylinux_2_28_x86_64.whl (3.0 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.28+ x86-64

hwp_ingest-0.1.1-cp310-abi3-manylinux_2_28_aarch64.whl (2.7 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.28+ ARM64

hwp_ingest-0.1.1-cp310-abi3-macosx_11_0_arm64.whl (2.6 MB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

hwp_ingest-0.1.1-cp310-abi3-macosx_10_12_x86_64.whl (2.7 MB view details)

Uploaded CPython 3.10+macOS 10.12+ x86-64

File details

Details for the file hwp_ingest-0.1.1.tar.gz.

File metadata

  • Download URL: hwp_ingest-0.1.1.tar.gz
  • Upload date:
  • Size: 2.5 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for hwp_ingest-0.1.1.tar.gz
Algorithm Hash digest
SHA256 87a424c13a7d9e67c1a4cc0dba6925eb53a950479a78989bc78f1aed01cdc4bc
MD5 90a67cf239c67db9173ed3da6d973e4e
BLAKE2b-256 f06b4d1aae017377accb88c84983157852f813de7e3af38e7d59288d469a7bb2

See more details on using hashes here.

Provenance

The following attestation bundles were made for hwp_ingest-0.1.1.tar.gz:

Publisher: publish.yml on iosif2/hwp-ingest

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file hwp_ingest-0.1.1-cp310-abi3-win_amd64.whl.

File metadata

  • Download URL: hwp_ingest-0.1.1-cp310-abi3-win_amd64.whl
  • Upload date:
  • Size: 2.8 MB
  • Tags: CPython 3.10+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for hwp_ingest-0.1.1-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 674b15133e67c26203857afb28c8efab1a4172a90d55637daabe0d9fdebb608b
MD5 31e9cc8b7b7ea9ef0b6bfa6505a4a001
BLAKE2b-256 056f69939afbbd08ee195b2eeb1f172fd0e197f57c553d33db54de5a7ad6aa64

See more details on using hashes here.

Provenance

The following attestation bundles were made for hwp_ingest-0.1.1-cp310-abi3-win_amd64.whl:

Publisher: publish.yml on iosif2/hwp-ingest

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file hwp_ingest-0.1.1-cp310-abi3-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for hwp_ingest-0.1.1-cp310-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 d94da40a840713fa79ddfed70c376d97810705070a4e217c3001070cd33877bb
MD5 418f680e66247cff06abb5a0d5132400
BLAKE2b-256 15b87547795834076a342eb1f989fec82779dcc8f47d5d2d0e5a0765ac03f974

See more details on using hashes here.

Provenance

The following attestation bundles were made for hwp_ingest-0.1.1-cp310-abi3-manylinux_2_28_x86_64.whl:

Publisher: publish.yml on iosif2/hwp-ingest

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file hwp_ingest-0.1.1-cp310-abi3-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for hwp_ingest-0.1.1-cp310-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 7d6303fab5df6d080b464e946d86f1f70cea049e5790e73f6c3d544e23ed430b
MD5 c0f04e3931a47dc8c1b9fbaa72c8fe2d
BLAKE2b-256 83ac47e5ea379b55504496084a19840c44ff12514ac2a273e5f3dd611c30ac4a

See more details on using hashes here.

Provenance

The following attestation bundles were made for hwp_ingest-0.1.1-cp310-abi3-manylinux_2_28_aarch64.whl:

Publisher: publish.yml on iosif2/hwp-ingest

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file hwp_ingest-0.1.1-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for hwp_ingest-0.1.1-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 1a9b249fd197d3f38343ff34cd25e8c0ebf31c2dad551dd5223cc5777ff7ac3f
MD5 7dfc163da1eac6451b1c1c892e26db20
BLAKE2b-256 42ac52bf6124b724844af08cc9f007071fb9bde7dddbe6d771c9be0f264beeb1

See more details on using hashes here.

Provenance

The following attestation bundles were made for hwp_ingest-0.1.1-cp310-abi3-macosx_11_0_arm64.whl:

Publisher: publish.yml on iosif2/hwp-ingest

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file hwp_ingest-0.1.1-cp310-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for hwp_ingest-0.1.1-cp310-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 5549e19f7a88fc8386493dd64e3533ec35892374e5262da030cb8a1551a23afd
MD5 aeb77ba13bc182c37995b732c1d892e9
BLAKE2b-256 5206cd9a8d3febebedd25e8c7c9a45372156e8b1e7f568132e35b3a04365c643

See more details on using hashes here.

Provenance

The following attestation bundles were made for hwp_ingest-0.1.1-cp310-abi3-macosx_10_12_x86_64.whl:

Publisher: publish.yml on iosif2/hwp-ingest

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page