athena-python-docx 0.24.0__tar.gz → 0.26.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 (431) hide show
  1. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/AGENTS.md +263 -72
  2. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/PKG-INFO +1 -1
  3. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/__init__.py +1 -1
  4. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/_buffer.py +17 -0
  5. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/_http_doc.py +157 -10
  6. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/_image_utils.py +95 -22
  7. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/_postproc.py +103 -142
  8. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/_timeouts.py +2 -0
  9. athena_python_docx-0.26.0/docx/blkcntnr.py +58 -0
  10. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/client.py +19 -0
  11. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/commands.py +179 -16
  12. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/comments.py +135 -53
  13. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/document.py +318 -131
  14. athena_python_docx-0.26.0/docx/drawing/__init__.py +60 -0
  15. athena_python_docx-0.26.0/docx/enum/base.py +151 -0
  16. athena_python_docx-0.26.0/docx/enum/dml.py +42 -0
  17. athena_python_docx-0.26.0/docx/enum/section.py +59 -0
  18. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/enum/style.py +13 -23
  19. athena_python_docx-0.26.0/docx/enum/table.py +68 -0
  20. athena_python_docx-0.26.0/docx/enum/text.py +241 -0
  21. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/errors.py +46 -15
  22. athena_python_docx-0.26.0/docx/image/__init__.py +5 -0
  23. athena_python_docx-0.26.0/docx/image/exceptions.py +13 -0
  24. athena_python_docx-0.26.0/docx/image/image.py +153 -0
  25. athena_python_docx-0.26.0/docx/opc/coreprops.py +253 -0
  26. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/section.py +370 -289
  27. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/shape.py +62 -66
  28. athena_python_docx-0.26.0/docx/styles/__init__.py +38 -0
  29. athena_python_docx-0.26.0/docx/styles/_table.py +596 -0
  30. athena_python_docx-0.26.0/docx/styles/latent.py +220 -0
  31. athena_python_docx-0.26.0/docx/styles/style.py +923 -0
  32. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/styles/styles.py +151 -112
  33. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/table.py +426 -322
  34. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/text/hyperlink.py +9 -3
  35. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/text/paragraph.py +343 -120
  36. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/text/parfmt.py +12 -7
  37. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/text/run.py +392 -184
  38. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/text/tabstops.py +18 -65
  39. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/pyproject.toml +1 -1
  40. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/scripts/release.sh +2 -2
  41. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/fake_session.py +94 -13
  42. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/02_multiple_headings.json +1 -0
  43. athena_python_docx-0.26.0/tests/fidelity/op_snapshots/104_core_properties_datetime.json +21 -0
  44. athena_python_docx-0.26.0/tests/fidelity/op_snapshots/15_run_add_break_page.json +6 -0
  45. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/17_table_basic.json +1 -0
  46. athena_python_docx-0.24.0/tests/fidelity/op_snapshots/45_cell_text_round_trip.json → athena_python_docx-0.26.0/tests/fidelity/op_snapshots/22_table_cell_paragraphs_iteration.json +1 -0
  47. athena_python_docx-0.26.0/tests/fidelity/op_snapshots/28_section_add_new.json +3 -0
  48. athena_python_docx-0.26.0/tests/fidelity/op_snapshots/29_section_headers_linked.json +8 -0
  49. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/32_styles_add_paragraph_style.json +1 -0
  50. athena_python_docx-0.26.0/tests/fidelity/op_snapshots/33_core_properties_set_and_get.json +8 -0
  51. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/35_full_report.json +1 -0
  52. athena_python_docx-0.26.0/tests/fidelity/op_snapshots/45_cell_text_round_trip.json +5 -0
  53. athena_python_docx-0.26.0/tests/fidelity/op_snapshots/48_font_color_round_trip.json +5 -0
  54. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/49_resume_layout.json +1 -0
  55. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/50_multi_section_doc.json +0 -4
  56. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/53_apply_style_to_paragraphs.json +1 -0
  57. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/56_everything_in_one.json +3 -1
  58. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/61_cell_paragraph_with_runs.json +2 -2
  59. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/62_many_cell_paragraphs.json +0 -5
  60. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/63_table_style_round_trip.json +1 -0
  61. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/64_many_sections.json +0 -8
  62. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/65_20x20_table_formatted.json +1 -0
  63. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/68_invoice.json +1 -0
  64. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/69_newsletter.json +2 -5
  65. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/71_academic_paper.json +1 -0
  66. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/72_legal_contract.json +1 -0
  67. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/73_form_with_many_tables.json +1 -0
  68. athena_python_docx-0.26.0/tests/fidelity/op_snapshots/76_rgbcolor_from_string.json +5 -0
  69. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/78_paragraph_copy_style.json +1 -0
  70. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/79_bulk_cell_formatting.json +1 -0
  71. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/80_apply_style_after_add_run.json +1 -0
  72. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/81_multi_page_with_breaks.json +2 -2
  73. athena_python_docx-0.26.0/tests/fidelity/op_snapshots/85_header_footer_access.json +7 -0
  74. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/90_cell_add_paragraph_styled.json +2 -2
  75. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/92_margins_every_section.json +0 -4
  76. athena_python_docx-0.24.0/tests/fidelity/op_snapshots/47_font_size_round_trip.json → athena_python_docx-0.26.0/tests/fidelity/op_snapshots/93_font_bool_reads_after_set.json +1 -1
  77. athena_python_docx-0.26.0/tests/fidelity/op_snapshots/96_paragraph_contains_page_break.json +7 -0
  78. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/97_document_styles_by_key.json +1 -0
  79. athena_python_docx-0.26.0/tests/fidelity/op_snapshots/98_style_contains_check.json +6 -0
  80. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/ex02_unicode_everywhere.json +1 -0
  81. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/ex05_long_text_in_cell.json +1 -0
  82. athena_python_docx-0.26.0/tests/fidelity/op_snapshots/ex08_many_continuous_sections.json +12 -0
  83. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/ex10_complex_bom.json +16 -120
  84. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/ex11_banded_rows_formatting.json +1 -0
  85. athena_python_docx-0.26.0/tests/fidelity/op_snapshots/ex13_cell_with_10_paragraphs.json +35 -0
  86. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/ex14_styled_report_table.json +1 -0
  87. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/ex17_all_break_kinds.json +2 -1
  88. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/ex20_kitchen_sink_v2.json +13 -8
  89. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/mega01_book_chapter.json +13 -24
  90. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/mega02_research_proposal.json +3 -2
  91. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/mega03_financial_statement.json +1 -0
  92. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/mega04_recipe_card.json +1 -0
  93. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/mega05_user_manual.json +1 -0
  94. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/mega07_budget_spreadsheet.json +1 -0
  95. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/mega08_product_catalog.json +1 -0
  96. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/mega09_signed_contract.json +1 -0
  97. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/mega10_api_documentation.json +1 -0
  98. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/rw01_official_quickstart.json +2 -1
  99. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/rw02_paragraph_style_list.json +1 -0
  100. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/rw04_section_page_setup.json +0 -2
  101. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/rw05_toc_pattern.json +2 -1
  102. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/rw06_meeting_minutes.json +1 -0
  103. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/rw08_table_merged_header.json +1 -0
  104. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/rw10_colored_grid_table.json +1 -0
  105. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/rw11_header_text.json +3 -0
  106. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/rw12_first_page_footer.json +6 -0
  107. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/rw13_even_page_header.json +6 -0
  108. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/rw15_paragraph_style_instance.json +1 -0
  109. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/parity/README.md +4 -1
  110. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/parity/intentional_deviations.json +14 -27
  111. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/parity/test_parity_gap.py +32 -11
  112. athena_python_docx-0.26.0/tests/test_add_section.py +206 -0
  113. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_athena_extensions_registry.py +4 -0
  114. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_block_not_found_error.py +29 -0
  115. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_buffer.py +43 -6
  116. athena_python_docx-0.26.0/tests/test_cell_borders_spec.py +100 -0
  117. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_cell_fastpath_runs.py +35 -3
  118. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_cell_inner_format_stash.py +12 -2
  119. athena_python_docx-0.26.0/tests/test_cell_merge.py +443 -0
  120. athena_python_docx-0.26.0/tests/test_cell_paragraphs_listed.py +234 -0
  121. athena_python_docx-0.26.0/tests/test_cell_text_replace_semantics.py +76 -0
  122. athena_python_docx-0.26.0/tests/test_color_format_theme.py +134 -0
  123. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_commands.py +19 -7
  124. athena_python_docx-0.26.0/tests/test_comments.py +436 -0
  125. athena_python_docx-0.26.0/tests/test_core_properties.py +191 -0
  126. athena_python_docx-0.26.0/tests/test_drawing_image.py +267 -0
  127. athena_python_docx-0.26.0/tests/test_enum_parity.py +449 -0
  128. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_http_transport.py +10 -10
  129. athena_python_docx-0.26.0/tests/test_inline_shape_size.py +58 -0
  130. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_iter_inner_content.py +3 -3
  131. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_list_styles.py +8 -3
  132. athena_python_docx-0.26.0/tests/test_missing_modules.py +238 -0
  133. athena_python_docx-0.26.0/tests/test_page_break.py +80 -0
  134. athena_python_docx-0.26.0/tests/test_paragraph_runs_hyperlinks.py +85 -0
  135. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_parity_misc.py +2 -2
  136. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_parity_round2.py +73 -41
  137. athena_python_docx-0.26.0/tests/test_pdf_export_and_page_renders.py +321 -0
  138. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_phase_a_behavior.py +12 -3
  139. athena_python_docx-0.26.0/tests/test_phase_b_headers_footers.py +750 -0
  140. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_postproc_cell_format_rewrite.py +75 -154
  141. athena_python_docx-0.26.0/tests/test_restart_numbering.py +207 -0
  142. athena_python_docx-0.26.0/tests/test_run_formatting_wire.py +154 -0
  143. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_run_identity.py +8 -2
  144. athena_python_docx-0.26.0/tests/test_run_mark_inheritance.py +453 -0
  145. athena_python_docx-0.26.0/tests/test_run_table_style_objects.py +329 -0
  146. athena_python_docx-0.26.0/tests/test_run_text_python_docx.py +190 -0
  147. athena_python_docx-0.26.0/tests/test_run_text_refreshes_paragraph.py +60 -0
  148. athena_python_docx-0.26.0/tests/test_sdk_reads_served.py +191 -0
  149. athena_python_docx-0.26.0/tests/test_section_read_lengths.py +91 -0
  150. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_add_picture.py +9 -11
  151. athena_python_docx-0.26.0/tests/test_silent_stub_enum_section.py +54 -0
  152. athena_python_docx-0.26.0/tests/test_silent_stub_inline_shape.py +73 -0
  153. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_misc.py +7 -14
  154. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_paragraph_strict.py +13 -9
  155. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_paragraph_style_strict.py +2 -1
  156. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_parfmt.py +44 -13
  157. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_row_col_cell.py +3 -1
  158. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_run_add_break.py +7 -7
  159. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_run_underline.py +1 -1
  160. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_section_dimensions.py +43 -8
  161. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_style.py +13 -11
  162. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_table_audit.py +1 -1
  163. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_table_layout.py +1 -1
  164. athena_python_docx-0.26.0/tests/test_style_formatting_writes.py +290 -0
  165. athena_python_docx-0.26.0/tests/test_style_metadata_writes.py +276 -0
  166. athena_python_docx-0.26.0/tests/test_style_names.py +357 -0
  167. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_style_setters_contract.py +11 -14
  168. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_table_style_id_resolution.py +4 -2
  169. athena_python_docx-0.26.0/tests/test_text_control_characters.py +233 -0
  170. athena_python_docx-0.26.0/tests/test_uv_lock_version.py +23 -0
  171. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_wire_contract.py +137 -11
  172. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/uv.lock +1 -1
  173. athena_python_docx-0.24.0/docx/enum/section.py +0 -72
  174. athena_python_docx-0.24.0/docx/enum/table.py +0 -52
  175. athena_python_docx-0.24.0/docx/enum/text.py +0 -258
  176. athena_python_docx-0.24.0/docx/opc/coreprops.py +0 -248
  177. athena_python_docx-0.24.0/docx/styles/__init__.py +0 -1
  178. athena_python_docx-0.24.0/docx/styles/style.py +0 -607
  179. athena_python_docx-0.24.0/tests/fidelity/op_snapshots/104_core_properties_datetime.json +0 -1
  180. athena_python_docx-0.24.0/tests/fidelity/op_snapshots/15_run_add_break_page.json +0 -5
  181. athena_python_docx-0.24.0/tests/fidelity/op_snapshots/22_table_cell_paragraphs_iteration.json +0 -9
  182. athena_python_docx-0.24.0/tests/fidelity/op_snapshots/28_section_add_new.json +0 -5
  183. athena_python_docx-0.24.0/tests/fidelity/op_snapshots/29_section_headers_linked.json +0 -6
  184. athena_python_docx-0.24.0/tests/fidelity/op_snapshots/30_styles_iteration.json +0 -3
  185. athena_python_docx-0.24.0/tests/fidelity/op_snapshots/33_core_properties_set_and_get.json +0 -1
  186. athena_python_docx-0.24.0/tests/fidelity/op_snapshots/48_font_color_round_trip.json +0 -6
  187. athena_python_docx-0.24.0/tests/fidelity/op_snapshots/85_header_footer_access.json +0 -5
  188. athena_python_docx-0.24.0/tests/fidelity/op_snapshots/93_font_bool_reads_after_set.json +0 -8
  189. athena_python_docx-0.24.0/tests/fidelity/op_snapshots/96_paragraph_contains_page_break.json +0 -6
  190. athena_python_docx-0.24.0/tests/fidelity/op_snapshots/ex08_many_continuous_sections.json +0 -32
  191. athena_python_docx-0.24.0/tests/fidelity/op_snapshots/ex13_cell_with_10_paragraphs.json +0 -34
  192. athena_python_docx-0.24.0/tests/test_cell_text_replace_semantics.py +0 -116
  193. athena_python_docx-0.24.0/tests/test_comments.py +0 -238
  194. athena_python_docx-0.24.0/tests/test_phase_b_headers_footers.py +0 -281
  195. athena_python_docx-0.24.0/tests/test_run_mark_inheritance.py +0 -164
  196. athena_python_docx-0.24.0/tests/test_silent_stub_enum_section.py +0 -83
  197. athena_python_docx-0.24.0/tests/test_silent_stub_inline_shape.py +0 -105
  198. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/.gitignore +0 -0
  199. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/CLAUDE.md +0 -0
  200. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/DOCX_EXEC_LAB.md +0 -0
  201. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/README.md +0 -0
  202. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/_athena_extension.py +0 -0
  203. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/_batching.py +0 -0
  204. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/_citations.py +0 -0
  205. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/_execution.py +0 -0
  206. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/_http.py +0 -0
  207. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/_ptc.py +0 -0
  208. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/_references.py +0 -0
  209. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/_run_order.py +0 -0
  210. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/_table_styles.py +0 -0
  211. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/api.py +0 -0
  212. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/bookmarks.py +0 -0
  213. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/charts.py +0 -0
  214. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/enum/__init__.py +0 -0
  215. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/enum/shape.py +1 -1
  216. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/exceptions.py +0 -0
  217. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/fields.py +0 -0
  218. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/footnotes.py +0 -0
  219. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/math.py +0 -0
  220. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/opc/__init__.py +0 -0
  221. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/oxml/__init__.py +0 -0
  222. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/revisions.py +0 -0
  223. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/sdt.py +0 -0
  224. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/session.py +0 -0
  225. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/settings.py +0 -0
  226. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/shared.py +0 -0
  227. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/text/__init__.py +0 -0
  228. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/text/font.py +0 -0
  229. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/text/pagebreak.py +0 -0
  230. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/toc.py +0 -0
  231. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/docx/typing.py +0 -0
  232. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/scripts/docx_exec_lab.py +0 -0
  233. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/scripts/docx_exec_lab_examples/fast_table_fill.py +0 -0
  234. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/scripts/docx_exec_lab_examples/find_replace_literal.py +0 -0
  235. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/scripts/docx_exec_lab_server.py +0 -0
  236. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/scripts/dump_wire_fixtures.py +0 -0
  237. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/scripts/round_trip_smoke.py +0 -0
  238. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/scripts/smoke_test_block_not_found.py +0 -0
  239. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/scripts/validate_find_replace_asset.py +0 -0
  240. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/__init__.py +0 -0
  241. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/conftest.py +0 -0
  242. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/METHODOLOGY.md +0 -0
  243. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/README.md +0 -0
  244. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/__init__.py +0 -0
  245. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/ab_probe_cases.py +0 -0
  246. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/ab_probe_runner.py +0 -0
  247. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/auto_gen_cases.py +0 -0
  248. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/binary_round_trip.py +0 -0
  249. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/cases.py +0 -0
  250. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/complex_cases.py +0 -0
  251. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/coverage_report.py +0 -0
  252. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/extract.py +0 -0
  253. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/extreme_cases.py +0 -0
  254. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/firm_templates/README.md +0 -0
  255. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/firm_templates/__init__.py +0 -0
  256. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/firm_templates/_runner.py +0 -0
  257. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/firm_templates/extractor.py +0 -0
  258. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/firm_templates/test_pw_corpus.py +0 -0
  259. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/firm_templates/test_pw_research_digest.py +0 -0
  260. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/local_runner.py +0 -0
  261. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/mega_cases.py +0 -0
  262. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshot.py +0 -0
  263. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/01_basic_paragraph.json +0 -0
  264. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/03_runs_with_formatting.json +0 -0
  265. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/04_font_name_and_size.json +0 -0
  266. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/05_font_color_rgb.json +0 -0
  267. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/06_font_character_properties.json +0 -0
  268. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/07_font_subscript_superscript.json +0 -0
  269. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/08_font_highlight.json +0 -0
  270. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/09_paragraph_alignment.json +0 -0
  271. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/100_table_negative_indexing.json +0 -0
  272. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/101_table_cells_flat_iteration.json +0 -0
  273. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/102_text_with_embedded_special_chars.json +0 -0
  274. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/105_default_one_section.json +0 -0
  275. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/106_heading_paragraph_format.json +0 -0
  276. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/107_varying_row_heights.json +0 -0
  277. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/10_paragraph_indents.json +0 -0
  278. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/11_paragraph_spacing.json +0 -0
  279. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/12_paragraph_keep_options.json +0 -0
  280. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/13_paragraph_tab_stops.json +0 -0
  281. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/14_run_add_tab_and_break.json +0 -0
  282. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/16_paragraph_clear_and_insert_before.json +0 -0
  283. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/18_table_cell_text.json +0 -0
  284. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/19_table_row_column_sizing.json +0 -0
  285. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/20_table_cell_vertical_alignment.json +0 -0
  286. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/21_table_alignment_and_autofit.json +0 -0
  287. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/24_table_add_row_column.json +0 -0
  288. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/25_table_merge_cells.json +0 -0
  289. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/26_section_page_setup.json +0 -0
  290. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/27_section_margins.json +0 -0
  291. /athena_python_docx-0.24.0/tests/fidelity/op_snapshots/31_styles_lookup_and_default.json → /athena_python_docx-0.26.0/tests/fidelity/op_snapshots/30_styles_iteration.json +0 -0
  292. /athena_python_docx-0.24.0/tests/fidelity/op_snapshots/98_style_contains_check.json → /athena_python_docx-0.26.0/tests/fidelity/op_snapshots/31_styles_lookup_and_default.json +0 -0
  293. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/34_inline_shapes_iterate_empty.json +0 -0
  294. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/36_replace_text_in_paragraph.json +0 -0
  295. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/37_iterate_runs_and_format_all_bold.json +0 -0
  296. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/38_font_all_properties.json +0 -0
  297. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/39_large_body_100_paragraphs.json +0 -0
  298. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/40_large_table_10x10.json +0 -0
  299. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/41_unicode_and_emoji.json +0 -0
  300. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/42_very_long_paragraph.json +0 -0
  301. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/43_paragraph_text_round_trip.json +0 -0
  302. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/44_paragraph_alignment_round_trip.json +0 -0
  303. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/46_run_text_setter_round_trip.json +0 -0
  304. /athena_python_docx-0.24.0/tests/fidelity/op_snapshots/76_rgbcolor_from_string.json → /athena_python_docx-0.26.0/tests/fidelity/op_snapshots/47_font_size_round_trip.json +0 -0
  305. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/52_iterate_everything.json +0 -0
  306. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/54_empty_everything.json +0 -0
  307. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/55_single_character_runs.json +0 -0
  308. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/57_runs_after_multiple_text_appends.json +0 -0
  309. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/58_modify_runs_in_place.json +0 -0
  310. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/59_indent_round_trip.json +0 -0
  311. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/60_space_round_trip.json +0 -0
  312. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/66_toc_like_structure.json +0 -0
  313. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/67_paragraph_insert_before_chain.json +0 -0
  314. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/70_add_and_iterate_back.json +0 -0
  315. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/74_paragraph_with_10_runs.json +0 -0
  316. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/75_paragraph_negative_first_line_indent.json +0 -0
  317. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/77_length_unit_conversions.json +0 -0
  318. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/82_add_text_on_existing_run.json +0 -0
  319. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/83_clear_then_repopulate_paragraph.json +0 -0
  320. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/84_table_reread_row_count.json +0 -0
  321. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/86_font_read_unset_returns_none.json +0 -0
  322. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/87_500_paragraph_doc.json +0 -0
  323. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/88_mixed_content_iteration.json +0 -0
  324. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/89_alignment_clear_via_none.json +0 -0
  325. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/91_many_small_tables.json +0 -0
  326. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/94_page_break_before_paragraph.json +0 -0
  327. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/95_paragraph_hyperlinks_empty.json +0 -0
  328. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/99_run_add_picture_from_bytes.json +0 -0
  329. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/ex03_1000_paragraphs.json +0 -0
  330. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/ex04_50x50_table.json +0 -0
  331. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/ex06_hundred_tiny_runs.json +0 -0
  332. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/ex07_every_font_boolean.json +0 -0
  333. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/ex09_many_tab_stops.json +0 -0
  334. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/ex12_section_reconfigure.json +0 -0
  335. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/ex15_paragraph_all_format_props.json +0 -0
  336. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/ex16_runs_interleaved_with_breaks.json +0 -0
  337. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/ex18_read_back_large_doc.json +0 -0
  338. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/ex19_mutate_all_runs.json +0 -0
  339. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/mega06_complex_newsletter.json +0 -0
  340. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/rw03_character_formatting.json +0 -0
  341. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/rw07_dense_formatting_demo.json +0 -0
  342. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/op_snapshots/rw09_bulk_run_iteration.json +0 -0
  343. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/ours_spec.json +0 -0
  344. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/parity_crawl.py +0 -0
  345. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/parity_diff.json +0 -0
  346. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/real_world_cases.py +0 -0
  347. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/round_trip_tests.py +0 -0
  348. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/stock_spec.json +0 -0
  349. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/fidelity/test_e2e_against_staging.py +0 -0
  350. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/parity/__init__.py +0 -0
  351. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/parity/baseline_gaps.json +0 -0
  352. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/parity/compare.py +0 -0
  353. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/parity/introspect.py +0 -0
  354. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/parity/reports/GAP_ANALYSIS.md +0 -0
  355. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/parity/reports/gap_report.json +0 -0
  356. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/parity/run_parity.py +0 -0
  357. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/parity/snapshots/athena_latest.json +0 -0
  358. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/parity/snapshots/upstream_python_docx_1.2.0.json +0 -0
  359. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_add_section_extract_items.py +0 -0
  360. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_athena_extension_creates_session_open.py +0 -0
  361. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_athena_extensions_contract.py +0 -0
  362. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_batching_perf.py +0 -0
  363. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_cell_add_paragraph_wire_shape.py +0 -0
  364. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_cell_add_table_not_supported.py +0 -0
  365. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_cell_inner_add_hyperlink_stash.py +0 -0
  366. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_cell_inner_add_run_via_cell_insert.py +0 -0
  367. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_cell_inner_run_format_stash.py +0 -0
  368. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_cell_inner_run_guard.py +0 -0
  369. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_cell_text_plain_fastpath.py +0 -0
  370. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_citations.py +0 -0
  371. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_collapsed_range_format.py +0 -0
  372. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_command_dataclasses.py +0 -0
  373. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_document_asset_id_property.py +0 -0
  374. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_document_clear.py +0 -0
  375. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_document_create.py +0 -0
  376. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_document_create_from_template.py +0 -0
  377. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_document_factory_validation.py +0 -0
  378. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_docx_exec_lab.py +0 -0
  379. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_docx_exec_lab_server.py +0 -0
  380. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_e2e_partial_failure_cascade.py +0 -0
  381. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_execution_scope.py +0 -0
  382. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_find_replace_session_open.py +0 -0
  383. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_hyperlink_coalescing.py +0 -0
  384. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_image_url_data_uri.py +0 -0
  385. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_inline_shape_alt_text.py +0 -0
  386. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_insert_deferred.py +0 -0
  387. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_merged_cell_secondary_slot.py +0 -0
  388. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_merged_cells.py +0 -0
  389. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_oxml_shim.py +0 -0
  390. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_paragraph_text_len_cache.py +0 -0
  391. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_partial_failure_cascade.py +0 -0
  392. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_phase_c_tables.py +0 -0
  393. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_positional_cell_id.py +0 -0
  394. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_postproc_cell_run_format_rewrite.py +0 -0
  395. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_postproc_ref_restore.py +0 -0
  396. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_pr19766_review_fixes.py +0 -0
  397. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_ptc.py +0 -0
  398. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_python_docx_api_parity.py +0 -0
  399. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_revisions.py +0 -0
  400. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_run_add_picture_anchor.py +0 -0
  401. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_add_paragraph_style.py +0 -0
  402. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_add_run.py +0 -0
  403. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_cell_add_paragraph.py +0 -0
  404. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_comments_add_comment.py +0 -0
  405. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_comments_get.py +0 -0
  406. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_document_audit.py +0 -0
  407. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_document_element.py +0 -0
  408. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_font_audit.py +0 -0
  409. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_header_footer.py +0 -0
  410. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_hyperlink.py +0 -0
  411. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_insert_paragraph_before.py +0 -0
  412. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_paragraph_style.py +0 -0
  413. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_run_bool_setters.py +0 -0
  414. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_run_style.py +0 -0
  415. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_run_style_strict.py +0 -0
  416. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_run_text.py +0 -0
  417. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_section_audit.py +0 -0
  418. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_section_onoff.py +0 -0
  419. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_settings.py +0 -0
  420. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_shared_audit.py +0 -0
  421. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_styles.py +0 -0
  422. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_table_cell.py +0 -0
  423. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_silent_stub_table_dimensions.py +0 -0
  424. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_smoke_integration.py +0 -0
  425. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_style_acceptance.py +0 -0
  426. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_style_font.py +0 -0
  427. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_table_set_cell_perf.py +0 -0
  428. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_temporarily_unavailable.py +0 -0
  429. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_validate_find_replace_asset_script.py +0 -0
  430. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_xml_attr_guard.py +0 -0
  431. {athena_python_docx-0.24.0 → athena_python_docx-0.26.0}/tests/test_zod_wire_contract.py +0 -0
