python-hwpx 6.5.0__tar.gz → 6.7.0__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.
Files changed (460) hide show
  1. {python_hwpx-6.5.0/src/python_hwpx.egg-info → python_hwpx-6.7.0}/PKG-INFO +12 -25
  2. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/README.md +11 -24
  3. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/pyproject.toml +88 -1
  4. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/__init__.py +14 -0
  5. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/_document/_legacy.py +5 -3
  6. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/_document/fields.py +337 -25
  7. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/_document/layout.py +351 -68
  8. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/_document/media.py +210 -38
  9. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/_document/memos.py +85 -20
  10. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/_document/ns/fields.py +64 -3
  11. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/_document/ns/media.py +37 -4
  12. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/_document/ns/notes.py +2 -2
  13. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/_document/ns/page.py +27 -4
  14. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/_document/ns/parts.py +102 -2
  15. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/_document/ns/shapes.py +102 -10
  16. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/_document/ns/styles.py +175 -8
  17. python_hwpx-6.7.0/src/hwpx/_document/ns/text.py +312 -0
  18. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/_document/ns/tracking.py +5 -1
  19. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/_document/persistence.py +78 -17
  20. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/_document/shapes.py +177 -8
  21. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/_document/tracked.py +49 -1
  22. python_hwpx-6.7.0/src/hwpx/_moved_modules.py +118 -0
  23. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/body_patch.py +6 -2
  24. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/capabilities.py +1 -1
  25. python_hwpx-6.7.0/src/hwpx/data/contract_docs/known-traps.md +127 -0
  26. python_hwpx-6.7.0/src/hwpx/data/contract_docs/mutation-semantics.md +116 -0
  27. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/data/contract_docs/support-matrix.md +12 -13
  28. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/document.py +107 -10
  29. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/equation/authoring.py +30 -25
  30. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/equation/eqedit.py +61 -4
  31. python_hwpx-6.7.0/src/hwpx/equation/measure.py +422 -0
  32. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/equation/tokens.py +14 -1
  33. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/errors.py +62 -3
  34. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/experimental.py +8 -0
  35. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/form_fit/__init__.py +4 -0
  36. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/form_fit/apply.py +8 -2
  37. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/form_fit/engine.py +25 -77
  38. python_hwpx-6.7.0/src/hwpx/form_fit/measure.py +1546 -0
  39. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/form_fit/policy.py +7 -1
  40. python_hwpx-6.7.0/src/hwpx/hwp5/__init__.py +7 -0
  41. python_hwpx-6.7.0/src/hwpx/hwp5/binary.py +124 -0
  42. python_hwpx-6.7.0/src/hwpx/hwp5/bodytext.py +201 -0
  43. python_hwpx-6.7.0/src/hwpx/hwp5/cfb.py +601 -0
  44. python_hwpx-6.7.0/src/hwpx/hwp5/controls.py +1175 -0
  45. python_hwpx-6.7.0/src/hwpx/hwp5/docinfo.py +881 -0
  46. python_hwpx-6.7.0/src/hwpx/hwp5/docinfo_writer.py +647 -0
  47. python_hwpx-6.7.0/src/hwpx/hwp5/errors.py +75 -0
  48. python_hwpx-6.7.0/src/hwpx/hwp5/fileheader.py +87 -0
  49. python_hwpx-6.7.0/src/hwpx/hwp5/header_xml.py +703 -0
  50. python_hwpx-6.7.0/src/hwpx/hwp5/owpml.py +390 -0
  51. python_hwpx-6.7.0/src/hwpx/hwp5/package.py +331 -0
  52. python_hwpx-6.7.0/src/hwpx/hwp5/reader.py +149 -0
  53. python_hwpx-6.7.0/src/hwpx/hwp5/records.py +214 -0
  54. python_hwpx-6.7.0/src/hwpx/hwp5/section_common.py +149 -0
  55. python_hwpx-6.7.0/src/hwpx/hwp5/section_writer.py +1826 -0
  56. python_hwpx-6.7.0/src/hwpx/hwp5/section_xml.py +1514 -0
  57. python_hwpx-6.7.0/src/hwpx/hwp5/shape_xml.py +709 -0
  58. python_hwpx-6.7.0/src/hwpx/hwp5/shapes.py +842 -0
  59. python_hwpx-6.7.0/src/hwpx/hwp5/summary.py +204 -0
  60. python_hwpx-6.7.0/src/hwpx/hwp5/writer.py +325 -0
  61. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/ingest/hwpx_converter.py +1 -1
  62. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/layout/__init__.py +2 -0
  63. python_hwpx-6.7.0/src/hwpx/layout/lint.py +737 -0
  64. python_hwpx-6.7.0/src/hwpx/layout/pages.py +2245 -0
  65. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/model.py +2 -0
  66. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/objects/__init__.py +13 -1
  67. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/objects/form_field.py +90 -3
  68. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/objects/results.py +131 -0
  69. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/opc/package.py +148 -16
  70. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/opc/relationships.py +88 -4
  71. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/opc/xml_utils.py +44 -15
  72. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/_document_primitives.py +76 -56
  73. python_hwpx-6.7.0/src/hwpx/oxml/_paragraph_text_edit.py +144 -0
  74. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/color.py +36 -1
  75. python_hwpx-6.7.0/src/hwpx/oxml/curves.py +231 -0
  76. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/document_parts.py +131 -160
  77. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/drop_cap.py +65 -15
  78. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/dutmal_compose.py +19 -10
  79. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/field_marks.py +38 -7
  80. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/header.py +45 -35
  81. python_hwpx-6.7.0/src/hwpx/oxml/header_fonts.py +322 -0
  82. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/header_part.py +43 -42
  83. python_hwpx-6.7.0/src/hwpx/oxml/hyperlink_form.py +159 -0
  84. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/master_page_authoring.py +130 -6
  85. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/memo.py +185 -11
  86. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/note_authoring.py +3 -4
  87. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/numbering_kinds.py +82 -2
  88. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/objects.py +112 -66
  89. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/paragraph.py +80 -90
  90. python_hwpx-6.7.0/src/hwpx/oxml/paragraph_heading.py +70 -0
  91. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/run.py +209 -44
  92. python_hwpx-6.7.0/src/hwpx/oxml/section.py +663 -0
  93. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/section_format.py +218 -13
  94. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/section_layout.py +87 -0
  95. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/section_story.py +266 -39
  96. python_hwpx-6.7.0/src/hwpx/oxml/shape_position.py +282 -0
  97. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/table.py +222 -87
  98. python_hwpx-6.7.0/src/hwpx/oxml/table_merge.py +82 -0
  99. python_hwpx-6.7.0/src/hwpx/oxml/table_sizes.py +420 -0
  100. python_hwpx-6.7.0/src/hwpx/oxml/utils.py +214 -0
  101. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/patch.py +16 -3
  102. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/quality/save_pipeline.py +4 -1
  103. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/table_patch.py +265 -81
  104. python_hwpx-6.7.0/src/hwpx/tools/_schemas/owpml-body.xsd +18 -0
  105. python_hwpx-6.7.0/src/hwpx/tools/_schemas/owpml-core.xsd +905 -0
  106. python_hwpx-6.7.0/src/hwpx/tools/_schemas/owpml-header.xsd +1869 -0
  107. python_hwpx-6.7.0/src/hwpx/tools/_schemas/owpml-paralist.xsd +2813 -0
  108. python_hwpx-6.7.0/src/hwpx/tools/_schemas/owpml-xml.xsd +15 -0
  109. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/document_merge.py +96 -16
  110. python_hwpx-6.7.0/src/hwpx/tools/exporter.py +783 -0
  111. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/id_integrity.py +22 -35
  112. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/layout_preview.py +49 -4
  113. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/mail_merge.py +19 -13
  114. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/markdown_export.py +37 -16
  115. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/package_validator.py +349 -26
  116. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/read_fidelity.py +4 -4
  117. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/redline.py +4 -4
  118. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/repair.py +38 -2
  119. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/table_navigation.py +3 -2
  120. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/template_analyzer.py +14 -7
  121. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/text_extractor.py +54 -24
  122. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/toc_author.py +118 -15
  123. python_hwpx-6.7.0/src/hwpx/tools/validator.py +486 -0
  124. {python_hwpx-6.5.0 → python_hwpx-6.7.0/src/python_hwpx.egg-info}/PKG-INFO +12 -25
  125. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/python_hwpx.egg-info/SOURCES.txt +117 -0
  126. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_add_control.py +17 -5
  127. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_add_heading.py +74 -8
  128. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_authoring_defaults.py +33 -14
  129. python_hwpx-6.7.0/tests/test_border_line_types.py +72 -0
  130. python_hwpx-6.7.0/tests/test_cell_border_neighbors.py +135 -0
  131. python_hwpx-6.7.0/tests/test_cell_fields.py +224 -0
  132. python_hwpx-6.7.0/tests/test_cell_margins.py +311 -0
  133. python_hwpx-6.7.0/tests/test_cell_text_rewrite_semantics.py +119 -0
  134. python_hwpx-6.7.0/tests/test_char_pr_child_order.py +64 -0
  135. python_hwpx-6.7.0/tests/test_character_width_ratio.py +35 -0
  136. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_chart_authoring.py +141 -0
  137. python_hwpx-6.7.0/tests/test_color_arguments.py +170 -0
  138. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_container_authoring.py +68 -29
  139. python_hwpx-6.7.0/tests/test_curve_connector_authoring.py +160 -0
  140. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_document_formatting.py +68 -15
  141. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_document_merge.py +172 -3
  142. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_documentation_code_fences.py +2 -2
  143. python_hwpx-6.7.0/tests/test_drop_cap_authoring.py +258 -0
  144. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_dutmal_compose_authoring.py +34 -5
  145. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_edit_fidelity_corpus.py +16 -5
  146. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_engine_surface_6_0.py +14 -0
  147. python_hwpx-6.7.0/tests/test_equalize_widths_per_row.py +297 -0
  148. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_equation_authoring.py +42 -2
  149. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_equation_converter.py +52 -0
  150. python_hwpx-6.7.0/tests/test_equation_measure_hancom_saved.py +97 -0
  151. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_equation_render.py +24 -0
  152. python_hwpx-6.7.0/tests/test_equation_size.py +107 -0
  153. python_hwpx-6.7.0/tests/test_error_messages.py +143 -0
  154. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_existing_document_format_editing.py +5 -3
  155. python_hwpx-6.7.0/tests/test_export_captions_dutmal.py +162 -0
  156. python_hwpx-6.7.0/tests/test_export_cell_text_spaces.py +29 -0
  157. python_hwpx-6.7.0/tests/test_export_list_labels.py +194 -0
  158. python_hwpx-6.7.0/tests/test_export_notes.py +202 -0
  159. python_hwpx-6.7.0/tests/test_export_text_boxes.py +157 -0
  160. python_hwpx-6.7.0/tests/test_exporter_table_text.py +164 -0
  161. python_hwpx-6.7.0/tests/test_field_type_ids.py +120 -0
  162. python_hwpx-6.7.0/tests/test_fill_image_hancom_modes.py +73 -0
  163. python_hwpx-6.7.0/tests/test_form_fields.py +372 -0
  164. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_form_fit.py +201 -18
  165. python_hwpx-6.7.0/tests/test_form_fit_hancom_rules.py +721 -0
  166. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_form_fit_integration.py +13 -0
  167. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_gap_closure_tools.py +36 -16
  168. python_hwpx-6.7.0/tests/test_header_control_before_field.py +78 -0
  169. python_hwpx-6.7.0/tests/test_heading_style_shapes.py +58 -0
  170. python_hwpx-6.7.0/tests/test_hwp5_container.py +255 -0
  171. python_hwpx-6.7.0/tests/test_hwp5_hancom_files.py +154 -0
  172. python_hwpx-6.7.0/tests/test_hwp5_open.py +1188 -0
  173. python_hwpx-6.7.0/tests/test_hwp5_save.py +1888 -0
  174. python_hwpx-6.7.0/tests/test_hyperlink_hancom_form.py +110 -0
  175. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_image_object_workflow.py +98 -0
  176. python_hwpx-6.7.0/tests/test_insert_row_merged_cells.py +130 -0
  177. python_hwpx-6.7.0/tests/test_instid_attribute_case.py +126 -0
  178. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_integration_hwpx_compatibility.py +1 -1
  179. python_hwpx-6.7.0/tests/test_internal_calls_skip_moved_names.py +77 -0
  180. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_layout_cache_scope.py +81 -0
  181. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_layout_lint.py +282 -3
  182. python_hwpx-6.7.0/tests/test_layout_page_estimate.py +758 -0
  183. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_layout_preview.py +3 -2
  184. python_hwpx-6.7.0/tests/test_line_width_arguments.py +94 -0
  185. python_hwpx-6.7.0/tests/test_list_continue.py +112 -0
  186. python_hwpx-6.7.0/tests/test_list_defaults_vs_hancom.py +80 -0
  187. python_hwpx-6.7.0/tests/test_manifest_resolve_once.py +52 -0
  188. python_hwpx-6.7.0/tests/test_markdown_export_shape_text.py +75 -0
  189. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_master_page_authoring.py +11 -0
  190. python_hwpx-6.7.0/tests/test_master_page_pages_taken.py +181 -0
  191. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_memo_and_style_editing.py +133 -1
  192. python_hwpx-6.7.0/tests/test_memo_fields.py +93 -0
  193. python_hwpx-6.7.0/tests/test_merge_cells_hancom_files.py +46 -0
  194. python_hwpx-6.7.0/tests/test_merge_cells_keeps_contents.py +180 -0
  195. python_hwpx-6.7.0/tests/test_moved_module_imports.py +105 -0
  196. python_hwpx-6.7.0/tests/test_namespace_normalization.py +109 -0
  197. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_native_edit_contract.py +6 -6
  198. python_hwpx-6.7.0/tests/test_ns_shapes.py +198 -0
  199. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_ns_tracking.py +7 -10
  200. python_hwpx-6.7.0/tests/test_number_formats.py +132 -0
  201. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_opc_package.py +7 -7
  202. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_oxml_modularization.py +7 -5
  203. python_hwpx-6.7.0/tests/test_package_hygiene.py +558 -0
  204. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_page_number_control.py +29 -0
  205. python_hwpx-6.7.0/tests/test_page_number_format.py +73 -0
  206. python_hwpx-6.7.0/tests/test_page_orientation.py +157 -0
  207. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_para_pr_dedup.py +3 -2
  208. python_hwpx-6.7.0/tests/test_paragraph_align_distribute_space.py +41 -0
  209. python_hwpx-6.7.0/tests/test_paragraph_border.py +168 -0
  210. python_hwpx-6.7.0/tests/test_paragraph_format_targets.py +218 -0
  211. python_hwpx-6.7.0/tests/test_paragraph_hyperlink_style.py +127 -0
  212. python_hwpx-6.7.0/tests/test_paragraph_margin_default_scale.py +89 -0
  213. python_hwpx-6.7.0/tests/test_paragraph_property_lookup.py +51 -0
  214. python_hwpx-6.7.0/tests/test_paragraph_remove_in_containers.py +133 -0
  215. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_polygon_authoring.py +17 -3
  216. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_product_boundary.py +20 -1
  217. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_public_artifact_hygiene.py +2 -0
  218. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_read_fidelity.py +48 -0
  219. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_recover_broken_zip.py +1 -1
  220. python_hwpx-6.7.0/tests/test_remove_unused_charts.py +104 -0
  221. python_hwpx-6.7.0/tests/test_remove_unused_images.py +84 -0
  222. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_repair_repack.py +4 -4
  223. python_hwpx-6.7.0/tests/test_replace_text_barriers.py +113 -0
  224. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_return_contract.py +2 -0
  225. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_run_choice_atom_authoring.py +6 -8
  226. python_hwpx-6.7.0/tests/test_run_content_kinds.py +117 -0
  227. python_hwpx-6.7.0/tests/test_run_font_refs.py +53 -0
  228. python_hwpx-6.7.0/tests/test_run_style_base.py +100 -0
  229. python_hwpx-6.7.0/tests/test_save_keeps_inline_text_caches.py +78 -0
  230. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_save_pipeline.py +16 -0
  231. python_hwpx-6.7.0/tests/test_save_verifies_once.py +62 -0
  232. python_hwpx-6.7.0/tests/test_section_clear_body.py +611 -0
  233. python_hwpx-6.7.0/tests/test_section_columns.py +157 -0
  234. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_section_headers.py +91 -0
  235. python_hwpx-6.7.0/tests/test_section_ids_order.py +136 -0
  236. python_hwpx-6.7.0/tests/test_set_column_widths_uniform_split.py +64 -0
  237. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_shape_geometry_contract.py +32 -1
  238. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_shape_open_safety_risk_check.py +41 -33
  239. python_hwpx-6.7.0/tests/test_shape_original_size.py +167 -0
  240. python_hwpx-6.7.0/tests/test_shape_position_frames.py +321 -0
  241. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_split_merged_cell.py +2 -2
  242. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_stable_surface.py +7 -5
  243. python_hwpx-6.7.0/tests/test_stale_layout_cache_sweep.py +174 -0
  244. python_hwpx-6.7.0/tests/test_story_edits_reach_control_copy.py +256 -0
  245. python_hwpx-6.7.0/tests/test_style_font_border_reads.py +779 -0
  246. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_style_resolution.py +53 -0
  247. python_hwpx-6.7.0/tests/test_tab_character_writing.py +103 -0
  248. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_tab_definition_version_switch.py +67 -26
  249. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_table_cell_equalize.py +8 -7
  250. python_hwpx-6.7.0/tests/test_table_page_flow.py +57 -0
  251. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_table_patch.py +1 -1
  252. python_hwpx-6.7.0/tests/test_table_patch_structure_fixes.py +224 -0
  253. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_template_analyzer_enrichment.py +1 -0
  254. python_hwpx-6.7.0/tests/test_text_box_fields.py +87 -0
  255. python_hwpx-6.7.0/tests/test_text_extractor_nested_once.py +107 -0
  256. python_hwpx-6.7.0/tests/test_text_inline_elements.py +180 -0
  257. python_hwpx-6.7.0/tests/test_text_replace_everywhere.py +211 -0
  258. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_toc_author.py +137 -8
  259. python_hwpx-6.7.0/tests/test_tracked_paragraph_delete_break.py +47 -0
  260. python_hwpx-6.7.0/tests/test_validator_form_parameters.py +96 -0
  261. python_hwpx-6.7.0/tests/test_validator_full_schema.py +152 -0
  262. python_hwpx-6.7.0/tests/test_validator_hancom_open_rules.py +313 -0
  263. python_hwpx-6.7.0/tests/test_validator_section_ids.py +141 -0
  264. python_hwpx-6.5.0/src/hwpx/_document/ns/text.py +0 -175
  265. python_hwpx-6.5.0/src/hwpx/data/contract_docs/known-traps.md +0 -68
  266. python_hwpx-6.5.0/src/hwpx/data/contract_docs/mutation-semantics.md +0 -65
  267. python_hwpx-6.5.0/src/hwpx/form_fit/measure.py +0 -596
  268. python_hwpx-6.5.0/src/hwpx/layout/lint.py +0 -391
  269. python_hwpx-6.5.0/src/hwpx/oxml/_paragraph_text_edit.py +0 -42
  270. python_hwpx-6.5.0/src/hwpx/oxml/section.py +0 -365
  271. python_hwpx-6.5.0/src/hwpx/oxml/utils.py +0 -94
  272. python_hwpx-6.5.0/src/hwpx/tools/exporter.py +0 -220
  273. python_hwpx-6.5.0/src/hwpx/tools/validator.py +0 -207
  274. python_hwpx-6.5.0/tests/test_drop_cap_authoring.py +0 -141
  275. python_hwpx-6.5.0/tests/test_error_messages.py +0 -57
  276. python_hwpx-6.5.0/tests/test_form_fields.py +0 -101
  277. python_hwpx-6.5.0/tests/test_instid_attribute_case.py +0 -100
  278. python_hwpx-6.5.0/tests/test_ns_shapes.py +0 -79
  279. python_hwpx-6.5.0/tests/test_table_page_flow.py +0 -18
  280. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/LICENSE +0 -0
  281. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/NOTICE +0 -0
  282. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/setup.cfg +0 -0
  283. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/_document/__init__.py +0 -0
  284. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/_document/_resolve.py +0 -0
  285. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/_document/_units.py +0 -0
  286. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/_document/headings.py +0 -0
  287. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/_document/highlight.py +0 -0
  288. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/_document/ns/__init__.py +0 -0
  289. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/_document/ns/_base.py +0 -0
  290. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/_document/ns/refs.py +0 -0
  291. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/_document/ns/tables.py +0 -0
  292. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/data/Skeleton.hwpx +0 -0
  293. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/data/contract_docs/recipes-traversal.md +0 -0
  294. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/equation/__init__.py +0 -0
  295. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/equation/mathml.py +0 -0
  296. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/equation/render.py +0 -0
  297. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/form_fit/report.py +0 -0
  298. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/ingest/__init__.py +0 -0
  299. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/ingest/base.py +0 -0
  300. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/layout/report.py +0 -0
  301. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/mutation_report.py +0 -0
  302. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/objects/binary_item.py +0 -0
  303. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/objects/checkbox.py +0 -0
  304. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/objects/highlight.py +0 -0
  305. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/objects/tracked.py +0 -0
  306. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/opc/security.py +0 -0
  307. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/__init__.py +0 -0
  308. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/_document_impl.py +0 -0
  309. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/body.py +0 -0
  310. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/canonical_defaults.py +0 -0
  311. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/common.py +0 -0
  312. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/document.py +0 -0
  313. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/document_metadata.py +0 -0
  314. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/header_compat.py +0 -0
  315. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/history_part.py +0 -0
  316. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/master_page.py +0 -0
  317. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/namespaces.py +0 -0
  318. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/numbering.py +0 -0
  319. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/parser.py +0 -0
  320. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/schema.py +0 -0
  321. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/settings.py +0 -0
  322. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/simple_parts.py +0 -0
  323. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/oxml/version_part.py +0 -0
  324. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/package.py +0 -0
  325. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/plan/__init__.py +0 -0
  326. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/plan/_execute.py +0 -0
  327. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/plan/_model.py +0 -0
  328. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/plan/_schema.py +0 -0
  329. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/plan/_validate.py +0 -0
  330. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/py.typed +0 -0
  331. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/quality/__init__.py +0 -0
  332. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/quality/ledger.py +0 -0
  333. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/quality/policy.py +0 -0
  334. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/quality/rendering.py +0 -0
  335. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/quality/report.py +0 -0
  336. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/templates.py +0 -0
  337. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/__init__.py +0 -0
  338. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/_schemas/header.xsd +0 -0
  339. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/_schemas/section.xsd +0 -0
  340. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/archive_cli.py +0 -0
  341. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/doc_diff.py +0 -0
  342. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/document_viewer.py +0 -0
  343. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/generic_inventory.py +0 -0
  344. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/idempotence.py +0 -0
  345. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/ir_equality.py +0 -0
  346. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/object_finder.py +0 -0
  347. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/package_reconcile.py +0 -0
  348. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/page_guard.py +0 -0
  349. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/recover.py +0 -0
  350. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/report_utils.py +0 -0
  351. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/roundtrip_diff.py +0 -0
  352. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/table_cleanup.py +0 -0
  353. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/text_extract_cli.py +0 -0
  354. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/hwpx/tools/toc_fidelity.py +0 -0
  355. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/python_hwpx.egg-info/dependency_links.txt +0 -0
  356. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/python_hwpx.egg-info/entry_points.txt +0 -0
  357. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/python_hwpx.egg-info/requires.txt +0 -0
  358. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/src/python_hwpx.egg-info/top_level.txt +0 -0
  359. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_adoption_metrics_snapshot.py +0 -0
  360. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_arc_authoring.py +0 -0
  361. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_authoring_quality_corpus.py +0 -0
  362. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_blind_eval_fixture.py +0 -0
  363. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_body_patch.py +0 -0
  364. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_border_fill_image_gradient.py +0 -0
  365. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_build_element_census.py +0 -0
  366. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_byte_patch_identity.py +0 -0
  367. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_capabilities_surface.py +0 -0
  368. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_cell_line_spacing.py +0 -0
  369. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_check_box_authoring.py +0 -0
  370. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_column_break.py +0 -0
  371. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_comment_node_robustness.py +0 -0
  372. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_contract_docs_sync.py +0 -0
  373. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_corpus_read_fidelity.py +0 -0
  374. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_coverage_ledger.py +0 -0
  375. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_coverage_promotion.py +0 -0
  376. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_coverage_targets.py +0 -0
  377. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_deviations_registry.py +0 -0
  378. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_doc_diff.py +0 -0
  379. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_document_context_manager.py +0 -0
  380. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_document_facade_surface.py +0 -0
  381. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_document_metadata.py +0 -0
  382. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_document_ops_runtime_boundary.py +0 -0
  383. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_document_save_api.py +0 -0
  384. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_document_viewer.py +0 -0
  385. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_edit_plan.py +0 -0
  386. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_editor_surface_inventory.py +0 -0
  387. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_error_contract.py +0 -0
  388. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_evalplan_core_primitives.py +0 -0
  389. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_field_marks.py +0 -0
  390. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_form_field_authoring.py +0 -0
  391. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_form_fill_core_primitives.py +0 -0
  392. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_fuzz_catalog_derive_expected.py +0 -0
  393. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_fuzz_loop.py +0 -0
  394. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_fuzz_regressions.py +0 -0
  395. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_golden_api.py +0 -0
  396. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_header_compat_authoring.py +0 -0
  397. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_highlight_authoring.py +0 -0
  398. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_hp_tab_support.py +0 -0
  399. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_hwpxlib_corpus_read.py +0 -0
  400. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_id_generator_range.py +0 -0
  401. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_id_integrity.py +0 -0
  402. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_index_mark.py +0 -0
  403. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_ingest.py +0 -0
  404. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_inline_models.py +0 -0
  405. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_integration_roundtrip.py +0 -0
  406. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_library_boundary_closure.py +0 -0
  407. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_llms_txt.py +0 -0
  408. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_mail_merge_xlsx.py +0 -0
  409. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_markdown_export.py +0 -0
  410. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_memo_shape_authoring.py +0 -0
  411. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_moved_surface_hints.py +0 -0
  412. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_mutation_report.py +0 -0
  413. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_namespace_handling.py +0 -0
  414. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_namespace_hygiene.py +0 -0
  415. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_new_features.py +0 -0
  416. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_note_authoring_contract.py +0 -0
  417. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_ns_fields.py +0 -0
  418. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_ns_media.py +0 -0
  419. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_ns_notes.py +0 -0
  420. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_ns_page.py +0 -0
  421. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_ns_refs.py +0 -0
  422. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_ns_tables.py +0 -0
  423. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_open_safety_corpus.py +0 -0
  424. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_outline_numbering.py +0 -0
  425. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_oxml_parsing.py +0 -0
  426. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_packaging_license_metadata.py +0 -0
  427. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_packaging_py_typed.py +0 -0
  428. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_paragraph_keep_together.py +0 -0
  429. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_paragraph_property_version_switch.py +0 -0
  430. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_paragraph_section_management.py +0 -0
  431. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_part_hierarchy_read_models.py +0 -0
  432. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_public_runtime_boundary.py +0 -0
  433. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_redline_authoring.py +0 -0
  434. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_redline_verify.py +0 -0
  435. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_release_workflow_safety.py +0 -0
  436. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_report_utils.py +0 -0
  437. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_repr_snapshots.py +0 -0
  438. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_roundtrip_fidelity.py +0 -0
  439. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_roundtrip_fidelity_corpus.py +0 -0
  440. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_row_heights.py +0 -0
  441. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_safe_edit_example.py +0 -0
  442. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_section_properties_real_roundtrip.py +0 -0
  443. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_set_paragraph_format_keep.py +0 -0
  444. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_skeleton_template_ids.py +0 -0
  445. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_split_cell.py +0 -0
  446. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_table_cleanup.py +0 -0
  447. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_table_label.py +0 -0
  448. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_table_navigation.py +0 -0
  449. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_table_patch_dryrun.py +0 -0
  450. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_table_patch_m105.py +0 -0
  451. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_table_split_merge.py +0 -0
  452. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_tables_default_border.py +0 -0
  453. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_text_extractor_annotations.py +0 -0
  454. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_text_extractor_run_choice_atoms.py +0 -0
  455. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_title_mark.py +0 -0
  456. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_toc_fidelity.py +0 -0
  457. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_tracked_overlap_render_smoke.py +0 -0
  458. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_validation_severity.py +0 -0
  459. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_validator_comment_nodes.py +0 -0
  460. {python_hwpx-6.5.0 → python_hwpx-6.7.0}/tests/test_version_metadata.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-hwpx
