athena-python-docx 0.14.0__tar.gz → 0.15.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 (349) hide show
  1. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/CLAUDE.md +23 -1
  2. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/PKG-INFO +1 -1
  3. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/__init__.py +3 -1
  4. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/_buffer.py +53 -7
  5. athena_python_docx-0.15.0/docx/_execution.py +64 -0
  6. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/_http.py +19 -8
  7. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/client.py +24 -4
  8. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/document.py +83 -0
  9. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/errors.py +13 -0
  10. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/table.py +67 -10
  11. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/pyproject.toml +1 -1
  12. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_athena_extensions_registry.py +1 -0
  13. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_buffer.py +57 -2
  14. athena_python_docx-0.15.0/tests/test_cell_text_replace_semantics.py +116 -0
  15. athena_python_docx-0.15.0/tests/test_document_clear.py +132 -0
  16. athena_python_docx-0.15.0/tests/test_execution_scope.py +26 -0
  17. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/uv.lock +1 -1
  18. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/.gitignore +0 -0
  19. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/README.md +0 -0
  20. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/_athena_extension.py +0 -0
  21. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/_batching.py +0 -0
  22. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/_http_doc.py +0 -0
  23. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/_image_utils.py +0 -0
  24. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/_postproc.py +0 -0
  25. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/_ptc.py +0 -0
  26. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/_table_styles.py +0 -0
  27. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/api.py +0 -0
  28. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/bookmarks.py +0 -0
  29. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/charts.py +0 -0
  30. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/commands.py +0 -0
  31. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/comments.py +0 -0
  32. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/enum/__init__.py +0 -0
  33. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/enum/section.py +0 -0
  34. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/enum/style.py +0 -0
  35. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/enum/table.py +0 -0
  36. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/enum/text.py +0 -0
  37. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/exceptions.py +0 -0
  38. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/fields.py +0 -0
  39. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/footnotes.py +0 -0
  40. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/math.py +0 -0
  41. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/opc/__init__.py +0 -0
  42. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/opc/coreprops.py +0 -0
  43. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/oxml/__init__.py +0 -0
  44. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/revisions.py +0 -0
  45. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/sdt.py +0 -0
  46. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/section.py +0 -0
  47. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/session.py +0 -0
  48. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/settings.py +0 -0
  49. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/shape.py +0 -0
  50. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/shared.py +0 -0
  51. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/styles/__init__.py +0 -0
  52. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/styles/style.py +0 -0
  53. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/styles/styles.py +0 -0
  54. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/text/__init__.py +0 -0
  55. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/text/font.py +0 -0
  56. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/text/hyperlink.py +0 -0
  57. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/text/pagebreak.py +0 -0
  58. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/text/paragraph.py +0 -0
  59. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/text/parfmt.py +0 -0
  60. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/text/run.py +0 -0
  61. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/text/tabstops.py +0 -0
  62. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/toc.py +0 -0
  63. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/docx/typing.py +0 -0
  64. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/scripts/publish.sh +0 -0
  65. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/scripts/release.sh +0 -0
  66. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/scripts/round_trip_smoke.py +0 -0
  67. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/scripts/smoke_test_block_not_found.py +0 -0
  68. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/__init__.py +0 -0
  69. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/conftest.py +0 -0
  70. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/METHODOLOGY.md +0 -0
  71. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/README.md +0 -0
  72. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/__init__.py +0 -0
  73. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/ab_probe_cases.py +0 -0
  74. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/ab_probe_runner.py +0 -0
  75. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/auto_gen_cases.py +0 -0
  76. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/binary_round_trip.py +0 -0
  77. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/cases.py +0 -0
  78. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/complex_cases.py +0 -0
  79. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/coverage_report.py +0 -0
  80. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/extract.py +0 -0
  81. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/extreme_cases.py +0 -0
  82. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/fake_session.py +0 -0
  83. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/firm_templates/README.md +0 -0
  84. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/firm_templates/__init__.py +0 -0
  85. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/firm_templates/_runner.py +0 -0
  86. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/firm_templates/extractor.py +0 -0
  87. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/firm_templates/test_pw_corpus.py +0 -0
  88. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/firm_templates/test_pw_research_digest.py +0 -0
  89. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/local_runner.py +0 -0
  90. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/mega_cases.py +0 -0
  91. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshot.py +0 -0
  92. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/01_basic_paragraph.json +0 -0
  93. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/02_multiple_headings.json +0 -0
  94. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/03_runs_with_formatting.json +0 -0
  95. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/04_font_name_and_size.json +0 -0
  96. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/05_font_color_rgb.json +0 -0
  97. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/06_font_character_properties.json +0 -0
  98. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/07_font_subscript_superscript.json +0 -0
  99. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/08_font_highlight.json +0 -0
  100. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/09_paragraph_alignment.json +0 -0
  101. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/100_table_negative_indexing.json +0 -0
  102. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/101_table_cells_flat_iteration.json +0 -0
  103. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/102_text_with_embedded_special_chars.json +0 -0
  104. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/104_core_properties_datetime.json +0 -0
  105. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/105_default_one_section.json +0 -0
  106. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/106_heading_paragraph_format.json +0 -0
  107. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/107_varying_row_heights.json +0 -0
  108. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/10_paragraph_indents.json +0 -0
  109. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/11_paragraph_spacing.json +0 -0
  110. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/12_paragraph_keep_options.json +0 -0
  111. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/13_paragraph_tab_stops.json +0 -0
  112. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/14_run_add_tab_and_break.json +0 -0
  113. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/15_run_add_break_page.json +0 -0
  114. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/16_paragraph_clear_and_insert_before.json +0 -0
  115. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/17_table_basic.json +0 -0
  116. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/18_table_cell_text.json +0 -0
  117. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/19_table_row_column_sizing.json +0 -0
  118. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/20_table_cell_vertical_alignment.json +0 -0
  119. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/21_table_alignment_and_autofit.json +0 -0
  120. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/22_table_cell_paragraphs_iteration.json +0 -0
  121. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/24_table_add_row_column.json +0 -0
  122. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/25_table_merge_cells.json +0 -0
  123. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/26_section_page_setup.json +0 -0
  124. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/27_section_margins.json +0 -0
  125. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/28_section_add_new.json +0 -0
  126. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/29_section_headers_linked.json +0 -0
  127. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/30_styles_iteration.json +0 -0
  128. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/31_styles_lookup_and_default.json +0 -0
  129. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/32_styles_add_paragraph_style.json +0 -0
  130. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/33_core_properties_set_and_get.json +0 -0
  131. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/34_inline_shapes_iterate_empty.json +0 -0
  132. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/35_full_report.json +0 -0
  133. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/36_replace_text_in_paragraph.json +0 -0
  134. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/37_iterate_runs_and_format_all_bold.json +0 -0
  135. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/38_font_all_properties.json +0 -0
  136. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/39_large_body_100_paragraphs.json +0 -0
  137. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/40_large_table_10x10.json +0 -0
  138. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/41_unicode_and_emoji.json +0 -0
  139. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/42_very_long_paragraph.json +0 -0
  140. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/43_paragraph_text_round_trip.json +0 -0
  141. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/44_paragraph_alignment_round_trip.json +0 -0
  142. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/45_cell_text_round_trip.json +0 -0
  143. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/46_run_text_setter_round_trip.json +0 -0
  144. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/47_font_size_round_trip.json +0 -0
  145. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/48_font_color_round_trip.json +0 -0
  146. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/49_resume_layout.json +0 -0
  147. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/50_multi_section_doc.json +0 -0
  148. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/52_iterate_everything.json +0 -0
  149. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/53_apply_style_to_paragraphs.json +0 -0
  150. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/54_empty_everything.json +0 -0
  151. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/55_single_character_runs.json +0 -0
  152. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/56_everything_in_one.json +0 -0
  153. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/57_runs_after_multiple_text_appends.json +0 -0
  154. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/58_modify_runs_in_place.json +0 -0
  155. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/59_indent_round_trip.json +0 -0
  156. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/60_space_round_trip.json +0 -0
  157. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/61_cell_paragraph_with_runs.json +0 -0
  158. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/62_many_cell_paragraphs.json +0 -0
  159. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/63_table_style_round_trip.json +0 -0
  160. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/64_many_sections.json +0 -0
  161. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/65_20x20_table_formatted.json +0 -0
  162. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/66_toc_like_structure.json +0 -0
  163. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/67_paragraph_insert_before_chain.json +0 -0
  164. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/68_invoice.json +0 -0
  165. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/69_newsletter.json +0 -0
  166. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/70_add_and_iterate_back.json +0 -0
  167. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/71_academic_paper.json +0 -0
  168. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/72_legal_contract.json +0 -0
  169. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/73_form_with_many_tables.json +0 -0
  170. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/74_paragraph_with_10_runs.json +0 -0
  171. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/75_paragraph_negative_first_line_indent.json +0 -0
  172. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/76_rgbcolor_from_string.json +0 -0
  173. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/77_length_unit_conversions.json +0 -0
  174. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/78_paragraph_copy_style.json +0 -0
  175. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/79_bulk_cell_formatting.json +0 -0
  176. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/80_apply_style_after_add_run.json +0 -0
  177. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/81_multi_page_with_breaks.json +0 -0
  178. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/82_add_text_on_existing_run.json +0 -0
  179. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/83_clear_then_repopulate_paragraph.json +0 -0
  180. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/84_table_reread_row_count.json +0 -0
  181. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/85_header_footer_access.json +0 -0
  182. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/86_font_read_unset_returns_none.json +0 -0
  183. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/87_500_paragraph_doc.json +0 -0
  184. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/88_mixed_content_iteration.json +0 -0
  185. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/89_alignment_clear_via_none.json +0 -0
  186. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/90_cell_add_paragraph_styled.json +0 -0
  187. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/91_many_small_tables.json +0 -0
  188. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/92_margins_every_section.json +0 -0
  189. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/93_font_bool_reads_after_set.json +0 -0
  190. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/94_page_break_before_paragraph.json +0 -0
  191. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/95_paragraph_hyperlinks_empty.json +0 -0
  192. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/96_paragraph_contains_page_break.json +0 -0
  193. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/97_document_styles_by_key.json +0 -0
  194. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/98_style_contains_check.json +0 -0
  195. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/99_run_add_picture_from_bytes.json +0 -0
  196. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/ex02_unicode_everywhere.json +0 -0
  197. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/ex03_1000_paragraphs.json +0 -0
  198. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/ex04_50x50_table.json +0 -0
  199. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/ex05_long_text_in_cell.json +0 -0
  200. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/ex06_hundred_tiny_runs.json +0 -0
  201. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/ex07_every_font_boolean.json +0 -0
  202. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/ex08_many_continuous_sections.json +0 -0
  203. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/ex09_many_tab_stops.json +0 -0
  204. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/ex10_complex_bom.json +0 -0
  205. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/ex11_banded_rows_formatting.json +0 -0
  206. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/ex12_section_reconfigure.json +0 -0
  207. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/ex13_cell_with_10_paragraphs.json +0 -0
  208. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/ex14_styled_report_table.json +0 -0
  209. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/ex15_paragraph_all_format_props.json +0 -0
  210. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/ex16_runs_interleaved_with_breaks.json +0 -0
  211. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/ex17_all_break_kinds.json +0 -0
  212. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/ex18_read_back_large_doc.json +0 -0
  213. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/ex19_mutate_all_runs.json +0 -0
  214. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/ex20_kitchen_sink_v2.json +0 -0
  215. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/mega01_book_chapter.json +0 -0
  216. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/mega02_research_proposal.json +0 -0
  217. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/mega03_financial_statement.json +0 -0
  218. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/mega04_recipe_card.json +0 -0
  219. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/mega05_user_manual.json +0 -0
  220. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/mega06_complex_newsletter.json +0 -0
  221. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/mega07_budget_spreadsheet.json +0 -0
  222. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/mega08_product_catalog.json +0 -0
  223. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/mega09_signed_contract.json +0 -0
  224. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/mega10_api_documentation.json +0 -0
  225. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/rw01_official_quickstart.json +0 -0
  226. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/rw02_paragraph_style_list.json +0 -0
  227. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/rw03_character_formatting.json +0 -0
  228. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/rw04_section_page_setup.json +0 -0
  229. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/rw05_toc_pattern.json +0 -0
  230. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/rw06_meeting_minutes.json +0 -0
  231. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/rw07_dense_formatting_demo.json +0 -0
  232. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/rw08_table_merged_header.json +0 -0
  233. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/rw09_bulk_run_iteration.json +0 -0
  234. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/rw10_colored_grid_table.json +0 -0
  235. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/rw11_header_text.json +0 -0
  236. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/rw12_first_page_footer.json +0 -0
  237. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/rw13_even_page_header.json +0 -0
  238. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/op_snapshots/rw15_paragraph_style_instance.json +0 -0
  239. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/ours_spec.json +0 -0
  240. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/parity_crawl.py +0 -0
  241. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/parity_diff.json +0 -0
  242. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/real_world_cases.py +0 -0
  243. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/round_trip_tests.py +0 -0
  244. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/runner.py +0 -0
  245. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/stock_spec.json +0 -0
  246. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/fidelity/test_e2e_against_staging.py +0 -0
  247. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/parity/README.md +0 -0
  248. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/parity/__init__.py +0 -0
  249. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/parity/baseline_gaps.json +0 -0
  250. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/parity/compare.py +0 -0
  251. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/parity/intentional_deviations.json +0 -0
  252. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/parity/introspect.py +0 -0
  253. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/parity/reports/GAP_ANALYSIS.md +0 -0
  254. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/parity/reports/gap_report.json +0 -0
  255. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/parity/run_parity.py +0 -0
  256. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/parity/snapshots/athena_latest.json +0 -0
  257. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/parity/snapshots/upstream_python_docx_1.2.0.json +0 -0
  258. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/parity/test_parity_gap.py +0 -0
  259. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_add_section_extract_items.py +0 -0
  260. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_athena_extensions_contract.py +0 -0
  261. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_batching_perf.py +0 -0
  262. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_block_not_found_error.py +0 -0
  263. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_cell_add_paragraph_wire_shape.py +0 -0
  264. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_cell_add_table_not_supported.py +0 -0
  265. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_cell_inner_add_hyperlink_stash.py +0 -0
  266. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_cell_inner_add_run_via_cell_insert.py +0 -0
  267. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_cell_inner_format_stash.py +0 -0
  268. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_cell_inner_run_format_stash.py +0 -0
  269. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_cell_inner_run_guard.py +0 -0
  270. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_cell_text_plain_fastpath.py +0 -0
  271. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_collapsed_range_format.py +0 -0
  272. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_command_dataclasses.py +0 -0
  273. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_commands.py +0 -0
  274. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_comments.py +0 -0
  275. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_document_asset_id_property.py +0 -0
  276. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_document_create.py +0 -0
  277. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_document_create_from_template.py +0 -0
  278. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_document_factory_validation.py +0 -0
  279. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_e2e_partial_failure_cascade.py +0 -0
  280. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_find_replace_session_open.py +0 -0
  281. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_http_transport.py +0 -0
  282. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_hyperlink_coalescing.py +0 -0
  283. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_insert_deferred.py +0 -0
  284. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_iter_inner_content.py +0 -0
  285. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_list_styles.py +0 -0
  286. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_merged_cell_secondary_slot.py +0 -0
  287. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_merged_cells.py +0 -0
  288. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_oxml_shim.py +0 -0
  289. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_paragraph_text_len_cache.py +0 -0
  290. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_parity_misc.py +0 -0
  291. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_parity_round2.py +0 -0
  292. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_partial_failure_cascade.py +0 -0
  293. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_phase_a_behavior.py +0 -0
  294. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_phase_b_headers_footers.py +0 -0
  295. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_phase_c_tables.py +0 -0
  296. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_postproc_cell_format_rewrite.py +0 -0
  297. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_postproc_cell_run_format_rewrite.py +0 -0
  298. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_postproc_ref_restore.py +0 -0
  299. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_pr19766_review_fixes.py +0 -0
  300. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_ptc.py +0 -0
  301. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_python_docx_api_parity.py +0 -0
  302. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_revisions.py +0 -0
  303. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_add_paragraph_style.py +0 -0
  304. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_add_picture.py +0 -0
  305. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_add_run.py +0 -0
  306. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_cell_add_paragraph.py +0 -0
  307. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_comments_add_comment.py +0 -0
  308. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_comments_get.py +0 -0
  309. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_document_audit.py +0 -0
  310. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_document_element.py +0 -0
  311. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_enum_section.py +0 -0
  312. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_font_audit.py +0 -0
  313. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_header_footer.py +0 -0
  314. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_hyperlink.py +0 -0
  315. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_inline_shape.py +0 -0
  316. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_insert_paragraph_before.py +0 -0
  317. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_misc.py +0 -0
  318. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_paragraph_strict.py +0 -0
  319. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_paragraph_style.py +0 -0
  320. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_paragraph_style_strict.py +0 -0
  321. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_parfmt.py +0 -0
  322. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_row_col_cell.py +0 -0
  323. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_run_add_break.py +0 -0
  324. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_run_bool_setters.py +0 -0
  325. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_run_style.py +0 -0
  326. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_run_style_strict.py +0 -0
  327. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_run_text.py +0 -0
  328. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_run_underline.py +0 -0
  329. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_section_audit.py +0 -0
  330. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_section_dimensions.py +0 -0
  331. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_section_onoff.py +0 -0
  332. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_settings.py +0 -0
  333. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_shared_audit.py +0 -0
  334. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_style.py +0 -0
  335. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_styles.py +0 -0
  336. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_table_audit.py +0 -0
  337. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_table_cell.py +0 -0
  338. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_table_dimensions.py +0 -0
  339. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_silent_stub_table_layout.py +0 -0
  340. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_smoke_integration.py +0 -0
  341. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_style_acceptance.py +0 -0
  342. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_style_font.py +0 -0
  343. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_style_setters_contract.py +0 -0
  344. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_table_set_cell_perf.py +0 -0
  345. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_table_style_id_resolution.py +0 -0
  346. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_temporarily_unavailable.py +0 -0
  347. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_wire_contract.py +0 -0
  348. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_xml_attr_guard.py +0 -0
  349. {athena_python_docx-0.14.0 → athena_python_docx-0.15.0}/tests/test_zod_wire_contract.py +0 -0