@@ -31,14 +31,14 @@ These standard python-docx members don't apply to a DOCX Studio-backed SDK:
31
31
 
32
32
  - `Paragraph._p`, `Run._r` — XML element access (no local XML)
33
33
  - `Document.part`, `Paragraph.part`, `Run.part` — package part access
34
- - `Document.core_properties.last_modified_by` — we use Keryx attribution instead
35
34
  - `Document.settings` — Word app settings (not surfaced by DOCX Studio)
36
35
  - `InlineShape.chart` — charts are not currently surfaced by the SDK.
37
36
  - `Comment.add_paragraph` / `Comment.add_table` /
38
37
  `Comment.iter_inner_content` / `Comment.paragraphs` /
39
- `Comment.tables` — DOCX Studio models a comment as a single text body,
40
- not a `BlockItemContainer`. Use `Comment.text` instead. The
41
- paragraph/table-bearing surface raises `CommentsNotImplementedError`.
38
+ `Comment.tables` — DOCX Studio models a comment as a single text body.
39
+ `Comment` is a `docx.blkcntnr.BlockItemContainer`, as `_Cell` and the
40
+ header/footer proxies are, but its paragraph/table-bearing surface raises
41
+ `CommentsNotImplementedError`. Use `Comment.text` instead.
42
42
  - **`_Cell.add_table(rows, cols)`** — surface preserved for parity
