athena-python-docx 0.28.0__tar.gz → 0.30.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 (444) hide show
  1. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/AGENTS.md +148 -38
  2. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/PKG-INFO +1 -1
  3. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/__init__.py +1 -1
  4. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/_buffer.py +49 -12
  5. athena_python_docx-0.30.0/docx/_capabilities.py +38 -0
  6. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/_http_doc.py +247 -26
  7. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/_postproc.py +25 -0
  8. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/_run_order.py +149 -3
  9. athena_python_docx-0.30.0/docx/_tracked.py +40 -0
  10. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/bookmarks.py +13 -9
  11. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/commands.py +92 -18
  12. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/comments.py +135 -46
  13. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/document.py +109 -40
  14. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/enum/shape.py +6 -2
  15. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/errors.py +19 -3
  16. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/fields.py +17 -3
  17. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/sdt.py +19 -0
  18. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/section.py +90 -79
  19. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/shape.py +52 -4
  20. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/table.py +239 -56
  21. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/text/paragraph.py +194 -13
  22. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/text/run.py +168 -31
  23. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/pyproject.toml +1 -1
  24. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/ab_probe_cases.py +21 -0
  25. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/15_run_add_break_page.json +1 -0
  26. athena_python_docx-0.30.0/tests/fidelity/op_snapshots/54_empty_everything.json +6 -0
  27. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/56_everything_in_one.json +2 -0
  28. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/96_paragraph_contains_page_break.json +1 -0
  29. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/99_run_add_picture_from_bytes.json +1 -0
  30. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/ex16_runs_interleaved_with_breaks.json +1 -0
  31. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/ex17_all_break_kinds.json +1 -0
  32. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/ex20_kitchen_sink_v2.json +7 -0
  33. athena_python_docx-0.30.0/tests/fidelity/op_snapshots/rw16_header_footer_tables.json +15 -0
  34. athena_python_docx-0.30.0/tests/fidelity/op_snapshots/rw17_header_letterhead_filled.json +21 -0
  35. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/real_world_cases.py +34 -0
  36. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fixtures/note_reference_reads.json +71 -1
  37. athena_python_docx-0.30.0/tests/fixtures/ruby_reads.json +204 -0
  38. athena_python_docx-0.30.0/tests/fixtures/symbol_reads.json +163 -0
  39. athena_python_docx-0.30.0/tests/live/baseline.json +258 -0
  40. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/live/reader.py +12 -0
  41. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/live/runner.py +51 -9
  42. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/live/test_live_runner.py +28 -0
  43. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/parity/intentional_deviations.json +49 -0
  44. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_athena_extensions_registry.py +1 -0
  45. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_batch_chunking.py +166 -0
  46. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_cell_fastpath_runs.py +5 -1
  47. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_cell_paragraphs_listed.py +1 -0
  48. athena_python_docx-0.30.0/tests/test_comment_paragraphs.py +184 -0
  49. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_comments.py +17 -9
  50. athena_python_docx-0.30.0/tests/test_content_control_value.py +75 -0
  51. athena_python_docx-0.30.0/tests/test_empty_hyperlinks.py +91 -0
  52. athena_python_docx-0.30.0/tests/test_export_docx_clean.py +138 -0
  53. athena_python_docx-0.30.0/tests/test_field_refresh.py +32 -0
  54. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_field_runs.py +5 -0
  55. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_http_transport.py +5 -1
  56. athena_python_docx-0.30.0/tests/test_inline_page_break.py +70 -0
  57. athena_python_docx-0.30.0/tests/test_inline_shape_type.py +95 -0
  58. athena_python_docx-0.30.0/tests/test_inline_shapes_floating.py +60 -0
  59. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_note_reference_reads_python_docx_parity.py +9 -5
  60. athena_python_docx-0.30.0/tests/test_paragraph_delete.py +186 -0
  61. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_parity_misc.py +2 -2
  62. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_phase_b_headers_footers.py +110 -2
  63. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_postproc_ref_restore.py +48 -0
  64. athena_python_docx-0.30.0/tests/test_read_run_ranges.py +153 -0
  65. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_revisions.py +55 -1
  66. athena_python_docx-0.30.0/tests/test_ruby_reads_python_docx_parity.py +192 -0
  67. athena_python_docx-0.30.0/tests/test_run_edges.py +138 -0
  68. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_run_identity.py +1 -0
  69. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_run_mark_inheritance.py +88 -42
  70. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_document_audit.py +44 -54
  71. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_header_footer.py +32 -17
  72. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_misc.py +7 -13
  73. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_table_audit.py +93 -0
  74. athena_python_docx-0.30.0/tests/test_symbol_reads_python_docx_parity.py +122 -0
  75. athena_python_docx-0.30.0/tests/test_table_read_reuse.py +266 -0
  76. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_text_control_characters.py +11 -5
  77. athena_python_docx-0.30.0/tests/test_tracked_revisions_offsets.py +183 -0
  78. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_wire_contract.py +7 -1
  79. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/uv.lock +1 -1
  80. athena_python_docx-0.28.0/tests/fidelity/op_snapshots/54_empty_everything.json +0 -4
  81. athena_python_docx-0.28.0/tests/live/baseline.json +0 -1925
  82. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/.gitignore +0 -0
  83. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/CLAUDE.md +0 -0
  84. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/DOCX_EXEC_LAB.md +0 -0
  85. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/README.md +0 -0
  86. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/_athena_extension.py +0 -0
  87. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/_batching.py +0 -0
  88. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/_citations.py +0 -0
  89. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/_execution.py +0 -0
  90. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/_http.py +0 -0
  91. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/_image_utils.py +0 -0
  92. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/_ptc.py +0 -0
  93. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/_references.py +0 -0
  94. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/_table_styles.py +0 -0
  95. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/_timeouts.py +0 -0
  96. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/api.py +0 -0
  97. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/blkcntnr.py +0 -0
  98. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/charts.py +0 -0
  99. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/client.py +0 -0
  100. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/drawing/__init__.py +0 -0
  101. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/enum/__init__.py +0 -0
  102. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/enum/base.py +0 -0
  103. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/enum/dml.py +0 -0
  104. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/enum/section.py +0 -0
  105. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/enum/style.py +0 -0
  106. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/enum/table.py +0 -0
  107. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/enum/text.py +0 -0
  108. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/exceptions.py +0 -0
  109. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/footnotes.py +0 -0
  110. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/image/__init__.py +0 -0
  111. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/image/exceptions.py +0 -0
  112. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/image/image.py +0 -0
  113. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/math.py +0 -0
  114. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/opc/__init__.py +0 -0
  115. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/opc/coreprops.py +0 -0
  116. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/oxml/__init__.py +0 -0
  117. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/revisions.py +0 -0
  118. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/session.py +0 -0
  119. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/settings.py +0 -0
  120. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/shared.py +0 -0
  121. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/styles/__init__.py +0 -0
  122. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/styles/_table.py +0 -0
  123. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/styles/latent.py +0 -0
  124. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/styles/style.py +0 -0
  125. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/styles/styles.py +0 -0
  126. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/text/__init__.py +0 -0
  127. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/text/font.py +0 -0
  128. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/text/hyperlink.py +0 -0
  129. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/text/pagebreak.py +0 -0
  130. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/text/parfmt.py +0 -0
  131. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/text/tabstops.py +0 -0
  132. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/toc.py +0 -0
  133. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/docx/typing.py +0 -0
  134. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/scripts/docx_exec_lab.py +0 -0
  135. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/scripts/docx_exec_lab_examples/fast_table_fill.py +0 -0
  136. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/scripts/docx_exec_lab_examples/find_replace_literal.py +0 -0
  137. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/scripts/docx_exec_lab_server.py +0 -0
  138. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/scripts/dump_wire_fixtures.py +0 -0
  139. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/scripts/release.sh +0 -0
  140. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/scripts/round_trip_smoke.py +0 -0
  141. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/scripts/smoke_test_block_not_found.py +0 -0
  142. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/scripts/validate_find_replace_asset.py +0 -0
  143. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/__init__.py +0 -0
  144. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/conftest.py +0 -0
  145. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/METHODOLOGY.md +0 -0
  146. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/README.md +0 -0
  147. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/__init__.py +0 -0
  148. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/ab_probe_runner.py +0 -0
  149. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/auto_gen_cases.py +0 -0
  150. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/binary_round_trip.py +0 -0
  151. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/cases.py +0 -0
  152. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/complex_cases.py +0 -0
  153. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/coverage_report.py +0 -0
  154. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/extract.py +0 -0
  155. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/extreme_cases.py +0 -0
  156. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/fake_session.py +0 -0
  157. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/firm_templates/README.md +0 -0
  158. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/firm_templates/__init__.py +0 -0
  159. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/firm_templates/_runner.py +0 -0
  160. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/firm_templates/extractor.py +0 -0
  161. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/firm_templates/test_pw_corpus.py +0 -0
  162. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/firm_templates/test_pw_research_digest.py +0 -0
  163. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/local_runner.py +0 -0
  164. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/mega_cases.py +0 -0
  165. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshot.py +0 -0
  166. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/01_basic_paragraph.json +0 -0
  167. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/02_multiple_headings.json +0 -0
  168. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/03_runs_with_formatting.json +0 -0
  169. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/04_font_name_and_size.json +0 -0
  170. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/05_font_color_rgb.json +0 -0
  171. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/06_font_character_properties.json +0 -0
  172. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/07_font_subscript_superscript.json +0 -0
  173. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/08_font_highlight.json +0 -0
  174. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/09_paragraph_alignment.json +0 -0
  175. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/100_table_negative_indexing.json +0 -0
  176. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/101_table_cells_flat_iteration.json +0 -0
  177. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/102_text_with_embedded_special_chars.json +0 -0
  178. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/104_core_properties_datetime.json +0 -0
  179. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/105_default_one_section.json +0 -0
  180. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/106_heading_paragraph_format.json +0 -0
  181. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/107_varying_row_heights.json +0 -0
  182. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/10_paragraph_indents.json +0 -0
  183. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/11_paragraph_spacing.json +0 -0
  184. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/12_paragraph_keep_options.json +0 -0
  185. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/13_paragraph_tab_stops.json +0 -0
  186. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/14_run_add_tab_and_break.json +0 -0
  187. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/16_paragraph_clear_and_insert_before.json +0 -0
  188. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/17_table_basic.json +0 -0
  189. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/18_table_cell_text.json +0 -0
  190. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/19_table_row_column_sizing.json +0 -0
  191. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/20_table_cell_vertical_alignment.json +0 -0
  192. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/21_table_alignment_and_autofit.json +0 -0
  193. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/22_table_cell_paragraphs_iteration.json +0 -0
  194. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/24_table_add_row_column.json +0 -0
  195. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/25_table_merge_cells.json +0 -0
  196. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/26_section_page_setup.json +0 -0
  197. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/27_section_margins.json +0 -0
  198. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/28_section_add_new.json +0 -0
  199. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/29_section_headers_linked.json +0 -0
  200. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/30_styles_iteration.json +0 -0
  201. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/31_styles_lookup_and_default.json +0 -0
  202. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/32_styles_add_paragraph_style.json +0 -0
  203. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/33_core_properties_set_and_get.json +0 -0
  204. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/34_inline_shapes_iterate_empty.json +0 -0
  205. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/35_full_report.json +0 -0
  206. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/36_replace_text_in_paragraph.json +0 -0
  207. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/37_iterate_runs_and_format_all_bold.json +0 -0
  208. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/38_font_all_properties.json +0 -0
  209. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/39_large_body_100_paragraphs.json +0 -0
  210. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/40_large_table_10x10.json +0 -0
  211. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/41_unicode_and_emoji.json +0 -0
  212. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/42_very_long_paragraph.json +0 -0
  213. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/43_paragraph_text_round_trip.json +0 -0
  214. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/44_paragraph_alignment_round_trip.json +0 -0
  215. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/45_cell_text_round_trip.json +0 -0
  216. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/46_run_text_setter_round_trip.json +0 -0
  217. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/47_font_size_round_trip.json +0 -0
  218. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/48_font_color_round_trip.json +0 -0
  219. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/49_resume_layout.json +0 -0
  220. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/50_multi_section_doc.json +0 -0
  221. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/52_iterate_everything.json +0 -0
  222. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/53_apply_style_to_paragraphs.json +0 -0
  223. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/55_single_character_runs.json +0 -0
  224. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/57_runs_after_multiple_text_appends.json +0 -0
  225. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/58_modify_runs_in_place.json +0 -0
  226. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/59_indent_round_trip.json +0 -0
  227. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/60_space_round_trip.json +0 -0
  228. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/61_cell_paragraph_with_runs.json +0 -0
  229. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/62_many_cell_paragraphs.json +0 -0
  230. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/63_table_style_round_trip.json +0 -0
  231. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/64_many_sections.json +0 -0
  232. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/65_20x20_table_formatted.json +0 -0
  233. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/66_toc_like_structure.json +0 -0
  234. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/67_paragraph_insert_before_chain.json +0 -0
  235. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/68_invoice.json +0 -0
  236. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/69_newsletter.json +0 -0
  237. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/70_add_and_iterate_back.json +0 -0
  238. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/71_academic_paper.json +0 -0
  239. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/72_legal_contract.json +0 -0
  240. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/73_form_with_many_tables.json +0 -0
  241. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/74_paragraph_with_10_runs.json +0 -0
  242. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/75_paragraph_negative_first_line_indent.json +0 -0
  243. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/76_rgbcolor_from_string.json +0 -0
  244. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/77_length_unit_conversions.json +0 -0
  245. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/78_paragraph_copy_style.json +0 -0
  246. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/79_bulk_cell_formatting.json +0 -0
  247. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/80_apply_style_after_add_run.json +0 -0
  248. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/81_multi_page_with_breaks.json +0 -0
  249. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/82_add_text_on_existing_run.json +0 -0
  250. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/83_clear_then_repopulate_paragraph.json +0 -0
  251. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/84_table_reread_row_count.json +0 -0
  252. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/85_header_footer_access.json +0 -0
  253. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/86_font_read_unset_returns_none.json +0 -0
  254. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/87_500_paragraph_doc.json +0 -0
  255. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/88_mixed_content_iteration.json +0 -0
  256. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/89_alignment_clear_via_none.json +0 -0
  257. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/90_cell_add_paragraph_styled.json +0 -0
  258. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/91_many_small_tables.json +0 -0
  259. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/92_margins_every_section.json +0 -0
  260. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/93_font_bool_reads_after_set.json +0 -0
  261. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/94_page_break_before_paragraph.json +0 -0
  262. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/95_paragraph_hyperlinks_empty.json +0 -0
  263. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/97_document_styles_by_key.json +0 -0
  264. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/98_style_contains_check.json +0 -0
  265. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/ex02_unicode_everywhere.json +0 -0
  266. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/ex03_1000_paragraphs.json +0 -0
  267. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/ex04_50x50_table.json +0 -0
  268. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/ex05_long_text_in_cell.json +0 -0
  269. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/ex06_hundred_tiny_runs.json +0 -0
  270. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/ex07_every_font_boolean.json +0 -0
  271. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/ex08_many_continuous_sections.json +0 -0
  272. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/ex09_many_tab_stops.json +0 -0
  273. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/ex10_complex_bom.json +0 -0
  274. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/ex11_banded_rows_formatting.json +0 -0
  275. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/ex12_section_reconfigure.json +0 -0
  276. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/ex13_cell_with_10_paragraphs.json +0 -0
  277. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/ex14_styled_report_table.json +0 -0
  278. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/ex15_paragraph_all_format_props.json +0 -0
  279. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/ex18_read_back_large_doc.json +0 -0
  280. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/ex19_mutate_all_runs.json +0 -0
  281. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/mega01_book_chapter.json +0 -0
  282. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/mega02_research_proposal.json +0 -0
  283. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/mega03_financial_statement.json +0 -0
  284. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/mega04_recipe_card.json +0 -0
  285. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/mega05_user_manual.json +0 -0
  286. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/mega06_complex_newsletter.json +0 -0
  287. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/mega07_budget_spreadsheet.json +0 -0
  288. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/mega08_product_catalog.json +0 -0
  289. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/mega09_signed_contract.json +0 -0
  290. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/mega10_api_documentation.json +0 -0
  291. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/rw01_official_quickstart.json +0 -0
  292. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/rw02_paragraph_style_list.json +0 -0
  293. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/rw03_character_formatting.json +0 -0
  294. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/rw04_section_page_setup.json +0 -0
  295. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/rw05_toc_pattern.json +0 -0
  296. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/rw06_meeting_minutes.json +0 -0
  297. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/rw07_dense_formatting_demo.json +0 -0
  298. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/rw08_table_merged_header.json +0 -0
  299. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/rw09_bulk_run_iteration.json +0 -0
  300. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/rw10_colored_grid_table.json +0 -0
  301. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/rw11_header_text.json +0 -0
  302. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/rw12_first_page_footer.json +0 -0
  303. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/rw13_even_page_header.json +0 -0
  304. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/op_snapshots/rw15_paragraph_style_instance.json +0 -0
  305. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/ours_spec.json +0 -0
  306. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/parity_crawl.py +0 -0
  307. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/parity_diff.json +0 -0
  308. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/round_trip_tests.py +0 -0
  309. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/stock_spec.json +0 -0
  310. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fidelity/test_e2e_against_staging.py +0 -0
  311. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/fixtures/field_reads.json +0 -0
  312. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/live/__init__.py +0 -0
  313. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/live/sdk_driver.py +0 -0
  314. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/live/stock_driver.py +0 -0
  315. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/parity/README.md +0 -0
  316. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/parity/__init__.py +0 -0
  317. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/parity/baseline_gaps.json +0 -0
  318. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/parity/compare.py +0 -0
  319. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/parity/introspect.py +0 -0
  320. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/parity/reports/GAP_ANALYSIS.md +0 -0
  321. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/parity/reports/gap_report.json +0 -0
  322. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/parity/run_parity.py +0 -0
  323. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/parity/snapshots/athena_latest.json +0 -0
  324. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/parity/snapshots/upstream_python_docx_1.2.0.json +0 -0
  325. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/parity/test_parity_gap.py +0 -0
  326. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_add_section.py +0 -0
  327. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_add_section_extract_items.py +0 -0
  328. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_athena_extension_creates_session_open.py +0 -0
  329. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_athena_extensions_contract.py +0 -0
  330. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_batching_perf.py +0 -0
  331. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_block_not_found_error.py +0 -0
  332. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_buffer.py +0 -0
  333. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_cell_add_paragraph_wire_shape.py +0 -0
  334. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_cell_add_table_not_supported.py +0 -0
  335. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_cell_borders_spec.py +0 -0
  336. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_cell_inner_add_hyperlink_stash.py +0 -0
  337. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_cell_inner_add_run_via_cell_insert.py +0 -0
  338. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_cell_inner_format_stash.py +0 -0
  339. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_cell_inner_run_format_stash.py +0 -0
  340. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_cell_inner_run_guard.py +0 -0
  341. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_cell_merge.py +0 -0
  342. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_cell_text_plain_fastpath.py +0 -0
  343. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_cell_text_replace_semantics.py +0 -0
  344. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_citations.py +0 -0
  345. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_collapsed_range_format.py +0 -0
  346. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_color_format_theme.py +0 -0
  347. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_command_dataclasses.py +0 -0
  348. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_commands.py +0 -0
  349. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_core_properties.py +0 -0
  350. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_document_asset_id_property.py +0 -0
  351. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_document_clear.py +0 -0
  352. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_document_create.py +0 -0
  353. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_document_create_from_template.py +0 -0
  354. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_document_factory_validation.py +0 -0
  355. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_docx_exec_lab.py +0 -0
  356. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_docx_exec_lab_server.py +0 -0
  357. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_drawing_image.py +0 -0
  358. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_e2e_partial_failure_cascade.py +0 -0
  359. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_enum_parity.py +0 -0
  360. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_execution_scope.py +0 -0
  361. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_field_reads_python_docx_parity.py +0 -0
  362. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_find_replace_session_open.py +0 -0
  363. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_hyperlink_coalescing.py +0 -0
  364. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_image_url_data_uri.py +0 -0
  365. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_inline_shape_alt_text.py +0 -0
  366. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_inline_shape_size.py +0 -0
  367. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_insert_deferred.py +0 -0
  368. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_iter_inner_content.py +0 -0
  369. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_list_styles.py +0 -0
  370. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_merged_cell_secondary_slot.py +0 -0
  371. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_merged_cells.py +0 -0
  372. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_missing_modules.py +0 -0
  373. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_oxml_shim.py +0 -0
  374. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_page_break.py +0 -0
  375. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_paragraph_runs_hyperlinks.py +0 -0
  376. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_paragraph_text_len_cache.py +0 -0
  377. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_parity_round2.py +0 -0
  378. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_partial_failure_cascade.py +0 -0
  379. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_pdf_export_and_page_renders.py +0 -0
  380. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_phase_a_behavior.py +0 -0
  381. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_phase_c_tables.py +0 -0
  382. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_positional_cell_id.py +0 -0
  383. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_postproc_cell_format_rewrite.py +0 -0
  384. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_postproc_cell_run_format_rewrite.py +0 -0
  385. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_pr19766_review_fixes.py +0 -0
  386. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_ptc.py +0 -0
  387. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_python_docx_api_parity.py +0 -0
  388. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_repeated_node_read.py +0 -0
  389. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_restart_numbering.py +0 -0
  390. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_round_trip_smoke_script.py +0 -0
  391. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_run_add_picture_anchor.py +0 -0
  392. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_run_formatting_wire.py +0 -0
  393. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_run_table_style_objects.py +0 -0
  394. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_run_text_python_docx.py +0 -0
  395. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_run_text_refreshes_paragraph.py +0 -0
  396. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_sdk_reads_served.py +0 -0
  397. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_section_read_lengths.py +0 -0
  398. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_add_paragraph_style.py +0 -0
  399. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_add_picture.py +0 -0
  400. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_add_run.py +0 -0
  401. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_cell_add_paragraph.py +0 -0
  402. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_comments_add_comment.py +0 -0
  403. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_comments_get.py +0 -0
  404. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_document_element.py +0 -0
  405. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_enum_section.py +0 -0
  406. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_font_audit.py +0 -0
  407. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_hyperlink.py +0 -0
  408. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_inline_shape.py +0 -0
  409. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_insert_paragraph_before.py +0 -0
  410. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_paragraph_strict.py +0 -0
  411. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_paragraph_style.py +0 -0
  412. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_paragraph_style_strict.py +0 -0
  413. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_parfmt.py +0 -0
  414. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_row_col_cell.py +0 -0
  415. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_run_add_break.py +0 -0
  416. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_run_bool_setters.py +0 -0
  417. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_run_style.py +0 -0
  418. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_run_style_strict.py +0 -0
  419. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_run_text.py +0 -0
  420. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_run_underline.py +0 -0
  421. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_section_audit.py +0 -0
  422. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_section_dimensions.py +0 -0
  423. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_section_onoff.py +0 -0
  424. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_settings.py +0 -0
  425. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_shared_audit.py +0 -0
  426. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_style.py +0 -0
  427. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_styles.py +0 -0
  428. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_table_cell.py +0 -0
  429. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_table_dimensions.py +0 -0
  430. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_silent_stub_table_layout.py +0 -0
  431. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_smoke_integration.py +0 -0
  432. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_style_acceptance.py +0 -0
  433. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_style_font.py +0 -0
  434. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_style_formatting_writes.py +0 -0
  435. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_style_metadata_writes.py +0 -0
  436. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_style_names.py +0 -0
  437. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_style_setters_contract.py +0 -0
  438. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_table_set_cell_perf.py +0 -0
  439. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_table_style_id_resolution.py +0 -0
  440. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_temporarily_unavailable.py +0 -0
  441. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_uv_lock_version.py +0 -0
  442. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_validate_find_replace_asset_script.py +0 -0
  443. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_xml_attr_guard.py +0 -0
  444. {athena_python_docx-0.28.0 → athena_python_docx-0.30.0}/tests/test_zod_wire_contract.py +0 -0