@@ -349,6 +349,18 @@ Issue numbers reference `python-openxml/python-docx`.
349
349
  wontfix upstream but the request keeps recurring. Routes through
350
350
  `ExportPDF` (SuperDoc handles the actual conversion).
351
351
 
352
+ - **`Document.clear()`** (0.14.0+) — empty the document body so subsequent
353
+ writes start from a clean slate. python-docx has no equivalent (it
354
+ operates on local files where the caller can simply construct a new
355
+ ``Document``). Iterates every top-level paragraph and table cell and
356
+ empties their text content. Block structure is preserved (SuperDoc has
357
+ no wire op to delete blocks today), so post-clear the doc holds N
358
+ empty paragraphs rather than collapsing to a single one — for a truly
359
+ empty body, call ``Document.create()`` to mint a fresh asset instead.
360
+ Closes the gap that prompted the 0.14 series' agent-side ``find_replace``
361
+ cleanup loops, which left horizontal-rule and scratch-content artifacts
362
+ in the document during failed-run recoveries.
363
+
352
364
  - **`Document.export_docx(path=None, *, include_revisions=False)
353
365
  -> bytes`** (0.11.4+) — export the document's current state as
354
366
  ``.docx`` bytes, optionally writing to ``path``. Closes the gap
@@ -602,6 +614,16 @@ This is a **thin HTTP client** that mimics the sync python-docx API.
602
614
  the context-manager exit drain explicitly; `docx.flush_all()` is