43
43
  (signature matches python-docx, no `width` kwarg) but raises
44
44
  :class:`docx.errors.NestedTableNotSupportedError` (subclass of
@@ -71,18 +71,41 @@ runtime, pending additional docx-editor command support. Behavior should be
71
71
  pinned by focused tests and documented in
72
72
  `docx-studio/DOCX_STUDIO_LIMITATIONS.md`.
73
73
 
74
- - **24 setters on `BaseStyle` / `CharacterStyle` / `ParagraphStyle`**
75
- (`name`, `style_id`, `hidden`, `locked`, `priority`, `quick_style`,
76
- `unhide_when_used`, `base_style`, `next_paragraph_style`) emit
77
- `PendingStyleMutationWarning` and stash on `_overrides`.
78
- The current `doc.styles.apply` command surface is constrained to
79
- `target.scope: "docDefaults"` — no per-style metadata variant.
80
- Behavior pinned by `tests/test_style_setters_contract.py` (11
81
- tests); when docx-editor lands a metadata op, those tests will need
82
- to flip to assert real bus calls.
83
- - **`Styles.latent_styles`** returns an empty `_LatentStyles` —
84
- `DocInfoResult.styles` only surfaces `paragraphStyles[]` (a flat
85
- usage-count list), not the OOXML `<w:latentStyles>` block.
74
+ - **Style setters on `BaseStyle` / `CharacterStyle` / `ParagraphStyle`.**
75
+ The metadata setters (`name`, `hidden`, `locked`, `priority`,
76
+ `quick_style`, `unhide_when_used`, `base_style`,
77
+ `next_paragraph_style`) write the style's definition
78
+ (`SetStyleMetadata`), `Styles.add_style` adds one (`CreateStyle`), and
79
+ a paragraph or character style's formatting (`style.font.*`,
80
+ `style.paragraph_format.*`) is written too (`SetStyleFormatting`); each
81
+ reads back from the style table, whose `metadata` / `font` /
82
+ `paragraphFormat` entries are the capability signal
83
+ (`tests/test_style_metadata_writes.py`,
84
+ `tests/test_style_formatting_writes.py`). `style_id`, `delete()`, a
85
+ table style's formatting and base, a style's tab stops, and every style write on
86
+ a docx-studio without that signal emit `PendingStyleMutationWarning`
87
+ (or its paragraph-format / registry variant) and stash on
88
+ `_overrides` (`tests/test_style_setters_contract.py`).
89
+ - **A picture is a run, and `Run.iter_inner_content()` yields its
90
+ `docx.drawing.Drawing`.** As python-docx reads a `w:r` holding a
91
+ `w:drawing`, `Paragraph.runs` and `iter_inner_content()` hold a run with
92
+ text `""` for each picture (docx-studio reports it as a
93
+ `{drawing: {imageId}}` inline), and a linked picture is a run of its
94
+ `Hyperlink`. `run.text = ...` and `run.clear()` on a picture run remove the
95
+ picture with its text (`Replace` with `removePictures`). The drawing's
96
+ `has_picture` is True and its `image` is a `docx.image.image.Image` read
97
+ through `ImagesGet` (python-docx's `blob`, `content_type`, `px_width`,
98
+ `horz_dpi`, `width`, `scaled_dimensions`, …). A picture in a table cell or
99
+ a header has no id to read its image by, so `.image` raises `ValueError`;
100
+ an older docx-studio does not report pictures, so they are not runs there.
101
+ - **`Styles.latent_styles`** (`docx.styles.latent.LatentStyles`) reads
102
+ the document's `<w:latentStyles>` (defaults and each `w:lsdException`)
103
+ from docx-studio's `Info` (`includeStyles` → `latentStyles`), as python-docx
104
+ reads them. Writing them is not supported: a setter, `add_latent_style`
105
+ and `_LatentStyle.delete` emit `PendingLatentStylesWriteWarning` and
106
+ change nothing. A docx-studio that predates the read (or a document
107
+ without a source copy) reads as empty, with
108
+ `PendingLatentStylesReadWarning`.
86
109
 
