python-hwpx 2.0__tar.gz → 2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_hwpx-2.0 → python_hwpx-2.2}/LICENSE +32 -32
- python_hwpx-2.2/PKG-INFO +257 -0
- python_hwpx-2.2/README.md +190 -0
- {python_hwpx-2.0 → python_hwpx-2.2}/pyproject.toml +86 -86
- {python_hwpx-2.0 → python_hwpx-2.2}/setup.cfg +4 -4
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/__init__.py +36 -36
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/document.py +890 -889
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/opc/package.py +514 -514
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/opc/xml_utils.py +50 -50
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/oxml/__init__.py +220 -220
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/oxml/body.py +435 -435
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/oxml/common.py +36 -36
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/oxml/document.py +3469 -3450
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/oxml/header.py +1369 -1369
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/oxml/header_part.py +10 -10
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/oxml/memo.py +10 -10
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/oxml/paragraph.py +10 -10
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/oxml/parser.py +72 -72
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/oxml/schema.py +44 -44
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/oxml/section.py +10 -10
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/oxml/table.py +10 -10
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/oxml/utils.py +85 -85
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/package.py +24 -24
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/templates.py +33 -33
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/tools/__init__.py +36 -36
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/tools/_schemas/header.xsd +14 -14
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/tools/_schemas/section.xsd +12 -12
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/tools/object_finder.py +347 -347
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/tools/text_extractor.py +726 -726
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/tools/validator.py +184 -184
- python_hwpx-2.2/src/python_hwpx.egg-info/PKG-INFO +257 -0
- {python_hwpx-2.0 → python_hwpx-2.2}/tests/test_coverage_targets.py +74 -74
- {python_hwpx-2.0 → python_hwpx-2.2}/tests/test_document_context_manager.py +65 -65
- {python_hwpx-2.0 → python_hwpx-2.2}/tests/test_document_formatting.py +679 -611
- {python_hwpx-2.0 → python_hwpx-2.2}/tests/test_document_save_api.py +55 -55
- {python_hwpx-2.0 → python_hwpx-2.2}/tests/test_inline_models.py +113 -113
- {python_hwpx-2.0 → python_hwpx-2.2}/tests/test_integration_hwpx_compatibility.py +228 -228
- {python_hwpx-2.0 → python_hwpx-2.2}/tests/test_memo_and_style_editing.py +305 -305
- {python_hwpx-2.0 → python_hwpx-2.2}/tests/test_opc_package.py +81 -81
- {python_hwpx-2.0 → python_hwpx-2.2}/tests/test_oxml_parsing.py +385 -385
- {python_hwpx-2.0 → python_hwpx-2.2}/tests/test_packaging_py_typed.py +38 -38
- {python_hwpx-2.0 → python_hwpx-2.2}/tests/test_repr_snapshots.py +68 -68
- {python_hwpx-2.0 → python_hwpx-2.2}/tests/test_section_headers.py +143 -143
- {python_hwpx-2.0 → python_hwpx-2.2}/tests/test_tables_default_border.py +81 -81
- {python_hwpx-2.0 → python_hwpx-2.2}/tests/test_text_extractor_annotations.py +126 -126
- {python_hwpx-2.0 → python_hwpx-2.2}/tests/test_version_metadata.py +25 -25
- python_hwpx-2.0/PKG-INFO +0 -167
- python_hwpx-2.0/README.md +0 -100
- python_hwpx-2.0/src/python_hwpx.egg-info/PKG-INFO +0 -167
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/data/Skeleton.hwpx +0 -0
- {python_hwpx-2.0 → python_hwpx-2.2}/src/hwpx/py.typed +0 -0
- {python_hwpx-2.0 → python_hwpx-2.2}/src/python_hwpx.egg-info/SOURCES.txt +0 -0
- {python_hwpx-2.0 → python_hwpx-2.2}/src/python_hwpx.egg-info/dependency_links.txt +0 -0
- {python_hwpx-2.0 → python_hwpx-2.2}/src/python_hwpx.egg-info/entry_points.txt +0 -0
- {python_hwpx-2.0 → python_hwpx-2.2}/src/python_hwpx.egg-info/requires.txt +0 -0
- {python_hwpx-2.0 → python_hwpx-2.2}/src/python_hwpx.egg-info/top_level.txt +0 -0
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
Non-Commercial License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2024 python-hwpx Maintainers
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to use,
|
|
7
|
-
copy, modify, merge, publish, distribute, and sublicense the Software only for
|
|
8
|
-
non-commercial purposes, subject to the following conditions:
|
|
9
|
-
|
|
10
|
-
1. Non-Commercial Use Only. The Software may be used, copied, modified,
|
|
11
|
-
merged, published, distributed, and sublicensed only for non-commercial
|
|
12
|
-
purposes. "Non-Commercial" means use that is not primarily intended for or
|
|
13
|
-
directed toward commercial advantage, monetary compensation, or any form of
|
|
14
|
-
direct or indirect commercial exploitation.
|
|
15
|
-
|
|
16
|
-
2. Attribution. The above copyright notice and this permission notice shall be
|
|
17
|
-
included in all copies or substantial portions of the Software.
|
|
18
|
-
|
|
19
|
-
3. No Warranty of Commercial Support. The maintainers are not obligated to
|
|
20
|
-
provide commercial support, maintenance, or updates.
|
|
21
|
-
|
|
22
|
-
THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
23
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24
|
-
FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
|
25
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
26
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
27
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
28
|
-
SOFTWARE.
|
|
29
|
-
|
|
30
|
-
If you require permissions to use this Software for commercial purposes,
|
|
31
|
-
please contact the copyright holders to negotiate an alternative licensing
|
|
32
|
-
arrangement.
|
|
1
|
+
Non-Commercial License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 python-hwpx Maintainers
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to use,
|
|
7
|
+
copy, modify, merge, publish, distribute, and sublicense the Software only for
|
|
8
|
+
non-commercial purposes, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
1. Non-Commercial Use Only. The Software may be used, copied, modified,
|
|
11
|
+
merged, published, distributed, and sublicensed only for non-commercial
|
|
12
|
+
purposes. "Non-Commercial" means use that is not primarily intended for or
|
|
13
|
+
directed toward commercial advantage, monetary compensation, or any form of
|
|
14
|
+
direct or indirect commercial exploitation.
|
|
15
|
+
|
|
16
|
+
2. Attribution. The above copyright notice and this permission notice shall be
|
|
17
|
+
included in all copies or substantial portions of the Software.
|
|
18
|
+
|
|
19
|
+
3. No Warranty of Commercial Support. The maintainers are not obligated to
|
|
20
|
+
provide commercial support, maintenance, or updates.
|
|
21
|
+
|
|
22
|
+
THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
23
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
|
25
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
26
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
27
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
28
|
+
SOFTWARE.
|
|
29
|
+
|
|
30
|
+
If you require permissions to use this Software for commercial purposes,
|
|
31
|
+
please contact the copyright holders to negotiate an alternative licensing
|
|
32
|
+
arrangement.
|
python_hwpx-2.2/PKG-INFO
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: python-hwpx
|
|
3
|
+
Version: 2.2
|
|
4
|
+
Summary: Hancom HWPX 패키지를 로드하고 편집하기 위한 Python 유틸리티 모음
|
|
5
|
+
Author: python-hwpx Maintainers
|
|
6
|
+
License: Non-Commercial License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2024 python-hwpx Maintainers
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to use,
|
|
12
|
+
copy, modify, merge, publish, distribute, and sublicense the Software only for
|
|
13
|
+
non-commercial purposes, subject to the following conditions:
|
|
14
|
+
|
|
15
|
+
1. Non-Commercial Use Only. The Software may be used, copied, modified,
|
|
16
|
+
merged, published, distributed, and sublicensed only for non-commercial
|
|
17
|
+
purposes. "Non-Commercial" means use that is not primarily intended for or
|
|
18
|
+
directed toward commercial advantage, monetary compensation, or any form of
|
|
19
|
+
direct or indirect commercial exploitation.
|
|
20
|
+
|
|
21
|
+
2. Attribution. The above copyright notice and this permission notice shall be
|
|
22
|
+
included in all copies or substantial portions of the Software.
|
|
23
|
+
|
|
24
|
+
3. No Warranty of Commercial Support. The maintainers are not obligated to
|
|
25
|
+
provide commercial support, maintenance, or updates.
|
|
26
|
+
|
|
27
|
+
THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
28
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
29
|
+
FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
|
30
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
31
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
32
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
33
|
+
SOFTWARE.
|
|
34
|
+
|
|
35
|
+
If you require permissions to use this Software for commercial purposes,
|
|
36
|
+
please contact the copyright holders to negotiate an alternative licensing
|
|
37
|
+
arrangement.
|
|
38
|
+
|
|
39
|
+
Project-URL: Homepage, https://github.com/airmang/python-hwpx
|
|
40
|
+
Project-URL: Documentation, https://github.com/airmang/python-hwpx/tree/main/docs
|
|
41
|
+
Project-URL: Issues, https://github.com/airmang/python-hwpx/issues
|
|
42
|
+
Keywords: hwp,hwpx,hancom,opc,xml
|
|
43
|
+
Classifier: Development Status :: 3 - Alpha
|
|
44
|
+
Classifier: Intended Audience :: Developers
|
|
45
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
46
|
+
Classifier: Programming Language :: Python :: 3
|
|
47
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
48
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
49
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
50
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
51
|
+
Classifier: Topic :: Text Processing :: Markup :: XML
|
|
52
|
+
Requires-Python: >=3.10
|
|
53
|
+
Description-Content-Type: text/markdown
|
|
54
|
+
License-File: LICENSE
|
|
55
|
+
Requires-Dist: lxml<6,>=4.9
|
|
56
|
+
Provides-Extra: dev
|
|
57
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
58
|
+
Requires-Dist: twine>=4.0; extra == "dev"
|
|
59
|
+
Requires-Dist: pytest>=7.4; extra == "dev"
|
|
60
|
+
Provides-Extra: test
|
|
61
|
+
Requires-Dist: pytest>=7.4; extra == "test"
|
|
62
|
+
Requires-Dist: pytest-cov>=5.0; extra == "test"
|
|
63
|
+
Provides-Extra: typecheck
|
|
64
|
+
Requires-Dist: mypy>=1.10; extra == "typecheck"
|
|
65
|
+
Requires-Dist: pyright>=1.1.390; extra == "typecheck"
|
|
66
|
+
Dynamic: license-file
|
|
67
|
+
|
|
68
|
+
<p align="center">
|
|
69
|
+
<h1 align="center">python-hwpx</h1>
|
|
70
|
+
<p align="center">
|
|
71
|
+
<strong>HWPX 문서를 Python으로 읽고, 편집하고, 생성합니다.</strong>
|
|
72
|
+
</p>
|
|
73
|
+
<p align="center">
|
|
74
|
+
<a href="https://pypi.org/project/python-hwpx/"><img src="https://img.shields.io/pypi/v/python-hwpx?color=blue&label=PyPI" alt="PyPI"></a>
|
|
75
|
+
<a href="https://pypi.org/project/python-hwpx/"><img src="https://img.shields.io/pypi/pyversions/python-hwpx" alt="Python"></a>
|
|
76
|
+
<a href="https://github.com/airmang/python-hwpx/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-Non--Commercial-green" alt="License"></a>
|
|
77
|
+
<a href="https://airmang.github.io/python-hwpx/"><img src="https://img.shields.io/badge/docs-Sphinx-8CA1AF" alt="Docs"></a>
|
|
78
|
+
</p>
|
|
79
|
+
</p>
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
`python-hwpx`는 한컴오피스의 [HWPX 포맷](https://www.hancom.com/)을 순수 Python으로 다루는 라이브러리입니다.
|
|
84
|
+
한/글 설치 없이, OS에 관계없이 HWPX 문서의 구조를 파싱하고 콘텐츠를 조작할 수 있습니다.
|
|
85
|
+
|
|
86
|
+
> **pyhwpx / pyhwp와 다른 점?**
|
|
87
|
+
> `pyhwpx`는 Windows COM 자동화 기반이라 한/글이 설치된 Windows에서만 동작합니다.
|
|
88
|
+
> `pyhwp`는 레거시 `.hwp`(v5 바이너리) 전용입니다.
|
|
89
|
+
> `python-hwpx`는 OWPML/OPC 기반 `.hwpx`를 직접 파싱하므로 **Linux, macOS, CI 환경 어디서든** 동작합니다.
|
|
90
|
+
|
|
91
|
+
## 설치
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
pip install python-hwpx
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
> 유일한 의존성은 `lxml`입니다.
|
|
98
|
+
|
|
99
|
+
## Quick Start
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
from hwpx.document import HwpxDocument
|
|
103
|
+
|
|
104
|
+
# 기존 문서 열기
|
|
105
|
+
doc = HwpxDocument.open("보고서.hwpx")
|
|
106
|
+
|
|
107
|
+
# 빈 문서 새로 만들기
|
|
108
|
+
doc = HwpxDocument.new()
|
|
109
|
+
|
|
110
|
+
# 문단 추가
|
|
111
|
+
doc.add_paragraph("python-hwpx로 생성한 문단입니다.")
|
|
112
|
+
|
|
113
|
+
# 표 추가 (2×3)
|
|
114
|
+
table = doc.add_table(rows=2, cols=3)
|
|
115
|
+
table.set_cell_text(0, 0, "이름")
|
|
116
|
+
table.set_cell_text(0, 1, "부서")
|
|
117
|
+
table.set_cell_text(0, 2, "연락처")
|
|
118
|
+
|
|
119
|
+
# 메모 추가 (한/글에서 바로 표시)
|
|
120
|
+
paragraph = doc.paragraphs[0]
|
|
121
|
+
doc.add_memo_with_anchor("검토 필요", paragraph=paragraph)
|
|
122
|
+
|
|
123
|
+
# 저장
|
|
124
|
+
doc.save("결과물.hwpx")
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## 주요 기능
|
|
128
|
+
|
|
129
|
+
### 📄 문서 편집
|
|
130
|
+
|
|
131
|
+
문단, 표, 메모, 머리말/꼬리말을 Python 객체로 다룹니다.
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
# 머리말·꼬리말
|
|
135
|
+
doc.set_header_text("기밀 문서", page_type="BOTH")
|
|
136
|
+
doc.set_footer_text("— 1 —", page_type="BOTH")
|
|
137
|
+
|
|
138
|
+
# 표 셀 병합·분할
|
|
139
|
+
table.merge_cells(0, 0, 1, 1) # (0,0)~(1,1) 병합
|
|
140
|
+
table.set_cell_text(0, 0, "병합된 셀", logical=True, split_merged=True)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### 🔍 텍스트 추출 & 검색
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
from hwpx import TextExtractor, ObjectFinder
|
|
147
|
+
|
|
148
|
+
# 텍스트 추출
|
|
149
|
+
for section in TextExtractor("문서.hwpx"):
|
|
150
|
+
for para in section.paragraphs:
|
|
151
|
+
print(para.text)
|
|
152
|
+
|
|
153
|
+
# 특정 객체 탐색
|
|
154
|
+
for obj in ObjectFinder("문서.hwpx").find("tbl"):
|
|
155
|
+
print(obj.tag, obj.attributes)
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### 🎨 스타일 기반 텍스트 치환
|
|
159
|
+
|
|
160
|
+
서식(색상, 밑줄, charPrIDRef)으로 런을 필터링해 선택적으로 교체합니다.
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
# 빨간색 텍스트만 찾아서 치환
|
|
164
|
+
doc.replace_text_in_runs(
|
|
165
|
+
"임시", "확정",
|
|
166
|
+
text_color="#FF0000",
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
# 특정 서식의 런 검색
|
|
170
|
+
runs = doc.find_runs_by_style(underline_type="SINGLE")
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### 🏗️ 저수준 XML 제어
|
|
174
|
+
|
|
175
|
+
OWPML 스키마에 매핑된 데이터클래스로 XML 구조를 직접 다룹니다.
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
# 헤더 참조 목록
|
|
179
|
+
doc.border_fills # 테두리 채우기
|
|
180
|
+
doc.bullets # 글머리표
|
|
181
|
+
doc.styles # 스타일
|
|
182
|
+
doc.track_changes # 변경 추적
|
|
183
|
+
|
|
184
|
+
# 바탕쪽·이력·버전 파트
|
|
185
|
+
doc.master_pages
|
|
186
|
+
doc.histories
|
|
187
|
+
doc.version
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## 아키텍처
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
python-hwpx
|
|
194
|
+
├── hwpx.document # 고수준 편집 API (HwpxDocument)
|
|
195
|
+
├── hwpx.package # OPC 컨테이너 읽기/쓰기
|
|
196
|
+
├── hwpx.oxml # OWPML XML ↔ 데이터클래스 매핑
|
|
197
|
+
│ ├── document.py # 섹션, 문단, 표, 런, 메모
|
|
198
|
+
│ ├── header.py # 헤더 참조 목록 (스타일, 글머리표, 변경추적 등)
|
|
199
|
+
│ └── body.py # 타입이 지정된 본문 모델
|
|
200
|
+
├── hwpx.tools
|
|
201
|
+
│ ├── text_extractor # 텍스트 추출 파이프라인
|
|
202
|
+
│ ├── object_finder # 객체 탐색 유틸리티
|
|
203
|
+
│ └── validator # 스키마 유효성 검사 (hwpx-validate CLI)
|
|
204
|
+
└── hwpx.templates # 내장 빈 문서 템플릿
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## CLI
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
# HWPX 문서 스키마 유효성 검사
|
|
211
|
+
hwpx-validate 문서.hwpx
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## 문서
|
|
215
|
+
|
|
216
|
+
| | |
|
|
217
|
+
|---|---|
|
|
218
|
+
| **[📖 전체 문서](https://airmang.github.io/python-hwpx/)** | Sphinx 기반 API 레퍼런스, 사용 가이드, FAQ |
|
|
219
|
+
| **[🚀 빠른 시작](https://airmang.github.io/python-hwpx/quickstart.html)** | 5분 안에 HWPX 문서 다루기 |
|
|
220
|
+
| **[📚 사용 가이드](https://airmang.github.io/python-hwpx/usage.html)** | 50+ 실전 사용 패턴 |
|
|
221
|
+
| **[🔧 API 레퍼런스](https://airmang.github.io/python-hwpx/api_reference.html)** | 클래스·메서드 상세 명세 |
|
|
222
|
+
| **[📐 스키마 개요](https://airmang.github.io/python-hwpx/schema-overview.html)** | OWPML 스키마 구조 설명 |
|
|
223
|
+
|
|
224
|
+
## 요구 사항
|
|
225
|
+
|
|
226
|
+
- Python 3.10+
|
|
227
|
+
- lxml ≥ 4.9
|
|
228
|
+
|
|
229
|
+
## 알려진 제약
|
|
230
|
+
|
|
231
|
+
`add_shape()` / `add_control()`은 한/글이 요구하는 모든 하위 요소를 생성하지 않습니다.
|
|
232
|
+
복잡한 개체를 추가할 때는 한/글에서 열어 검증해 주세요.
|
|
233
|
+
|
|
234
|
+
## 기여하기
|
|
235
|
+
|
|
236
|
+
버그 리포트, 기능 제안, PR 모두 환영합니다.
|
|
237
|
+
개발 환경 설정과 테스트 방법은 [CONTRIBUTING.md](CONTRIBUTING.md)를 참고하세요.
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
git clone https://github.com/airmang/python-hwpx.git
|
|
241
|
+
cd python-hwpx
|
|
242
|
+
pip install -e ".[dev]"
|
|
243
|
+
pytest
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## License
|
|
247
|
+
|
|
248
|
+
[MIT](LICENSE) © 고규현 (Kyuhyun Koh)
|
|
249
|
+
|
|
250
|
+
<br>
|
|
251
|
+
|
|
252
|
+
## Author
|
|
253
|
+
|
|
254
|
+
**고규현** — 광교고등학교 정보·컴퓨터 교사
|
|
255
|
+
|
|
256
|
+
- ✉️ [kokyuhyun@hotmail.com](mailto:kokyuhyun@hotmail.com)
|
|
257
|
+
- 🐙 [@airmang](https://github.com/airmang)
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<h1 align="center">python-hwpx</h1>
|
|
3
|
+
<p align="center">
|
|
4
|
+
<strong>HWPX 문서를 Python으로 읽고, 편집하고, 생성합니다.</strong>
|
|
5
|
+
</p>
|
|
6
|
+
<p align="center">
|
|
7
|
+
<a href="https://pypi.org/project/python-hwpx/"><img src="https://img.shields.io/pypi/v/python-hwpx?color=blue&label=PyPI" alt="PyPI"></a>
|
|
8
|
+
<a href="https://pypi.org/project/python-hwpx/"><img src="https://img.shields.io/pypi/pyversions/python-hwpx" alt="Python"></a>
|
|
9
|
+
<a href="https://github.com/airmang/python-hwpx/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-Non--Commercial-green" alt="License"></a>
|
|
10
|
+
<a href="https://airmang.github.io/python-hwpx/"><img src="https://img.shields.io/badge/docs-Sphinx-8CA1AF" alt="Docs"></a>
|
|
11
|
+
</p>
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
`python-hwpx`는 한컴오피스의 [HWPX 포맷](https://www.hancom.com/)을 순수 Python으로 다루는 라이브러리입니다.
|
|
17
|
+
한/글 설치 없이, OS에 관계없이 HWPX 문서의 구조를 파싱하고 콘텐츠를 조작할 수 있습니다.
|
|
18
|
+
|
|
19
|
+
> **pyhwpx / pyhwp와 다른 점?**
|
|
20
|
+
> `pyhwpx`는 Windows COM 자동화 기반이라 한/글이 설치된 Windows에서만 동작합니다.
|
|
21
|
+
> `pyhwp`는 레거시 `.hwp`(v5 바이너리) 전용입니다.
|
|
22
|
+
> `python-hwpx`는 OWPML/OPC 기반 `.hwpx`를 직접 파싱하므로 **Linux, macOS, CI 환경 어디서든** 동작합니다.
|
|
23
|
+
|
|
24
|
+
## 설치
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install python-hwpx
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
> 유일한 의존성은 `lxml`입니다.
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from hwpx.document import HwpxDocument
|
|
36
|
+
|
|
37
|
+
# 기존 문서 열기
|
|
38
|
+
doc = HwpxDocument.open("보고서.hwpx")
|
|
39
|
+
|
|
40
|
+
# 빈 문서 새로 만들기
|
|
41
|
+
doc = HwpxDocument.new()
|
|
42
|
+
|
|
43
|
+
# 문단 추가
|
|
44
|
+
doc.add_paragraph("python-hwpx로 생성한 문단입니다.")
|
|
45
|
+
|
|
46
|
+
# 표 추가 (2×3)
|
|
47
|
+
table = doc.add_table(rows=2, cols=3)
|
|
48
|
+
table.set_cell_text(0, 0, "이름")
|
|
49
|
+
table.set_cell_text(0, 1, "부서")
|
|
50
|
+
table.set_cell_text(0, 2, "연락처")
|
|
51
|
+
|
|
52
|
+
# 메모 추가 (한/글에서 바로 표시)
|
|
53
|
+
paragraph = doc.paragraphs[0]
|
|
54
|
+
doc.add_memo_with_anchor("검토 필요", paragraph=paragraph)
|
|
55
|
+
|
|
56
|
+
# 저장
|
|
57
|
+
doc.save("결과물.hwpx")
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## 주요 기능
|
|
61
|
+
|
|
62
|
+
### 📄 문서 편집
|
|
63
|
+
|
|
64
|
+
문단, 표, 메모, 머리말/꼬리말을 Python 객체로 다룹니다.
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
# 머리말·꼬리말
|
|
68
|
+
doc.set_header_text("기밀 문서", page_type="BOTH")
|
|
69
|
+
doc.set_footer_text("— 1 —", page_type="BOTH")
|
|
70
|
+
|
|
71
|
+
# 표 셀 병합·분할
|
|
72
|
+
table.merge_cells(0, 0, 1, 1) # (0,0)~(1,1) 병합
|
|
73
|
+
table.set_cell_text(0, 0, "병합된 셀", logical=True, split_merged=True)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 🔍 텍스트 추출 & 검색
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
from hwpx import TextExtractor, ObjectFinder
|
|
80
|
+
|
|
81
|
+
# 텍스트 추출
|
|
82
|
+
for section in TextExtractor("문서.hwpx"):
|
|
83
|
+
for para in section.paragraphs:
|
|
84
|
+
print(para.text)
|
|
85
|
+
|
|
86
|
+
# 특정 객체 탐색
|
|
87
|
+
for obj in ObjectFinder("문서.hwpx").find("tbl"):
|
|
88
|
+
print(obj.tag, obj.attributes)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### 🎨 스타일 기반 텍스트 치환
|
|
92
|
+
|
|
93
|
+
서식(색상, 밑줄, charPrIDRef)으로 런을 필터링해 선택적으로 교체합니다.
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
# 빨간색 텍스트만 찾아서 치환
|
|
97
|
+
doc.replace_text_in_runs(
|
|
98
|
+
"임시", "확정",
|
|
99
|
+
text_color="#FF0000",
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# 특정 서식의 런 검색
|
|
103
|
+
runs = doc.find_runs_by_style(underline_type="SINGLE")
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 🏗️ 저수준 XML 제어
|
|
107
|
+
|
|
108
|
+
OWPML 스키마에 매핑된 데이터클래스로 XML 구조를 직접 다룹니다.
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
# 헤더 참조 목록
|
|
112
|
+
doc.border_fills # 테두리 채우기
|
|
113
|
+
doc.bullets # 글머리표
|
|
114
|
+
doc.styles # 스타일
|
|
115
|
+
doc.track_changes # 변경 추적
|
|
116
|
+
|
|
117
|
+
# 바탕쪽·이력·버전 파트
|
|
118
|
+
doc.master_pages
|
|
119
|
+
doc.histories
|
|
120
|
+
doc.version
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## 아키텍처
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
python-hwpx
|
|
127
|
+
├── hwpx.document # 고수준 편집 API (HwpxDocument)
|
|
128
|
+
├── hwpx.package # OPC 컨테이너 읽기/쓰기
|
|
129
|
+
├── hwpx.oxml # OWPML XML ↔ 데이터클래스 매핑
|
|
130
|
+
│ ├── document.py # 섹션, 문단, 표, 런, 메모
|
|
131
|
+
│ ├── header.py # 헤더 참조 목록 (스타일, 글머리표, 변경추적 등)
|
|
132
|
+
│ └── body.py # 타입이 지정된 본문 모델
|
|
133
|
+
├── hwpx.tools
|
|
134
|
+
│ ├── text_extractor # 텍스트 추출 파이프라인
|
|
135
|
+
│ ├── object_finder # 객체 탐색 유틸리티
|
|
136
|
+
│ └── validator # 스키마 유효성 검사 (hwpx-validate CLI)
|
|
137
|
+
└── hwpx.templates # 내장 빈 문서 템플릿
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## CLI
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
# HWPX 문서 스키마 유효성 검사
|
|
144
|
+
hwpx-validate 문서.hwpx
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## 문서
|
|
148
|
+
|
|
149
|
+
| | |
|
|
150
|
+
|---|---|
|
|
151
|
+
| **[📖 전체 문서](https://airmang.github.io/python-hwpx/)** | Sphinx 기반 API 레퍼런스, 사용 가이드, FAQ |
|
|
152
|
+
| **[🚀 빠른 시작](https://airmang.github.io/python-hwpx/quickstart.html)** | 5분 안에 HWPX 문서 다루기 |
|
|
153
|
+
| **[📚 사용 가이드](https://airmang.github.io/python-hwpx/usage.html)** | 50+ 실전 사용 패턴 |
|
|
154
|
+
| **[🔧 API 레퍼런스](https://airmang.github.io/python-hwpx/api_reference.html)** | 클래스·메서드 상세 명세 |
|
|
155
|
+
| **[📐 스키마 개요](https://airmang.github.io/python-hwpx/schema-overview.html)** | OWPML 스키마 구조 설명 |
|
|
156
|
+
|
|
157
|
+
## 요구 사항
|
|
158
|
+
|
|
159
|
+
- Python 3.10+
|
|
160
|
+
- lxml ≥ 4.9
|
|
161
|
+
|
|
162
|
+
## 알려진 제약
|
|
163
|
+
|
|
164
|
+
`add_shape()` / `add_control()`은 한/글이 요구하는 모든 하위 요소를 생성하지 않습니다.
|
|
165
|
+
복잡한 개체를 추가할 때는 한/글에서 열어 검증해 주세요.
|
|
166
|
+
|
|
167
|
+
## 기여하기
|
|
168
|
+
|
|
169
|
+
버그 리포트, 기능 제안, PR 모두 환영합니다.
|
|
170
|
+
개발 환경 설정과 테스트 방법은 [CONTRIBUTING.md](CONTRIBUTING.md)를 참고하세요.
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
git clone https://github.com/airmang/python-hwpx.git
|
|
174
|
+
cd python-hwpx
|
|
175
|
+
pip install -e ".[dev]"
|
|
176
|
+
pytest
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## License
|
|
180
|
+
|
|
181
|
+
[MIT](LICENSE) © 고규현 (Kyuhyun Koh)
|
|
182
|
+
|
|
183
|
+
<br>
|
|
184
|
+
|
|
185
|
+
## Author
|
|
186
|
+
|
|
187
|
+
**고규현** — 광교고등학교 정보·컴퓨터 교사
|
|
188
|
+
|
|
189
|
+
- ✉️ [kokyuhyun@hotmail.com](mailto:kokyuhyun@hotmail.com)
|
|
190
|
+
- 🐙 [@airmang](https://github.com/airmang)
|
|
@@ -1,86 +1,86 @@
|
|
|
1
|
-
[build-system]
|
|
2
|
-
requires = ["setuptools", "wheel"]
|
|
3
|
-
build-backend = "setuptools.build_meta"
|
|
4
|
-
|
|
5
|
-
[project]
|
|
6
|
-
name = "python-hwpx"
|
|
7
|
-
version = "2.
|
|
8
|
-
description = "Hancom HWPX 패키지를 로드하고 편집하기 위한 Python 유틸리티 모음"
|
|
9
|
-
readme = { file = "README.md", content-type = "text/markdown" }
|
|
10
|
-
license = { file = "LICENSE" }
|
|
11
|
-
requires-python = ">=3.10"
|
|
12
|
-
authors = [
|
|
13
|
-
{ name = "python-hwpx Maintainers" },
|
|
14
|
-
]
|
|
15
|
-
keywords = ["hwp", "hwpx", "hancom", "opc", "xml"]
|
|
16
|
-
classifiers = [
|
|
17
|
-
"Development Status :: 3 - Alpha",
|
|
18
|
-
"Intended Audience :: Developers",
|
|
19
|
-
"License :: OSI Approved :: MIT License",
|
|
20
|
-
"Programming Language :: Python :: 3",
|
|
21
|
-
"Programming Language :: Python :: 3.10",
|
|
22
|
-
"Programming Language :: Python :: 3.11",
|
|
23
|
-
"Programming Language :: Python :: 3.12",
|
|
24
|
-
"Topic :: Software Development :: Libraries",
|
|
25
|
-
"Topic :: Text Processing :: Markup :: XML",
|
|
26
|
-
]
|
|
27
|
-
dependencies = [
|
|
28
|
-
"lxml>=4.9,<6",
|
|
29
|
-
]
|
|
30
|
-
|
|
31
|
-
[project.optional-dependencies]
|
|
32
|
-
dev = [
|
|
33
|
-
"build>=1.0",
|
|
34
|
-
"twine>=4.0",
|
|
35
|
-
"pytest>=7.4",
|
|
36
|
-
]
|
|
37
|
-
test = [
|
|
38
|
-
"pytest>=7.4",
|
|
39
|
-
"pytest-cov>=5.0",
|
|
40
|
-
]
|
|
41
|
-
typecheck = [
|
|
42
|
-
"mypy>=1.10",
|
|
43
|
-
"pyright>=1.1.390",
|
|
44
|
-
]
|
|
45
|
-
|
|
46
|
-
[project.urls]
|
|
47
|
-
Homepage = "https://github.com/airmang/python-hwpx"
|
|
48
|
-
Documentation = "https://github.com/airmang/python-hwpx/tree/main/docs"
|
|
49
|
-
Issues = "https://github.com/airmang/python-hwpx/issues"
|
|
50
|
-
|
|
51
|
-
[project.scripts]
|
|
52
|
-
hwpx-validate = "hwpx.tools.validator:main"
|
|
53
|
-
|
|
54
|
-
[tool.setuptools]
|
|
55
|
-
package-dir = { "" = "src" }
|
|
56
|
-
include-package-data = true
|
|
57
|
-
|
|
58
|
-
[tool.setuptools.packages.find]
|
|
59
|
-
where = ["src"]
|
|
60
|
-
include = ["hwpx*"]
|
|
61
|
-
|
|
62
|
-
[tool.setuptools.package-data]
|
|
63
|
-
"hwpx" = ["py.typed"]
|
|
64
|
-
"hwpx.tools" = ["_schemas/*.xsd"]
|
|
65
|
-
"hwpx.data" = ["Skeleton.hwpx"]
|
|
66
|
-
|
|
67
|
-
[tool.pytest.ini_options]
|
|
68
|
-
pythonpath = ["src"]
|
|
69
|
-
addopts = "-ra"
|
|
70
|
-
testpaths = ["tests"]
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
[tool.mypy]
|
|
74
|
-
python_version = "3.10"
|
|
75
|
-
files = ["src/hwpx/document.py", "src/hwpx/oxml/document.py"]
|
|
76
|
-
ignore_missing_imports = true
|
|
77
|
-
|
|
78
|
-
[[tool.mypy.overrides]]
|
|
79
|
-
module = ["hwpx.document", "hwpx.oxml.document"]
|
|
80
|
-
ignore_errors = true
|
|
81
|
-
|
|
82
|
-
[tool.pyright]
|
|
83
|
-
include = ["src/hwpx/document.py", "src/hwpx/oxml/document.py"]
|
|
84
|
-
pythonVersion = "3.10"
|
|
85
|
-
typeCheckingMode = "off"
|
|
86
|
-
reportMissingTypeStubs = false
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "python-hwpx"
|
|
7
|
+
version = "2.2"
|
|
8
|
+
description = "Hancom HWPX 패키지를 로드하고 편집하기 위한 Python 유틸리티 모음"
|
|
9
|
+
readme = { file = "README.md", content-type = "text/markdown" }
|
|
10
|
+
license = { file = "LICENSE" }
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "python-hwpx Maintainers" },
|
|
14
|
+
]
|
|
15
|
+
keywords = ["hwp", "hwpx", "hancom", "opc", "xml"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 3 - Alpha",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Topic :: Software Development :: Libraries",
|
|
25
|
+
"Topic :: Text Processing :: Markup :: XML",
|
|
26
|
+
]
|
|
27
|
+
dependencies = [
|
|
28
|
+
"lxml>=4.9,<6",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.optional-dependencies]
|
|
32
|
+
dev = [
|
|
33
|
+
"build>=1.0",
|
|
34
|
+
"twine>=4.0",
|
|
35
|
+
"pytest>=7.4",
|
|
36
|
+
]
|
|
37
|
+
test = [
|
|
38
|
+
"pytest>=7.4",
|
|
39
|
+
"pytest-cov>=5.0",
|
|
40
|
+
]
|
|
41
|
+
typecheck = [
|
|
42
|
+
"mypy>=1.10",
|
|
43
|
+
"pyright>=1.1.390",
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
[project.urls]
|
|
47
|
+
Homepage = "https://github.com/airmang/python-hwpx"
|
|
48
|
+
Documentation = "https://github.com/airmang/python-hwpx/tree/main/docs"
|
|
49
|
+
Issues = "https://github.com/airmang/python-hwpx/issues"
|
|
50
|
+
|
|
51
|
+
[project.scripts]
|
|
52
|
+
hwpx-validate = "hwpx.tools.validator:main"
|
|
53
|
+
|
|
54
|
+
[tool.setuptools]
|
|
55
|
+
package-dir = { "" = "src" }
|
|
56
|
+
include-package-data = true
|
|
57
|
+
|
|
58
|
+
[tool.setuptools.packages.find]
|
|
59
|
+
where = ["src"]
|
|
60
|
+
include = ["hwpx*"]
|
|
61
|
+
|
|
62
|
+
[tool.setuptools.package-data]
|
|
63
|
+
"hwpx" = ["py.typed"]
|
|
64
|
+
"hwpx.tools" = ["_schemas/*.xsd"]
|
|
65
|
+
"hwpx.data" = ["Skeleton.hwpx"]
|
|
66
|
+
|
|
67
|
+
[tool.pytest.ini_options]
|
|
68
|
+
pythonpath = ["src"]
|
|
69
|
+
addopts = "-ra"
|
|
70
|
+
testpaths = ["tests"]
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
[tool.mypy]
|
|
74
|
+
python_version = "3.10"
|
|
75
|
+
files = ["src/hwpx/document.py", "src/hwpx/oxml/document.py"]
|
|
76
|
+
ignore_missing_imports = true
|
|
77
|
+
|
|
78
|
+
[[tool.mypy.overrides]]
|
|
79
|
+
module = ["hwpx.document", "hwpx.oxml.document"]
|
|
80
|
+
ignore_errors = true
|
|
81
|
+
|
|
82
|
+
[tool.pyright]
|
|
83
|
+
include = ["src/hwpx/document.py", "src/hwpx/oxml/document.py"]
|
|
84
|
+
pythonVersion = "3.10"
|
|
85
|
+
typeCheckingMode = "off"
|
|
86
|
+
reportMissingTypeStubs = false
|