3
- Version: 6.5.0
3
+ Version: 6.7.0
4
4
  Summary: 한글 없이 HWPX 문서를 열고, 편집하고, 생성하고, 검증하는 Python 문서 라이브러리
5
5
  Author: python-hwpx Maintainers
6
6
  License-Expression: Apache-2.0
@@ -68,7 +68,7 @@ Dynamic: license-file
68
68
 
69
69
  한컴오피스가 없어도 됩니다. HWPX는 ZIP+XML(OWPML) 포맷이라 순수 파이썬만으로
70
70
  읽고, 고치고, 새로 만들 수 있습니다 — Windows·macOS·Linux·CI, 그리고
71
- **파이썬이 도는 ChatGPT 채팅 안에서도** 그대로 동작합니다. 기존 문서의 저장은 요청한 보존 등급과 실제 검증 결과를 영수증으로 남깁니다.
71
+ **파이썬이 도는 ChatGPT 채팅 안에서도** 그대로 동작합니다.
72
72
  새 문서의 한컴 호환성은 아래에 날짜·버전을 명시한 코퍼스로 측정합니다.
73
73
 
74
74
  <p align="center">
@@ -109,7 +109,7 @@ from hwpx import HwpxDocument
109
109
 
110
110
  doc = HwpxDocument.new()