87
110
  ### Intentional deviations (additions / different semantics)
88
111
 
@@ -100,31 +123,36 @@ not file-backed. Each is documented in the relevant docstring.
100
123
  URIs. Local paths and file-like streams behave exactly as upstream.
101
124
  The dispatch lives in ``docx._image_utils.load_image_bytes``; a failed
102
125
  fetch/decode raises a ``ValueError`` at the call site rather than a
103
- bare transport error. This is the only image-input deviation — the
104
- resulting bytes still flow through the same magic-byte
105
- ``sniff_content_type`` → base64 ``data:`` URI → ``create.image`` path.
126
+ bare transport error. The resulting bytes go through the same
127
+ signature check as upstream: a stream that is no PNG, JPEG, GIF, BMP or
128
+ TIFF (nor, beyond python-docx, WebP or SVG) raises
129
+ ``docx.image.exceptions.UnrecognizedImageError`` whatever its file name,
130
+ where it used to land as a 6" x 4.5" guess
131
+ (``docx._image_utils.image_content_type``).
106
132
 
107
133
  - **Built-in table style friendly names resolve to OOXML styleIds.**
108
134
  Word's ``styles.xml`` ships built-in table styles whose styleIds
109
135
  (``LightGrid-Accent1``, ``MediumShading1-Accent2``, …) differ from
