athena-python-docx 0.21.3__tar.gz → 0.21.6__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 (384) hide show
  1. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/PKG-INFO +1 -1
  2. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/__init__.py +3 -2
  3. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/_buffer.py +87 -1
  4. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/client.py +8 -3
  5. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/table.py +50 -0
  6. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/text/paragraph.py +34 -0
  7. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/text/run.py +26 -1
  8. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/pyproject.toml +1 -1
  9. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/fake_session.py +60 -46
  10. athena_python_docx-0.21.6/tests/fidelity/op_snapshots/20_table_cell_vertical_alignment.json +6 -0
  11. athena_python_docx-0.21.6/tests/fidelity/op_snapshots/22_table_cell_paragraphs_iteration.json +9 -0
  12. athena_python_docx-0.21.6/tests/fidelity/op_snapshots/35_full_report.json +39 -0
  13. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/45_cell_text_round_trip.json +0 -2
  14. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/56_everything_in_one.json +0 -6
  15. athena_python_docx-0.21.6/tests/fidelity/op_snapshots/61_cell_paragraph_with_runs.json +8 -0
  16. athena_python_docx-0.21.6/tests/fidelity/op_snapshots/62_many_cell_paragraphs.json +19 -0
  17. athena_python_docx-0.21.6/tests/fidelity/op_snapshots/65_20x20_table_formatted.json +604 -0
  18. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/68_invoice.json +0 -8
  19. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/69_newsletter.json +0 -24
  20. athena_python_docx-0.21.6/tests/fidelity/op_snapshots/79_bulk_cell_formatting.json +35 -0
  21. athena_python_docx-0.21.6/tests/fidelity/op_snapshots/90_cell_add_paragraph_styled.json +8 -0
  22. athena_python_docx-0.21.6/tests/fidelity/op_snapshots/ex11_banded_rows_formatting.json +124 -0
  23. athena_python_docx-0.21.6/tests/fidelity/op_snapshots/ex13_cell_with_10_paragraphs.json +34 -0
  24. athena_python_docx-0.21.6/tests/fidelity/op_snapshots/ex14_styled_report_table.json +37 -0
  25. athena_python_docx-0.21.6/tests/fidelity/op_snapshots/ex20_kitchen_sink_v2.json +272 -0
  26. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/mega01_book_chapter.json +3 -87
  27. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/mega02_research_proposal.json +5 -53
  28. athena_python_docx-0.21.6/tests/fidelity/op_snapshots/mega03_financial_statement.json +45 -0
  29. athena_python_docx-0.21.6/tests/fidelity/op_snapshots/mega05_user_manual.json +49 -0
  30. athena_python_docx-0.21.6/tests/fidelity/op_snapshots/mega07_budget_spreadsheet.json +50 -0
  31. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/mega09_signed_contract.json +2 -24
  32. athena_python_docx-0.21.6/tests/fidelity/op_snapshots/mega10_api_documentation.json +95 -0
  33. athena_python_docx-0.21.6/tests/fidelity/op_snapshots/rw10_colored_grid_table.json +36 -0
  34. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_buffer.py +97 -0
  35. athena_python_docx-0.21.6/tests/test_cell_fastpath_runs.py +208 -0
  36. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_positional_cell_id.py +29 -0
  37. athena_python_docx-0.21.6/tests/test_run_add_picture_anchor.py +69 -0
  38. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/uv.lock +1 -1
  39. athena_python_docx-0.21.3/tests/fidelity/op_snapshots/20_table_cell_vertical_alignment.json +0 -12
  40. athena_python_docx-0.21.3/tests/fidelity/op_snapshots/22_table_cell_paragraphs_iteration.json +0 -19
  41. athena_python_docx-0.21.3/tests/fidelity/op_snapshots/35_full_report.json +0 -78
  42. athena_python_docx-0.21.3/tests/fidelity/op_snapshots/61_cell_paragraph_with_runs.json +0 -19
  43. athena_python_docx-0.21.3/tests/fidelity/op_snapshots/62_many_cell_paragraphs.json +0 -53
  44. athena_python_docx-0.21.3/tests/fidelity/op_snapshots/65_20x20_table_formatted.json +0 -2804
  45. athena_python_docx-0.21.3/tests/fidelity/op_snapshots/79_bulk_cell_formatting.json +0 -89
  46. athena_python_docx-0.21.3/tests/fidelity/op_snapshots/90_cell_add_paragraph_styled.json +0 -14
  47. athena_python_docx-0.21.3/tests/fidelity/op_snapshots/ex11_banded_rows_formatting.json +0 -764
  48. athena_python_docx-0.21.3/tests/fidelity/op_snapshots/ex13_cell_with_10_paragraphs.json +0 -94
  49. athena_python_docx-0.21.3/tests/fidelity/op_snapshots/ex14_styled_report_table.json +0 -148
  50. athena_python_docx-0.21.3/tests/fidelity/op_snapshots/ex20_kitchen_sink_v2.json +0 -632
  51. athena_python_docx-0.21.3/tests/fidelity/op_snapshots/mega03_financial_statement.json +0 -122
  52. athena_python_docx-0.21.3/tests/fidelity/op_snapshots/mega05_user_manual.json +0 -137
  53. athena_python_docx-0.21.3/tests/fidelity/op_snapshots/mega07_budget_spreadsheet.json +0 -170
  54. athena_python_docx-0.21.3/tests/fidelity/op_snapshots/mega10_api_documentation.json +0 -271
  55. athena_python_docx-0.21.3/tests/fidelity/op_snapshots/rw10_colored_grid_table.json +0 -132
  56. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/.gitignore +0 -0
  57. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/CLAUDE.md +0 -0
  58. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/DOCX_EXEC_LAB.md +0 -0
  59. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/README.md +0 -0
  60. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/_athena_extension.py +0 -0
  61. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/_batching.py +0 -0
  62. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/_citations.py +0 -0
  63. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/_execution.py +0 -0
  64. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/_http.py +0 -0
  65. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/_http_doc.py +0 -0
  66. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/_image_utils.py +0 -0
  67. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/_postproc.py +0 -0
  68. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/_ptc.py +0 -0
  69. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/_references.py +0 -0
  70. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/_table_styles.py +0 -0
  71. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/_timeouts.py +0 -0
  72. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/api.py +0 -0
  73. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/bookmarks.py +0 -0
  74. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/charts.py +0 -0
  75. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/commands.py +0 -0
  76. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/comments.py +0 -0
  77. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/document.py +0 -0
  78. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/enum/__init__.py +0 -0
  79. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/enum/section.py +0 -0
  80. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/enum/shape.py +0 -0
  81. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/enum/style.py +0 -0
  82. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/enum/table.py +0 -0
  83. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/enum/text.py +0 -0
  84. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/errors.py +0 -0
  85. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/exceptions.py +0 -0
  86. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/fields.py +0 -0
  87. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/footnotes.py +0 -0
  88. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/math.py +0 -0
  89. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/opc/__init__.py +0 -0
  90. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/opc/coreprops.py +0 -0
  91. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/oxml/__init__.py +0 -0
  92. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/revisions.py +0 -0
  93. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/sdt.py +0 -0
  94. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/section.py +0 -0
  95. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/session.py +0 -0
  96. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/settings.py +0 -0
  97. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/shape.py +0 -0
  98. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/shared.py +0 -0
  99. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/styles/__init__.py +0 -0
  100. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/styles/style.py +0 -0
  101. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/styles/styles.py +0 -0
  102. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/text/__init__.py +0 -0
  103. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/text/font.py +0 -0
  104. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/text/hyperlink.py +0 -0
  105. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/text/pagebreak.py +0 -0
  106. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/text/parfmt.py +0 -0
  107. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/text/tabstops.py +0 -0
  108. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/toc.py +0 -0
  109. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/docx/typing.py +0 -0
  110. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/scripts/docx_exec_lab.py +0 -0
  111. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/scripts/docx_exec_lab_examples/fast_table_fill.py +0 -0
  112. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/scripts/docx_exec_lab_examples/find_replace_literal.py +0 -0
  113. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/scripts/docx_exec_lab_server.py +0 -0
  114. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/scripts/dump_wire_fixtures.py +0 -0
  115. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/scripts/publish.sh +0 -0
  116. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/scripts/release.sh +0 -0
  117. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/scripts/round_trip_smoke.py +0 -0
  118. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/scripts/smoke_test_block_not_found.py +0 -0
  119. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/scripts/validate_find_replace_asset.py +0 -0
  120. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/__init__.py +0 -0
  121. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/conftest.py +0 -0
  122. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/METHODOLOGY.md +0 -0
  123. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/README.md +0 -0
  124. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/__init__.py +0 -0
  125. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/ab_probe_cases.py +0 -0
  126. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/ab_probe_runner.py +0 -0
  127. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/auto_gen_cases.py +0 -0
  128. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/binary_round_trip.py +0 -0
  129. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/cases.py +0 -0
  130. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/complex_cases.py +0 -0
  131. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/coverage_report.py +0 -0
  132. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/extract.py +0 -0
  133. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/extreme_cases.py +0 -0
  134. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/firm_templates/README.md +0 -0
  135. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/firm_templates/__init__.py +0 -0
  136. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/firm_templates/_runner.py +0 -0
  137. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/firm_templates/extractor.py +0 -0
  138. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/firm_templates/test_pw_corpus.py +0 -0
  139. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/firm_templates/test_pw_research_digest.py +0 -0
  140. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/local_runner.py +0 -0
  141. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/mega_cases.py +0 -0
  142. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshot.py +0 -0
  143. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/01_basic_paragraph.json +0 -0
  144. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/02_multiple_headings.json +0 -0
  145. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/03_runs_with_formatting.json +0 -0
  146. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/04_font_name_and_size.json +0 -0
  147. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/05_font_color_rgb.json +0 -0
  148. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/06_font_character_properties.json +0 -0
  149. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/07_font_subscript_superscript.json +0 -0
  150. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/08_font_highlight.json +0 -0
  151. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/09_paragraph_alignment.json +0 -0
  152. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/100_table_negative_indexing.json +0 -0
  153. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/101_table_cells_flat_iteration.json +0 -0
  154. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/102_text_with_embedded_special_chars.json +0 -0
  155. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/104_core_properties_datetime.json +0 -0
  156. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/105_default_one_section.json +0 -0
  157. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/106_heading_paragraph_format.json +0 -0
  158. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/107_varying_row_heights.json +0 -0
  159. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/10_paragraph_indents.json +0 -0
  160. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/11_paragraph_spacing.json +0 -0
  161. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/12_paragraph_keep_options.json +0 -0
  162. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/13_paragraph_tab_stops.json +0 -0
  163. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/14_run_add_tab_and_break.json +0 -0
  164. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/15_run_add_break_page.json +0 -0
  165. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/16_paragraph_clear_and_insert_before.json +0 -0
  166. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/17_table_basic.json +0 -0
  167. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/18_table_cell_text.json +0 -0
  168. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/19_table_row_column_sizing.json +0 -0
  169. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/21_table_alignment_and_autofit.json +0 -0
  170. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/24_table_add_row_column.json +0 -0
  171. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/25_table_merge_cells.json +0 -0
  172. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/26_section_page_setup.json +0 -0
  173. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/27_section_margins.json +0 -0
  174. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/28_section_add_new.json +0 -0
  175. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/29_section_headers_linked.json +0 -0
  176. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/30_styles_iteration.json +0 -0
  177. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/31_styles_lookup_and_default.json +0 -0
  178. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/32_styles_add_paragraph_style.json +0 -0
  179. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/33_core_properties_set_and_get.json +0 -0
  180. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/34_inline_shapes_iterate_empty.json +0 -0
  181. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/36_replace_text_in_paragraph.json +0 -0
  182. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/37_iterate_runs_and_format_all_bold.json +0 -0
  183. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/38_font_all_properties.json +0 -0
  184. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/39_large_body_100_paragraphs.json +0 -0
  185. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/40_large_table_10x10.json +0 -0
  186. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/41_unicode_and_emoji.json +0 -0
  187. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/42_very_long_paragraph.json +0 -0
  188. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/43_paragraph_text_round_trip.json +0 -0
  189. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/44_paragraph_alignment_round_trip.json +0 -0
  190. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/46_run_text_setter_round_trip.json +0 -0
  191. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/47_font_size_round_trip.json +0 -0
  192. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/48_font_color_round_trip.json +0 -0
  193. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/49_resume_layout.json +0 -0
  194. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/50_multi_section_doc.json +0 -0
  195. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/52_iterate_everything.json +0 -0
  196. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/53_apply_style_to_paragraphs.json +0 -0
  197. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/54_empty_everything.json +0 -0
  198. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/55_single_character_runs.json +0 -0
  199. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/57_runs_after_multiple_text_appends.json +0 -0
  200. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/58_modify_runs_in_place.json +0 -0
  201. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/59_indent_round_trip.json +0 -0
  202. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/60_space_round_trip.json +0 -0
  203. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/63_table_style_round_trip.json +0 -0
  204. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/64_many_sections.json +0 -0
  205. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/66_toc_like_structure.json +0 -0
  206. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/67_paragraph_insert_before_chain.json +0 -0
  207. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/70_add_and_iterate_back.json +0 -0
  208. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/71_academic_paper.json +0 -0
  209. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/72_legal_contract.json +0 -0
  210. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/73_form_with_many_tables.json +0 -0
  211. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/74_paragraph_with_10_runs.json +0 -0
  212. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/75_paragraph_negative_first_line_indent.json +0 -0
  213. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/76_rgbcolor_from_string.json +0 -0
  214. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/77_length_unit_conversions.json +0 -0
  215. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/78_paragraph_copy_style.json +0 -0
  216. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/80_apply_style_after_add_run.json +0 -0
  217. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/81_multi_page_with_breaks.json +0 -0
  218. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/82_add_text_on_existing_run.json +0 -0
  219. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/83_clear_then_repopulate_paragraph.json +0 -0
  220. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/84_table_reread_row_count.json +0 -0
  221. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/85_header_footer_access.json +0 -0
  222. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/86_font_read_unset_returns_none.json +0 -0
  223. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/87_500_paragraph_doc.json +0 -0
  224. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/88_mixed_content_iteration.json +0 -0
  225. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/89_alignment_clear_via_none.json +0 -0
  226. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/91_many_small_tables.json +0 -0
  227. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/92_margins_every_section.json +0 -0
  228. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/93_font_bool_reads_after_set.json +0 -0
  229. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/94_page_break_before_paragraph.json +0 -0
  230. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/95_paragraph_hyperlinks_empty.json +0 -0
  231. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/96_paragraph_contains_page_break.json +0 -0
  232. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/97_document_styles_by_key.json +0 -0
  233. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/98_style_contains_check.json +0 -0
  234. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/99_run_add_picture_from_bytes.json +0 -0
  235. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/ex02_unicode_everywhere.json +0 -0
  236. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/ex03_1000_paragraphs.json +0 -0
  237. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/ex04_50x50_table.json +0 -0
  238. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/ex05_long_text_in_cell.json +0 -0
  239. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/ex06_hundred_tiny_runs.json +0 -0
  240. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/ex07_every_font_boolean.json +0 -0
  241. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/ex08_many_continuous_sections.json +0 -0
  242. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/ex09_many_tab_stops.json +0 -0
  243. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/ex10_complex_bom.json +0 -0
  244. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/ex12_section_reconfigure.json +0 -0
  245. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/ex15_paragraph_all_format_props.json +0 -0
  246. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/ex16_runs_interleaved_with_breaks.json +0 -0
  247. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/ex17_all_break_kinds.json +0 -0
  248. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/ex18_read_back_large_doc.json +0 -0
  249. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/ex19_mutate_all_runs.json +0 -0
  250. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/mega04_recipe_card.json +0 -0
  251. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/mega06_complex_newsletter.json +0 -0
  252. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/mega08_product_catalog.json +0 -0
  253. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/rw01_official_quickstart.json +0 -0
  254. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/rw02_paragraph_style_list.json +0 -0
  255. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/rw03_character_formatting.json +0 -0
  256. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/rw04_section_page_setup.json +0 -0
  257. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/rw05_toc_pattern.json +0 -0
  258. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/rw06_meeting_minutes.json +0 -0
  259. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/rw07_dense_formatting_demo.json +0 -0
  260. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/rw08_table_merged_header.json +0 -0
  261. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/rw09_bulk_run_iteration.json +0 -0
  262. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/rw11_header_text.json +0 -0
  263. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/rw12_first_page_footer.json +0 -0
  264. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/rw13_even_page_header.json +0 -0
  265. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/op_snapshots/rw15_paragraph_style_instance.json +0 -0
  266. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/ours_spec.json +0 -0
  267. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/parity_crawl.py +0 -0
  268. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/parity_diff.json +0 -0
  269. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/real_world_cases.py +0 -0
  270. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/round_trip_tests.py +0 -0
  271. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/stock_spec.json +0 -0
  272. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/fidelity/test_e2e_against_staging.py +0 -0
  273. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/parity/README.md +0 -0
  274. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/parity/__init__.py +0 -0
  275. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/parity/baseline_gaps.json +0 -0
  276. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/parity/compare.py +0 -0
  277. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/parity/intentional_deviations.json +0 -0
  278. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/parity/introspect.py +0 -0
  279. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/parity/reports/GAP_ANALYSIS.md +0 -0
  280. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/parity/reports/gap_report.json +0 -0
  281. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/parity/run_parity.py +0 -0
  282. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/parity/snapshots/athena_latest.json +0 -0
  283. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/parity/snapshots/upstream_python_docx_1.2.0.json +0 -0
  284. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/parity/test_parity_gap.py +0 -0
  285. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_add_section_extract_items.py +0 -0
  286. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_athena_extensions_contract.py +0 -0
  287. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_athena_extensions_registry.py +0 -0
  288. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_batching_perf.py +0 -0
  289. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_block_not_found_error.py +0 -0
  290. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_cell_add_paragraph_wire_shape.py +0 -0
  291. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_cell_add_table_not_supported.py +0 -0
  292. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_cell_inner_add_hyperlink_stash.py +0 -0
  293. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_cell_inner_add_run_via_cell_insert.py +0 -0
  294. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_cell_inner_format_stash.py +0 -0
  295. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_cell_inner_run_format_stash.py +0 -0
  296. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_cell_inner_run_guard.py +0 -0
  297. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_cell_text_plain_fastpath.py +0 -0
  298. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_cell_text_replace_semantics.py +0 -0
  299. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_citations.py +0 -0
  300. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_collapsed_range_format.py +0 -0
  301. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_command_dataclasses.py +0 -0
  302. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_commands.py +0 -0
  303. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_comments.py +0 -0
  304. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_document_asset_id_property.py +0 -0
  305. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_document_clear.py +0 -0
  306. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_document_create.py +0 -0
  307. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_document_create_from_template.py +0 -0
  308. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_document_factory_validation.py +0 -0
  309. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_docx_exec_lab.py +0 -0
  310. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_docx_exec_lab_server.py +0 -0
  311. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_e2e_partial_failure_cascade.py +0 -0
  312. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_execution_scope.py +0 -0
  313. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_find_replace_session_open.py +0 -0
  314. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_http_transport.py +0 -0
  315. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_hyperlink_coalescing.py +0 -0
  316. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_image_url_data_uri.py +0 -0
  317. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_insert_deferred.py +0 -0
  318. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_iter_inner_content.py +0 -0
  319. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_list_styles.py +0 -0
  320. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_merged_cell_secondary_slot.py +0 -0
  321. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_merged_cells.py +0 -0
  322. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_oxml_shim.py +0 -0
  323. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_paragraph_text_len_cache.py +0 -0
  324. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_parity_misc.py +0 -0
  325. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_parity_round2.py +0 -0
  326. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_partial_failure_cascade.py +0 -0
  327. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_phase_a_behavior.py +0 -0
  328. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_phase_b_headers_footers.py +0 -0
  329. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_phase_c_tables.py +0 -0
  330. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_postproc_cell_format_rewrite.py +0 -0
  331. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_postproc_cell_run_format_rewrite.py +0 -0
  332. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_postproc_ref_restore.py +0 -0
  333. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_pr19766_review_fixes.py +0 -0
  334. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_ptc.py +0 -0
  335. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_python_docx_api_parity.py +0 -0
  336. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_revisions.py +0 -0
  337. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_add_paragraph_style.py +0 -0
  338. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_add_picture.py +0 -0
  339. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_add_run.py +0 -0
  340. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_cell_add_paragraph.py +0 -0
  341. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_comments_add_comment.py +0 -0
  342. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_comments_get.py +0 -0
  343. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_document_audit.py +0 -0
  344. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_document_element.py +0 -0
  345. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_enum_section.py +0 -0
  346. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_font_audit.py +0 -0
  347. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_header_footer.py +0 -0
  348. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_hyperlink.py +0 -0
  349. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_inline_shape.py +0 -0
  350. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_insert_paragraph_before.py +0 -0
  351. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_misc.py +0 -0
  352. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_paragraph_strict.py +0 -0
  353. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_paragraph_style.py +0 -0
  354. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_paragraph_style_strict.py +0 -0
  355. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_parfmt.py +0 -0
  356. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_row_col_cell.py +0 -0
  357. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_run_add_break.py +0 -0
  358. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_run_bool_setters.py +0 -0
  359. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_run_style.py +0 -0
  360. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_run_style_strict.py +0 -0
  361. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_run_text.py +0 -0
  362. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_run_underline.py +0 -0
  363. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_section_audit.py +0 -0
  364. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_section_dimensions.py +0 -0
  365. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_section_onoff.py +0 -0
  366. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_settings.py +0 -0
  367. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_shared_audit.py +0 -0
  368. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_style.py +0 -0
  369. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_styles.py +0 -0
  370. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_table_audit.py +0 -0
  371. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_table_cell.py +0 -0
  372. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_table_dimensions.py +0 -0
  373. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_silent_stub_table_layout.py +0 -0
  374. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_smoke_integration.py +0 -0
  375. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_style_acceptance.py +0 -0
  376. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_style_font.py +0 -0
  377. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_style_setters_contract.py +0 -0
  378. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_table_set_cell_perf.py +0 -0
  379. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_table_style_id_resolution.py +0 -0
  380. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_temporarily_unavailable.py +0 -0
  381. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_validate_find_replace_asset_script.py +0 -0
  382. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_wire_contract.py +0 -0
  383. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_xml_attr_guard.py +0 -0
  384. {athena_python_docx-0.21.3 → athena_python_docx-0.21.6}/tests/test_zod_wire_contract.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: athena-python-docx