111
111
  doc.add_heading("2026 운영계획", level=1)
112
- doc.add_paragraph("가. 추진 배경", style="개요 2")
112
+ doc.add_paragraph("추진 배경", style="개요 2") # 한/글이 "가." 번호를 붙인다
113
113
  doc.save_to_path("계획.hwpx")
114
114
  ```
115
115
 
@@ -130,7 +130,7 @@ doc.save_to_path("계획.hwpx")
130
130
  - **편집** — 문단·표·이미지·머리글/바닥글·메모·각주, 줄간격·여백·쪽번호 같은 서식
131
131
  - **양식 채우기** — 라벨로 셀을 찾아 값만 채우기, 행·열 조정 같은 구조 편집도 바이트 보존으로
132
132
  - **생성·일괄 처리** — 새 문서 저작, 목차·상호참조, mail merge, 텍스트 diff, 변경추적(redline)
133
- - **검증·안전** — 패키지 구조 검증 CLI, 열림 안전 게이트, 모든 저장에 영수증(`MutationReport`)
133
+ - **검증·안전** — 패키지 구조 검증 CLI, 열림 안전 게이트, 저장 결과 보고(`return_report=True`)
134
134
 
135
135
  자세한 내용: [5분 퀵스타트](docs/quickstart.md) · [사용 가이드](docs/usage.md) · [API 레퍼런스](https://airmang.github.io/python-hwpx/) · [예제](docs/examples.md)
136
136
 
@@ -152,20 +152,6 @@ report = doc.save_to_path("신청서-작성완료.hwpx", mode="patch", fallback=
152
152
  바이트 보존을 요구합니다. 수정 파트 내부의 보존과 시각적 배치는 별도 확인이
153
153
  필요합니다. 출력 재개봉과 내용 확인까지 포함한 경로는 [안전한 쓰기 계약](docs/safe-write-contract.md)을 따르세요.
154
154
 
155
- ### 저장에는 영수증이 따라옵니다
156
-
157
- ```python
158
- report = doc.save_to_path("결과.hwpx", return_report=True)
159
- print(report.actual_mode) # "patch" 또는 "rebuild" — 실제 저장 등급
160
- print(report.preservation.untouched_part_payloads.to_dict())
161
- # {"verified": 17, "changed": 0}
162
- ```
163
-
164
- `mode="patch", fallback="error"`는 보존 등급 미달 시 출력하지 않습니다.
165
- 기본 `auto`는 달성 가능한 등급을 선택합니다. `report.ok`는 요청 반영이나 시각
166
- 검증 완료를 뜻하지 않습니다.
167
- 전체 규칙: [안전한 쓰기 계약](docs/safe-write-contract.md).
168
-
169
155
  *예제 중 **독립 실행 예제** 표시가 없는 블록은 여러분의 기존 문서를 입력으로
170
156
  쓰는 조각입니다. 예제별 Python 블록 판정은
171
157
  [실행 ledger](docs/python-example-ledger.json)에 동결돼 있습니다.*
@@ -175,10 +161,9 @@ print(report.preservation.untouched_part_payloads.to_dict())
175
161
  만든 파일이 실제 한컴오피스에서 열리는지 재서 그대로 공개합니다. 측정마다
176
162
  스택과 날짜를 병기합니다:
177
163
 
178
- - **한컴 열림 120/120 · 렌더 검증 120/120** — 현행 스택(5.7.0 · 실한컴
179
- 12.0.0.3288 · 2026-08-03)의 축소 측정: 기준 스트라텀 + 신규 저작 표면
180
- 6종(각주·누름틀·수식·차트·체크박스·편집 계획). 영수증은 행마다 bucket이
181
- 있어 `jq` 한 줄로 재현됩니다
164
+ - **한컴 열림 120/120 · 렌더 검증 120/120** — 기준 문서군 + 저작 기능
165
+ 6종(각주·누름틀·수식·차트·체크박스·편집 계획) 축소 측정
166
+ (5.7.0 · 실한컴 12.0.0.3288 · 2026-08-03)
182
167
  - **한컴 열림 476/476** — 전수 동결 코퍼스(N=497) 측정
183
168
  (3.4.1 · 실한컴 12.0.0.3288 · 2026-07-19)
184
169
  - **미수정 영역 바이트 보존 497/497** · 개인정보 유출 0
@@ -218,13 +203,15 @@ GitHub Release에 첨부되는 `py3-none-any` wheel을 문서와 함께 올리
218
203
 
219
204
  | | python-hwpx | pyhwpx | pyhwp |
220
205
  |---|---|---|---|
221
- | **대상 포맷** | `.hwpx` (OWPML/OPC) | `.hwpx` | `.hwp` (v5 바이너리) |
206
+ | **대상 포맷** | `.hwpx` (OWPML/OPC), `.hwp` (HWP 5.0) | `.hwpx` | `.hwp` (v5 바이너리) |
222
207
  | **한/글 설치** | 불필요 | 필요 (Windows COM) | 불필요 |
223
208
  | **크로스 플랫폼** | ✅ Linux / macOS / Windows / CI | ❌ Windows 전용 | ✅ |
224
209
  | **편집/생성 API** | ✅ | ✅ (COM) | ❌ 대부분 읽기 |
225
210
  | **AI 에이전트 연동 (MCP)** | ✅ companion 경유 | ❌ | ❌ |
226
211
 
227
- > HWP(v5 바이너리)는 지원하지 않습니다. 한컴오피스에서 HWPX로 변환 후 사용하세요.
212
+ > HWP 5.0(`.hwp`)은 `HwpxDocument.open`으로 열어 같은 API로 편집하고,
213
+ > `save_to_path("x.hwp")`로 HWP로 저장합니다. 옮기지 못한 내용은
214
+ > `document.conversion_report`에 남고, 암호·배포용 문서는 `Hwp5Error`로 거부합니다.
228
215
 
229
216
  ## 알려진 제약
230
217
 
@@ -232,7 +219,7 @@ GitHub Release에 첨부되는 `py3-none-any` wheel을 문서와 함께 올리
232
219
  열지 못하는 파일이 됩니다(호출 시 경고만 나옵니다). 도형은 `add_line()` /
233
220
  `add_rectangle()` / `add_ellipse()`를 쓰세요.
234
221
  - 그림은 단순 개체 생성까지 지원합니다 (그룹·효과 미지원).
235
- - 암호화된 HWPX는 지원하지 않습니다.
222
+ - 암호화된 HWPX와 암호·배포용 HWP는 지원하지 않습니다.
236
223
 
237
224
  ## 기여하기
238
225
 
@@ -17,7 +17,7 @@
17
17
 
18
18
  한컴오피스가 없어도 됩니다. HWPX는 ZIP+XML(OWPML) 포맷이라 순수 파이썬만으로
19
19
  읽고, 고치고, 새로 만들 수 있습니다 — Windows·macOS·Linux·CI, 그리고
20
- **파이썬이 도는 ChatGPT 채팅 안에서도** 그대로 동작합니다. 기존 문서의 저장은 요청한 보존 등급과 실제 검증 결과를 영수증으로 남깁니다.
20
+ **파이썬이 도는 ChatGPT 채팅 안에서도** 그대로 동작합니다.
21
21
  새 문서의 한컴 호환성은 아래에 날짜·버전을 명시한 코퍼스로 측정합니다.
22
22
 
23
23
  <p align="center">
@@ -58,7 +58,7 @@ from hwpx import HwpxDocument
58
58
 
59
59
  doc = HwpxDocument.new()
60
60
  doc.add_heading("2026 운영계획", level=1)
61
- doc.add_paragraph("가. 추진 배경", style="개요 2")
61
+ doc.add_paragraph("추진 배경", style="개요 2") # 한/글이 "가." 번호를 붙인다
62
62
  doc.save_to_path("계획.hwpx")
63
63
  ```
