python-hwpx 3.5.0__py3-none-any.whl → 3.6.0__py3-none-any.whl
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.
- hwpx/form_fit/engine.py +43 -0
- hwpx/form_fit/measure.py +52 -0
- hwpx/opc/package.py +59 -0
- hwpx/oxml/document_parts.py +8 -4
- hwpx/oxml/paragraph.py +3 -0
- hwpx/oxml/run.py +4 -0
- hwpx/oxml/table.py +11 -0
- {python_hwpx-3.5.0.dist-info → python_hwpx-3.6.0.dist-info}/METADATA +2 -2
- {python_hwpx-3.5.0.dist-info → python_hwpx-3.6.0.dist-info}/RECORD +14 -14
- {python_hwpx-3.5.0.dist-info → python_hwpx-3.6.0.dist-info}/WHEEL +0 -0
- {python_hwpx-3.5.0.dist-info → python_hwpx-3.6.0.dist-info}/entry_points.txt +0 -0
- {python_hwpx-3.5.0.dist-info → python_hwpx-3.6.0.dist-info}/licenses/LICENSE +0 -0
- {python_hwpx-3.5.0.dist-info → python_hwpx-3.6.0.dist-info}/licenses/NOTICE +0 -0
- {python_hwpx-3.5.0.dist-info → python_hwpx-3.6.0.dist-info}/top_level.txt +0 -0
hwpx/form_fit/engine.py
CHANGED
|
@@ -55,6 +55,26 @@ class FitEngine:
|
|
|
55
55
|
policy: FitPolicy | None = None,
|
|
56
56
|
*,
|
|
57
57
|
field_id: str | None = None,
|
|
58
|
+
) -> FitResult:
|
|
59
|
+
result = self._fit_decide(value, slot, policy, field_id=field_id)
|
|
60
|
+
inline_count = int(getattr(slot, "inline_object_count", 0) or 0)
|
|
61
|
+
if inline_count and (value or "") != "":
|
|
62
|
+
inline_width = float(getattr(slot, "inline_object_width", 0.0) or 0.0)
|
|
63
|
+
result.warnings.append(
|
|
64
|
+
f"cell line shared with {inline_count} inline control(s) "
|
|
65
|
+
f"({inline_width:.0f} HWPUNIT deducted from the width budget); "
|
|
66
|
+
"control-sharing cells are unusual fill targets — verify with a "
|
|
67
|
+
"render gate or pick the intended value cell"
|
|
68
|
+
)
|
|
69
|
+
return result
|
|
70
|
+
|
|
71
|
+
def _fit_decide(
|
|
72
|
+
self,
|
|
73
|
+
value: str,
|
|
74
|
+
slot: SlotMetrics,
|
|
75
|
+
policy: FitPolicy | None = None,
|
|
76
|
+
*,
|
|
77
|
+
field_id: str | None = None,
|
|
58
78
|
) -> FitResult:
|
|
59
79
|
policy = policy or FitPolicy()
|
|
60
80
|
value = "" if value is None else str(value)
|
|
@@ -77,6 +97,29 @@ class FitEngine:
|
|
|
77
97
|
if policy.mode == "expand_row":
|
|
78
98
|
return self._expand_row(value, slot, policy, field_id)
|
|
79
99
|
|
|
100
|
+
# Inline objects can consume the whole line; with less than a glyph of
|
|
101
|
+
# width left there is nothing to reshape into — refuse with a message
|
|
102
|
+
# that names the cause instead of an absurd wrapped-line estimate.
|
|
103
|
+
if (
|
|
104
|
+
int(getattr(slot, "inline_object_count", 0) or 0)
|
|
105
|
+
and slot.available_width < slot.font_pt * 100.0 * 0.6
|
|
106
|
+
):
|
|
107
|
+
return FitResult(
|
|
108
|
+
ok=False,
|
|
109
|
+
value=value,
|
|
110
|
+
applied_value=value,
|
|
111
|
+
lines=0,
|
|
112
|
+
font_pt=slot.font_pt,
|
|
113
|
+
overflow_detected=True,
|
|
114
|
+
confidence="high",
|
|
115
|
+
errors=[
|
|
116
|
+
"FIELD_OVERFLOW: inline control(s) leave no usable width in "
|
|
117
|
+
"this cell; choose the intended value cell or allow row "
|
|
118
|
+
"expansion"
|
|
119
|
+
],
|
|
120
|
+
field_id=field_id,
|
|
121
|
+
)
|
|
122
|
+
|
|
80
123
|
# Reshaping ladder: wrap, shrink, or wrap_then_shrink, then fail_on_overflow.
|
|
81
124
|
wrap_lines = policy.effective_max_lines if policy.may_wrap else 1
|
|
82
125
|
wrap_slot = replace(slot, max_lines=wrap_lines)
|
hwpx/form_fit/measure.py
CHANGED
|
@@ -221,6 +221,13 @@ class SlotMetrics:
|
|
|
221
221
|
# Per-line advance as a multiple of the em, from the cell's declared paragraph
|
|
222
222
|
# line spacing (PERCENT). ``None`` falls back to ``DEFAULT_LINE_SPACING_RATIO``.
|
|
223
223
|
line_spacing_ratio: float | None = None
|
|
224
|
+
# Width already consumed on the line by inline treat-as-char objects
|
|
225
|
+
# (checkboxes, form controls, pictures) that share the target paragraph.
|
|
226
|
+
# Their declared ``hp:sz/@width`` is subtracted from the usable width —
|
|
227
|
+
# ignoring them made the engine call "fits" on a fill that real Hancom
|
|
228
|
+
# wrapped, growing the row and repaginating a 10-page form (S-087 P0).
|
|
229
|
+
inline_object_width: float = 0.0
|
|
230
|
+
inline_object_count: int = 0
|
|
224
231
|
# A cell height existed but was unusable (merged row-span fragment, or an
|
|
225
232
|
# auto-grow floor shorter than one line). Records "height budget unavailable"
|
|
226
233
|
# so the fit reports width-only honestly rather than guessing a vertical fit.
|
|
@@ -473,6 +480,11 @@ def resolve_slot_metrics(
|
|
|
473
480
|
element = getattr(cell, "element", None)
|
|
474
481
|
left, right = _cell_margin(element) if element is not None else (0, 0)
|
|
475
482
|
inner = max(raw_width - left - right, 0.0) * safety
|
|
483
|
+
inline_width, inline_count = (
|
|
484
|
+
_inline_object_width(element) if element is not None else (0.0, 0)
|
|
485
|
+
)
|
|
486
|
+
if inline_width:
|
|
487
|
+
inner = max(inner - inline_width, 0.0)
|
|
476
488
|
resolved_pt = font_pt if font_pt is not None else _first_run_font_pt(cell, document)
|
|
477
489
|
line_ratio = _first_para_line_spacing_ratio(cell, document)
|
|
478
490
|
|
|
@@ -503,9 +515,49 @@ def resolve_slot_metrics(
|
|
|
503
515
|
available_height=available_height,
|
|
504
516
|
line_spacing_ratio=line_ratio,
|
|
505
517
|
height_unavailable=height_unavailable,
|
|
518
|
+
inline_object_width=inline_width,
|
|
519
|
+
inline_object_count=inline_count,
|
|
506
520
|
)
|
|
507
521
|
|
|
508
522
|
|
|
523
|
+
def _inline_object_width(cell_element: object) -> tuple[float, int]:
|
|
524
|
+
"""Total declared width of inline treat-as-char objects in the cell.
|
|
525
|
+
|
|
526
|
+
Checkboxes and similar form controls flow on the text line
|
|
527
|
+
(``hp:pos/@treatAsChar='1'``) and consume their ``hp:sz/@width``; a fill
|
|
528
|
+
value shares whatever width remains. Objects without a declared size are
|
|
529
|
+
counted but contribute 0 width (the count still signals reduced trust).
|
|
530
|
+
"""
|
|
531
|
+
|
|
532
|
+
total = 0.0
|
|
533
|
+
count = 0
|
|
534
|
+
iter_fn = getattr(cell_element, "iter", None)
|
|
535
|
+
if iter_fn is None:
|
|
536
|
+
return 0.0, 0
|
|
537
|
+
for node in iter_fn():
|
|
538
|
+
tag = getattr(node, "tag", "")
|
|
539
|
+
if not isinstance(tag, str):
|
|
540
|
+
continue
|
|
541
|
+
local = tag.rsplit("}", 1)[-1].lower()
|
|
542
|
+
if local != "pos":
|
|
543
|
+
continue
|
|
544
|
+
if (node.get("treatAsChar") or "").strip() not in {"1", "true", "TRUE"}:
|
|
545
|
+
continue
|
|
546
|
+
holder = node.getparent() if hasattr(node, "getparent") else None
|
|
547
|
+
if holder is None:
|
|
548
|
+
continue
|
|
549
|
+
count += 1
|
|
550
|
+
for sibling in holder:
|
|
551
|
+
sib_local = str(getattr(sibling, "tag", "")).rsplit("}", 1)[-1].lower()
|
|
552
|
+
if sib_local == "sz":
|
|
553
|
+
try:
|
|
554
|
+
total += float(sibling.get("width") or 0)
|
|
555
|
+
except (TypeError, ValueError):
|
|
556
|
+
pass
|
|
557
|
+
break
|
|
558
|
+
return total, count
|
|
559
|
+
|
|
560
|
+
|
|
509
561
|
__all__ = [
|
|
510
562
|
"SlotMetrics",
|
|
511
563
|
"Measurement",
|
hwpx/opc/package.py
CHANGED
|
@@ -159,10 +159,69 @@ def _local_name(element: etree._Element) -> str:
|
|
|
159
159
|
return tag
|
|
160
160
|
|
|
161
161
|
|
|
162
|
+
def _paragraph_plain_text_length(paragraph: etree._Element) -> int | None:
|
|
163
|
+
"""Plain text length of a simple paragraph, or ``None`` when unjudgeable.
|
|
164
|
+
|
|
165
|
+
Mirrors the oxml-side stale detector: only paragraphs made purely of runs
|
|
166
|
+
with text/tab-like children can be judged at the byte boundary; anything
|
|
167
|
+
else (controls, tables, fields) returns ``None`` so its cache is kept.
|
|
168
|
+
"""
|
|
169
|
+
total = 0
|
|
170
|
+
for child in paragraph:
|
|
171
|
+
child_name = _local_name(child).lower()
|
|
172
|
+
if child_name in _LAYOUT_CACHE_ELEMENT_NAMES:
|
|
173
|
+
continue
|
|
174
|
+
if child_name != "run":
|
|
175
|
+
return None
|
|
176
|
+
for run_child in child:
|
|
177
|
+
run_child_name = _local_name(run_child).lower()
|
|
178
|
+
if run_child_name == "t":
|
|
179
|
+
total += len("".join(run_child.itertext()))
|
|
180
|
+
elif run_child_name in {"tab", "linebreak", "hyphen", "nbspace"}:
|
|
181
|
+
total += 1
|
|
182
|
+
else:
|
|
183
|
+
return None
|
|
184
|
+
return total
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def _paragraph_layout_cache_is_stale(paragraph: etree._Element) -> bool:
|
|
188
|
+
text_length = _paragraph_plain_text_length(paragraph)
|
|
189
|
+
if text_length is None:
|
|
190
|
+
return False
|
|
191
|
+
for child in paragraph:
|
|
192
|
+
if _local_name(child).lower() not in _LAYOUT_CACHE_ELEMENT_NAMES:
|
|
193
|
+
continue
|
|
194
|
+
for line_seg in child:
|
|
195
|
+
if _local_name(line_seg).lower() != "lineseg":
|
|
196
|
+
continue
|
|
197
|
+
textpos = line_seg.get("textpos")
|
|
198
|
+
if textpos is None:
|
|
199
|
+
continue
|
|
200
|
+
try:
|
|
201
|
+
if int(textpos) > text_length:
|
|
202
|
+
return True
|
|
203
|
+
except ValueError:
|
|
204
|
+
return True
|
|
205
|
+
return False
|
|
206
|
+
|
|
207
|
+
|
|
162
208
|
def _strip_section_layout_caches(payload: bytes) -> bytes:
|
|
209
|
+
"""Drop only *stale* paragraph layout caches from a section payload.
|
|
210
|
+
|
|
211
|
+
Valid caches are the authored layout of untouched paragraphs; removing
|
|
212
|
+
them forces the editor to re-lay-out entire multi-page documents, which
|
|
213
|
+
shifted page counts and stacked glyphs in the wild form-fill differential
|
|
214
|
+
(specs/031 P0 receipt). The mutating APIs upstream clear the caches of
|
|
215
|
+
exactly the paragraphs they touch, so this byte-boundary sweep only
|
|
216
|
+
guards against writers that left a provably stale cache behind.
|
|
217
|
+
"""
|
|
163
218
|
root = parse_xml(payload)
|
|
164
219
|
removed = False
|
|
165
220
|
for parent in root.iter():
|
|
221
|
+
if _local_name(parent).lower() != "p":
|
|
222
|
+
continue
|
|
223
|
+
if not _paragraph_layout_cache_is_stale(parent):
|
|
224
|
+
continue
|
|
166
225
|
for child in list(parent):
|
|
167
226
|
if _local_name(child).lower() in _LAYOUT_CACHE_ELEMENT_NAMES:
|
|
168
227
|
parent.remove(child)
|
hwpx/oxml/document_parts.py
CHANGED
|
@@ -1086,10 +1086,14 @@ class HwpxOxmlDocument:
|
|
|
1086
1086
|
if self._manifest_dirty:
|
|
1087
1087
|
updates[self._manifest_path] = _serialize_xml(self._manifest)
|
|
1088
1088
|
for section in self._sections:
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1089
|
+
# Edit-scoped invalidation: the mutating APIs (cell/paragraph/run
|
|
1090
|
+
# text and style setters) clear the caches of exactly the
|
|
1091
|
+
# paragraphs they touch, so even a dirty section only needs the
|
|
1092
|
+
# stale sweep as a safety net. Nuking every cache here forced
|
|
1093
|
+
# Hancom to re-lay-out untouched pages of multi-page forms, which
|
|
1094
|
+
# is what stacked glyphs and shifted page counts in the wild
|
|
1095
|
+
# form-fill differential (specs/031 P0 receipt).
|
|
1096
|
+
section.remove_stale_layout_caches()
|
|
1093
1097
|
for section in self._sections:
|
|
1094
1098
|
if section.dirty:
|
|
1095
1099
|
updates[section.part_name] = section.to_bytes()
|
hwpx/oxml/paragraph.py
CHANGED
|
@@ -914,6 +914,9 @@ class HwpxOxmlParagraph:
|
|
|
914
914
|
changed = True
|
|
915
915
|
|
|
916
916
|
if changed:
|
|
917
|
+
# A style swap changes glyph metrics, so the cached line layout of
|
|
918
|
+
# this paragraph no longer holds.
|
|
919
|
+
_clear_paragraph_layout_cache(self.element)
|
|
917
920
|
self.section.mark_dirty()
|
|
918
921
|
|
|
919
922
|
__all__ = ["HwpxOxmlParagraph"]
|
hwpx/oxml/run.py
CHANGED
|
@@ -320,12 +320,16 @@ class HwpxOxmlRun:
|
|
|
320
320
|
if value is None:
|
|
321
321
|
if "charPrIDRef" in self.element.attrib:
|
|
322
322
|
del self.element.attrib["charPrIDRef"]
|
|
323
|
+
_clear_paragraph_layout_cache(self.paragraph.element)
|
|
323
324
|
self.paragraph.section.mark_dirty()
|
|
324
325
|
return
|
|
325
326
|
|
|
326
327
|
new_value = str(value)
|
|
327
328
|
if self.element.get("charPrIDRef") != new_value:
|
|
328
329
|
self.element.set("charPrIDRef", new_value)
|
|
330
|
+
# A style swap changes glyph metrics, so the cached line layout of
|
|
331
|
+
# the containing paragraph no longer holds.
|
|
332
|
+
_clear_paragraph_layout_cache(self.paragraph.element)
|
|
329
333
|
self.paragraph.section.mark_dirty()
|
|
330
334
|
|
|
331
335
|
def _plain_text_nodes(self) -> list[ET.Element]:
|
hwpx/oxml/table.py
CHANGED
|
@@ -209,6 +209,7 @@ class HwpxOxmlTableCell:
|
|
|
209
209
|
sublist.set("lineWrap", "BREAK")
|
|
210
210
|
if split_paragraphs:
|
|
211
211
|
self._set_split_paragraph_text(sanitized_value)
|
|
212
|
+
self._clear_own_layout_caches()
|
|
212
213
|
self.element.set("dirty", "1")
|
|
213
214
|
self.table.mark_dirty()
|
|
214
215
|
return
|
|
@@ -226,9 +227,19 @@ class HwpxOxmlTableCell:
|
|
|
226
227
|
current = current.getparent() if hasattr(current, "getparent") else None
|
|
227
228
|
if current is not None:
|
|
228
229
|
current.set("charPrIDRef", "0")
|
|
230
|
+
self._clear_own_layout_caches()
|
|
229
231
|
self.element.set("dirty", "1")
|
|
230
232
|
self.table.mark_dirty()
|
|
231
233
|
|
|
234
|
+
def _clear_own_layout_caches(self) -> None:
|
|
235
|
+
# Edit-scoped invalidation: only this cell's paragraphs lose their
|
|
236
|
+
# layout caches, so Hancom re-lays-out just the filled cell instead of
|
|
237
|
+
# the whole section (specs/031 P0 — the whole-section nuke shifted
|
|
238
|
+
# pages and stacked glyphs on multi-page forms).
|
|
239
|
+
for node in self.element.iter():
|
|
240
|
+
if _element_local_name(node) == "p":
|
|
241
|
+
_clear_paragraph_layout_cache(node)
|
|
242
|
+
|
|
232
243
|
def remove(self) -> None:
|
|
233
244
|
self._row_element.remove(self.element)
|
|
234
245
|
self.table.mark_dirty()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-hwpx
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.6.0
|
|
4
4
|
Summary: 한글 없이 HWPX 문서를 열고, 편집하고, 생성하고, 검증하는 Python 자동화 라이브러리
|
|
5
5
|
Author: python-hwpx Maintainers
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -70,7 +70,7 @@ Dynamic: license-file
|
|
|
70
70
|
`hwpx-mcp-server`와 `hwpx-plugin`은 같은 프로젝트가 직접 유지보수하는 first-party 연동 구성요소입니다.
|
|
71
71
|
“first-party”는 프로젝트 유지보수 관계를 뜻하며, 한컴 또는 제3자의 공식 인증을 뜻하지 않습니다.
|
|
72
72
|
|
|
73
|
-
현재 PyPI 공개 릴리스는 `python-hwpx 3.
|
|
73
|
+
현재 PyPI 공개 릴리스는 `python-hwpx 3.6.0`입니다. 일반
|
|
74
74
|
`pip install python-hwpx`로 이 릴리스를 설치할 수 있습니다.
|
|
75
75
|
현재 패키지 분류는 `Development Status :: 3 - Alpha`입니다. 이 분류는 API와 제품의
|
|
76
76
|
성숙도를 나타내며, 공개 버전이나 플러그인의 최소 호환 버전을 대신하지 않습니다.
|
|
@@ -94,8 +94,8 @@ hwpx/exam/parser.py,sha256=hA_oq_8i1XpmzJ8xw1L7R6LenxREKRvlOwMMXbs9Mpc,5026
|
|
|
94
94
|
hwpx/exam/profile.py,sha256=pEYpgwoNUuMToHMJjiknHykjXs0UobGuYW67N_3VnEQ,4071
|
|
95
95
|
hwpx/form_fit/__init__.py,sha256=l1HcFge4u_wL2vogB-VxSMrb-8h7zUT_IgTWMtnH9CM,1779
|
|
96
96
|
hwpx/form_fit/apply.py,sha256=X2q7K-mLku4AXxm4-xP80QGzhBlpzpqA_Ade8aPXzNY,3450
|
|
97
|
-
hwpx/form_fit/engine.py,sha256=
|
|
98
|
-
hwpx/form_fit/measure.py,sha256=
|
|
97
|
+
hwpx/form_fit/engine.py,sha256=DiAGTRbpaH3WJNAiimRiv9KWHA-ijtUd5W2za-QhaWQ,21576
|
|
98
|
+
hwpx/form_fit/measure.py,sha256=gnSfqccm7_3oTKv3HH6Zs77r2bToxzmfvUWN2zshDE8,22323
|
|
99
99
|
hwpx/form_fit/policy.py,sha256=iXAatjS7ZycOdKgMCL4Q_kYg0qnogFPdRNlr_ecOvjc,3106
|
|
100
100
|
hwpx/form_fit/report.py,sha256=h1NzQfbj1JYvZtKUi0DckJNWGnUHMZtQ3iCzbUxUjHA,3305
|
|
101
101
|
hwpx/form_fit/seal.py,sha256=QsPzFagaEi7UKAXS-iFwiZs8rLG-_Fo9RixLc2OaqbU,17640
|
|
@@ -106,7 +106,7 @@ hwpx/ingest/hwpx_converter.py,sha256=HOUCFYO-HK4WRpWiN5sA_kZIvdv439mkZ6PMCFU3hLg
|
|
|
106
106
|
hwpx/layout/__init__.py,sha256=qotAVhol_yrPlOHvQfs68nx7ADYxPcwITYNA9gMutUM,1158
|
|
107
107
|
hwpx/layout/lint.py,sha256=byhIkP5av_il1cDdm71Oj_Em7-HUuU0w1nwhzu8tpto,15410
|
|
108
108
|
hwpx/layout/report.py,sha256=lwTIEWrZRHXc02k8_vpcaXNEcU1dDQ3dZ48y7Fxkxkc,3957
|
|
109
|
-
hwpx/opc/package.py,sha256=
|
|
109
|
+
hwpx/opc/package.py,sha256=7i9h5HU2Vwfl5-SWPy8OHIfmLxrxTbkGnSqIc-Z0IUk,37824
|
|
110
110
|
hwpx/opc/relationships.py,sha256=tPWLHRMlw0Spvtwou2jCDRfHdcm9FEKKLd95YVHLwYI,6971
|
|
111
111
|
hwpx/opc/security.py,sha256=hsA73sZxUoGIgy2zue9EnV7ChHMfasnplmqzxFs3Mp4,4419
|
|
112
112
|
hwpx/opc/xml_utils.py,sha256=L_fHY1-D5I_TfdRkDQV-bn55EnXc6AqEDWItfMpawVs,3840
|
|
@@ -117,22 +117,22 @@ hwpx/oxml/body.py,sha256=j-MJFHgInfOuFYYf-tsjFXvzPvKLt7HqUvc5Lhmp0is,30586
|
|
|
117
117
|
hwpx/oxml/canonical_defaults.py,sha256=WHAK7u_W-PDv3P3N1-1-aWAoiUgBh4x-UybFL4NqW-w,3791
|
|
118
118
|
hwpx/oxml/common.py,sha256=TJkafzg7x4T3J29tZchRZk57ZTsrM9PEiqGT3rX3w5o,1044
|
|
119
119
|
hwpx/oxml/document.py,sha256=0Ml-t2fwa4f2xMfu5jbkOoh_KDKCCf3gNpaYICRV-KY,1172
|
|
120
|
-
hwpx/oxml/document_parts.py,sha256=
|
|
120
|
+
hwpx/oxml/document_parts.py,sha256=fbj_MA8imnKhz6XN2ufNAMPYNI5xi0dCNjEv0nGESwo,41692
|
|
121
121
|
hwpx/oxml/header.py,sha256=4LtTDPe7YW0o_4jPv3Rd-vyv5suRfebecxtTWbF65Uw,50011
|
|
122
122
|
hwpx/oxml/header_part.py,sha256=BIwdzDlwJSxcVIErZ8jQuT2vQ4Tndr4Xa87beYbpSFU,50640
|
|
123
123
|
hwpx/oxml/memo.py,sha256=QlmuELEzywnmywgjm94S3vzJB8wPpoFOmI8KVuzoNPw,9484
|
|
124
124
|
hwpx/oxml/namespaces.py,sha256=c7JfdOdJbzrhyHvjbxoeeeloRE3xPuoB7v3YI8SmKDk,6524
|
|
125
125
|
hwpx/oxml/numbering.py,sha256=9a0ARGW1DkKsTF7mEEXM4FA5loQmzIBuqE4APA8UFIQ,669
|
|
126
126
|
hwpx/oxml/objects.py,sha256=44778UkUuoNZoAxIbaA6VjAbzDm0auV7TPtllhQyln0,15767
|
|
127
|
-
hwpx/oxml/paragraph.py,sha256
|
|
127
|
+
hwpx/oxml/paragraph.py,sha256=-E8A-DjKagjm47xNPnPkbIUYWNdEdAQowzl4X-EP6uI,32893
|
|
128
128
|
hwpx/oxml/parser.py,sha256=pIfyNdW3WdFkCcE8JFY7hn1fobRbMngzfhVZICvWeVs,2937
|
|
129
|
-
hwpx/oxml/run.py,sha256=
|
|
129
|
+
hwpx/oxml/run.py,sha256=F939J1W6zQjr-JQ1Z8-nKh2s7NQ_0Okov4QJAEyw_5M,15503
|
|
130
130
|
hwpx/oxml/schema.py,sha256=ElR3_IIhhPPZEqJtNKMNCHA-VFVLdhL454W_4spuvlc,1284
|
|
131
131
|
hwpx/oxml/section.py,sha256=i3t1SKIMneA1qWAajDlmZ-yrWJF9VvqT-aoq3mRXtxE,11638
|
|
132
132
|
hwpx/oxml/section_format.py,sha256=EKqod989mzcaPz-lDKM1Y7atdpFX9x_SdQ8zfCL3BpU,18320
|
|
133
133
|
hwpx/oxml/section_story.py,sha256=zvUV7O4dtogWcM9-zudRAszCHRwfzTBMW2GGI1Q24kg,22410
|
|
134
134
|
hwpx/oxml/simple_parts.py,sha256=dOVKWlUCQV8GePH0WRWPUmRylvH5O8bu0B6jj_4lejk,1864
|
|
135
|
-
hwpx/oxml/table.py,sha256=
|
|
135
|
+
hwpx/oxml/table.py,sha256=SPm4a3s_xSq1DNBh-2VSK87mIGroPnSyLeBSM50-4ok,39708
|
|
136
136
|
hwpx/oxml/utils.py,sha256=2L9au3SD_MFkFt2DXx3udXBT5caYuYO623lhGhgldVo,2972
|
|
137
137
|
hwpx/presets/__init__.py,sha256=I3gSJDT2tuvxXbw3FOmI3CnbxvjDMPZfppyg6OlMHOI,535
|
|
138
138
|
hwpx/presets/proposal.py,sha256=2yzLfDxOAT0P19dPX1RBWh56_AIOMsWqINDadtnKQoc,21176
|
|
@@ -199,10 +199,10 @@ hwpx/visual/page_qa.py,sha256=AuJCySfLIdXjPeekhAc3YnrIWOsN0sI35Pnz8BZ6Pro,7278
|
|
|
199
199
|
hwpx/visual/qa_contracts.py,sha256=1cjoiRTAWgi7NgE8SPc6bKxdoUfKx9nyou1mgC47TxY,10506
|
|
200
200
|
hwpx/visual/qa_metrics.py,sha256=I7RdybN-f1Fvcv2j-ceDPoek51nOkMui1Zrd7TEX_C8,9838
|
|
201
201
|
hwpx/visual/report.py,sha256=2RhXN1KBYOZTim9FNpeUhaaDHR7oFxI6Z2DLUkDIiwE,1717
|
|
202
|
-
python_hwpx-3.
|
|
203
|
-
python_hwpx-3.
|
|
204
|
-
python_hwpx-3.
|
|
205
|
-
python_hwpx-3.
|
|
206
|
-
python_hwpx-3.
|
|
207
|
-
python_hwpx-3.
|
|
208
|
-
python_hwpx-3.
|
|
202
|
+
python_hwpx-3.6.0.dist-info/licenses/LICENSE,sha256=_ubz4wv-BkkT3l3gu-QuH7JGeVjuRYGZoZK95eNsCHU,9688
|
|
203
|
+
python_hwpx-3.6.0.dist-info/licenses/NOTICE,sha256=k48h6EaGQE8Y1c0dS9sIOOcz4YqkbcImWClF7pBOgsg,2473
|
|
204
|
+
python_hwpx-3.6.0.dist-info/METADATA,sha256=L4frTvOU4Mi8VP5EDr3ps2UPQ5c5Qx1Yadn0uu_CXVU,13561
|
|
205
|
+
python_hwpx-3.6.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
206
|
+
python_hwpx-3.6.0.dist-info/entry_points.txt,sha256=PVUBTBQtBHiflQ9XBjfd004w-LrDibgZjwzxgu8Tx7w,480
|
|
207
|
+
python_hwpx-3.6.0.dist-info/top_level.txt,sha256=R1iToqDh80Nf2oQhRjTN0rbN2X6kyDUizIocZjkhuxc,5
|
|
208
|
+
python_hwpx-3.6.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|