110
- their display names (``"Light Grid Accent 1"``, …). Stock
111
- python-docx resolves the friendly form against the loaded
112
- document's styles collection at write time. We can't read
113
- ``styles.xml`` over HTTP, so ``Document.add_table(style=...)`` /
114
- ``Table.style`` setter consult an in-process map
115
- (``docx._table_styles.BUILTIN_TABLE_STYLE_IDS``) covering every
116
- Word 2007 and Word 2013+ built-in table style (204 entries) before
117
- the value reaches ``<w:tblStyle w:val="..."/>``. Without this
118
- mapping Word can't resolve the friendly name in ``styles.xml``
119
- and silently falls back to ``Normal Table`` (no borders, no
120
- header fill, no banding). Custom user-defined style names pass
121
- through unchanged. Whether Word actually renders a Word 2013+
122
- style after resolution also depends on the exported
123
- ``styles.xml`` containing the matching ``<w:style w:type="table">``
124
- definition. If the exported ``styles.xml`` only carries the Word 2007
125
- set, Word 2013+ styleIds resolve in the ``<w:tblStyle>`` element but
126
- still fall back to ``Normal Table`` until the export path ships an
127
- expanded ``styles.xml``.
136
+ their display names (``"Light Grid Accent 1"``, …). Like python-docx,
137
+ ``Document.add_table(style=...)`` / the ``Table.style`` setter resolve
138
+ a name through the document's style table (docx-studio ``Info``) and
139
+ raise ``KeyError`` for a name it lacks — except a Word built-in table
140
+ style docx-studio holds Word's definition of (python-docx's default
141
+ template: Table Grid, Light Shading … Colorful Grid and their accents),
142
+ which resolves through an in-process map
143
+ (``docx._table_styles.BUILTIN_TABLE_STYLE_IDS``) when the document does
144
+ not define it: the editor draws it from that definition and the export
145
+ adds the definition to ``styles.xml``, as Word does when the style is
146
+ applied. A Word 2013+ table style (Grid Table, List Table, Plain Table)
147
+ the document lacks raises ``KeyError``, as in python-docx, whose
148
+ template defines none. Against a docx-studio that sends no table every
149
+ built-in name (Word 2007 and 2013+, 204 entries) is sent as its id, and
150
+ custom names pass through unchanged. ``Document.add_table`` with no
151
+ style keeps Athena's brand table look (direct cell borders and zebra
152
+ fill, no ``w:tblStyle``) where python-docx's table has none; a style
153
+ set on the table replaces that look, and borders and fills set on its
154
+ cells stay. ``table.style = None`` removes an existing table's style as
155
+ python-docx does (``DOCX_STUDIO_LIMITATIONS.md`` § 25).
128
156
 
129
157
  - **`Document.create(name=, base_url=, api_key=, parent_folder_id=, workspace_id=, docx=, agora_base_url=)`**
130
158
  classmethod. Stock python-docx returns a blank in-memory document
@@ -185,10 +213,10 @@ not file-backed. Each is documented in the relevant docstring.
185
213
 
186
214
  - **`Document.user_name: str | None` / `Document.user_email: str |
187
215
  None`** — author identity threaded through to DOCX Studio on session-
188
- open for tracked-change attribution. python-docx's
189
- `Document.core_properties.last_modified_by` is the closest upstream
190
- surface; we use the DOCX Studio-native fields directly because DOCX Studio
191
- bakes them into the change records.
216
+ open for tracked-change attribution; DOCX Studio bakes them into the
217
+ change records. Separate from `Document.core_properties.last_modified_by`,
218
+ the `docProps/core.xml` metadata the SDK reads and writes as python-docx
219
+ does.
192
220
 