64
64
 
@@ -79,7 +79,7 @@ doc.save_to_path("계획.hwpx")
79
79
  - **편집** — 문단·표·이미지·머리글/바닥글·메모·각주, 줄간격·여백·쪽번호 같은 서식
80
80
  - **양식 채우기** — 라벨로 셀을 찾아 값만 채우기, 행·열 조정 같은 구조 편집도 바이트 보존으로
81
81
  - **생성·일괄 처리** — 새 문서 저작, 목차·상호참조, mail merge, 텍스트 diff, 변경추적(redline)
82
- - **검증·안전** — 패키지 구조 검증 CLI, 열림 안전 게이트, 모든 저장에 영수증(`MutationReport`)
82
+ - **검증·안전** — 패키지 구조 검증 CLI, 열림 안전 게이트, 저장 결과 보고(`return_report=True`)
83
83
 
84
84
  자세한 내용: [5분 퀵스타트](docs/quickstart.md) · [사용 가이드](docs/usage.md) · [API 레퍼런스](https://airmang.github.io/python-hwpx/) · [예제](docs/examples.md)
85
85
 
@@ -101,20 +101,6 @@ report = doc.save_to_path("신청서-작성완료.hwpx", mode="patch", fallback=
101
101
  바이트 보존을 요구합니다. 수정 파트 내부의 보존과 시각적 배치는 별도 확인이
102
102
  필요합니다. 출력 재개봉과 내용 확인까지 포함한 경로는 [안전한 쓰기 계약](docs/safe-write-contract.md)을 따르세요.
103
103
 
104
- ### 저장에는 영수증이 따라옵니다
105
-
106
- ```python
107
- report = doc.save_to_path("결과.hwpx", return_report=True)
108
- print(report.actual_mode) # "patch" 또는 "rebuild" — 실제 저장 등급
109
- print(report.preservation.untouched_part_payloads.to_dict())
110
- # {"verified": 17, "changed": 0}
111
- ```
112
-
113
- `mode="patch", fallback="error"`는 보존 등급 미달 시 출력하지 않습니다.
114
- 기본 `auto`는 달성 가능한 등급을 선택합니다. `report.ok`는 요청 반영이나 시각
115
- 검증 완료를 뜻하지 않습니다.
116
- 전체 규칙: [안전한 쓰기 계약](docs/safe-write-contract.md).
117
-
118
104
  *예제 중 **독립 실행 예제** 표시가 없는 블록은 여러분의 기존 문서를 입력으로
119
105
  쓰는 조각입니다. 예제별 Python 블록 판정은
120
106
  [실행 ledger](docs/python-example-ledger.json)에 동결돼 있습니다.*
@@ -124,10 +110,9 @@ print(report.preservation.untouched_part_payloads.to_dict())
124
110
  만든 파일이 실제 한컴오피스에서 열리는지 재서 그대로 공개합니다. 측정마다
125
111
  스택과 날짜를 병기합니다:
126
112
 
127
- - **한컴 열림 120/120 · 렌더 검증 120/120** — 현행 스택(5.7.0 · 실한컴
128
- 12.0.0.3288 · 2026-08-03)의 축소 측정: 기준 스트라텀 + 신규 저작 표면
129
- 6종(각주·누름틀·수식·차트·체크박스·편집 계획). 영수증은 행마다 bucket이
130
- 있어 `jq` 한 줄로 재현됩니다
113
+ - **한컴 열림 120/120 · 렌더 검증 120/120** — 기준 문서군 + 저작 기능
114
+ 6종(각주·누름틀·수식·차트·체크박스·편집 계획) 축소 측정
115
+ (5.7.0 · 실한컴 12.0.0.3288 · 2026-08-03)
131
116
  - **한컴 열림 476/476** — 전수 동결 코퍼스(N=497) 측정
132
117
  (3.4.1 · 실한컴 12.0.0.3288 · 2026-07-19)
133
118
  - **미수정 영역 바이트 보존 497/497** · 개인정보 유출 0
@@ -167,13 +152,15 @@ GitHub Release에 첨부되는 `py3-none-any` wheel을 문서와 함께 올리
167
152
 
168
153
  | | python-hwpx | pyhwpx | pyhwp |
169
154
  |---|---|---|---|
170
- | **대상 포맷** | `.hwpx` (OWPML/OPC) | `.hwpx` | `.hwp` (v5 바이너리) |
155
+ | **대상 포맷** | `.hwpx` (OWPML/OPC), `.hwp` (HWP 5.0) | `.hwpx` | `.hwp` (v5 바이너리) |
171
156
  | **한/글 설치** | 불필요 | 필요 (Windows COM) | 불필요 |
172
157
  | **크로스 플랫폼** | ✅ Linux / macOS / Windows / CI | ❌ Windows 전용 | ✅ |
173
158
  | **편집/생성 API** | ✅ | ✅ (COM) | ❌ 대부분 읽기 |
174
159
  | **AI 에이전트 연동 (MCP)** | ✅ companion 경유 | ❌ | ❌ |
175
160
 
176
- > HWP(v5 바이너리)는 지원하지 않습니다. 한컴오피스에서 HWPX로 변환 후 사용하세요.
161
+ > HWP 5.0(`.hwp`)은 `HwpxDocument.open`으로 열어 같은 API로 편집하고,
162
+ > `save_to_path("x.hwp")`로 HWP로 저장합니다. 옮기지 못한 내용은
163
+ > `document.conversion_report`에 남고, 암호·배포용 문서는 `Hwp5Error`로 거부합니다.
177
164
 
178
165
  ## 알려진 제약
179
166
 
@@ -181,7 +168,7 @@ GitHub Release에 첨부되는 `py3-none-any` wheel을 문서와 함께 올리
181
168
  열지 못하는 파일이 됩니다(호출 시 경고만 나옵니다). 도형은 `add_line()` /
182
169
  `add_rectangle()` / `add_ellipse()`를 쓰세요.
183
170
  - 그림은 단순 개체 생성까지 지원합니다 (그룹·효과 미지원).
184
- - 암호화된 HWPX는 지원하지 않습니다.
171
+ - 암호화된 HWPX와 암호·배포용 HWP는 지원하지 않습니다.
185
172
 
186
173
  ## 기여하기
187
174
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "python-hwpx"
7
- version = "6.5.0"
7
+ version = "6.7.0"
8
8
  description = "한글 없이 HWPX 문서를 열고, 편집하고, 생성하고, 검증하는 Python 문서 라이브러리"
9
9
  readme = { file = "README.md", content-type = "text/markdown" }
10
10
  license = "Apache-2.0"
@@ -109,6 +109,9 @@ packages = [
109
109
  "hwpx.data",
110
110
  "hwpx.equation",
111
111
  "hwpx.form_fit",
112
+ # HWP 5.0(.hwp) 읽기·쓰기. `hwpx/__init__.py`가 이 패키지를 가져오므로 빠지면
113
+ # 휠에서 `import hwpx`가 깨진다.
114
+ "hwpx.hwp5",
112
115
  "hwpx.ingest",
113
116
  "hwpx.layout",
114
117
  # 6.0: add_* 가 반환하는 도메인 객체·결과 dataclass (WP-C가 채운다).
@@ -283,6 +286,48 @@ files = [
283
286
  # headroom -- same escape valve as dutmal_compose.py/objects.py/
284
287
  # field_marks.py above, per the WP-A rule.
285
288
  "src/hwpx/oxml/note_authoring.py",
289
+ # Grid clean-up after a cell merge (rows left without cells, columns no
290
+ # cell starts at) moved out of table.py -- born in the gate, per the WP-A rule.
291
+ "src/hwpx/oxml/table_merge.py",
292
+ # Hyperlink field target form (Hancom's Command/Path parameters,
293
+ # written and read in one place) -- born in the gate, per the WP-A rule.
294
+ "src/hwpx/oxml/hyperlink_form.py",
295
+ # Table width/height distribution (distribute cell width row by row) moved out
296
+ # of table.py -- born in the gate, per the WP-A rule.
297
+ "src/hwpx/oxml/table_sizes.py",
298
+ # A paragraph shape's heading (outline levels 8 to 10 in Hancom's hp:switch form),
299
+ # written and read in one place -- born in the gate, per the WP-A rule.
300
+ "src/hwpx/oxml/paragraph_heading.py",
301
+ # Floating-shape reference frames (set_position) and shape-text
302
+ # vertical alignment -- objects.py's overflow module (1600-line cap),
303
+ # born in the gate, per the WP-A rule.
304
+ "src/hwpx/oxml/shape_position.py",
305
+ # Font table and border-fill reads plus replace_font (header.xml) --
306
+ # born in the gate, per the WP-A rule.
307
+ "src/hwpx/oxml/header_fonts.py",
308
+ # HWP 5.0 (.hwp) container and record layer -- born in the gate, per the
309
+ # WP-A rule.
310
+ "src/hwpx/hwp5/__init__.py",
311
+ "src/hwpx/hwp5/bodytext.py",
312
+ "src/hwpx/hwp5/cfb.py",
313
+ "src/hwpx/hwp5/docinfo.py",
314
+ "src/hwpx/hwp5/errors.py",
315
+ "src/hwpx/hwp5/fileheader.py",
316
+ "src/hwpx/hwp5/reader.py",
317
+ "src/hwpx/hwp5/records.py",
318
+ "src/hwpx/hwp5/binary.py",
319
+ "src/hwpx/hwp5/header_xml.py",
320
+ "src/hwpx/hwp5/owpml.py",
321
+ "src/hwpx/hwp5/package.py",
322
+ "src/hwpx/hwp5/section_xml.py",
323
+ "src/hwpx/hwp5/summary.py",
324
+ "src/hwpx/hwp5/controls.py",
325
+ "src/hwpx/hwp5/docinfo_writer.py",
326
+ "src/hwpx/hwp5/section_writer.py",
327
+ "src/hwpx/hwp5/shapes.py",
328
+ "src/hwpx/hwp5/section_common.py",
329
+ "src/hwpx/hwp5/shape_xml.py",
330
+ "src/hwpx/hwp5/writer.py",
286
331
  ]
287
332
  # 칩 후보 1 ✅ 6.14 트레인㊾-1에서 해소: `src/hwpx/table_patch.py`(2073줄,
288
333
  # 6.12 트레인㊸ 갭⑤ 정리 시 team-lead가 지목, f7e4e67 리뷰) — 위 files
@@ -450,6 +495,48 @@ include = [
450
495
  # headroom -- same escape valve as dutmal_compose.py/objects.py/
451
496
  # field_marks.py above, per the WP-A rule.
452
497
  "src/hwpx/oxml/note_authoring.py",
498
+ # Grid clean-up after a cell merge (rows left without cells, columns no
499
+ # cell starts at) moved out of table.py -- born in the gate, per the WP-A rule.
500
+ "src/hwpx/oxml/table_merge.py",
501
+ # Hyperlink field target form (Hancom's Command/Path parameters,
502
+ # written and read in one place) -- born in the gate, per the WP-A rule.
503
+ "src/hwpx/oxml/hyperlink_form.py",
504
+ # Table width/height distribution (distribute cell width row by row) moved out
505
+ # of table.py -- born in the gate, per the WP-A rule.
506
+ "src/hwpx/oxml/table_sizes.py",
507
+ # A paragraph shape's heading (outline levels 8 to 10 in Hancom's hp:switch form),
508
+ # written and read in one place -- born in the gate, per the WP-A rule.
509
+ "src/hwpx/oxml/paragraph_heading.py",
510
+ # Floating-shape reference frames (set_position) and shape-text
511
+ # vertical alignment -- objects.py's overflow module (1600-line cap),
512
+ # born in the gate, per the WP-A rule.
513
+ "src/hwpx/oxml/shape_position.py",
514
+ # Font table and border-fill reads plus replace_font (header.xml) --
515
+ # born in the gate, per the WP-A rule.
516
+ "src/hwpx/oxml/header_fonts.py",
517
+ # HWP 5.0 (.hwp) container and record layer -- born in the gate, per the
518
+ # WP-A rule.
519
+ "src/hwpx/hwp5/__init__.py",
520
+ "src/hwpx/hwp5/bodytext.py",
521
+ "src/hwpx/hwp5/cfb.py",
522
+ "src/hwpx/hwp5/docinfo.py",
523
+ "src/hwpx/hwp5/errors.py",
524
+ "src/hwpx/hwp5/fileheader.py",
525
+ "src/hwpx/hwp5/reader.py",
526
+ "src/hwpx/hwp5/records.py",
527
+ "src/hwpx/hwp5/binary.py",
528
+ "src/hwpx/hwp5/header_xml.py",
529
+ "src/hwpx/hwp5/owpml.py",
530
+ "src/hwpx/hwp5/package.py",
531
+ "src/hwpx/hwp5/section_xml.py",
532
+ "src/hwpx/hwp5/summary.py",
533
+ "src/hwpx/hwp5/controls.py",
534
+ "src/hwpx/hwp5/docinfo_writer.py",
535
+ "src/hwpx/hwp5/section_writer.py",
536
+ "src/hwpx/hwp5/shapes.py",
537
+ "src/hwpx/hwp5/section_common.py",
538
+ "src/hwpx/hwp5/shape_xml.py",
539
+ "src/hwpx/hwp5/writer.py",
453
540
  ]
454
541
  pythonVersion = "3.10"
455
542
  typeCheckingMode = "basic"
@@ -45,6 +45,10 @@ _EXPERIMENTAL_EXPORTS = {
45
45
  "LayoutPreview": "hwpx.tools.layout_preview",
46
46
  "PreviewPage": "hwpx.tools.layout_preview",
47
47
  "render_layout_preview": "hwpx.tools.layout_preview",
48
+ # 쪽 수 추정(한/글 없이, 줄마다 쪽·단·세로 위치). 계약 유동.
49
+ "EstimatedLine": "hwpx.layout.pages",
50
+ "PageEstimate": "hwpx.layout.pages",
51
+ "estimate_pages": "hwpx.layout.pages",
48
52
  # 문서 프리뷰 뷰어(3.8.0 신규). 계약 유동.
49
53
  "DocumentViewer": "hwpx.tools.document_viewer",
50
54
  "render_document_viewer": "hwpx.tools.document_viewer",
@@ -347,6 +351,13 @@ def __dir__() -> list[str]:
347
351
  )
348
352
 
349
353
 
354
+ # ``import hwpx.builder`` goes through the import system, not ``__getattr__``,
355
+ # so the moved module names get their destination from a finder instead.
356
+ from . import _moved_modules
357
+
358
+ _moved_modules.install(_MOVED_TO_COMPANION)
359
+
360
+
350
361
  # --- stable 최상위 표면 (eager import) ------------------------------------------
351
362
  from .tools.text_extractor import (
352
363
  DEFAULT_NAMESPACES,
@@ -376,6 +387,7 @@ from .tools.package_validator import (
376
387
  )
377
388
  from .ingest import HwpxMarkdownConverter
378
389
  from .errors import HwpxError
390
+ from .hwp5.errors import Hwp5ConversionWarning, Hwp5Error
379
391
  from .mutation_report import (
380
392
  MutationReport,
381
393
  PreservationDowngradeError,
@@ -415,6 +427,8 @@ __all__ = [
415
427
  "PackageValidationReport",
416
428
  "BytePreservingPatchResult",
417
429
  "HwpxError",
430
+ "Hwp5Error",
431
+ "Hwp5ConversionWarning",
418
432
  "MutationReport",
419
433
  "PreservationDowngradeError",
420
434
  "ParagraphTextPatch",
@@ -615,7 +615,7 @@ class _LegacyFacade:
615
615
  field_id: str | None = None,
616
616
  author: str | None = None,
617
617
  created: datetime | str | None = None,
618
- number: int = 1,
618
+ number: int | None = None,
619
619
  anchor_char_pr_id_ref: str | int | None = None,
620
620
  ) -> tuple[HwpxOxmlMemo, HwpxOxmlParagraph, str]:
621
621
  """Create a memo and ensure it is visible by anchoring a MEMO field."""
@@ -801,7 +801,7 @@ class _LegacyFacade:
801
801
  field_id: str | None = None,
802
802
  author: str | None = None,
803
803
  created: datetime | str | None = None,
804
- number: int = 1,
804
+ number: int | None = None,
805
805
  char_pr_id_ref: str | int | None = None,
806
806
  ) -> str:
807
807
  """Attach a MEMO field control to *paragraph* so Hangul shows *memo*."""
@@ -1241,7 +1241,9 @@ class _LegacyFacade:
1241
1241
  """Remove an embedded image by its manifest item id.
1242
1242
 
1243
1243
  This removes the binary data from the ZIP, the manifest entry, and
1244
- the header binItem entry.
1244
+ the header binItem entry. An item the document still points at is
1245
+ refused with ``HwpxValueError`` (code ``media-item-in-use``);
1246
+ ``doc.media.remove_image(item_id, force=True)`` removes it anyway.
1245
1247
 
1246
1248
  Returns:
1247
1249
  ``True`` if any component was removed.