603
615
  the Daytona-prelude hook that flushes every live buffer in the
604
616
  process.
617
+ - Execution scope: executor sandboxes may keep Python globals
618
+ between tool calls so imports, constants, and helper functions can be
619
+ reused. Live SDK objects are different. The executor calls
620
+ `docx.begin_execution(request_id)` at the start of each tool call;
621
+ `Session` and `CommandBuffer` stamp that id and raise
622
+ `StaleDocumentHandleError` if a later call tries to reuse old
623
+ `Document`/paragraph/run/table/cell handles. `docx.flush_all(strict=True)`
624
+ is the executor path and raises `FlushAllError` for failed flushes or
625
+ stale pending buffers; plain `docx.flush_all()` keeps the historical
626
+ log-and-swallow behavior for local scripts.
605
627
  - **Insert deferral (0.8.0+):** `Insert` was removed from the
606
628
  response-bearing set because every in-tree caller
607
629
  (`Paragraph._insert_run_text_segments`, `Run.add_text`, `_Cell.text`)
@@ -650,7 +672,7 @@ This is a **thin HTTP client** that mimics the sync python-docx API.
650
672
  follow-up — the wire format is typed end-to-end either way.
651
673
  - **Programmatic Tool Calling (PTC):** every `CommandBuffer.call` and