193
221
  - **`Document.revisions: Revisions`** — collection of tracked changes
194
222
  with iteration, `get(id)`, `accept_all()`, `reject_all()`,
@@ -197,6 +225,21 @@ not file-backed. Each is documented in the relevant docstring.
197
225
  has zero track-changes API, so this entire surface is an Athena
198
226
  extension wired to DOCX Studio's `doc.trackChanges.{list,get,decide}`.
199
227
 
228
+ - **Style writes refuse what would write a broken document.** python-docx
229
+ writes these into `styles.xml`; the SDK raises before anything is sent,
230
+ because the result would be a document Word cannot resolve
231
+ (`tests/test_style_metadata_writes.py`):
232
+ - `Styles.add_style` raises `ValueError` for a style id the document
233
+ already has (a name without the space, `"Heading1"`, derives the id
234
+ of the existing Heading 1), where python-docx appends a second
235
+ definition of that id;
236
+ - `base_style = ` a style whose `basedOn` chain reaches this one (itself
237
+ included) raises `ValueError`, where python-docx writes a chain Word
238
+ refuses;
239
+ - `priority = True` raises `TypeError`, where python-docx (to which a
240
+ `bool` is an `int`) writes `w:uiPriority w:val="True"`, not a
241
+ number; any other non-`int` raises `TypeError` in both.
242
+
200
243
  ### Athena extensions for most-requested upstream features (v0.11.0+)
201
244
 
202
245
  These surfaces are **additions** to python-docx, not deviations from
@@ -268,7 +311,14 @@ Issue numbers reference `python-openxml/python-docx`.
268
311
  inside_horizontal=, inside_vertical=)`** + **`_Cell.borders`**
269
312
  property + **`Table.set_borders(...)`** — per-edge border control.
270
313
  python-docx issue #201 (5 👍), #1238 demand a cell-borders API.
271
- Routes through `SetCellBorders` / `SetTableBorders`.
314
+ Routes through `SetCellBorders` / `SetTableBorders`. Each edge is
315
+ `{"style", "size_pt", "color", "space"}` (points; `sizePt` also
316
+ accepted) or `"single 0.5pt #D9D9D9"`; the SDK validates it and sends
317
+ `{style, sizePt, color: "#RRGGBB", space}`. Any other key (`val`, `sz`,
318
+ `size`, `width`) raises `ValueError` naming the accepted form, and
319
+ docx-studio refuses it too (`InvalidBorderSpec`): such edges were once
320
+ stored without their size and colour, and one with no style broke every
321
+ later export of the document.
272
322
 
273
323
  - **`_Cell.set_shading(*, fill=, pattern=, color=)`** +
274
324
  **`_Cell.shading`** property — cell fill / shading. python-docx
@@ -280,7 +330,10 @@ Issue numbers reference `python-openxml/python-docx`.
280
330
  python-docx surfaces `_Cell.grid_span` (horizontal) but the
281
331
  vertical merge state and master detection are issue #1312, #1434,
282
332
  #1458. Pure derived properties from existing `tables.getCells`
283
- data.
333
+ data: docx-studio reports `vMerge` for the grid position asked
334
+ about (`"restart"` on the merged cell's first row, `"continue"`
335
+ below it), while `text`, `grid_span` and writes resolve to the
336
+ merged cell from any position it covers.
284
337
 
285
338
  - **`Table.add_row(*, copy_format_from=None)`** — when `copy_format_from`
286
339
  is provided (int row index or `_Row`), the new row inherits height,
@@ -366,11 +419,57 @@ Issue numbers reference `python-openxml/python-docx`.
366
419
  numbering reads. python-docx issue #471 (13 👍) demands access to
367
420
  list metadata. Routes through `NumberingGet`.
368
421
 
422
+ - **`Paragraph.restart_numbering(start=1)`** (0.26.0+) — restart the
423
+ paragraph's numbered list at `start`, as Word's "Restart at 1" does
424
+ ("Set Numbering Value" for another start). All `"List Number"`
425
+ paragraphs share one numbering, as in Word and python-docx, so a list
426
+ after a heading or table counts on (3, 4) until restarted. python-docx
427
+ has no way to restart a list: issue #25, open since 2014. Routes
428
+ through `ListsSplit` (`restartNumbering: true`, `start`), sent in a
429
+ request of its own after the buffered edits. docx-studio adds a `w:num`
430
+ on the list's `w:abstractNum` whose
431
+ `<w:lvlOverride w:ilvl="N"><w:startOverride w:val="start"/>` (ECMA-376
432
+ §17.9.27) starts the paragraph's level, and points the paragraph and the
433
+ later items of its `w:num` at it: up to the next item of a shallower
434
+ level, the next list restarted on its own, or the end of the document.
435
+ Headings, tables, body text and other lists between the items do not
436
+ end the list, because Word counts across them. A header or footer
437
+ paragraph restarts within its part, whose paragraphs count on their own.
438
+ The same restart again changes nothing. A paragraph that takes no number (plain, heading,
439
+ bullet) raises `docx.errors.NotNumberedListItemError` (a `ValueError`);
440
+ `start` outside 0..32767 raises `ValueError`; a docx-studio API without
441
+ the handler raises `DocxUnsupportedCommandError`. The new `w:num` lives
442
+ in the source package, so each restart stores the package again (one
443
+ copy in the room's history) until #41656 item 7's writers store it by
444
+ reference.
445
+
369
446
  - **`Document.to_pdf(*, quality=None, destination=None,
370
447
  include_revisions=False) -> bytes`** — render to PDF. python-docx
371
448
  issue #113 was closed as
372
449
  wontfix upstream but the request keeps recurring. Routes through
373
- `ExportPDF` (DOCX Studio handles the actual conversion).
450
+ `ExportPDF` (0.25.0+ opens the session first and sends buffered edits in
451
+ the same request). DOCX Studio lays the document out with the engine the
452
+ editor paginates with and paints every page onto Skia's PDF backend: a
453
+ vector PDF with selectable text in embedded fonts that matches
454
+ `render_page` — no LibreOffice anywhere, so never install it in a sandbox.
455
+ `quality` is `"draft"` (pictures as JPEG), `"standard"` (default) or
456
+ `"high"`; `include_revisions=True` shows tracked changes as markup (the
457
+ default renders them accepted); `destination` writes a local file and
458
+ refuses asset ids and URLs with `ValueError`. A deployment that cannot
459
+ produce the PDF raises `DocxUnsupportedCommandError` naming the reason.
460
+ `GET /docs/:id/export.pdf` serves the same PDF read-only (VIEW gate).
461
+
462
+ - **`Document.render_page(page_number=1, scale=2, as_pil=False)`** +
463
+ **`Document.screenshot_to_path(path, page=1, scale=2) -> Path`** +
464
+ **`Document.page_count`** (0.25.0+) — look at the document as the editor
465
+ lays it out: one page (numbered from 1) as PNG bytes or a Pillow image,
466
+ written to disk, and the page count. Names follow
467
+ athena-python-pptx's `slide.render(scale=2, as_pil=True)` and
468
+ athena-openpyxl's `Worksheet.screenshot_to_path`. Buffered edits flush
469
+ first. Backed by docx-studio's read-only `GET /docs/:id/pages/:n.png` and
470
+ `GET /docs/:id/layout.json` (VIEW gate, the SDK's API key); a page past
471
+ the end raises `PageOutOfRangeError` (an `IndexError`) carrying
472
+ `page_count`.
374
473
 
375
474
  - **`Document.clear()`** (0.14.0+) — empty the document body so subsequent
376
475
  writes start from a clean slate. python-docx has no equivalent (it
@@ -723,28 +822,35 @@ gaps. The items below are the **residual intentional deviations** that
723
822
  remain because matching upstream would break the asset-backed/HTTP
724
823
  architecture or a DOCX Studio constraint:
725
824
 
726
- - **`WD_*` enum `.value` is the DOCX Studio wire string, not the MS Word
727
- integer constant.** `WD_ALIGN_PARAGRAPH.CENTER.value == "center"`
728
- (upstream: `1`); `int(member)` / `member == 1` / `WD_*(1)` therefore
729
- differ. The string value is load-bearing — every command serializes
730
- `enum.value` directly onto the wire (`underline=value.value`,
731
- `WD_COLOR_INDEX(v).value`, …), so int-valuing the enums would require
732
- re-plumbing the entire command layer. Members are accessed by name
733
- (`WD_ALIGN_PARAGRAPH.CENTER`), so the drift is academic for normal
734
- use. (`WD_STYLE`/`WD_BUILTIN_STYLE` and `WD_INLINE_SHAPE_TYPE` are NOT
735
- wire-load-bearing and DO carry the upstream int values.)
825
+ - **Enum-typed setters also take the member's DOCX Studio string.** The
826
+ `WD_*` / `MSO_*` enums are python-docx's (`docx.enum.base.BaseEnum` /
827
+ `BaseXmlEnum`): every member is its MS API int
828
+ (`WD_ALIGN_PARAGRAPH.CENTER == 1`, `str()` is `"CENTER (1)"`), XML
829
+ enums carry `xml_value` and `from_xml`/`to_xml`, and the aliases are
830
+ upstream's (`WD_ALIGN_PARAGRAPH is WD_PARAGRAPH_ALIGNMENT`,
831
+ `WD_BREAK.TEXT_WRAPPING is WD_BREAK.LINE_CLEAR_ALL`). Setters take a
832
+ member or its int value as upstream does; they additionally accept the
833
+ string DOCX Studio's commands carry for a member (`"center"`, `"wavy"`,
834
+ the `w:` XML value, …) where upstream rejects strings. The SDK sends
835
+ `member.to_docx_studio()` and reads with `from_docx_studio()`, never
836
+ `.value`. Members DOCX Studio can't apply are sent as their closest
837
+ value with `PendingEnumCoercionWarning` (distributed / kashida / Thai
838
+ justification → `"justify"`; `LIST`/`CLEAR`/`END`/`NUM`/`START` tabs →
839
+ `"left"`); `WD_ALIGN_VERTICAL.BOTH` goes as `"center"`. `INHERITED`
840
+ raises `ValueError` ("has no XML representation") as upstream's
841
+ `to_xml` does, and a bool is its int value (`True` is the member valued
842
+ 1), as upstream reads it. `Table.alignment`
843
+ reads as `WD_TABLE_ALIGNMENT` and takes its three members (upstream
844
+ reads the equal `WD_PARAGRAPH_ALIGNMENT` member and takes any of its
845
+ values), and `Table.table_direction` reads as `WD_TABLE_DIRECTION`
846
+ (upstream: the equal bool). `WD_BUILTIN_STYLE` members carry no
847
+ per-member docstring.
736
848
 
737
849
  - **`RGBColor.from_string` additionally accepts a leading `#`.** Upstream