@@ -40,12 +40,14 @@ These standard python-docx members don't apply to a DOCX Studio-backed SDK:
40
40
  - `Document.part`, `Paragraph.part`, `Run.part` — package part access
41
41
  - `Document.settings` — Word app settings (not surfaced by DOCX Studio)
42
42
  - `InlineShape.chart` — charts are not currently surfaced by the SDK.
43
- - `Comment.add_paragraph` / `Comment.add_table` /
44
- `Comment.iter_inner_content` / `Comment.paragraphs` /
45
- `Comment.tables` — DOCX Studio models a comment as a single text body.
46
- `Comment` is a `docx.blkcntnr.BlockItemContainer`, as `_Cell` and the
47
- header/footer proxies are, but its paragraph/table-bearing surface raises
48
- `CommentsNotImplementedError`. Use `Comment.text` instead.
43
+ - `Comment.add_table` / `Comment.tables` — a DOCX Studio comment holds
44
+ paragraphs only. `Comment` is a `docx.blkcntnr.BlockItemContainer`, as
45
+ `_Cell` and the header/footer proxies are: `paragraphs`,
46
+ `add_paragraph`, `iter_inner_content` and `text` work as in python-docx
47
+ 1.2.0 (the paragraphs list the comment's story, `blocks.list` with
48
+ `in: {storyType: "comment"}`, and `add_paragraph` sends
49
+ `CommentsParagraphAppend`), while `tables` is empty and `add_table`
50
+ raises `CommentsNotImplementedError`.
49
51
  - **`_Cell.add_table(rows, cols)`** — surface preserved for parity