3
- Version: 0.21.3
3
+ Version: 0.21.6
4
4
  Summary: Drop-in replacement for python-docx that connects to Athena's DOCX Studio collaborative document stack
5
5
  Project-URL: Homepage, https://athenaintelligence.ai
6
6
  Author-email: Athena Intelligence <engineering@athenaintelligence.ai>
@@ -6,10 +6,10 @@ See CLAUDE.md for the API parity contract.
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
- __version__ = "0.21.3"
9
+ __version__ = "0.21.6"
10
10
 
11
11
  from docx.api import Document
12
- from docx._buffer import flush_all
12
+ from docx._buffer import discard_all, flush_all
13
13
 
14
14
  # Re-exports python-docx ships at docx top-level for convenience.
15
15
  from docx.shared import Emu, Inches, Pt, Cm, Mm, Twips, Length, RGBColor
@@ -25,6 +25,7 @@ __all__ = [
25
25
  "Length",
26
26
  "RGBColor",
27
27
  "flush_all",
28
+ "discard_all",
28
29
  "__version__",
29
30
  ]
30
31
 
@@ -245,6 +245,42 @@ def flush_all(*, strict: bool = False) -> None:
245
245
  raise FlushAllError(failures=failures)
246
246
 
247
247
 
248
+ def discard_all() -> int:
249
+ """Drop the pending commands of every live CommandBuffer; return the count.
250
+
251
+ The failed-script counterpart of :func:`flush_all`: after user code
252
+ raises, the executor discards the half-buffered tail instead of posting
253
+ it (see :meth:`CommandBuffer.discard_pending`). Safe to call when no
254
+ buffers exist (returns 0).
255
+
256
+ Buffers from a previous ``execute_word_document_code`` call are skipped
257
+ (mirroring :func:`flush_all`'s stale handling) so cross-execution
258
+ leftovers stay visible to diagnostics instead of being silently
259
+ swallowed. Best-effort like :meth:`CommandBuffer.discard_pending`: a
260
+ batch already handed to an in-flight flush cannot be recalled.
261
+ """
262
+ with _registry_lock:
263
+ snapshot = list(_active_buffers)
264
+ live = [ref for ref in snapshot if ref() is not None]
265
+ _active_buffers[:] = live
266
+
267
+ dropped = 0
268
+ for ref in live:
269
+ buf = ref()
270
+ if buf is None:
271
+ continue
272
+ if buf.is_stale_for_current_execution:
273
+ pending_count = buf.pending_count
274
+ if pending_count > 0:
275
+ sys.stderr.write(
276
+ f"[docx-sdk] discard_all: skipping stale buffer "
277
+ f"{buf.asset_id} with {pending_count} unflushed command(s)\n",
278
+ )
279
+ continue
280
+ dropped += buf.discard_pending()
281
+ return dropped
282
+
283
+
248
284
  # ---------------------------------------------------------------------------
