athena-python-docx 0.22.0__tar.gz → 0.23.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 (369) hide show
  1. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/AGENTS.md +13 -0
  2. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/PKG-INFO +1 -1
  3. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/__init__.py +1 -1
  4. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/_citations.py +122 -1
  5. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/text/paragraph.py +6 -1
  6. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/pyproject.toml +1 -1
  7. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_citations.py +183 -0
  8. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/.gitignore +0 -0
  9. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/CLAUDE.md +0 -0
  10. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/DOCX_EXEC_LAB.md +0 -0
  11. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/README.md +0 -0
  12. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/_athena_extension.py +0 -0
  13. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/_batching.py +0 -0
  14. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/_buffer.py +0 -0
  15. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/_execution.py +0 -0
  16. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/_http.py +0 -0
  17. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/_http_doc.py +0 -0
  18. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/_image_utils.py +0 -0
  19. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/_postproc.py +0 -0
  20. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/_ptc.py +0 -0
  21. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/_references.py +0 -0
  22. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/_table_styles.py +0 -0
  23. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/_timeouts.py +0 -0
  24. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/api.py +0 -0
  25. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/bookmarks.py +0 -0
  26. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/charts.py +0 -0
  27. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/client.py +0 -0
  28. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/commands.py +0 -0
  29. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/comments.py +0 -0
  30. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/document.py +0 -0
  31. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/enum/__init__.py +0 -0
  32. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/enum/section.py +0 -0
  33. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/enum/shape.py +0 -0
  34. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/enum/style.py +0 -0
  35. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/enum/table.py +0 -0
  36. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/enum/text.py +0 -0
  37. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/errors.py +0 -0
  38. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/exceptions.py +0 -0
  39. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/fields.py +0 -0
  40. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/footnotes.py +0 -0
  41. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/math.py +0 -0
  42. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/opc/__init__.py +0 -0
  43. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/opc/coreprops.py +0 -0
  44. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/oxml/__init__.py +0 -0
  45. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/revisions.py +0 -0
  46. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/sdt.py +0 -0
  47. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/section.py +0 -0
  48. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/session.py +0 -0
  49. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/settings.py +0 -0
  50. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/shape.py +0 -0
  51. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/shared.py +0 -0
  52. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/styles/__init__.py +0 -0
  53. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/styles/style.py +0 -0
  54. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/styles/styles.py +0 -0
  55. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/table.py +0 -0
  56. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/text/__init__.py +0 -0
  57. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/text/font.py +0 -0
  58. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/text/hyperlink.py +0 -0
  59. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/text/pagebreak.py +0 -0
  60. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/text/parfmt.py +0 -0
  61. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/text/run.py +0 -0
  62. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/text/tabstops.py +0 -0
  63. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/toc.py +0 -0
  64. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/docx/typing.py +0 -0
  65. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/scripts/docx_exec_lab.py +0 -0
  66. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/scripts/docx_exec_lab_examples/fast_table_fill.py +0 -0
  67. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/scripts/docx_exec_lab_examples/find_replace_literal.py +0 -0
  68. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/scripts/docx_exec_lab_server.py +0 -0
  69. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/scripts/dump_wire_fixtures.py +0 -0
  70. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/scripts/release.sh +0 -0
  71. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/scripts/round_trip_smoke.py +0 -0
  72. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/scripts/smoke_test_block_not_found.py +0 -0
  73. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/scripts/validate_find_replace_asset.py +0 -0
  74. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/__init__.py +0 -0
  75. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/conftest.py +0 -0
  76. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/METHODOLOGY.md +0 -0
  77. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/README.md +0 -0
  78. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/__init__.py +0 -0
  79. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/ab_probe_cases.py +0 -0
  80. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/ab_probe_runner.py +0 -0
  81. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/auto_gen_cases.py +0 -0
  82. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/binary_round_trip.py +0 -0
  83. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/cases.py +0 -0
  84. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/complex_cases.py +0 -0
  85. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/coverage_report.py +0 -0
  86. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/extract.py +0 -0
  87. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/extreme_cases.py +0 -0
  88. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/fake_session.py +0 -0
  89. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/firm_templates/README.md +0 -0
  90. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/firm_templates/__init__.py +0 -0
  91. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/firm_templates/_runner.py +0 -0
  92. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/firm_templates/extractor.py +0 -0
  93. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/firm_templates/test_pw_corpus.py +0 -0
  94. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/firm_templates/test_pw_research_digest.py +0 -0
  95. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/local_runner.py +0 -0
  96. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/mega_cases.py +0 -0
  97. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshot.py +0 -0
  98. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/01_basic_paragraph.json +0 -0
  99. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/02_multiple_headings.json +0 -0
  100. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/03_runs_with_formatting.json +0 -0
  101. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/04_font_name_and_size.json +0 -0
  102. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/05_font_color_rgb.json +0 -0
  103. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/06_font_character_properties.json +0 -0
  104. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/07_font_subscript_superscript.json +0 -0
  105. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/08_font_highlight.json +0 -0
  106. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/09_paragraph_alignment.json +0 -0
  107. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/100_table_negative_indexing.json +0 -0
  108. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/101_table_cells_flat_iteration.json +0 -0
  109. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/102_text_with_embedded_special_chars.json +0 -0
  110. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/104_core_properties_datetime.json +0 -0
  111. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/105_default_one_section.json +0 -0
  112. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/106_heading_paragraph_format.json +0 -0
  113. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/107_varying_row_heights.json +0 -0
  114. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/10_paragraph_indents.json +0 -0
  115. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/11_paragraph_spacing.json +0 -0
  116. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/12_paragraph_keep_options.json +0 -0
  117. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/13_paragraph_tab_stops.json +0 -0
  118. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/14_run_add_tab_and_break.json +0 -0
  119. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/15_run_add_break_page.json +0 -0
  120. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/16_paragraph_clear_and_insert_before.json +0 -0
  121. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/17_table_basic.json +0 -0
  122. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/18_table_cell_text.json +0 -0
  123. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/19_table_row_column_sizing.json +0 -0
  124. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/20_table_cell_vertical_alignment.json +0 -0
  125. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/21_table_alignment_and_autofit.json +0 -0
  126. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/22_table_cell_paragraphs_iteration.json +0 -0
  127. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/24_table_add_row_column.json +0 -0
  128. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/25_table_merge_cells.json +0 -0
  129. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/26_section_page_setup.json +0 -0
  130. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/27_section_margins.json +0 -0
  131. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/28_section_add_new.json +0 -0
  132. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/29_section_headers_linked.json +0 -0
  133. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/30_styles_iteration.json +0 -0
  134. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/31_styles_lookup_and_default.json +0 -0
  135. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/32_styles_add_paragraph_style.json +0 -0
  136. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/33_core_properties_set_and_get.json +0 -0
  137. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/34_inline_shapes_iterate_empty.json +0 -0
  138. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/35_full_report.json +0 -0
  139. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/36_replace_text_in_paragraph.json +0 -0
  140. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/37_iterate_runs_and_format_all_bold.json +0 -0
  141. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/38_font_all_properties.json +0 -0
  142. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/39_large_body_100_paragraphs.json +0 -0
  143. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/40_large_table_10x10.json +0 -0
  144. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/41_unicode_and_emoji.json +0 -0
  145. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/42_very_long_paragraph.json +0 -0
  146. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/43_paragraph_text_round_trip.json +0 -0
  147. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/44_paragraph_alignment_round_trip.json +0 -0
  148. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/45_cell_text_round_trip.json +0 -0
  149. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/46_run_text_setter_round_trip.json +0 -0
  150. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/47_font_size_round_trip.json +0 -0
  151. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/48_font_color_round_trip.json +0 -0
  152. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/49_resume_layout.json +0 -0
  153. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/50_multi_section_doc.json +0 -0
  154. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/52_iterate_everything.json +0 -0
  155. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/53_apply_style_to_paragraphs.json +0 -0
  156. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/54_empty_everything.json +0 -0
  157. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/55_single_character_runs.json +0 -0
  158. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/56_everything_in_one.json +0 -0
  159. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/57_runs_after_multiple_text_appends.json +0 -0
  160. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/58_modify_runs_in_place.json +0 -0
  161. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/59_indent_round_trip.json +0 -0
  162. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/60_space_round_trip.json +0 -0
  163. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/61_cell_paragraph_with_runs.json +0 -0
  164. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/62_many_cell_paragraphs.json +0 -0
  165. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/63_table_style_round_trip.json +0 -0
  166. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/64_many_sections.json +0 -0
  167. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/65_20x20_table_formatted.json +0 -0
  168. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/66_toc_like_structure.json +0 -0
  169. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/67_paragraph_insert_before_chain.json +0 -0
  170. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/68_invoice.json +0 -0
  171. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/69_newsletter.json +0 -0
  172. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/70_add_and_iterate_back.json +0 -0
  173. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/71_academic_paper.json +0 -0
  174. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/72_legal_contract.json +0 -0
  175. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/73_form_with_many_tables.json +0 -0
  176. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/74_paragraph_with_10_runs.json +0 -0
  177. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/75_paragraph_negative_first_line_indent.json +0 -0
  178. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/76_rgbcolor_from_string.json +0 -0
  179. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/77_length_unit_conversions.json +0 -0
  180. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/78_paragraph_copy_style.json +0 -0
  181. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/79_bulk_cell_formatting.json +0 -0
  182. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/80_apply_style_after_add_run.json +0 -0
  183. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/81_multi_page_with_breaks.json +0 -0
  184. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/82_add_text_on_existing_run.json +0 -0
  185. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/83_clear_then_repopulate_paragraph.json +0 -0
  186. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/84_table_reread_row_count.json +0 -0
  187. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/85_header_footer_access.json +0 -0
  188. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/86_font_read_unset_returns_none.json +0 -0
  189. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/87_500_paragraph_doc.json +0 -0
  190. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/88_mixed_content_iteration.json +0 -0
  191. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/89_alignment_clear_via_none.json +0 -0
  192. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/90_cell_add_paragraph_styled.json +0 -0
  193. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/91_many_small_tables.json +0 -0
  194. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/92_margins_every_section.json +0 -0
  195. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/93_font_bool_reads_after_set.json +0 -0
  196. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/94_page_break_before_paragraph.json +0 -0
  197. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/95_paragraph_hyperlinks_empty.json +0 -0
  198. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/96_paragraph_contains_page_break.json +0 -0
  199. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/97_document_styles_by_key.json +0 -0
  200. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/98_style_contains_check.json +0 -0
  201. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/99_run_add_picture_from_bytes.json +0 -0
  202. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/ex02_unicode_everywhere.json +0 -0
  203. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/ex03_1000_paragraphs.json +0 -0
  204. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/ex04_50x50_table.json +0 -0
  205. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/ex05_long_text_in_cell.json +0 -0
  206. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/ex06_hundred_tiny_runs.json +0 -0
  207. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/ex07_every_font_boolean.json +0 -0
  208. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/ex08_many_continuous_sections.json +0 -0
  209. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/ex09_many_tab_stops.json +0 -0
  210. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/ex10_complex_bom.json +0 -0
  211. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/ex11_banded_rows_formatting.json +0 -0
  212. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/ex12_section_reconfigure.json +0 -0
  213. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/ex13_cell_with_10_paragraphs.json +0 -0
  214. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/ex14_styled_report_table.json +0 -0
  215. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/ex15_paragraph_all_format_props.json +0 -0
  216. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/ex16_runs_interleaved_with_breaks.json +0 -0
  217. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/ex17_all_break_kinds.json +0 -0
  218. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/ex18_read_back_large_doc.json +0 -0
  219. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/ex19_mutate_all_runs.json +0 -0
  220. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/ex20_kitchen_sink_v2.json +0 -0
  221. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/mega01_book_chapter.json +0 -0
  222. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/mega02_research_proposal.json +0 -0
  223. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/mega03_financial_statement.json +0 -0
  224. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/mega04_recipe_card.json +0 -0
  225. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/mega05_user_manual.json +0 -0
  226. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/mega06_complex_newsletter.json +0 -0
  227. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/mega07_budget_spreadsheet.json +0 -0
  228. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/mega08_product_catalog.json +0 -0
  229. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/mega09_signed_contract.json +0 -0
  230. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/mega10_api_documentation.json +0 -0
  231. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/rw01_official_quickstart.json +0 -0
  232. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/rw02_paragraph_style_list.json +0 -0
  233. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/rw03_character_formatting.json +0 -0
  234. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/rw04_section_page_setup.json +0 -0
  235. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/rw05_toc_pattern.json +0 -0
  236. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/rw06_meeting_minutes.json +0 -0
  237. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/rw07_dense_formatting_demo.json +0 -0
  238. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/rw08_table_merged_header.json +0 -0
  239. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/rw09_bulk_run_iteration.json +0 -0
  240. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/rw10_colored_grid_table.json +0 -0
  241. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/rw11_header_text.json +0 -0
  242. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/rw12_first_page_footer.json +0 -0
  243. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/rw13_even_page_header.json +0 -0
  244. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/op_snapshots/rw15_paragraph_style_instance.json +0 -0
  245. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/ours_spec.json +0 -0
  246. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/parity_crawl.py +0 -0
  247. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/parity_diff.json +0 -0
  248. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/real_world_cases.py +0 -0
  249. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/round_trip_tests.py +0 -0
  250. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/stock_spec.json +0 -0
  251. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/fidelity/test_e2e_against_staging.py +0 -0
  252. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/parity/README.md +0 -0
  253. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/parity/__init__.py +0 -0
  254. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/parity/baseline_gaps.json +0 -0
  255. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/parity/compare.py +0 -0
  256. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/parity/intentional_deviations.json +0 -0
  257. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/parity/introspect.py +0 -0
  258. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/parity/reports/GAP_ANALYSIS.md +0 -0
  259. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/parity/reports/gap_report.json +0 -0
  260. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/parity/run_parity.py +0 -0
  261. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/parity/snapshots/athena_latest.json +0 -0
  262. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/parity/snapshots/upstream_python_docx_1.2.0.json +0 -0
  263. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/parity/test_parity_gap.py +0 -0
  264. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_add_section_extract_items.py +0 -0
  265. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_athena_extension_creates_session_open.py +0 -0
  266. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_athena_extensions_contract.py +0 -0
  267. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_athena_extensions_registry.py +0 -0
  268. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_batching_perf.py +0 -0
  269. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_block_not_found_error.py +0 -0
  270. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_buffer.py +0 -0
  271. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_cell_add_paragraph_wire_shape.py +0 -0
  272. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_cell_add_table_not_supported.py +0 -0
  273. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_cell_fastpath_runs.py +0 -0
  274. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_cell_inner_add_hyperlink_stash.py +0 -0
  275. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_cell_inner_add_run_via_cell_insert.py +0 -0
  276. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_cell_inner_format_stash.py +0 -0
  277. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_cell_inner_run_format_stash.py +0 -0
  278. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_cell_inner_run_guard.py +0 -0
  279. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_cell_text_plain_fastpath.py +0 -0
  280. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_cell_text_replace_semantics.py +0 -0
  281. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_collapsed_range_format.py +0 -0
  282. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_command_dataclasses.py +0 -0
  283. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_commands.py +0 -0
  284. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_comments.py +0 -0
  285. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_document_asset_id_property.py +0 -0
  286. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_document_clear.py +0 -0
  287. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_document_create.py +0 -0
  288. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_document_create_from_template.py +0 -0
  289. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_document_factory_validation.py +0 -0
  290. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_docx_exec_lab.py +0 -0
  291. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_docx_exec_lab_server.py +0 -0
  292. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_e2e_partial_failure_cascade.py +0 -0
  293. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_execution_scope.py +0 -0
  294. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_find_replace_session_open.py +0 -0
  295. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_http_transport.py +0 -0
  296. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_hyperlink_coalescing.py +0 -0
  297. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_image_url_data_uri.py +0 -0
  298. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_insert_deferred.py +0 -0
  299. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_iter_inner_content.py +0 -0
  300. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_list_styles.py +0 -0
  301. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_merged_cell_secondary_slot.py +0 -0
  302. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_merged_cells.py +0 -0
  303. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_oxml_shim.py +0 -0
  304. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_paragraph_text_len_cache.py +0 -0
  305. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_parity_misc.py +0 -0
  306. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_parity_round2.py +0 -0
  307. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_partial_failure_cascade.py +0 -0
  308. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_phase_a_behavior.py +0 -0
  309. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_phase_b_headers_footers.py +0 -0
  310. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_phase_c_tables.py +0 -0
  311. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_positional_cell_id.py +0 -0
  312. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_postproc_cell_format_rewrite.py +0 -0
  313. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_postproc_cell_run_format_rewrite.py +0 -0
  314. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_postproc_ref_restore.py +0 -0
  315. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_pr19766_review_fixes.py +0 -0
  316. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_ptc.py +0 -0
  317. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_python_docx_api_parity.py +0 -0
  318. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_revisions.py +0 -0
  319. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_run_add_picture_anchor.py +0 -0
  320. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_run_mark_inheritance.py +0 -0
  321. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_add_paragraph_style.py +0 -0
  322. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_add_picture.py +0 -0
  323. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_add_run.py +0 -0
  324. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_cell_add_paragraph.py +0 -0
  325. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_comments_add_comment.py +0 -0
  326. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_comments_get.py +0 -0
  327. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_document_audit.py +0 -0
  328. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_document_element.py +0 -0
  329. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_enum_section.py +0 -0
  330. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_font_audit.py +0 -0
  331. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_header_footer.py +0 -0
  332. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_hyperlink.py +0 -0
  333. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_inline_shape.py +0 -0
  334. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_insert_paragraph_before.py +0 -0
  335. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_misc.py +0 -0
  336. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_paragraph_strict.py +0 -0
  337. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_paragraph_style.py +0 -0
  338. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_paragraph_style_strict.py +0 -0
  339. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_parfmt.py +0 -0
  340. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_row_col_cell.py +0 -0
  341. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_run_add_break.py +0 -0
  342. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_run_bool_setters.py +0 -0
  343. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_run_style.py +0 -0
  344. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_run_style_strict.py +0 -0
  345. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_run_text.py +0 -0
  346. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_run_underline.py +0 -0
  347. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_section_audit.py +0 -0
  348. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_section_dimensions.py +0 -0
  349. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_section_onoff.py +0 -0
  350. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_settings.py +0 -0
  351. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_shared_audit.py +0 -0
  352. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_style.py +0 -0
  353. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_styles.py +0 -0
  354. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_table_audit.py +0 -0
  355. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_table_cell.py +0 -0
  356. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_table_dimensions.py +0 -0
  357. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_silent_stub_table_layout.py +0 -0
  358. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_smoke_integration.py +0 -0
  359. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_style_acceptance.py +0 -0
  360. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_style_font.py +0 -0
  361. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_style_setters_contract.py +0 -0
  362. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_table_set_cell_perf.py +0 -0
  363. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_table_style_id_resolution.py +0 -0
  364. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_temporarily_unavailable.py +0 -0
  365. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_validate_find_replace_asset_script.py +0 -0
  366. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_wire_contract.py +0 -0
  367. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_xml_attr_guard.py +0 -0
  368. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/tests/test_zod_wire_contract.py +0 -0
  369. {athena_python_docx-0.22.0 → athena_python_docx-0.23.0}/uv.lock +0 -0