738
850
  rejects `"#FF0000"`; agents routinely pass it, so a single `#` is
739
851
  stripped before the (otherwise byte-identical) upstream slice parse.
740
852
  A strict superset — every value upstream accepts parses identically.
741
853
 
742
- - **`_Cell.vertical_alignment` setter accepts the four DOCX Studio wire
743
- tokens** (`"top"`/`"center"`/`"bottom"`/`"both"`) in addition to
744
- `WD_ALIGN_VERTICAL` members. Upstream rejects all plain strings; this
745
- is an ergonomic superset (typos like `"middle"` still raise
746
- `ValueError`).
747
-
748
854
  - **`Table.cell(row, col)` bounds-checks each axis independently** and
749
855
  raises `IndexError` for an out-of-range row or column. Upstream
750
856
  indexes a single flat row-major `_cells` list, so a column overflow
@@ -754,28 +860,113 @@ architecture or a DOCX Studio constraint:
754
860
  cheaply enumerate every cell. `(0,0)` and in-range negative indices
755
861
  behave identically to upstream.
756
862
 
757
- - **`BaseStyle.style_id` returns the display name for built-ins** (so
758
- `style_id == name`). The SDK is HTTP-only and can't read `styles.xml`
759
- to recover the OOXML styleId (`"Heading 1"` → `"Heading1"`); the wire
760
- format also uses the display name as the style id. Consequently
761
- `get_by_id("Heading1", …)` / `"Heading1" in styles` won't resolve the
762
- OOXML-id form (use the display name).
863
+ - **Unknown paragraph style names raise only when docx-studio has no
864
+ definition for them.** Style names and ids follow python-docx: `.name` is
865
+ the UI name (`"Heading 1"`), `.style_id` the id (`"Heading1"`), read from
866
+ the document's style table (docx-studio `Info` with `includeStyles`,
867
+ fetched once per session in `docx/styles/_table.py`). A style set by name
868
+ or id is sent as the document's id, and an unstyled paragraph reads as the
869
+ default paragraph style. `paragraph.style = …` raises `KeyError` for a
870
+ name the document defines no style for, like python-docx — except the
871
+ Word built-ins docx-studio holds a definition of
872
+ (`BUILTIN_PARAGRAPH_STYLE_NAMES`: `"Heading 4"`, `"List Bullet"`,
873
+ `"Footnote Text"`, `"TOC 1"`…), which many templates never write into
874
+ `styles.xml` until used. Those are sent by their Word id; the paragraph
875
+ holds `w:pStyle` alone, the editor paints it from that definition and
876
+ the export adds the definition (with a list of the document's own for a
877
+ numbered list style), as Word does when the style is applied. Heading 1–9,
878
+ Title, Subtitle, Quote, Intense Quote, List Paragraph, No Spacing and
879
+ Caption are defined by hand to current Word's definitions
880
+ (`packages/core/src/prosemirror/styles/latentBuiltInStyles.ts`); the
881
+ others are python-docx's default template's, and docx4j's
882
+ `KnownStyles.xml` (Word 2007) for the ones it lacks
883
+ (`packages/core/src/docx/builtInStyles.generated.ts`). `"List Bullet 4"`/
884
+ `"5"` and `"List Number 4"`/`"5"` raise `KeyError`: python-docx's template
885
+ holds no numbering for them. Against an older docx-studio (no style table)
886
+ a built-in name is sent as its id and anything else as given.
887
+ `Run.style` follows the same rule for character styles: it returns a
888
+ `CharacterStyle` (Default Paragraph Font for a run naming none), and a
889
+ name the document lacks raises `KeyError` unless docx-studio holds Word's
890
+ definition of it (`BUILTIN_CHARACTER_STYLE_NAMES` in
891
+ `docx/styles/_table.py`: `"Strong"`, `"Intense Emphasis"`, `"Book Title"`…).
892
+ `Document.add_table(style=)` and `Paragraph.add_run(style=)` resolve the
893
+ style before creating anything, so a rejected style leaves the document
894
+ untouched; python-docx raises after adding the table or run to its
895
+ in-memory tree, but an edit here is live.
763
896
 
764
897
  - **`Document.add_table(rows, cols)` requires `rows >= 1` and
765
898
  `cols >= 1`.** Upstream allows a 0-row/0-col grid you later populate,
766
899
  but DOCX Studio's ProseMirror table node can't represent one; the SDK