50
52
  (signature matches python-docx, no `width` kwarg) but raises
51
53
  :class:`docx.errors.NestedTableNotSupportedError` (subclass of
@@ -188,22 +190,40 @@ not file-backed. Each is documented in the relevant docstring.
188
190
  on the other studios: `Workbook.workbook_id` (xlsx) and
189
191
  `Presentation.deck_id` (pptx).
190
192
 
191
- - **`Document.save(path_or_stream=None)`** — argument is optional and,
192
- when supplied, raises
193
- :class:`docx.errors.LocalSaveTargetNotSupportedError`. Stock
194
- python-docx requires it and `TypeError`s on no-arg, but in an
195
- asset-backed SDK there is no local file to write — writes are always
196
- in-place against the Y.Doc. Forcing the upstream signature broke
197
- every agent invocation that reflexively called `doc.save()` (a
198
- near-universal Python pattern), so the no-arg form is supported.
199
- When a path or stream IS supplied, the SDK cannot fulfill the
200
- implied "write bytes to this target" contract, so the call raises
201
- loudly rather than silently flushing — agents must use Olympus's
202
- Export DOCX (which goes through the DOCX Studio session that already
203
- has the bytes) instead of expecting a local file.
204
-
205
- - **`Document.track_revisions: bool`** — when `True`, all subsequent
206
- mutations are recorded as tracked revisions instead of direct edits.
193
+ - **`Document.save(path_or_stream=None)`** — the argument is optional.
194
+ Stock python-docx requires it and `TypeError`s on no-arg, but writes
195
+ are always in place against the Y.Doc, and forcing the upstream
196
+ signature broke every agent invocation that reflexively called
197
+ `doc.save()`, so the no-arg form flushes and writes no file. With a
198
+ path (`str` or `os.PathLike`) or a binary stream, `save` also writes
199
+ the document's `.docx` there, as python-docx does, through
200
+ `export_docx` (0.29.0+; earlier versions raised
201
+ `LocalSaveTargetNotSupportedError`, which stays importable).
202
+
203
+ - **`Document.track_revisions: bool`** — when `True`, subsequent batches
204
+ are sent with `changeMode: "tracked"`, and docx-studio records their text
205
+ edits as Word revisions (`w:ins` / `w:del`): run and paragraph text,
206
+ `find_replace` in the body, new paragraphs and headings (an inserted
207
+ paragraph mark), whole paragraphs deleted (`paragraph.delete()`, 0.30.0+:
208
+ its content, fields included, and its paragraph mark), tabs and line breaks,
209
+ run formatting (`w:rPrChange`) and
210
+ `paragraph_format` properties (`w:pPrChange`). The replaced text stays, deleted,
211
+ and the new text follows it, so the SDK keeps its paragraph lengths and
212
+ run ranges that way (`docx/_tracked.py`): a tracked `run.text = value`
213
+ leaves the run over `value`, after its deleted text, and the paragraph
214
+ grows by `len(value)`. `find_replace` and (0.30.0+) `paragraph.text = value`
215
+ mark only the words that change, the words the old and new text share at
216
+ their start and end left as they are, so after a tracked `paragraph.text`
217
+ the SDK reads the paragraph's length back. Every batch says so to docx-studio
218
+ (`client.capabilities: ["trackedAuthoring", "trackedMinimalParagraphText"]`);
219
+ a docx-studio refuses a tracked edit from an SDK that does not declare
220
+ `trackedAuthoring`, and replaces a paragraph's whole text for one that
221
+ does not declare `trackedMinimalParagraphText`. A batch holding an edit it cannot
222
+ record yet (paragraph styles, tables, pictures, lists, sections, notes,
223
+ page breaks, header/footer/comment text) is refused (HTTP 422,
224
+ `TrackedChangesUnsupported`) and applies nothing; reads, exports,
225
+ comments and `TrackChangesDecide` run either way
226
+ (`DOCX_STUDIO_LIMITATIONS.md` § 32).
207
227
  python-docx upstream has no top-level toggle (the closest is
208
228
  hand-edited `<w:trackChanges/>` on `Document.settings.element`).
209
229
  We expose this as a Document-level property because every DOCX Studio
@@ -219,10 +239,14 @@ not file-backed. Each is documented in the relevant docstring.
219
239
  because the upstream package has no track-changes API at all.
220
240
 
221
241
  - **`Document.user_name: str | None` / `Document.user_email: str |
222
- None`** — author identity threaded through to DOCX Studio on session-
223
- open for tracked-change attribution; DOCX Studio bakes them into the
224
- change records. Separate from `Document.core_properties.last_modified_by`,
225
- the `docProps/core.xml` metadata the SDK reads and writes as python-docx
242
+ None`** — the name sent with each batch, which DOCX Studio uses as the
243
+ author of a comment that names none (unset, such a comment is by the
244
+ signed-in user, as "Jane Doe (Athena)"). It is not a tracked change's
245
+ author: DOCX Studio stamps those with the signed-in user agora's access
246
+ check names, as an agent writes for them ("Jane Doe (Athena)"), so a
247
+ script cannot choose who a redline's changes are by.
248
+ Separate from `Document.core_properties.last_modified_by`, the
249
+ `docProps/core.xml` metadata the SDK reads and writes as python-docx
226
250
  does.
227
251
 
228
252
  - **`Document.revisions: Revisions`** — collection of tracked changes
@@ -278,9 +302,10 @@ Issue numbers reference `python-openxml/python-docx`.
278
302
  `"FILENAME"`, `"NUMWORDS"`, `"REF"`, `"SEQ"`, `"TOC"`, and the
279
303
  generic `"FIELD"` escape hatch. python-docx has no field API
280
304
  whatsoever; issue #498 (page numbers) and #31 (23 comments) demand
281
- this. `Fields` is sequence-like; `Fields.refresh_all(scope?)`
282
- forces a recompute. Routes through `CreateField` / `FieldsRefresh`
283
- / `FieldsList`.
305
+ this. `Fields` is sequence-like; `Fields.refresh_all(scope?)` updates
306
+ every unlocked REF and SEQ result as Word's F9 does (PAGE, PAGEREF
307
+ and TOC results depend on pages and stay). Routes through
308
+ `CreateField` / `FieldsRefresh` / `FieldsList`.
284
309
 
285
310
  - **`Document.bookmarks: Bookmarks`** + **`Paragraph.add_bookmark
286
311
  (name)`** + **`Document.add_bookmark(name, *, paragraph=None,
@@ -435,6 +460,26 @@ Issue numbers reference `python-openxml/python-docx`.
435
460
  numbering reads. python-docx issue #471 (13 👍) demands access to
436
461
  list metadata. Routes through `NumberingGet`.
437
462
 
463
+ - **`Paragraph.delete()`** (0.30.0+) — delete the paragraph, its
464
+ paragraph mark included. python-docx has no paragraph delete (issue #33);
465
+ code written for it removes the element
466
+ (`p._element.getparent().remove(p._element)`), which this SDK cannot reach.
467
+ Routes through `DeleteParagraph`, sent in a request of its own after the
468
+ buffered edits (response-bearing, so a refusal raises at the call). With
469
+ tracking off docx-studio removes the paragraph, with the page and column
470
+ breaks the import keeps beside it; with `track_revisions` on it records
471
+ Word's tracked deletion of a whole paragraph: its content in `w:del`
472
+ (cross-reference and other fields with their codes and results, links,
473
+ note references) and its paragraph mark deleted, one revision. Accept All
474
+ removes it and the numbered paragraphs after it number on; Reject All
475
+ restores it. `paragraph.text = ""` leaves an empty, still numbered,
476
+ paragraph instead. docx-studio refuses (`DocxError`, nothing applied) the
477
+ document's last paragraph, one that ends a section, the only paragraph of
478
+ a table cell or content control, one holding part of a field that spans
479
+ paragraphs, one in a header, footer, comment or text box, and, tracked,
480
+ one in a table cell or holding a page break, a content control, a shape or
481
+ an equation (`DOCX_STUDIO_LIMITATIONS.md` § 32).
482
+
438
483
  - **`Paragraph.restart_numbering(start=1)`** (0.26.0+) — restart the
439
484
  paragraph's numbered list at `start`, as Word's "Restart at 1" does
440
485
  ("Set Numbering Value" for another start). All `"List Number"`
@@ -611,12 +656,10 @@ Issue numbers reference `python-openxml/python-docx`.
611
656
 
612
657
  - **`Document.export_docx(path=None, *, include_revisions=False)
613
658
  -> bytes`** (0.11.4+) — export the document's current state as
614
- ``.docx`` bytes, optionally writing to ``path``. Closes the gap
615
- left by ``Document.save(path)`` raising
616
- ``LocalSaveTargetNotSupportedError`` in this SDK: parity test
617
- harnesses and CI workflows need a programmatic .docx export to
618
- diff against ``python-docx`` output that doesn't require a
619
- human-driven Olympus UI action. Routes through ``ExportDocx`` →
659
+ ``.docx`` bytes, optionally writing to ``path``; ``Document.save(path_or_stream)``
660
+ writes its file through it. Parity test harnesses and CI workflows
661
+ use it to diff against ``python-docx`` output without a human-driven
662
+ Olympus UI action. Routes through ``ExportDocx`` →
620
663
  apps/api's backend export path. apps/api
621
664
  writes the session state to a temp ``.docx``, reads bytes back,
622
665
  base64-encodes for the wire, and unlinks the temp in a
@@ -625,6 +668,29 @@ Issue numbers reference `python-openxml/python-docx`.
625
668
  the current backend export path has no ``includeRevisions`` support,
626
669
  so honoring the flag isn't possible yet.
627
670
 
671
+ ``export_docx(path=None, *, include_revisions=False, clean=False,
672
+ clear_title=False)`` (0.29.0+): called with ``clean=True`` it returns a
673
+ clean copy for sending outside the firm instead, from
674
+ ``GET /docs/:id/export.docx?clean=1`` (VIEW gate): docx-studio imports
675
+ the export into an in-memory room, accepts every tracked change and
676
+ deletes every comment through the command runner, exports that room and
677
+ leaves out the author, last-modified-by, revision, company, manager,
678
+ template, editing-time and hyperlink-base properties, rsids, document
679
+ variables, custom properties, Custom XML (a content control bound to it
680
+ keeps its content, not its binding), the attached template, the attached
681
+ XML schema and the thumbnail; ``clear_title=True`` drops the title too.
682
+ Bookmarks, the creation date and the sensitivity label stay (the route's
683
+ ``removeSensitivityLabel=1`` drops the label; the SDK does not send it).
684
+ The live document is
685
+ not changed. The SDK refuses (``DocxUnsupportedCommandError``) an answer
686
+ without ``X-Docx-Clean-Copy: 1``, the plain export an older docx-studio
687
+ sends, and raises ``DocxError`` with docx-studio's reason when a header,
688
+ footer or note still holds a tracked change (the engine accepts the
689
+ body's only; ``DOCX_STUDIO_LIMITATIONS.md`` § 31). The in-process
690
+ post-export rewrites are applied to a clean copy as to a plain export,
691
+ and the copy is refused (``DocxError``) if they put revision, comment or
692
+ rsid markup back into ``word/document.xml``.
693
+
628
694
  Template seeding: ``Document.create()`` (no ``docx=``) already
629
695
  produces an exportable asset because ``POST /docs/empty`` seeds
630
696
  from the default Athena template, so ``export_docx`` works
@@ -915,6 +981,18 @@ architecture or a DOCX Studio constraint:
915
981
  but DOCX Studio's ProseMirror table node can't represent one; the SDK
916
982
  raises eagerly rather than failing opaquely on the wire.
917
983
 
984
+ - **`Document.add_table` writes Athena's brand table.** Owner decision
985
+ (2026-10-12): keep the brand defaults. The table's layout is fixed, so
986
+ `Table.autofit` reads `False` (python-docx leaves autofit on); its columns
987
+ share 9,360 twips, where python-docx shares the section's text width; and
988
+ in the fixed layout a column width the script sets sizes the column's
989
+ cells too, where python-docx sets the `w:gridCol` alone. It also draws
990
+ borders and a zebra fill, which no python-docx read sees. Recorded as
991
+ `live_deviations` for the script cases' `tables.autofit`, `tables.widths`
992
+ and `tables.cell_format` in `tests/parity/intentional_deviations.json`;
993
+ an imported table's gaps stay gaps, and so do the two cases whose
994
+ `cell_format` also differs for another cause (`except`).
995
+
918
996
  - **`_Cell.merge` raises `InvalidSpanError` for every span that would cut
919
997
  through a merged cell.** It merges what python-docx merges and refuses
920
998
  what python-docx refuses (an L- or T-shaped pair of corners), but where
@@ -944,8 +1022,9 @@ architecture or a DOCX Studio constraint:
944
1022
  `""`.** `Document.add_comment` / `Comments.add_comment` send `author`
945
1023
  and `initials` and docx-studio stores them as `w:author` /
946
1024
  `w:initials`, as python-docx does; with none (python-docx's default
947
- `""`) the author is `Document.user_name`, else `"Athena"`, and no
948
- initials are stored (`initials` then reads `None`). The SDK raises
1025
+ `""`) the author is `Document.user_name`, else the signed-in user agora's
1026
+ access check names as an agent writes for them, "Jane Doe (Athena)" (the
1027
+ author of the batch's tracked changes), else `"Athena"`, and no initials are stored (`initials` then reads `None`). The SDK raises
949
1028
  `ValueError` for what lxml refuses in an attribute, as python-docx
950
1029
  does, and also past docx-studio's caps (255 UTF-16 code units for an
951
1030
  author, 32 for initials); docx-studio turns tabs, line breaks and other
@@ -953,6 +1032,18 @@ architecture or a DOCX Studio constraint:
953
1032
  Keryx attributes the edit to the signed-in user (and agent), and
954
1033
  nothing reads a comment's author as identity.
955
1034
 
1035
+ - **A comment's paragraphs are in Word's comment style, which the export
1036
+ defines.** python-docx 1.2.0's `add_comment` and `Comment.add_paragraph`
1037
+ write `w:pStyle CommentText` (Word's built-in "annotation text", Comment
1038
+ Text in Word's UI) without defining the style in `styles.xml`, so
1039
+ python-docx reads those paragraphs as Normal. docx-studio writes the same
1040
+ `w:pStyle` and defines the style as Word does: `Comment.paragraphs[i].style`
1041
+ reads `Comment Text` (a built-in the document lacks reads back as that
1042
+ built-in, as above), and the export adds Word's definition of the style and
1043
+ of its linked `Comment Text Char` to `styles.xml`, so python-docx reads the
1044
+ exported paragraph as `annotation text`. Owner decision, 2026-10-12.
1045
+ Recorded in `tests/parity/intentional_deviations.json` (`live_deviations`).
1046
+
956
1047
  - **`ParagraphFormat.line_spacing_rule = None` warns-and-preserves on a
957
1048
  clear** rather than raising (upstream accepts `None` to clear, but DOCX
958
1049
  Studio's merging mutation ops have no single-attribute clear). It emits a
@@ -970,7 +1061,17 @@ architecture or a DOCX Studio constraint:
970
1061
  given. `Run.add_tab()` and `Run.add_break()` take the run's formatting, as
971
1062
  upstream appends them to the run's `w:r`; `Run.add_break(WD_BREAK.COLUMN)`
972
1063
  sends a column break (`breakType: "column"`), which docx-studio writes after
973
- the paragraph's content. `DOCX_STUDIO_LIMITATIONS.md` §26.
1064
+ the paragraph's content. `DOCX_STUDIO_LIMITATIONS.md` §26. `Run.text` and
1065
+ `Paragraph.text` leave a ruby's base text out (`w:ruby`, a phonetic guide
1066
+ over its base text), as upstream reads only a run's own text elements, while
1067
+ the base text keeps its room in the text-address space (`ruby` spans on the
1068
+ read's run; `tests/test_ruby_reads_python_docx_parity.py`). That holds while
1069
+ the paragraph's runs are as its records hold them, in the body, a table cell,
1070
+ a header, a footer or a comment; a paragraph with a link or a tracked change
1071
+ reads its runs from their marks, the base text included. A write to the run
1072
+ (its text, an append, its formatting) makes the base text ordinary text,
1073
+ which then reads as text: docx-studio keeps no guide through an edit, where
1074
+ upstream keeps the `w:ruby` through all but a text write.
974
1075
 
975
1076
  - **`CoreProperties.modified` is the time of the last save.** The asset is a
976
1077
  live Word document, and docx-studio stamps `dcterms:modified` when it saves
@@ -1104,6 +1205,15 @@ This is a **thin HTTP client** that mimics the sync python-docx API.
1104
1205
  the context-manager exit drain explicitly; `docx.flush_all()` is
1105
1206
  the executor-postamble hook that flushes every live buffer in the
1106
1207
  process.
1208
+ - A flush of more than 500 commands (`MAX_BATCH_COMMANDS`,
1209
+ docx-studio's request cap) goes out as consecutive requests, and
1210
+ docx-studio applies each all or nothing: when one fails, the requests
1211
+ before it are saved and it and every later one are not. The
1212
+ `DocxError` (0.29.0+) says how many of the flush's commands were
1213
+ applied and names the failed one by its flush index; it carries
1214
+ `unapplied_commands` and `failed_command`, and `partial_applied`
1215
+ holds the saved requests' results. A retry re-applies the unapplied
1216
+ edits, never the whole flush.
1107
1217
  - Execution scope: executor sandboxes may keep Python globals
1108
1218
  between tool calls so imports, constants, and helper functions can be
1109
1219
  reused. Live SDK objects are different. The executor calls
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: athena-python-docx
3
- Version: 0.28.0
3
+ Version: 0.30.0
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,7 +6,7 @@ See CLAUDE.md for the API parity contract.
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
- __version__ = "0.28.0"
9
+ __version__ = "0.30.0"
10
10
 
11
11
  from docx.api import Document
12
12
  from docx._buffer import discard_all, flush_all
@@ -43,7 +43,13 @@ from docx._execution import (
43
43
  is_stale_execution,
44
44
  )
45
45
  from docx._timeouts import timeout_for_commands
46
- from docx.commands import Command, GetNodeById, is_response_bearing, must_flush_immediately
46
+ from docx.commands import (
47
+ Command,
48
+ GetNodeById,
49
+ is_query,
50
+ is_response_bearing,
51
+ must_flush_immediately,
52
+ )
47
53
  from docx.errors import DocxError, DocxUnsupportedCommandError, FlushAllError
48
54
 
49
55
 
@@ -402,6 +408,11 @@ class CommandBuffer:
402
408
  # The last command's ``GetNodeById`` key, result and time, while
403
409
  # nothing has been sent or buffered after it (see :meth:`call`).
404
410
  self._last_read: tuple[str, Any, float] | None = None
411
+ # Counts each command that may change the document (anything but a
412
+ # query) this buffer has taken, buffered or sent, and each
413
+ # forget_reads(): a read kept from an earlier count (a ``Table``'s
414
+ # ``tables.get``) may no longer show the document. See ``writes``.
415
+ self._writes: int = 0
405
416
  _register(self)
406
417
 
407
418
  def register_proxy_id_ref(self, client_id: str, proxy: object, attr: str = "_node_id") -> None:
@@ -460,10 +471,15 @@ class CommandBuffer:
460
471
  if current == mode:
461
472
  return
462
473
  # Drain any queued commands with the *previous* mode before
463
- # adopting the new one.
464
- self.flush()
465
- with self._lock:
466
- self._change_mode = mode
474
+ # adopting the new one. The new mode is adopted even when that
475
+ # flush raises (docx-studio refuses a tracked batch that edits):
476
+ # ``Document`` has already recorded the new flag, so keeping the
477
+ # old mode here would refuse every later direct edit.
478
+ try:
479
+ self.flush()
480
+ finally:
481
+ with self._lock:
482
+ self._change_mode = mode
467
483
 
468
484
  def set_user(self, name: str | None, email: str | None = None) -> None:
469
485
  """Set the batch-level user identity.
@@ -485,11 +501,34 @@ class CommandBuffer:
485
501
  if email:
486
502
  self._user["email"] = email
487
503
 
504
+ @property
505
+ def writes(self) -> int:
506
+ """How many commands that may change the document this buffer has
507
+ taken, buffered or sent, plus each :meth:`forget_reads` (which a batch
508
+ another handle of the document sends calls). A read kept at one count
509
+ shows the document while the count stays, but for a collaborator's
510
+ edit."""
511
+ with self._lock:
512
+ return self._writes
513
+
488
514
  def forget_reads(self) -> None:
489
515
  """The next node read goes to the server, not to the read before it
490
- (:meth:`call`): for a read that checks the document before a write."""
516
+ (:meth:`call`), and so does a table's next read (``writes``): for a
517
+ read that checks the document before a write."""
491
518
  with self._lock:
492
519
  self._last_read = None
520
+ self._writes += 1
521
+
522
+ def ensure_usable(self) -> None:
523
+ """Raise as :meth:`call` does before it sends or reuses anything: for a
524
+ buffer of an earlier execution, a batch the idle timer failed to send,
525
+ and a closed buffer. A read kept outside the buffer checks it too."""
526
+ self._assert_current_execution()
527
+ self._raise_deferred_flush_error()
528
+ if self._closed:
529
+ raise RuntimeError(
530
+ f"CommandBuffer for {self._asset_id} is closed",
531
+ )
493
532
 
494
533
  def call(self, cmd: Command) -> Any:
495
534
  """Execute or buffer ``cmd``.
@@ -508,12 +547,7 @@ class CommandBuffer:
508
547
  ``clientIdMap`` on flush and the buffer rewrites each registered
509
548
  proxy's ``_node_id`` in-place.
510
549
  """
511
- self._assert_current_execution()
512
- self._raise_deferred_flush_error()
513
- if self._closed:
514
- raise RuntimeError(
515
- f"CommandBuffer for {self._asset_id} is closed",
516
- )
550
+ self.ensure_usable()
517
551
 
518
552
  # A read of the node the last command read, with nothing sent or
519
553
  # buffered since and within READ_REUSE_SECONDS of it, answers from
@@ -532,6 +566,9 @@ class CommandBuffer:
532
566
  and _now() - last_read[2] <= READ_REUSE_SECONDS
533
567
  ):
534
568
  return copy.deepcopy(last_read[1])
569
+ if not is_query(cmd):
570
+ with self._lock:
571
+ self._writes += 1
535
572
 
536
573
  # PTC begin: emit only for commands in the allow-list. Other
537
574
  # commands still flow through the buffer (and through the batched
@@ -0,0 +1,38 @@
1
+ """What the docx-studio a session talks to takes, from its ``Info`` reply.
2
+
3
+ A command shape an older docx-studio would refuse (``InsertLineBreak`` with
4
+ ``breakType: "page"``) is sent only to a server that names it in
5
+ ``Info.capabilities``; a server that names none gets the older shape. The
6
+ promotion rings put tenants on different docx-studio trains, so an SDK release
7
+ meets servers from before and after the capability.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import weakref
13
+ from typing import Any
14
+
15
+ from docx._batching import run_sync
16
+
17
+ # Session -> the capabilities its server reported, read once.
18
+ _capabilities: "weakref.WeakKeyDictionary[Any, dict[str, Any]]" = weakref.WeakKeyDictionary()
19
+
20
+
21
+ def server_takes(session: Any, capability: str) -> bool:
22
+ """True when the session's docx-studio reports ``capability``
23
+ (``Info.capabilities``), read on first use and kept for the session.
24
+
25
+ ``Info`` flushes the edits queued before it, as every read does.
26
+ """
27
+ if session is None:
28
+ return False
29
+ try:
30
+ known = _capabilities.get(session)
31
+ except TypeError:
32
+ return False
33
+ if known is None:
34
+ info: object = run_sync(session.doc.info({}))
35
+ reported = info.get("capabilities") if isinstance(info, dict) else None
36
+ known = reported if isinstance(reported, dict) else {}
37
+ _capabilities[session] = known
38
+ return known.get(capability) is True