652
674
  `flush` emits begin/end events to agora via `docx/_ptc.py` when run
653
- inside a Daytona sandbox with `ATHENA_PTC_URL` set. Each method call
675
+ inside an execution sandbox with `ATHENA_PTC_URL` set. Each method call
654
676
  surfaces as a nested sub-tool-card under the parent
655
677
  `run_python_code` tool. See
656
678
  [`docs/PROGRAMMATIC_TOOL_CALLING_GUIDE.md`](../../docs/PROGRAMMATIC_TOOL_CALLING_GUIDE.md)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: athena-python-docx
3
- Version: 0.14.0
3
+ Version: 0.15.0
4
4
  Summary: Drop-in replacement for python-docx that connects to Athena's Superdoc/Keryx collaborative document stack
5
5
  Project-URL: Homepage, https://athenaintelligence.ai
6
6
  Author-email: Athena Intelligence <engineering@athenaintelligence.ai>
@@ -6,8 +6,9 @@ See CLAUDE.md for the API parity contract.
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
- __version__ = "0.14.0"
9
+ __version__ = "0.15.0"
10
10
 
11
+ from docx._execution import begin_execution
11
12
  from docx.api import Document
12
13
  from docx._buffer import flush_all
13
14
  # Re-exports python-docx ships at docx top-level for convenience.