@@ -481,6 +481,19 @@ Issue numbers reference `python-openxml/python-docx`.
481
481
  an older API stores the record under the cell id, where nothing renders
482
482
  it and the next edit retires it.
483
483
 
484
+ - **Image region citations**: cite a region of an image asset with
485
+ ``AssetReference(id=<image>)`` + ``PixelRangeAnchor(x=, y=, width=,
486
+ height=)`` in source image pixels, or with a
487
+ ``/dashboard/spaces/?asset_ids=<image>&type=image&anchor=pixel_range&x=…&y=…&width=…&height=…``
488
+ citation string. DOCX Studio stores ``type=image`` and keeps ``excerpt``
489
+ out of the URL (the record keeps it as the span of the cited paragraph to
490
+ highlight). Since 0.23.0, ``add_citation`` raises ``ValueError`` for the
491
+ image citations that chat and Sheets reject (agora
492
+ ``validate_image_citation_url``): an image URL with ``excerpt`` or
493
+ ``#:~:text=`` and no anchor, a non-region anchor, a region anchor without
494
+ x, y, width and height, and an ``AssetMeta(asset_type="image")`` source
495
+ with a non-region anchor or with an excerpt and no anchor.
496
+
484
497
  - **`Document.export_docx(path=None, *, include_revisions=False)
485
498
  -> bytes`** (0.11.4+) — export the document's current state as