249
285
  # CommandBuffer
250
286
  # ---------------------------------------------------------------------------
@@ -316,6 +352,12 @@ class CommandBuffer:
316
352
  # original semantics.
317
353
  self._change_mode: str | None = None
318
354
  self._user: dict[str, str] | None = None
355
+ # A batch the background idle timer failed to deliver. The timer
356
+ # thread can't raise into user code, so the failure is stashed here
357
+ # and re-raised on the NEXT buffer interaction (call/flush) — a
358
+ # dropped batch must never be reported as success by a later
359
+ # ``doc.save()`` that finds an empty buffer.
360
+ self._deferred_flush_error: Exception | None = None
319
361
  # client_node_id → list of (proxy, attr) pairs to update with the
320
362
  # real nodeId after flush. Populated by ``add_paragraph`` /
321
363
  # ``add_heading`` / etc. when they queue a Create with a
@@ -422,6 +464,7 @@ class CommandBuffer:
422
464
  proxy's ``_node_id`` in-place.
423
465
  """
424
466
  self._assert_current_execution()
467
+ self._raise_deferred_flush_error()
425
468
  if self._closed:
426
469
  raise RuntimeError(
427
470
  f"CommandBuffer for {self._asset_id} is closed",
@@ -490,6 +533,7 @@ class CommandBuffer:
490
533
  UUID swap.
491
534
  """