@@ -23,6 +24,7 @@ __all__ = [
23
24
  "Twips",
24
25
  "Length",
25
26
  "RGBColor",
27
+ "begin_execution",
26
28
  "flush_all",
27
29
  "__version__",
28
30
  ]
@@ -34,8 +34,13 @@ import weakref
34
34
  from typing import TYPE_CHECKING, Any
35
35
 
36
36
  from docx import _ptc
37
+ from docx._execution import (
38
+ assert_current_execution,
39
+ current_execution_id,
40
+ is_stale_execution,
41
+ )
37
42
  from docx.commands import Command, is_response_bearing, must_flush_immediately
38
- from docx.errors import DocxError
43
+ from docx.errors import DocxError, FlushAllError
39
44
 
40
45
 
41
46
  def _apply_proxy_id_rewrites(
@@ -172,13 +177,17 @@ def _unregister(buffer: "CommandBuffer") -> None:
172
177
  ]
173
178
 
174
179
 
175
- def flush_all() -> None:
180
+ def flush_all(*, strict: bool = False) -> None:
176
181
  """Flush every live CommandBuffer in this process.
177
182
 
178
183
  Used by the Daytona sandbox prelude after user code returns, so
179
184
  buffered mutations make it to Keryx before the sandbox is suspended.
180
- Safe to call when no Buffers exist (no-op). Failures are logged and
181
- swallowed — we don't want one stuck buffer to mask the rest.
185
+ Safe to call when no Buffers exist (no-op).
186
+
187
+ By default, failures are logged and swallowed for backwards
188
+ compatibility with existing local scripts. The executor calls
189
+ ``flush_all(strict=True)`` so failed or stale writes surface as real tool
190
+ failures instead of being hidden in stderr.
182
191
  """
183
192
  with _registry_lock:
184
193
  snapshot = list(_active_buffers)
@@ -186,16 +195,35 @@ def flush_all() -> None:
186
195
  live = [ref for ref in snapshot if ref() is not None]
187
196
  _active_buffers[:] = live
188
197
 
198
+ failures: list[str] = []
189
199
  for ref in live:
190
200
  buf = ref()
191
201
  if buf is None:
192
202
  continue
203
+ if buf.is_stale_for_current_execution:
204
+ pending_count = buf.pending_count
205
+ if pending_count > 0:
206
+ msg = (
207
+ f"buffer {buf.asset_id} belongs to a previous "
208
+ f"execute_word_document_code call and still has "
209
+ f"{pending_count} unflushed command(s)"
210
+ )
211
+ if strict:
212
+ failures.append(msg)
213
+ else:
214
+ sys.stderr.write(f"[docx-sdk] flush_all: {msg}\n")
215
+ continue
193
216
  try:
194
217
  buf.flush()
195
218
  except Exception as e: # noqa: BLE001
196
- sys.stderr.write(
197
- f"[docx-sdk] flush_all: buffer {buf.asset_id} flush failed: {e}\n",
198
- )
219
+ msg = f"buffer {buf.asset_id} flush failed: {e}"
220
+ if strict:
221
+ failures.append(msg)
222
+ else:
223
+ sys.stderr.write(f"[docx-sdk] flush_all: {msg}\n")
224
+
225
+ if failures:
226
+ raise FlushAllError(failures)
199
227
 
200
228
 
201
229
  # ---------------------------------------------------------------------------
@@ -240,6 +268,7 @@ class CommandBuffer:
240
268
  self._timer: threading.Timer | None = None
241
269
  self._auto_flush_seconds: float = auto_flush_seconds
242
270
  self._closed: bool = False
271
+ self._execution_id: str | None = current_execution_id()
243
272
  # Track-changes envelope state — propagated as request-level
244
273
  # ``changeMode`` and ``user`` on every batch. ``Document``
245
274
  # mutates these via :meth:`set_change_mode` / :meth:`set_user`,
@@ -263,6 +292,7 @@ class CommandBuffer:
263
292
  the per-cmd result for ``real_node_id`` / ``real_entity_id``
264
293
  echoes and applies setattr to every registered ref.
265
294
  """
295
+ self._assert_current_execution()
266
296
  with self._lock:
267
297
  self._proxy_id_refs.setdefault(client_id, []).append((proxy, attr))
268
298
 
@@ -275,6 +305,10 @@ class CommandBuffer:
275
305
  with self._lock:
276
306
  return len(self._pending)
277
307
 
308
+ @property
309
+ def is_stale_for_current_execution(self) -> bool:
310
+ return is_stale_execution(self._execution_id)
311
+
278
312
  @property
279
313
  def change_mode(self) -> str | None:
280
314
  return self._change_mode
@@ -291,6 +325,7 @@ class CommandBuffer:
291
325
  retro-actively re-tag earlier mutations. ``mode`` is one of
292
326
  ``"direct"``, ``"tracked"``, or ``None`` to clear.
293
327
  """
328
+ self._assert_current_execution()
294
329
  if mode is not None and mode not in ("direct", "tracked"):
295
330
  raise ValueError(f"change_mode must be 'direct', 'tracked', or None; got {mode!r}")
296
331
  with self._lock:
@@ -311,6 +346,7 @@ class CommandBuffer:
311
346
  a pooled session ignore the value, but the payload is still
312
347
  included so a fresh session picks it up.
313
348
  """
349
+ self._assert_current_execution()
314
350
  if name is None:
315
351
  with self._lock:
316
352
  self._user = None
@@ -339,6 +375,7 @@ class CommandBuffer:
339
375
  ``clientIdMap`` on flush and the buffer rewrites each registered
340
376
  proxy's ``_node_id`` in-place.
341
377
  """
378
+ self._assert_current_execution()
342
379
  if self._closed:
343
380
  raise RuntimeError(
344
381
  f"CommandBuffer for {self._asset_id} is closed",
@@ -397,6 +434,7 @@ class CommandBuffer:
397
434
  proxies pick up real ids without the caller ever seeing the
398
435
  UUID swap.
399
436
  """
437
+ self._assert_current_execution()
400
438
  with self._lock:
401
439
  self._cancel_timer_locked()
402
440
  pending = self._pending
@@ -436,6 +474,7 @@ class CommandBuffer:
436
474
  """Flush and disable. Idempotent."""
437
475
  if self._closed:
438
476
  return
477
+ self._assert_current_execution()
439
478
  try:
440
479
  self.flush()
441
480
  finally:
@@ -453,6 +492,7 @@ class CommandBuffer:
453
492
  still get their real ids written back via the same flush-time
454
493
  rewrite that :meth:`flush` does.
455
494
  """
495
+ self._assert_current_execution()
456
496
  with self._lock:
457
497
  self._cancel_timer_locked()
458
498
  pending = self._pending
@@ -515,5 +555,11 @@ class CommandBuffer:
515
555
  f"[docx-sdk] auto-flush failed for {self._asset_id}: {e}\n",
516
556
  )
517
557
 
558
+ def _assert_current_execution(self) -> None:
559
+ assert_current_execution(
560
+ self._execution_id,
561
+ object_name=f"CommandBuffer for {self._asset_id}",
562
+ )
563
+
518
564
 
519
565
  __all__ = ["CommandBuffer", "flush_all", "DEFAULT_AUTO_FLUSH_SECONDS"]
@@ -0,0 +1,64 @@
1
+ """Execution-scope helpers for long-lived sandbox processes.
2
+
3
+ Document execution sandboxes intentionally keep Python globals alive between
4
+ tool calls so agents can reuse helper functions and imports. Live SDK handles
5
+ are different: a ``Document``/``Paragraph``/``Run`` proxy captures a transport
6
+ session and a snapshot of node ids from the moment it was opened. Reusing that
7
+ proxy in a later tool call can overwrite manual user edits made between calls.
8
+
9
+ The executor calls :func:`begin_execution` once per tool call. Sessions and
10
+ buffers created after that stamp themselves with the active execution id; any
11
+ later operation under a different id fails before issuing HTTP.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ from docx.errors import StaleDocumentHandleError
17
+
18
+ _current_execution_id: str | None = None
19
+
20
+
21
+ def begin_execution(execution_id: str | None) -> None:
22
+ """Mark the start of a logical executor call.
23
+
24
+ Passing ``None`` disables stale-handle checks, which keeps local scripts
25
+ and existing tests behaving like normal in-memory Python programs.
26
+ """
27
+ global _current_execution_id
28
+ _current_execution_id = str(execution_id) if execution_id else None
29
+
30
+
31
+ def current_execution_id() -> str | None:
32
+ """Return the active executor id, if one has been declared."""
33
+ return _current_execution_id
34
+
35
+
36
+ def is_stale_execution(owner_execution_id: str | None) -> bool:
37
+ """Whether an object stamped with ``owner_execution_id`` is stale."""
38
+ current = current_execution_id()
39
+ return current is not None and owner_execution_id != current
40
+
41
+
42
+ def assert_current_execution(
43
+ owner_execution_id: str | None,
44
+ *,
45
+ object_name: str,
46
+ ) -> None:
47
+ """Raise if an SDK object belongs to a prior executor call."""
48
+ if not is_stale_execution(owner_execution_id):
49
+ return
50
+ raise StaleDocumentHandleError(
51
+ f"{object_name} belongs to a previous execute_word_document_code call. "
52
+ "Reopen the document inside the current tool call with "
53
+ "Document('asset_xxx') and pass that fresh Document into reusable "
54
+ "helper functions. Imports, constants, and function definitions can "
55
+ "still persist across calls."
56
+ )
57
+
58
+
59
+ __all__ = [
60
+ "assert_current_execution",
61
+ "begin_execution",
62
+ "current_execution_id",
63
+ "is_stale_execution",
64
+ ]
@@ -100,17 +100,24 @@ def create_empty_document(
100
100
  DocxError: any other 4xx/5xx from the server.
101
101
  """
102
102
  resolved_base: str | None = base_url or os.environ.get(_BASE_URL_ENV)
103
- resolved_key: str | None = api_key or os.environ.get(_API_KEY_ENV)
103
+ # api_key falls back to ATHENA_API_KEY (the canonical Athena user API
104
+ # key) so code running in sandboxes that only inject ATHENA_API_KEY
105
+ # still authenticates without an extra env var.
106
+ resolved_key: str | None = (
107
+ api_key or os.environ.get(_API_KEY_ENV) or os.environ.get("ATHENA_API_KEY")
108
+ )
104
109
 
105
110
  if not resolved_base:
106
111
  raise SessionError(
107
112
  f"Missing base_url and {_BASE_URL_ENV} env var. "
108
- "Pass base_url= to Document.create() or set the env var.",
113
+ "Pass base_url= to Document.create() or set the env var "
114
+ '(e.g. ATHENA_DOCX_BASE_URL="https://docx-studio.prd.athenaintel.com").',
109
115
  )
110
116
  if not resolved_key:
111
117
  raise AuthenticationError(
112
118
  f"Missing api_key and {_API_KEY_ENV} env var. "
113
- "Pass api_key= to Document.create() or set the env var.",
119
+ "Pass api_key= to Document.create() or set the env var "
120
+ "(or set ATHENA_API_KEY as a fallback).",
114
121
  )
115
122
 
116
123
  url: str = resolved_base.rstrip("/") + "/docs/empty"