767
900
  raises eagerly rather than failing opaquely on the wire.
768
901
 
902
+ - **`_Cell.merge` raises `InvalidSpanError` for every span that would cut
903
+ through a merged cell.** It merges what python-docx merges and refuses
904
+ what python-docx refuses (an L- or T-shaped pair of corners), but where
905
+ a cell inside the rectangle crosses its edge python-docx sometimes
906
+ raises `ValueError` (no `w:tc` at the rectangle's left edge) or writes a
907
+ vertical merge Word reads as broken. docx-studio applies the merge, so
908
+ `merge()` sends a request of its own and raises at the call.
909
+
910
+ - **`core_properties.modified` follows saves that change the package.**
911
+ `doc.core_properties` reads and writes `docProps/core.xml` as python-docx
912
+ does (docx-studio `Info` with `includeCoreProperties`, `SetCoreProperties`;
913
+ `DOCX_STUDIO_LIMITATIONS.md` § 8), but docx-studio stamps `modified` with
914
+ the time of a save that changes the package, a core property included, as
915
+ Word does, where python-docx never stamps it. A `modified` the script sets
916
+ wins in the save that writes it (a later save in the same batch stamps
917
+ again). Every read asks docx-studio, which saves the batch's edits before it
918
+ answers, so a read sees the stamp, and a collaborator's save. A package
919
+ without `docProps/core.xml` reads
920
+ every property as missing, where python-docx adds its own default part
921
+ (title "Word Document", last modified by "python-docx").
922
+
769
923
  - **`Comment.comment_id` returns `str`, not `int`.** DOCX Studio uses
770
924
  non-numeric entity ids (`"c-42"`), so the upstream `int` contract
771
925
  can't be honored. Tracked in `DOCX_STUDIO_LIMITATIONS.md`.
772
926
 
773
- - **`Section` dimension setters and `ParagraphFormat.line_spacing_rule
774
- = None` warn-and-preserve on a clear** rather than raising (upstream
775
- accepts `None` to clear, but DOCX Studio's merging mutation ops have no
776
- single-attribute clear). They emit a `Pending…ClearWarning` and leave
777
- the value intact instead of destructively clearing the whole block.
778
- Tracked in `DOCX_STUDIO_LIMITATIONS.md`.
927
+ - **`add_comment` without an `author` stores the session's name, not
928
+ `""`.** `Document.add_comment` / `Comments.add_comment` send `author`
929
+ and `initials` and docx-studio stores them as `w:author` /
930
+ `w:initials`, as python-docx does; with none (python-docx's default
931
+ `""`) the author is `Document.user_name`, else `"Athena"`, and no
932
+ initials are stored (`initials` then reads `None`). The SDK raises
933
+ `ValueError` for what lxml refuses in an attribute, as python-docx
934
+ does, and also past docx-studio's caps (255 UTF-16 code units for an
935
+ author, 32 for initials); docx-studio turns tabs, line breaks and other
936
+ control characters into spaces. The author is display text only:
937
+ Keryx attributes the edit to the signed-in user (and agent), and
938
+ nothing reads a comment's author as identity.
939
+
940
+ - **`ParagraphFormat.line_spacing_rule = None` warns-and-preserves on a
941
+ clear** rather than raising (upstream accepts `None` to clear, but DOCX
942
+ Studio's merging mutation ops have no single-attribute clear). It emits a
943
+ `Pending…ClearWarning` and leaves the value intact instead of
944
+ destructively clearing the whole block. The `Section` dimension setters
945
+ remove the attribute for `None`, as upstream does (`null` on the wire),
946
+ on a docx-studio whose section read reports `clearsDimensions`; on an
947
+ older one they warn (`PendingSectionDimensionClearWarning`) and keep the
948
+ value. Tracked in `DOCX_STUDIO_LIMITATIONS.md`.
949
+
950
+ - **`Run.text` / `Paragraph.text` read Word's run elements as upstream
951
+ does** (`-` for a non-breaking hyphen, nothing for a soft hyphen or a
952
+ symbol; `\t` for a `w:ptab` in a room that holds it as a tab), but a tab or
953
+ break of an imported run can read as a run of its own. Writes keep text as
954
+ given. `Run.add_tab()` and `Run.add_break()` take the run's formatting, as
955
+ upstream appends them to the run's `w:r`; `Run.add_break(WD_BREAK.COLUMN)`
956
+ sends a column break (`breakType: "column"`), which docx-studio writes after
957
+ the paragraph's content. `DOCX_STUDIO_LIMITATIONS.md` §26.
958
+
959
+ - **Tracked changes read as Word's final view.** `Paragraph.text`, `runs`,
960
+ `iter_inner_content()`, `Hyperlink.text` / `runs` and `_Cell.text` include
961
+ the runs of a tracked insertion (`w:ins`) and leave out a deletion's
962
+ (`w:del`); upstream omits both, as it reads only a `w:p`'s direct `w:r` and
963
+ `w:hyperlink` children. Upstream cannot write tracked changes, so it has no
964
+ write-then-read case to match; with `track_revisions` on (the Athena
965
+ extension), `with doc.tracked_revisions(): p.text = "Updated forecast"`
966
+ deletes the old text and inserts the new, and upstream's omission would
967
+ read the paragraph back as `""`. Word's default views (Simple Markup, No
968
+ Markup) show insertions and hide deletions, as these reads do.
969
+ `doc.revisions` lists every change (`tests/test_run_text_python_docx.py`).
779
970
 
780
971
  ### If you need a deviation
781
972
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: athena-python-docx
3
- Version: 0.24.0
3
+ Version: 0.26.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.24.0"
9
+ __version__ = "0.26.0"
10
10
 
11
11
  from docx.api import Document
12
12
  from docx._buffer import discard_all, flush_all
@@ -341,6 +341,10 @@ class CommandBuffer:
341
341
  self._asset_id: str = asset_id
342
342
  self._pending: list[Command] = []
343
343
  self._lock: threading.RLock = threading.RLock()
344
+ # Held for the whole of a flush (drain + POST), so batches reach the
345
+ # server one at a time and in order, and a flush returns only once
346
+ # every batch taken before it has been delivered.
347
+ self._post_lock: threading.RLock = threading.RLock()
344
348
  self._timer: threading.Timer | None = None
345
349
  self._auto_flush_seconds: float = auto_flush_seconds
346
350
  self._closed: bool = False
@@ -532,6 +536,14 @@ class CommandBuffer:
532
536
  proxies pick up real ids without the caller ever seeing the
533
537
  UUID swap.
534
538
  """
539
+ # One batch in flight at a time: a flush that finds the queue empty
540
+ # still waits for a batch the idle timer already took and is posting,
541
+ # so a read that follows (a query, a page render) sees those edits and
542
+ # a failure of that batch is raised here.
543
+ with self._post_lock:
544
+ return self._flush_in_order()
545
+
546
+ def _flush_in_order(self) -> list[Any]:
535
547
  self._assert_current_execution()
536
548
  self._raise_deferred_flush_error()
537
549
  with self._lock:
@@ -599,7 +611,12 @@ class CommandBuffer:
599
611
  still get their real ids written back via the same flush-time
600
612
  rewrite that :meth:`flush` does.
601
613
  """
614
+ with self._post_lock:
615
+ return self._eager_flush_in_order(cmd)
616
+
617
+ def _eager_flush_in_order(self, cmd: Command) -> Any:
602
618
  self._assert_current_execution()
619
+ self._raise_deferred_flush_error()
603
620
  with self._lock:
604
621
  self._cancel_timer_locked()
605
622
  pending = self._pending