486
499
  ``.docx`` bytes, optionally writing to ``path``. Closes the gap
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: athena-python-docx
3
- Version: 0.22.0
3
+ Version: 0.23.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.22.0"
9
+ __version__ = "0.23.0"
10
10
 
11
11
  from docx.api import Document
12
12
  from docx._buffer import discard_all, flush_all
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import uuid
6
+ from collections.abc import Mapping
6
7
  from typing import Any
7
8
  from urllib.parse import parse_qs, urlparse
8
9
 
@@ -34,6 +35,87 @@ def source_ref_to_dict(source: AssetReference) -> dict[str, Any]:
34
35
  return source.to_dict()
35
36
 
36
37
 
38
+ _IMAGE_REGION_ANCHOR_TYPES: tuple[str, ...] = ("pixel_range", "rect")
39
+ _IMAGE_REGION_FIELDS: tuple[str, ...] = ("x", "y", "width", "height")
40
+
41
+
42
+ def _is_number(value: object) -> bool:
43
+ """True for what agora's anchor parser reads as a number (``float(...)``)."""
44
+ if isinstance(value, bool):
45
+ return False
46
+ if isinstance(value, (int, float)):
47
+ return True
48
+ if isinstance(value, str):
49
+ try:
50
+ float(value)
51
+ except ValueError:
52
+ return False
53
+ return True
54
+ return False
55
+
56
+
57
+ def check_image_citation(
58
+ *,
59
+ anchor_type: str | None,
60
+ has_excerpt: bool,
61
+ region: Mapping[str, object] | None = None,
62
+ ) -> None:
63
+ """Reject an image citation that chat and Sheets reject.
64
+
65
+ The same rules as agora's ``validate_citation_url`` for an image: an
66
+ image is cited by a region (``anchor=pixel_range`` with numeric x, y,
67
+ width and height in source image pixels), never by a page, a text anchor
68
+ or an excerpt. ``region`` holds the x, y, width and height values of a
69
+ region anchor (``None`` for a missing one).
70
+ """
71
+ if anchor_type and anchor_type not in _IMAGE_REGION_ANCHOR_TYPES:
72
+ raise ValueError(
73
+ f"An image citation cannot use anchor={anchor_type}. Cite a region "
74
+ "of the image: anchor=pixel_range with x, y, width and height in "
75
+ "source image pixels (PixelRangeAnchor)."
76
+ )
77
+ if not anchor_type and has_excerpt:
78
+ raise ValueError(
79
+ "An image citation cannot use an excerpt or a #:~:text= fragment: "
80
+ "an image has no text to find. Cite a region of the image: "
81
+ "anchor=pixel_range with x, y, width and height in source image "
82
+ "pixels (PixelRangeAnchor), and put the label in display_value."
83
+ )
84
+ if not anchor_type or region is None:
85
+ return
86
+ missing = [field for field in _IMAGE_REGION_FIELDS if region.get(field) is None]
87
+ if missing:
88
+ raise ValueError(
89
+ f"An image citation with anchor={anchor_type} needs x, y, width "
90
+ f"and height. Missing: {', '.join(missing)}."
91
+ )
92
+ not_numbers = [field for field in _IMAGE_REGION_FIELDS if not _is_number(region[field])]
93
+ if not_numbers:
94
+ raise ValueError(
95
+ f"An image citation with anchor={anchor_type} needs numbers for "
96
+ f"x, y, width and height. Not a number: {', '.join(not_numbers)}."
97
+ )
98
+
99
+
100
+ def _check_image_citation_url(query: str, fragment: str) -> None:
101
+ # Blank values are dropped, as agora's validator parses the query.
102
+ params = parse_qs(query)
103
+
104
+ def first(key: str) -> str | None:
105
+ values = params.get(key)
106
+ return values[0] if values else None
107
+
108
+ asset_type = (first("asset_type") or first("type") or "").lower()
109
+ if asset_type != "image":
110
+ return
111
+ anchor_type = (first("anchor") or "").lower() or None
112
+ check_image_citation(
113
+ anchor_type=anchor_type,
114
+ has_excerpt=first("excerpt") is not None or fragment.startswith(":~:text="),
115
+ region={field: first(field) for field in _IMAGE_REGION_FIELDS},
116
+ )
117
+
118
+
37
119
  def normalize_citation_string(citation_string: str) -> str:
38
120
  value = citation_string.strip()
39
121
  if not value:
@@ -49,6 +131,7 @@ def normalize_citation_string(citation_string: str) -> str:
49
131
  asset_ids = parse_qs(parsed.query).get("asset_ids")
50
132
  if not asset_ids or not asset_ids[0]:
51
133
  raise ValueError("Athena Spaces citation URLs must include asset_ids")
134
+ _check_image_citation_url(parsed.query, parsed.fragment)
52
135
  return value
53
136
 
54
137
  if not parsed.scheme and value.startswith("/"):
@@ -61,6 +144,7 @@ def normalize_citation_string(citation_string: str) -> str:
61
144
  if relative.path.rstrip("/") == "/dashboard/spaces":
62
145
  asset_ids = parse_qs(relative.query).get("asset_ids")
63
146
  if asset_ids and asset_ids[0]:
147
+ _check_image_citation_url(relative.query, relative.fragment)
64
148
  return value
65
149
  raise ValueError("Athena Spaces citation URLs must include asset_ids")
66
150
 
@@ -106,6 +190,35 @@ def destination_anchor_to_dict(destination_anchor: object) -> dict[str, Any]:
106
190
  )
107
191
 
108
192
 
193
+ def _check_typed_image_citation(
194
+ *,
195
+ source_ref: dict[str, Any],
196
+ source_anchor: dict[str, Any] | None,
197
+ excerpt: str | None,
198
+ ) -> None:
199
+ """Apply the image citation rules to an ``AssetReference`` source.
200
+
201
+ A ``PixelRangeAnchor`` / ``RectAnchor`` source is an image region:
202
+ DOCX Studio names it ``type=image`` and keeps the excerpt out of its URL
203
+ (the record keeps it as the span of the cited paragraph to highlight).
204
+ A source that ``AssetMeta(asset_type="image")`` names an image must use
205
+ one of those anchors.
206
+ """
207
+ anchor = source_anchor or source_ref.get("anchor")
208
+ anchor_type = anchor.get("type") if isinstance(anchor, dict) else None
209
+ meta = source_ref.get("meta")
210
+ asset_type = meta.get("assetType") if isinstance(meta, dict) else None
211
+ is_region = anchor_type in _IMAGE_REGION_ANCHOR_TYPES
212
+ if not is_region and str(asset_type or "").lower() != "image":
213
+ return
214
+ meta_excerpt = meta.get("excerpt") if isinstance(meta, dict) else None
215
+ check_image_citation(
216
+ anchor_type=anchor_type,
217
+ has_excerpt=excerpt is not None or meta_excerpt is not None,
218
+ region=anchor if is_region and isinstance(anchor, dict) else None,
219
+ )
220
+
221
+
109
222
  def build_add_citation_command(
110
223
  *,
111
224
  destination_anchor: object,
@@ -142,11 +255,19 @@ def build_add_citation_command(
142
255
  if source_ref is None and anchor is not None:
143
256
  raise ValueError("anchor requires an AssetReference source; encode the anchor in citation_string instead")
144
257
 
258
+ source_anchor = anchor_to_dict(anchor)
259
+ if source_ref is not None:
260
+ _check_typed_image_citation(
261
+ source_ref=source_ref,
262
+ source_anchor=source_anchor,
263
+ excerpt=excerpt,
264
+ )
265
+
145
266
  citation_id = new_citation_id()
146
267
  return citation_id, AddCitation(
147
268
  destination_anchor=destination_anchor_to_dict(destination_anchor),
148
269
  source_ref=source_ref,
149
- source_anchor=anchor_to_dict(anchor),
270
+ source_anchor=source_anchor,
150
271
  citation_string=normalized_citation_string,
151
272
  citation_id=citation_id,
152
273
  excerpt=excerpt,
@@ -1501,7 +1501,12 @@ class Paragraph:
1501
1501
  Pass either a serialized citation URL via ``citation_string`` /
1502
1502
  positional ``source`` string, or an ``AssetReference`` from
1503
1503
  ``docx._references`` plus an optional source ``anchor`` such as a
1504
- spreadsheet ``SheetRangeAnchor`` or a media ``TimeRangeAnchor``.
1504
+ spreadsheet ``SheetRangeAnchor``, a media ``TimeRangeAnchor`` or an
1505
+ image ``PixelRangeAnchor`` (a region in source image pixels). An
1506
+ image citation that chat and Sheets reject raises ``ValueError``: an
1507
+ excerpt with no region anchor, a page or text anchor, or a region
1508
+ without numeric x, y, width and height. An excerpt beside a region
1509
+ anchor is allowed; it names the span of this paragraph to highlight.
1505
1510
 
1506
1511
  A paragraph inside a table cell is citable too. ``cell.paragraphs[0]``
1507
1512
  stands for the whole cell, so the citation covers the text of the
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "athena-python-docx"
7
- version = "0.22.0"
7
+ version = "0.23.0"
8
8
  description = "Drop-in replacement for python-docx that connects to Athena's DOCX Studio collaborative document stack"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -435,3 +435,186 @@ def test_cell_add_citation_validates_the_source_before_sending() -> None:
435
435
  with pytest.raises(ValueError, match="source or citation_string"):
436
436
  cell.add_citation()
437
437
  assert session.commands == []
438
+
439
+
440
+ # ---------------------------------------------------------------------------
441
+ # Image region citations
442
+ # ---------------------------------------------------------------------------
443
+
444
+ _IMAGE_REGION_URL = (
445
+ "/dashboard/spaces/?asset_ids=asset_chart&type=image"
446
+ "&anchor=pixel_range&x=355&y=120&width=100&height=565"
447
+ )
448
+
449
+
450
+ def test_paragraph_add_citation_cites_an_image_region_with_pixel_range_anchor() -> None:
451
+ from docx._references import AssetReference, PixelRangeAnchor
452
+ from docx.text.paragraph import Paragraph
453
+
454
+ session = _FakeSession()
455
+ paragraph = Paragraph(session=session, node_id="para_1", text_len=48)
456
+
457
+ citation_id = paragraph.add_citation(
458
+ AssetReference(id="asset_chart"),
459
+ anchor=PixelRangeAnchor(x=355, y=120, width=100, height=565),
460
+ display_value="57.8",
461
+ )
462
+
463
+ [cmd] = session.commands
464
+ assert isinstance(cmd, AddCitation)
465
+ assert cmd.to_dict() == {
466
+ "type": "AddCitation",
467
+ "destinationAnchor": {"type": "pm_node", "nodeId": "para_1"},
468
+ "sourceRef": {"referenced": "asset", "id": "asset_chart"},
469
+ "sourceAnchor": {"type": "pixel_range", "x": 355, "y": 120, "width": 100, "height": 565},
470
+ "citationId": citation_id,
471
+ "displayValue": "57.8",
472
+ }
473
+
474
+
475
+ def test_image_region_citation_keeps_an_excerpt_for_the_cited_paragraph() -> None:
476
+ # Chat and Sheets accept an excerpt next to a region anchor; DOCX Studio
477
+ # keeps it on the record (the span to highlight) and out of the URL.
478
+ from docx._references import AssetReference, PixelRangeAnchor
479
+ from docx.text.paragraph import Paragraph
480
+
481
+ session = _FakeSession()
482
+ paragraph = Paragraph(session=session, node_id="para_1")
483
+
484
+ paragraph.add_citation(
485
+ AssetReference(id="asset_chart"),
486
+ anchor=PixelRangeAnchor(x=355, y=120, width=100, height=565),
487
+ excerpt="57.8",
488
+ )
489
+
490
+ [cmd] = session.commands
491
+ assert cmd.excerpt == "57.8"
492
+ assert cmd.source_anchor == {"type": "pixel_range", "x": 355, "y": 120, "width": 100, "height": 565}
493
+
494
+
495
+ def test_paragraph_add_citation_accepts_an_image_region_citation_string() -> None:
496
+ from docx.text.paragraph import Paragraph
497
+
498
+ session = _FakeSession()
499
+ paragraph = Paragraph(session=session, node_id="para_1")
500
+
501
+ paragraph.add_citation(_IMAGE_REGION_URL, display_value="East bar")
502
+ paragraph.add_citation(citation_string=f"https://app.athenaintel.com{_IMAGE_REGION_URL}")
503
+
504
+ assert [cmd.citation_string for cmd in session.commands] == [
505
+ _IMAGE_REGION_URL,
506
+ f"https://app.athenaintel.com{_IMAGE_REGION_URL}",
507
+ ]
508
+ assert all(cmd.source_ref is None and cmd.source_anchor is None for cmd in session.commands)
509
+
510
+
511
+ def test_cell_add_citation_cites_an_image_region() -> None:
512
+ from docx._references import AssetReference, PixelRangeAnchor
513
+ from docx.table import _Cell
514
+
515
+ session = _FakeSession()
516
+ cell = _Cell(table=_CellTableStub(session), row=1, col=1) # type: ignore[arg-type]
517
+
518
+ cell.add_citation(
519
+ AssetReference(id="asset_chart"),
520
+ anchor=PixelRangeAnchor(x=700, y=332, width=460, height=64),
521
+ )
522
+
523
+ [cmd] = session.commands
524
+ assert cmd.destination_anchor == {"type": "pm_node", "nodeId": "tc:2:1:1"}
525
+ assert cmd.source_anchor == {"type": "pixel_range", "x": 700, "y": 332, "width": 460, "height": 64}
526
+
527
+
528
+ @pytest.mark.parametrize(
529
+ ("citation_string", "message"),
530
+ [
531
+ (
532
+ "/dashboard/spaces/?asset_ids=asset_chart&type=image&excerpt=57.8",
533
+ "cannot use an excerpt",
534
+ ),
535
+ (
536
+ "https://app.athenaintel.com/dashboard/spaces/?asset_ids=asset_chart&type=image#:~:text=57.8",
537
+ "cannot use an excerpt",
538
+ ),
539
+ (
540
+ "/dashboard/spaces/?asset_ids=asset_chart&type=image&anchor=page&page=1",
541
+ "cannot use anchor=page",
542
+ ),
543
+ (
544
+ "/dashboard/spaces/?asset_ids=asset_chart&type=image&anchor=pixel_range&x=355&y=120&width=100",
545
+ "Missing: height",
546
+ ),
547
+ (
548
+ # A blank value is missing, as agora parses the query.
549
+ "/dashboard/spaces/?asset_ids=asset_chart&type=image&anchor=pixel_range&x=&y=120&width=100&height=565",
550
+ "Missing: x",
551
+ ),
552
+ (
553
+ "/dashboard/spaces/?asset_ids=asset_chart&type=image&anchor=pixel_range&x=oops&y=120&width=100&height=565",
554
+ "Not a number: x",
555
+ ),
556
+ (
557
+ "https://app.athenaintel.com/dashboard/spaces/?asset_ids=asset_chart&type=image"
558
+ "&anchor=rect&x=0.1&y=0.2&width=wide&height=0.4",
559
+ "Not a number: width",
560
+ ),
561
+ ],
562
+ )
563
+ def test_add_citation_rejects_the_image_citation_urls_chat_rejects(
564
+ citation_string: str, message: str
565
+ ) -> None:
566
+ from docx.text.paragraph import Paragraph
567
+
568
+ session = _FakeSession()
569
+ paragraph = Paragraph(session=session, node_id="para_1")
570
+
571
+ with pytest.raises(ValueError, match=message):
572
+ paragraph.add_citation(citation_string)
573
+ assert session.commands == []
574
+
575
+
576
+ def test_add_citation_accepts_an_image_reference_without_a_region() -> None:
577
+ # The whole image, with no excerpt: chat accepts it too.
578
+ from docx.text.paragraph import Paragraph
579
+
580
+ session = _FakeSession()
581
+ paragraph = Paragraph(session=session, node_id="para_1")
582
+
583
+ paragraph.add_citation("/dashboard/spaces/?asset_ids=asset_chart&type=image")
584
+ # A blank excerpt is no excerpt, as agora parses the query.
585
+ paragraph.add_citation("/dashboard/spaces/?asset_ids=asset_chart&type=image&excerpt=")
586
+
587
+ assert [cmd.citation_string for cmd in session.commands] == [
588
+ "/dashboard/spaces/?asset_ids=asset_chart&type=image",
589
+ "/dashboard/spaces/?asset_ids=asset_chart&type=image&excerpt=",
590
+ ]
591
+
592
+
593
+ def test_add_citation_rejects_a_typed_region_with_a_non_numeric_coordinate() -> None:
594
+ from docx._references import AssetReference, PixelRangeAnchor
595
+ from docx.text.paragraph import Paragraph
596
+
597
+ session = _FakeSession()
598
+ paragraph = Paragraph(session=session, node_id="para_1")
599
+
600
+ with pytest.raises(ValueError, match="Not a number: y"):
601
+ paragraph.add_citation(
602
+ AssetReference(id="asset_chart"),
603
+ anchor=PixelRangeAnchor(x=355, y="top", width=100, height=565), # type: ignore[arg-type]
604
+ )
605
+ assert session.commands == []
606
+
607
+
608
+ def test_add_citation_rejects_a_typed_image_source_without_a_region_anchor() -> None:
609
+ from docx._references import AssetMeta, AssetReference, PageAnchor
610
+ from docx.text.paragraph import Paragraph
611
+
612
+ session = _FakeSession()
613
+ paragraph = Paragraph(session=session, node_id="para_1")
614
+ image = AssetReference(id="asset_chart", meta=AssetMeta(asset_type="image"))
615
+
616
+ with pytest.raises(ValueError, match="cannot use anchor=page"):
617
+ paragraph.add_citation(image, anchor=PageAnchor(page=1))
618
+ with pytest.raises(ValueError, match="cannot use an excerpt"):
619
+ paragraph.add_citation(image, excerpt="57.8")
620
+ assert session.commands == []