@@ -256,7 +263,12 @@ def upload_document(
256
263
  import uuid
257
264
 
258
265
  resolved_docx_base: str | None = docx_base_url or os.environ.get(_BASE_URL_ENV)
259
- resolved_key: str | None = api_key or os.environ.get(_API_KEY_ENV)
266
+ # api_key falls back to ATHENA_API_KEY (the canonical Athena user API
267
+ # key) so code running in sandboxes that only inject ATHENA_API_KEY
268
+ # still authenticates without an extra env var.
269
+ resolved_key: str | None = (
270
+ api_key or os.environ.get(_API_KEY_ENV) or os.environ.get("ATHENA_API_KEY")
271
+ )
260
272
  resolved_agora_base: str | None = (
261
273
  agora_base_url
262
274
  or os.environ.get(_AGORA_BASE_URL_ENV)
@@ -273,7 +285,8 @@ def upload_document(
273
285
  if not resolved_key:
274
286
  raise AuthenticationError(
275
287
  f"Missing api_key and {_API_KEY_ENV} env var. "
276
- "Pass api_key= to Document.create() or set the env var.",
288
+ "Pass api_key= to Document.create() or set the env var "
289
+ "(or set ATHENA_API_KEY as a fallback).",
277
290
  )
278
291
 
279
292
  if not os.path.exists(docx_path):
@@ -297,9 +310,7 @@ def upload_document(
297
310
  qs["parent_folder_id"] = parent_folder_id
298
311
 
299
312
  url: str = (
300
- resolved_agora_base.rstrip("/")
301
- + "/api/super-docs/create-from-upload?"
302
- + urlencode(qs)
313
+ resolved_agora_base.rstrip("/") + "/api/super-docs/create-from-upload?" + urlencode(qs)
303
314
  )
304
315
 
305
316
  # Build a minimal multipart/form-data body without pulling in
@@ -22,6 +22,7 @@ import os
22
22
  from contextlib import asynccontextmanager
23
23
  from typing import TYPE_CHECKING, Any
24
24
 
25
+ from docx._execution import assert_current_execution, current_execution_id
25
26
  from docx.errors import (
26
27
  AuthenticationError,
27
28
  DocumentClosedError,
@@ -80,6 +81,7 @@ class Session:
80
81
  self._doc_handle: Any | None = None
81
82
  self._opened: bool = False
82
83
  self._closed: bool = False
84
+ self._execution_id: str | None = current_execution_id()
83
85
  # Collector for post-export OOXML rewrites (cell-inner format
84
86
  # ops + REF-field restorations + future Tier-B fidelity fixes).
85
87
  # Lives here so every proxy that reaches the session can stash;
@@ -109,6 +111,7 @@ class Session:
109
111
  AuthenticationError: missing or invalid api_key.
110
112
  SessionError: missing base_url or downstream open failure.
111
113
  """
114
+ self._assert_current_execution()
112
115
  if self._closed:
113
116
  raise DocumentClosedError(
114
117
  f"Session for asset {self._asset_id} was already closed.",
@@ -121,18 +124,25 @@ class Session:
121
124
  base_url: str | None = self._http_base_url or os.environ.get(
122
125
  "ATHENA_DOCX_BASE_URL",
123
126
  )
124
- api_key: str | None = self._http_api_key or os.environ.get(
125
- "ATHENA_DOCX_API_KEY",
127
+ # api_key falls back to ATHENA_API_KEY (the canonical Athena user API
128
+ # key) so code running in sandboxes that only inject ATHENA_API_KEY
129
+ # still authenticates without an extra env var.
130
+ api_key: str | None = (
131
+ self._http_api_key
132
+ or os.environ.get("ATHENA_DOCX_API_KEY")
133
+ or os.environ.get("ATHENA_API_KEY")
126
134
  )
127
135
  if not base_url:
128
136
  raise SessionError(
129
137
  "Missing base_url. Pass base_url= to Document(...) or set "
130
- "ATHENA_DOCX_BASE_URL.",
138
+ "the ATHENA_DOCX_BASE_URL environment variable (e.g. "
139
+ '"https://docx-studio.prd.athenaintel.com").',
131
140
  )
132
141
  if not api_key:
133
142
  raise AuthenticationError(
134
143
  "Missing api_key. Pass api_key= to Document(...) or set "
135
- "ATHENA_DOCX_API_KEY.",
144
+ "ATHENA_DOCX_API_KEY (or ATHENA_API_KEY as a fallback) in "
145
+ "the environment.",
136
146
  )
137
147
  client = HttpClient(base_url=base_url, api_key=api_key)
138
148
  self._client = client
@@ -143,6 +153,7 @@ class Session:
143
153
  @property
144
154
  def doc(self) -> Any:
145
155
  """Return the opened doc handle (the path-proxy entry point)."""
156
+ self._assert_current_execution()
146
157
  if not self._opened:
147
158
  raise SessionError(
148
159
  "Session not yet opened; call await session.open() first "
@@ -170,6 +181,7 @@ class Session:
170
181
  call shape that the rest of the SDK uses; in practice every
171
182
  SDK call site wraps this in :func:`docx._batching.run_sync`.
172
183
  """
184
+ self._assert_current_execution()
173
185
  if not self._opened:
174
186
  raise SessionError(
175
187
  "Session not yet opened; call await session.open() first "
@@ -194,6 +206,7 @@ class Session:
194
206
  ``in_place`` is accepted for back-compat with the legacy direct
195
207
  transport; writes are always against the asset's Y.Doc.
196
208
  """
209
+ self._assert_current_execution()
197
210
  if not self._opened:
198
211
  raise SessionError("Cannot save a session that was never opened.")
199
212
  if self._closed:
@@ -209,6 +222,7 @@ class Session:
209
222
  """Close the session. Idempotent."""
210
223
  if self._closed:
211
224
  return
225
+ self._assert_current_execution()
212
226
 
213
227
  handle = self._doc_handle
214
228
  buffer = getattr(handle, "buffer", None) if handle is not None else None
@@ -234,6 +248,12 @@ class Session:
234
248
  self._closed = True
235
249
  _log_info(f"Closed {self._asset_id}")
236
250
 
251
+ def _assert_current_execution(self) -> None:
252
+ assert_current_execution(
253
+ self._execution_id,
254
+ object_name=f"Document session for {self._asset_id}",
255
+ )
256
+
237
257
 
238
258
  @asynccontextmanager
239
259
  async def open_session(
@@ -1246,6 +1246,89 @@ class Document:
1246
1246
  # \r\n → \n\n (preserves paragraph-break semantics)
1247
1247
  return text.replace("\r\n", "\n\n").replace("\r", "\n")
1248
1248
 
1249
+ @athena_extension(
1250
+ since="0.14.0",
1251
+ description="Document.clear — empty paragraphs + cells so writes start from a clean slate.",
1252
+ )
1253
+ def clear(self) -> None:
1254
+ """Clear the document body so subsequent writes start from a clean slate.
1255
+
1256
+ Athena extension — python-docx has no equivalent. Empties every
1257
+ top-level paragraph's text content and every table cell's text
1258
+ content. The block structure (paragraphs and tables themselves)
1259
+ is preserved because SuperDoc does not yet expose a wire op to
1260
+ delete blocks; an agent recovering from a failed run can call
1261
+ ``doc.clear()`` then ``doc.add_paragraph(...)`` etc. without
1262
+ worrying about stale content concatenating onto its new writes.
1263
+
1264
+ Notes / caveats:
1265
+ - The post-clear document holds N empty paragraphs (one per
1266
+ previously-existing block-level paragraph) plus any empty
1267
+ tables. For most agent flows this is invisible because the
1268
+ first ``add_paragraph`` / ``add_heading`` extends the doc
1269
+ rather than overwriting block positions.
1270
+ - To get a TRULY empty body (single empty paragraph, no tables)
1271
+ create a fresh asset via ``Document.create()`` instead.
1272
+ - This method is best-effort: per-paragraph clear errors are
1273
+ swallowed so a partial clear doesn't take down the whole call.
1274
+ """
1275
+ from docx.text.paragraph import Paragraph as _Paragraph
1276
+
1277
+ self._ensure_open()
1278
+
1279
+ # Clear the list-chain state — the next add_paragraph after
1280
+ # clear() should start a new list, not attach to whatever the
1281
+ # previous run was doing.
1282
+ self._last_list_item_id = None
1283
+ self._last_list_kind = None
1284
+
1285
+ for paragraph in self.paragraphs:
1286
+ try:
1287
+ if not isinstance(paragraph, _Paragraph):
1288
+ continue
1289
+ if paragraph.text:
1290
+ paragraph.clear()
1291
+ except Exception as err:
1292
+ _log_warn(f"Document.clear: skipped a paragraph: {err!r}")
1293
+
1294
+ # Cell clearing must NOT go through ``cell.text = ""``: ``self.tables``
1295
+ # materializes fresh ephemeral ``Table`` proxies whose
1296
+ # ``_written_cells`` set is empty, so the setter would take the
1297
+ # fast (append) path — ``tables.set_cell insideEnd`` with an empty
1298
+ # paragraph fragment — which leaves prior cell content untouched.
1299
+ # Instead, drive ``doc.replace`` directly against each cell's
1300
+ # inner paragraphs (mirroring the clear-then-insert branch in
1301
+ # ``_Cell.text``) so the clear semantics don't depend on the
1302
+ # in-session write tracking that this code path bypasses.
1303
+ from docx.text.paragraph import _node_text
1304
+
1305
+ for table in self.tables:
1306
+ for row in table.rows:
1307
+ for cell in row.cells:
1308
+ try:
1309
+ existing_pids = cell._inner_paragraph_ids()
1310
+ for pid in existing_pids:
1311
+ existing_text = _node_text(self._session, pid)
1312
+ if not existing_text:
1313
+ continue
1314
+ run_sync(
1315
+ self._session.doc.replace(
1316
+ {
1317
+ "target": {
1318
+ "kind": "text",
1319
+ "blockId": pid,
1320
+ "range": {
1321
+ "start": 0,
1322
+ "end": len(existing_text),
1323
+ },
1324
+ },
1325
+ "text": "",
1326
+ },
1327
+ ),
1328
+ )
1329
+ except Exception as err:
1330
+ _log_warn(f"Document.clear: skipped a cell: {err!r}")
1331
+
1249
1332
  def add_paragraph(
1250
1333
  self,
1251
1334
  text: str = "",
@@ -111,6 +111,19 @@ class DocumentClosedError(DocxError):
111
111
  """Raised when operating on a closed Document."""
112
112
 
113
113
 
114
+ class StaleDocumentHandleError(DocxError):
115
+ """Raised when an SDK proxy from an earlier executor call is reused."""
116
+
117
+
118
+ class FlushAllError(DocxError):
119
+ """Raised by ``docx.flush_all(strict=True)`` when any live buffer fails."""
120
+
121
+ def __init__(self, failures: list[str]) -> None:
122
+ self.failures: list[str] = list(failures)
123
+ detail = "; ".join(self.failures)
124
+ super().__init__(f"docx.flush_all() failed: {detail}")
125
+
126
+
114
127
  class LocalSaveTargetNotSupportedError(DocxError, NotImplementedError):
115
128
  """Raised when ``Document.save(path_or_stream=...)`` is called with a
116
129
  non-None argument.