492
535
  self._assert_current_execution()
536
+ self._raise_deferred_flush_error()
493
537
  with self._lock:
494
538
  self._cancel_timer_locked()
495
539
  pending = self._pending
@@ -635,12 +679,54 @@ class CommandBuffer:
635
679
  self._timer.cancel()
636
680
  self._timer = None
637
681
 
682
+ def _raise_deferred_flush_error(self) -> None:
683
+ """Re-raise a failure captured by the background idle timer.
684
+
685
+ Cleared on raise so the surfaced traceback is delivered exactly once;
686
+ the batch it describes is already gone either way.
687
+ """
688
+ with self._lock:
689
+ err = self._deferred_flush_error
690
+ self._deferred_flush_error = None
691
+ if err is not None:
692
+ raise err
693
+
694
+ def discard_pending(self) -> int:
695
+ """Drop buffered commands without sending them; return the count.
696
+
697
+ Used by the sandbox executor when user code raised: posting the dead
698
+ script's half-buffered tail writes content whose prerequisites failed
699
+ (and duplicates it when the agent retries the whole script).
700
+
701
+ Best-effort: only commands still sitting in the pending queue are
702
+ dropped. A batch the idle timer has already drained and handed to the
703
+ HTTP client is in flight and cannot be recalled (the module
704
+ docstring's timer-race note applies here too).
705
+ """
706
+ with self._lock:
707
+ self._cancel_timer_locked()
708
+ pending = self._pending
709
+ self._pending = []
710
+ self._proxy_id_refs = {}
711
+ self._deferred_flush_error = None
712
+ _ptc_emit_end_batch(pending, is_error=True)
713
+ return len(pending)
714
+
638
715
  def _auto_flush(self) -> None:
639
716
  if self.is_stale_for_current_execution:
640
717
  return
641
718
  try:
642
719
  self.flush()
643
720
  except Exception as e: # noqa: BLE001
721
+ # The timer thread has no caller to raise into. Record the
722
+ # failure so the next call()/flush() (e.g. ``doc.save()``)
723
+ # surfaces it instead of reporting a drained buffer as success.
724
+ e.add_note(
725
+ "raised by a background docx-sdk auto-flush that failed earlier; "
726
+ "the commands in that batch were NOT applied",
727
+ )
728
+ with self._lock:
729
+ self._deferred_flush_error = e
644
730
  sys.stderr.write(
645
731
  f"[docx-sdk] auto-flush failed for {self._asset_id}: {e}\n",
646
732
  )
@@ -652,4 +738,4 @@ class CommandBuffer:
652
738
  )
653
739
 
654
740
 
655
- __all__ = ["CommandBuffer", "flush_all", "DEFAULT_AUTO_FLUSH_SECONDS"]
741
+ __all__ = ["CommandBuffer", "flush_all", "discard_all", "DEFAULT_AUTO_FLUSH_SECONDS"]
@@ -223,9 +223,14 @@ class Session:
223
223
 
224
224
  handle = self._doc_handle
225
225
  buffer = getattr(handle, "buffer", None) if handle is not None else None
226
- if buffer is not None:
227
- buffer.flush()
228
- _log_info(f"Saved {self._asset_id} (buffer drained)")
226
+ if buffer is None:
227
+ _log_info(f"Saved {self._asset_id} (no command buffer)")
228
+ return
229
+ flushed = buffer.flush()
230
+ # flush() raises on delivery failure — including one captured earlier
231
+ # by the background auto-flush — so this success line is only reached
232
+ # when nothing the buffer ever held was silently dropped.
233
+ _log_info(f"Saved {self._asset_id} ({len(flushed)} buffered command(s) flushed)")
229
234
 
230
235
  async def close(self) -> None:
231
236
  """Close the session. Idempotent."""
@@ -458,6 +458,13 @@ class Table:
458
458
  # Cells written before 0.15 (the pre-tracking world) silently fall
459
459
  # back to the legacy append behavior on their first 0.15+ rewrite.
460
460
  self._written_cells: set[tuple[int, int]] = set()
461
+ # Cell → plain text the SDK itself wrote this session via ``.text``.
462
+ # Powers the read-free ``_Cell.paragraphs``/``runs`` fast path: while
463
+ # a cell's full content is SDK-known (single plain-text run), header/
464
+ # zebra formatting loops need zero query round-trips. Any write the
465
+ # SDK can't model (markdown text, ``add_paragraph``, cell-inner
466
+ # ``add_run``) evicts the entry and restores the query path.
467
+ self._fastpath_cell_text: dict[tuple[int, int], str] = {}
461
468
 
462
469
  def _fresh_node_info(self) -> tuple[str, dict]:
463
470
  """Resolve the live nodeId and return ``(node_id, info_dict)``.
@@ -1900,6 +1907,10 @@ class _Cell:
1900
1907
  # to the same position takes the clear-then-insert branch above
1901
1908
  # (see ``Table._written_cells`` docstring).
1902
1909
  self._table._written_cells.add(cell_key)
1910
+ if _is_plain_text(value) and value:
1911
+ self._table._fastpath_cell_text[cell_key] = value
1912
+ else:
1913
+ self._table._fastpath_cell_text.pop(cell_key, None)
1903
1914
  return
1904
1915
  except Exception as e:
1905
1916
  raise RuntimeError(
@@ -1920,6 +1931,38 @@ class _Cell:
1920
1931
  # debugger and gives ``_apply_inline`` and friends something
1921
1932
  # stable to consult when we eventually add a materialization
1922
1933
  # fallback at the SDK layer.
1934
+ fast_text = self._table._fastpath_cell_text.get((self._row, self._col))
1935
+ if fast_text is not None:
1936
+ positional = self._positional_cell_id()
1937
+ if positional is not None:
1938
+ # Read-free fast path: the SDK wrote this cell's entire
1939
+ # content itself (one plain-text run), so it can hand back a
1940
+ # positional paragraph proxy without the per-cell
1941
+ # ``getNodeById`` walk. Formatting on its runs buffers a
1942
+ # whole-cell ``FormatApply`` against the ``tc:`` id — the
1943
+ # applier's documented cell-formatting semantics — so header/
1944
+ # zebra loops batch instead of paying one Y.Doc reload per
1945
+ # cell.
1946
+ ooxml_base = self._ooxml_address_base()
1947
+ fast_p = Paragraph(
1948
+ session=self._table._session,
1949
+ node_id=positional,
1950
+ node_type="paragraph",
1951
+ in_cell=True,
1952
+ cell_ooxml_address=(
1953
+ (*ooxml_base, 0) if ooxml_base is not None else None
1954
+ ),
1955
+ cell=self,
1956
+ )
1957
+ fast_p._cell_inner = True # type: ignore[attr-defined]
1958
+ fast_p._cell_address = { # type: ignore[attr-defined]
1959
+ "kind": "block",
1960
+ "nodeType": "tableCell",
1961
+ "nodeId": positional,
1962
+ }
1963
+ fast_p._fastpath_runs_text = fast_text # type: ignore[attr-defined]
1964
+ return [fast_p]
1965
+
1923
1966
  pids = self._inner_paragraph_ids()
1924
1967
  # Resolve the cell address ONCE and re-use it for every
1925
1968
  # paragraph; the original draft called ``self._cell_address()``
@@ -1988,6 +2031,9 @@ class _Cell:
1988
2031
  ) -> "Paragraph":
1989
2032
  """Append a paragraph to the cell.
1990
2033
 
2034
+ Evicts the cell from the read-free ``paragraphs`` fast path — the
2035
+ cell no longer holds the single SDK-written run that path models.
2036
+
1991
2037
  Mirrors python-docx ``_Cell.add_paragraph(text, style)``. The
1992
2038
  ``style`` argument accepts either a style id string or a
1993
2039
  :class:`docx.styles.style.ParagraphStyle` instance; previously
@@ -2025,6 +2071,10 @@ class _Cell:
2025
2071
  f"{type(style).__name__} {style!r}",
2026
2072
  )
2027
2073
 
2074
+ # Evict AFTER validation so a rejected call leaves the read-free
2075
+ # fast path intact (nothing mutated).
2076
+ self._table._fastpath_cell_text.pop((self._row, self._col), None)
2077
+
2028
2078
  fragment: dict = {
2029
2079
  "kind": "paragraph",
2030
2080
  "paragraph": {
@@ -448,6 +448,27 @@ class Paragraph:
448
448
  """
449
449
  from docx.text.run import Run
450
450
 
451
+ fast_text: object = getattr(self, "_fastpath_runs_text", None)
452
+ if isinstance(fast_text, str) and fast_text:
453
+ # Read-free fast path for a cell paragraph whose entire content
454
+ # the SDK wrote itself (see ``Table._fastpath_cell_text``): one
455
+ # synthetic run over the known text, no ``getNodeById`` walk.
456
+ # Format setters on it buffer a whole-cell ``FormatApply``
457
+ # against the positional ``tc:`` id; property READS may still
458
+ # trigger a live walk (the applier resolves ``tc:`` ids), so
459
+ # only the hot format-loop path is short-circuited.
460
+ self._text_len = len(fast_text)
461
+ fast_run = Run(
462
+ session=self._session,
463
+ block_id=self._node_id,
464
+ range_=(0, len(fast_text)),
465
+ inline={"type": "text", "text": fast_text},
466
+ in_cell=self._in_cell,
467
+ cell_ooxml_address=self._cell_ooxml_address,
468
+ )
469
+ fast_run._fastpath_text = fast_text # type: ignore[attr-defined]
470
+ return [fast_run]
471
+
451
472
  info: object = self._node_info()
452
473
  inlines: list[dict] = _walk_inlines(info)
453
474
  runs: list["Run"] = []
@@ -1131,6 +1152,19 @@ class Paragraph:
1131
1152
  f"or None; got {type(style).__name__} {style!r}",
1132
1153
  )
1133
1154
 
1155
+ # Content beyond the single SDK-written run: evict this paragraph's
1156
+ # cell from the read-free fast path so the next ``paragraphs``/
1157
+ # ``runs`` read reflects real server state. After validation so a
1158
+ # rejected call leaves the fast path intact (nothing mutated).
1159
+ self._fastpath_runs_text = None # type: ignore[attr-defined]
1160
+ cell = self._cell
1161
+ table = getattr(cell, "_table", None) if cell is not None else None
1162
+ if table is not None:
1163
+ row = getattr(cell, "_row", None)
1164
+ col = getattr(cell, "_col", None)
1165
+ if row is not None and col is not None:
1166
+ getattr(table, "_fastpath_cell_text", {}).pop((row, col), None)
1167
+
1134
1168
  # Use the cached paragraph text length when known — every
1135
1169
  # avoided ``_node_text`` here drops one ``get_node_by_id`` HTTP
1136
1170
  # round-trip. Linear ``doc.add_paragraph(); p.add_run(...);
@@ -336,6 +336,12 @@ class Run:
336
336
  # ---- text ----
337
337
  @property
338
338
  def text(self) -> str:
339
+ # Fast-path runs (see ``Table._fastpath_cell_text``) carry their
340
+ # known text — the whole point is zero read round-trips. Mutations
341
+ # through this proxy keep the attr in sync or clear it.
342
+ fast: object = getattr(self, "_fastpath_text", None)
343
+ if isinstance(fast, str):
344
+ return fast
339
345
  full: str = _block_text(self._session, self._block_id)
340
346
  return full[self._range[0] : self._range[1]]
341
347
 
@@ -399,7 +405,10 @@ class Run:
399
405
  f"{value!r}",
400
406
  )
401
407
  if self._check_cell_inner("text"):
408
+ # Warn-and-skip: nothing mutated, so the fast-path text cache
409
+ # (when present) still reflects reality — keep it.
402
410
  return
411
+ self._fastpath_text = None # type: ignore[attr-defined]
403
412
  old_len: int = self._range[1] - self._range[0]
404
413
  run_sync(
405
414
  self._session.doc.replace(
@@ -435,6 +444,7 @@ class Run:
435
444
  in_cell=True,
436
445
  cell_ooxml_address=getattr(self, "_cell_ooxml_address", None),
437
446
  )
447
+ self._fastpath_text = None # type: ignore[attr-defined]
438
448
  end: int = self._range[1]
439
449
  cursor: dict = {"kind": "text", "blockId": self._block_id, "offset": end}
440
450
  run_sync(
@@ -658,12 +668,27 @@ class Run:
658
668
  h_px: float = _emu_to_px(h_emu)
659
669
  w_pt: float = w_emu / 12700.0
660
670
  h_pt: float = h_emu / 12700.0
671
+ # Anchor inside this run's paragraph so the picture lands inline and
672
+ # inherits the paragraph's alignment/spacing — python-docx semantics,
673
+ # where ``run.add_picture`` places the image in that run's paragraph.
674
+ # Cell-inner paragraphs keep the legacy document-end block: their
675
+ # blockIds are not addressable by the applier's selection resolver.
676
+ at: dict = {"kind": "documentEnd"}
677
+ if not getattr(self, "_in_cell", False) and self._block_id:
678
+ at = {
679
+ "kind": "selection",
680
+ "start": {
681
+ "kind": "text",
682
+ "blockId": self._block_id,
683
+ "offset": self._range[1],
684
+ },
685
+ }
661
686
  result: object = run_sync(
662
687
  self._session.doc.create.image(
663
688
  {
664
689
  "src": data_uri,
665
690
  "size": {"width": w_px, "height": h_px},
666
- "at": {"kind": "documentEnd"},
691
+ "at": at,
667
692
  },
668
693
  ),
669
694
  )
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "athena-python-docx"
7
- version = "0.21.3"
7
+ version = "0.21.6"
8
8
  description = "Drop-in replacement for python-docx that connects to Athena's DOCX Studio collaborative document stack"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -162,6 +162,31 @@ class FakeDocState:
162
162
  return t
163
163
  return None
164
164
 
165
+ def _resolve_cell_ref(self, node_id: object) -> tuple[_Table, int, int, _Block] | None:
166
+ if not isinstance(node_id, str) or not node_id:
167
+ return None
168
+
169
+ parts = node_id.split(":")
170
+ if len(parts) == 4 and parts[0] == "tc":
171
+ try:
172
+ table_idx = int(parts[1])
173
+ row_idx = int(parts[2])
174
+ col_idx = int(parts[3])
175
+ except ValueError:
176
+ return None
177
+ if 0 <= table_idx < len(self.tables):
178
+ table = self.tables[table_idx]
179
+ if 0 <= row_idx < len(table.cells) and 0 <= col_idx < len(table.cells[row_idx]):
180
+ return (table, row_idx, col_idx, table.cells[row_idx][col_idx])
181
+ return None
182
+
183
+ for table in self.tables:
184
+ for row_idx, row in enumerate(table.cells):
185
+ for col_idx, cell in enumerate(row):
186
+ if node_id in {cell.node_id, f"cell_{table.node_id}_{row_idx}_{col_idx}"}:
187
+ return (table, row_idx, col_idx, cell)
188
+ return None
189
+
165
190
  def respond(self, op: str, params: dict) -> Any:
166
191
  # ---- header/footer part orchestration ----
167
192
  # _HeaderFooter.add_paragraph / add_table mint a new part on
@@ -273,33 +298,29 @@ class FakeDocState:
273
298
  "node": node,
274
299
  "address": {"kind": "block", "nodeType": b.node_type, "nodeId": b.node_id},
275
300
  }
276
- # Table cell
277
- for t in self.tables:
278
- for r_idx, row in enumerate(t.cells):
279
- for c_idx, cell in enumerate(row):
280
- if cell.node_id == nid or (
281
- params.get("nodeType") == "tableCell"
282
- and nid == f"cell_{t.node_id}_{r_idx}_{c_idx}"
283
- ):
284
- # Return a tree containing the inner paragraph
285
- inner = {
286
- "type": "paragraph",
287
- "attrs": {"nodeId": cell.node_id},
288
- "content": [{"type": "text", "text": cell.text}]
289
- if cell.text
290
- else [],
291
- }
292
- return {
293
- "node": {
294
- "nodeType": "tableCell",
295
- "tableCell": {"content": [inner]},
296
- },
297
- "address": {
298
- "kind": "block",
299
- "nodeType": "tableCell",
300
- "nodeId": cell.node_id,
301
- },
302
- }
301
+ # Table cell. The real docx-editor surface addresses cells by
302
+ # positional ids (tc:<tableIndex>:<row>:<col>), while DOCX Studio
303
+ # also exposes table-specific ids from tables.getCells. Support
304
+ # both so the fake exercises the same no-query fast path as agents.
305
+ cell_ref = self._resolve_cell_ref(nid)
306
+ if cell_ref is not None:
307
+ _table, _row_idx, _col_idx, cell = cell_ref
308
+ inner = {
309
+ "type": "paragraph",
310
+ "attrs": {"nodeId": cell.node_id},
311
+ "content": [{"type": "text", "text": cell.text}] if cell.text else [],
312
+ }
313
+ return {
314
+ "node": {
315
+ "nodeType": "tableCell",
316
+ "tableCell": {"content": [inner]},
317
+ },
318
+ "address": {
319
+ "kind": "block",
320
+ "nodeType": "tableCell",
321
+ "nodeId": cell.node_id,
322
+ },
323
+ }
303
324
  return {"node": {}, "address": {}}
304
325
 
305
326
  if op == "blocks.list":
@@ -515,16 +536,11 @@ class FakeDocState:
515
536
  if isinstance(t, str):
516
537
  appended += t
517
538
  # Find cell and append to its first paragraph.
518
- for t in self.tables:
519
- for r_idx, row in enumerate(t.cells):
520
- for c_idx, cell in enumerate(row):
521
- expected_ids = {
522
- f"cell_{t.node_id}_{r_idx}_{c_idx}",
523
- cell.node_id,
524
- }
525
- if cell_nid in expected_ids:
526
- cell.text = cell.text + appended
527
- cell.inlines = [{"run": {"text": cell.text}}] if cell.text else []
539
+ cell_ref = self._resolve_cell_ref(cell_nid)
540
+ if cell_ref is not None:
541
+ _table, _row_idx, _col_idx, cell = cell_ref
542
+ cell.text = cell.text + appended
543
+ cell.inlines = [{"run": {"text": cell.text}}] if cell.text else []
528
544
  return {"ok": True}
529
545
 
530
546
  # TableSetCell: address a cell by (tableNodeId, row, col) and
@@ -979,15 +995,13 @@ class FakeDocState:
979
995
  if op == "tables.setCellProperties":
980
996
  target = params.get("target") or {}
981
997
  nid = target.get("nodeId") or params.get("nodeId")
982
- # Find the cell
983
- for t in self.tables:
984
- for r_idx, row in enumerate(t.cells):
985
- for c_idx, _cell in enumerate(row):
986
- if nid == f"cell_{t.node_id}_{r_idx}_{c_idx}":
987
- if "verticalAlign" in params:
988
- t.cell_verticals[r_idx][c_idx] = params["verticalAlign"]
989
- if "preferredWidthPt" in params:
990
- t.cell_widths[r_idx][c_idx] = params["preferredWidthPt"]
998
+ cell_ref = self._resolve_cell_ref(nid)
999
+ if cell_ref is not None:
1000
+ t, r_idx, c_idx, _cell = cell_ref
1001
+ if "verticalAlign" in params:
1002
+ t.cell_verticals[r_idx][c_idx] = params["verticalAlign"]
1003
+ if "preferredWidthPt" in params:
1004
+ t.cell_widths[r_idx][c_idx] = params["preferredWidthPt"]
991
1005
  return {"ok": True}
992
1006
  if op == "tables.setTableOptions":
993
1007
  # Per DOCX Studio 1.8.1 setTableOptions only handles
@@ -0,0 +1,6 @@
1
+ [
2
+ "create.table",
3
+ "tables.setCellProperties",
4
+ "tables.setCellProperties",
5
+ "tables.setCellProperties"
6
+ ]
@@ -0,0 +1,9 @@
1
+ [
2
+ "create.table",
3
+ "tables.setCell",
4
+ "insert",
5
+ "getNodeById",
6
+ "getNodeById",
7
+ "getNodeById",
8
+ "getNodeById"
9
+ ]
@@ -0,0 +1,39 @@
1
+ [
2
+ "sections.list",
3
+ "sections.setPageMargins",
4
+ "sections.setPageMargins",
5
+ "create.paragraph",
6
+ "styles.paragraph.setStyle",
7
+ "format.paragraph.setAlignment",
8
+ "create.paragraph",
9
+ "insert",
10
+ "format.apply",
11
+ "insert",
12
+ "insert",
13
+ "format.apply",
14
+ "format.apply",
15
+ "insert",
16
+ "format.paragraph.setSpacing",
17
+ "create.heading",
18
+ "create.table",
19
+ "tables.setStyle",
20
+ "tables.get",
21
+ "tables.setLayout",
22
+ "tables.get",
23
+ "tables.get",
24
+ "tables.setCell",
25
+ "tables.setCell",
26
+ "tables.setCell",
27
+ "tables.setCellProperties",
28
+ "format.apply",
29
+ "tables.setCellProperties",
30
+ "format.apply",
31
+ "tables.setCellProperties",
32
+ "format.apply",
33
+ "tables.setCell",
34
+ "tables.setCell",
35
+ "tables.setCell",
36
+ "tables.setCell",
37
+ "tables.setCell",
38
+ "tables.setCell"
39
+ ]
@@ -1,8 +1,6 @@
1
1
  [
2
2
  "create.table",
3
3
  "tables.setCell",
4
- "tables.get",
5
- "tables.getCells",
6
4
  "getNodeById",
7
5
  "getNodeById"
8
6
  ]
@@ -29,16 +29,10 @@
29
29
  "tables.get",
30
30
  "tables.setLayout",
31
31
  "tables.setCell",
32
- "tables.get",
33
- "tables.getCells",
34
32
  "tables.setCellProperties",
35
33
  "tables.setCell",
36
- "tables.get",
37
- "tables.getCells",
38
34
  "tables.setCellProperties",
39
35
  "tables.setCell",
40
- "tables.get",
41
- "tables.getCells",
42
36
  "tables.setCellProperties",
43
37
  "tables.setCell",
44
38
  "tables.setCell",
@@ -0,0 +1,8 @@
1
+ [
2
+ "create.table",
3
+ "tables.setCell",
4
+ "getNodeById",
5
+ "insert",
6
+ "getNodeById",
7
+ "getNodeById"
8
+ ]
@@ -0,0 +1,19 @@
1
+ [
2
+ "create.table",
3
+ "insert",
4
+ "getNodeById",
5
+ "getNodeById",
6
+ "insert",
7
+ "getNodeById",
8
+ "getNodeById",
9
+ "insert",
10
+ "getNodeById",
11
+ "getNodeById",
12
+ "insert",
13
+ "getNodeById",
14
+ "getNodeById",
15
+ "insert",
16
+ "getNodeById",
17
+ "getNodeById",
18
+ "getNodeById"
19
+ ]