athena-python-docx 0.16.1__tar.gz → 0.17.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 (361) hide show
  1. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/CLAUDE.md +15 -0
  2. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/PKG-INFO +1 -1
  3. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/__init__.py +1 -1
  4. athena_python_docx-0.17.0/docx/_image_utils.py +214 -0
  5. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/document.py +7 -14
  6. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/text/run.py +8 -16
  7. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/pyproject.toml +1 -1
  8. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/70_add_and_iterate_back.json +1 -5
  9. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/ex18_read_back_large_doc.json +1 -101
  10. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/ex19_mutate_all_runs.json +0 -5
  11. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/rw09_bulk_run_iteration.json +0 -10
  12. athena_python_docx-0.17.0/tests/test_image_url_data_uri.py +283 -0
  13. athena_python_docx-0.16.1/docx/_image_utils.py +0 -90
  14. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/.gitignore +0 -0
  15. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/DOCX_EXEC_LAB.md +0 -0
  16. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/README.md +0 -0
  17. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/_athena_extension.py +0 -0
  18. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/_batching.py +0 -0
  19. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/_buffer.py +0 -0
  20. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/_execution.py +0 -0
  21. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/_http.py +0 -0
  22. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/_http_doc.py +0 -0
  23. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/_postproc.py +0 -0
  24. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/_ptc.py +0 -0
  25. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/_table_styles.py +0 -0
  26. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/_timeouts.py +0 -0
  27. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/api.py +0 -0
  28. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/bookmarks.py +0 -0
  29. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/charts.py +0 -0
  30. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/client.py +0 -0
  31. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/commands.py +0 -0
  32. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/comments.py +0 -0
  33. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/enum/__init__.py +0 -0
  34. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/enum/section.py +0 -0
  35. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/enum/style.py +0 -0
  36. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/enum/table.py +0 -0
  37. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/enum/text.py +0 -0
  38. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/errors.py +0 -0
  39. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/exceptions.py +0 -0
  40. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/fields.py +0 -0
  41. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/footnotes.py +0 -0
  42. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/math.py +0 -0
  43. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/opc/__init__.py +0 -0
  44. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/opc/coreprops.py +0 -0
  45. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/oxml/__init__.py +0 -0
  46. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/revisions.py +0 -0
  47. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/sdt.py +0 -0
  48. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/section.py +0 -0
  49. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/session.py +0 -0
  50. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/settings.py +0 -0
  51. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/shape.py +0 -0
  52. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/shared.py +0 -0
  53. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/styles/__init__.py +0 -0
  54. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/styles/style.py +0 -0
  55. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/styles/styles.py +0 -0
  56. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/table.py +0 -0
  57. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/text/__init__.py +0 -0
  58. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/text/font.py +0 -0
  59. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/text/hyperlink.py +0 -0
  60. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/text/pagebreak.py +0 -0
  61. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/text/paragraph.py +0 -0
  62. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/text/parfmt.py +0 -0
  63. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/text/tabstops.py +0 -0
  64. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/toc.py +0 -0
  65. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/docx/typing.py +0 -0
  66. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/scripts/docx_exec_lab.py +0 -0
  67. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/scripts/docx_exec_lab_examples/fast_table_fill.py +0 -0
  68. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/scripts/docx_exec_lab_examples/find_replace_literal.py +0 -0
  69. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/scripts/docx_exec_lab_server.py +0 -0
  70. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/scripts/publish.sh +0 -0
  71. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/scripts/release.sh +0 -0
  72. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/scripts/round_trip_smoke.py +0 -0
  73. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/scripts/smoke_test_block_not_found.py +0 -0
  74. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/scripts/validate_find_replace_asset.py +0 -0
  75. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/__init__.py +0 -0
  76. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/conftest.py +0 -0
  77. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/METHODOLOGY.md +0 -0
  78. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/README.md +0 -0
  79. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/__init__.py +0 -0
  80. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/ab_probe_cases.py +0 -0
  81. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/ab_probe_runner.py +0 -0
  82. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/auto_gen_cases.py +0 -0
  83. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/binary_round_trip.py +0 -0
  84. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/cases.py +0 -0
  85. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/complex_cases.py +0 -0
  86. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/coverage_report.py +0 -0
  87. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/extract.py +0 -0
  88. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/extreme_cases.py +0 -0
  89. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/fake_session.py +0 -0
  90. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/firm_templates/README.md +0 -0
  91. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/firm_templates/__init__.py +0 -0
  92. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/firm_templates/_runner.py +0 -0
  93. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/firm_templates/extractor.py +0 -0
  94. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/firm_templates/test_pw_corpus.py +0 -0
  95. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/firm_templates/test_pw_research_digest.py +0 -0
  96. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/local_runner.py +0 -0
  97. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/mega_cases.py +0 -0
  98. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshot.py +0 -0
  99. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/01_basic_paragraph.json +0 -0
  100. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/02_multiple_headings.json +0 -0
  101. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/03_runs_with_formatting.json +0 -0
  102. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/04_font_name_and_size.json +0 -0
  103. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/05_font_color_rgb.json +0 -0
  104. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/06_font_character_properties.json +0 -0
  105. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/07_font_subscript_superscript.json +0 -0
  106. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/08_font_highlight.json +0 -0
  107. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/09_paragraph_alignment.json +0 -0
  108. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/100_table_negative_indexing.json +0 -0
  109. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/101_table_cells_flat_iteration.json +0 -0
  110. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/102_text_with_embedded_special_chars.json +0 -0
  111. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/104_core_properties_datetime.json +0 -0
  112. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/105_default_one_section.json +0 -0
  113. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/106_heading_paragraph_format.json +0 -0
  114. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/107_varying_row_heights.json +0 -0
  115. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/10_paragraph_indents.json +0 -0
  116. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/11_paragraph_spacing.json +0 -0
  117. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/12_paragraph_keep_options.json +0 -0
  118. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/13_paragraph_tab_stops.json +0 -0
  119. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/14_run_add_tab_and_break.json +0 -0
  120. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/15_run_add_break_page.json +0 -0
  121. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/16_paragraph_clear_and_insert_before.json +0 -0
  122. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/17_table_basic.json +0 -0
  123. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/18_table_cell_text.json +0 -0
  124. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/19_table_row_column_sizing.json +0 -0
  125. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/20_table_cell_vertical_alignment.json +0 -0
  126. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/21_table_alignment_and_autofit.json +0 -0
  127. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/22_table_cell_paragraphs_iteration.json +0 -0
  128. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/24_table_add_row_column.json +0 -0
  129. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/25_table_merge_cells.json +0 -0
  130. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/26_section_page_setup.json +0 -0
  131. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/27_section_margins.json +0 -0
  132. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/28_section_add_new.json +0 -0
  133. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/29_section_headers_linked.json +0 -0
  134. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/30_styles_iteration.json +0 -0
  135. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/31_styles_lookup_and_default.json +0 -0
  136. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/32_styles_add_paragraph_style.json +0 -0
  137. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/33_core_properties_set_and_get.json +0 -0
  138. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/34_inline_shapes_iterate_empty.json +0 -0
  139. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/35_full_report.json +0 -0
  140. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/36_replace_text_in_paragraph.json +0 -0
  141. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/37_iterate_runs_and_format_all_bold.json +0 -0
  142. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/38_font_all_properties.json +0 -0
  143. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/39_large_body_100_paragraphs.json +0 -0
  144. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/40_large_table_10x10.json +0 -0
  145. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/41_unicode_and_emoji.json +0 -0
  146. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/42_very_long_paragraph.json +0 -0
  147. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/43_paragraph_text_round_trip.json +0 -0
  148. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/44_paragraph_alignment_round_trip.json +0 -0
  149. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/45_cell_text_round_trip.json +0 -0
  150. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/46_run_text_setter_round_trip.json +0 -0
  151. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/47_font_size_round_trip.json +0 -0
  152. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/48_font_color_round_trip.json +0 -0
  153. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/49_resume_layout.json +0 -0
  154. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/50_multi_section_doc.json +0 -0
  155. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/52_iterate_everything.json +0 -0
  156. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/53_apply_style_to_paragraphs.json +0 -0
  157. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/54_empty_everything.json +0 -0
  158. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/55_single_character_runs.json +0 -0
  159. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/56_everything_in_one.json +0 -0
  160. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/57_runs_after_multiple_text_appends.json +0 -0
  161. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/58_modify_runs_in_place.json +0 -0
  162. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/59_indent_round_trip.json +0 -0
  163. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/60_space_round_trip.json +0 -0
  164. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/61_cell_paragraph_with_runs.json +0 -0
  165. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/62_many_cell_paragraphs.json +0 -0
  166. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/63_table_style_round_trip.json +0 -0
  167. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/64_many_sections.json +0 -0
  168. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/65_20x20_table_formatted.json +0 -0
  169. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/66_toc_like_structure.json +0 -0
  170. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/67_paragraph_insert_before_chain.json +0 -0
  171. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/68_invoice.json +0 -0
  172. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/69_newsletter.json +0 -0
  173. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/71_academic_paper.json +0 -0
  174. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/72_legal_contract.json +0 -0
  175. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/73_form_with_many_tables.json +0 -0
  176. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/74_paragraph_with_10_runs.json +0 -0
  177. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/75_paragraph_negative_first_line_indent.json +0 -0
  178. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/76_rgbcolor_from_string.json +0 -0
  179. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/77_length_unit_conversions.json +0 -0
  180. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/78_paragraph_copy_style.json +0 -0
  181. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/79_bulk_cell_formatting.json +0 -0
  182. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/80_apply_style_after_add_run.json +0 -0
  183. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/81_multi_page_with_breaks.json +0 -0
  184. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/82_add_text_on_existing_run.json +0 -0
  185. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/83_clear_then_repopulate_paragraph.json +0 -0
  186. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/84_table_reread_row_count.json +0 -0
  187. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/85_header_footer_access.json +0 -0
  188. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/86_font_read_unset_returns_none.json +0 -0
  189. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/87_500_paragraph_doc.json +0 -0
  190. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/88_mixed_content_iteration.json +0 -0
  191. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/89_alignment_clear_via_none.json +0 -0
  192. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/90_cell_add_paragraph_styled.json +0 -0
  193. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/91_many_small_tables.json +0 -0
  194. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/92_margins_every_section.json +0 -0
  195. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/93_font_bool_reads_after_set.json +0 -0
  196. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/94_page_break_before_paragraph.json +0 -0
  197. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/95_paragraph_hyperlinks_empty.json +0 -0
  198. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/96_paragraph_contains_page_break.json +0 -0
  199. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/97_document_styles_by_key.json +0 -0
  200. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/98_style_contains_check.json +0 -0
  201. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/99_run_add_picture_from_bytes.json +0 -0
  202. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/ex02_unicode_everywhere.json +0 -0
  203. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/ex03_1000_paragraphs.json +0 -0
  204. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/ex04_50x50_table.json +0 -0
  205. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/ex05_long_text_in_cell.json +0 -0
  206. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/ex06_hundred_tiny_runs.json +0 -0
  207. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/ex07_every_font_boolean.json +0 -0
  208. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/ex08_many_continuous_sections.json +0 -0
  209. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/ex09_many_tab_stops.json +0 -0
  210. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/ex10_complex_bom.json +0 -0
  211. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/ex11_banded_rows_formatting.json +0 -0
  212. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/ex12_section_reconfigure.json +0 -0
  213. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/ex13_cell_with_10_paragraphs.json +0 -0
  214. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/ex14_styled_report_table.json +0 -0
  215. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/ex15_paragraph_all_format_props.json +0 -0
  216. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/ex16_runs_interleaved_with_breaks.json +0 -0
  217. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/ex17_all_break_kinds.json +0 -0
  218. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/ex20_kitchen_sink_v2.json +0 -0
  219. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/mega01_book_chapter.json +0 -0
  220. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/mega02_research_proposal.json +0 -0
  221. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/mega03_financial_statement.json +0 -0
  222. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/mega04_recipe_card.json +0 -0
  223. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/mega05_user_manual.json +0 -0
  224. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/mega06_complex_newsletter.json +0 -0
  225. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/mega07_budget_spreadsheet.json +0 -0
  226. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/mega08_product_catalog.json +0 -0
  227. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/mega09_signed_contract.json +0 -0
  228. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/mega10_api_documentation.json +0 -0
  229. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/rw01_official_quickstart.json +0 -0
  230. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/rw02_paragraph_style_list.json +0 -0
  231. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/rw03_character_formatting.json +0 -0
  232. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/rw04_section_page_setup.json +0 -0
  233. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/rw05_toc_pattern.json +0 -0
  234. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/rw06_meeting_minutes.json +0 -0
  235. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/rw07_dense_formatting_demo.json +0 -0
  236. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/rw08_table_merged_header.json +0 -0
  237. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/rw10_colored_grid_table.json +0 -0
  238. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/rw11_header_text.json +0 -0
  239. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/rw12_first_page_footer.json +0 -0
  240. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/rw13_even_page_header.json +0 -0
  241. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/op_snapshots/rw15_paragraph_style_instance.json +0 -0
  242. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/ours_spec.json +0 -0
  243. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/parity_crawl.py +0 -0
  244. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/parity_diff.json +0 -0
  245. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/real_world_cases.py +0 -0
  246. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/round_trip_tests.py +0 -0
  247. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/runner.py +0 -0
  248. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/stock_spec.json +0 -0
  249. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/fidelity/test_e2e_against_staging.py +0 -0
  250. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/parity/README.md +0 -0
  251. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/parity/__init__.py +0 -0
  252. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/parity/baseline_gaps.json +0 -0
  253. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/parity/compare.py +0 -0
  254. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/parity/intentional_deviations.json +0 -0
  255. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/parity/introspect.py +0 -0
  256. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/parity/reports/GAP_ANALYSIS.md +0 -0
  257. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/parity/reports/gap_report.json +0 -0
  258. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/parity/run_parity.py +0 -0
  259. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/parity/snapshots/athena_latest.json +0 -0
  260. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/parity/snapshots/upstream_python_docx_1.2.0.json +0 -0
  261. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/parity/test_parity_gap.py +0 -0
  262. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_add_section_extract_items.py +0 -0
  263. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_athena_extensions_contract.py +0 -0
  264. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_athena_extensions_registry.py +0 -0
  265. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_batching_perf.py +0 -0
  266. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_block_not_found_error.py +0 -0
  267. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_buffer.py +0 -0
  268. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_cell_add_paragraph_wire_shape.py +0 -0
  269. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_cell_add_table_not_supported.py +0 -0
  270. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_cell_inner_add_hyperlink_stash.py +0 -0
  271. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_cell_inner_add_run_via_cell_insert.py +0 -0
  272. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_cell_inner_format_stash.py +0 -0
  273. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_cell_inner_run_format_stash.py +0 -0
  274. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_cell_inner_run_guard.py +0 -0
  275. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_cell_text_plain_fastpath.py +0 -0
  276. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_cell_text_replace_semantics.py +0 -0
  277. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_collapsed_range_format.py +0 -0
  278. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_command_dataclasses.py +0 -0
  279. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_commands.py +0 -0
  280. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_comments.py +0 -0
  281. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_document_asset_id_property.py +0 -0
  282. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_document_clear.py +0 -0
  283. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_document_create.py +0 -0
  284. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_document_create_from_template.py +0 -0
  285. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_document_factory_validation.py +0 -0
  286. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_docx_exec_lab.py +0 -0
  287. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_docx_exec_lab_server.py +0 -0
  288. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_e2e_partial_failure_cascade.py +0 -0
  289. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_execution_scope.py +0 -0
  290. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_find_replace_session_open.py +0 -0
  291. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_http_transport.py +0 -0
  292. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_hyperlink_coalescing.py +0 -0
  293. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_insert_deferred.py +0 -0
  294. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_iter_inner_content.py +0 -0
  295. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_list_styles.py +0 -0
  296. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_merged_cell_secondary_slot.py +0 -0
  297. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_merged_cells.py +0 -0
  298. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_oxml_shim.py +0 -0
  299. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_paragraph_text_len_cache.py +0 -0
  300. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_parity_misc.py +0 -0
  301. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_parity_round2.py +0 -0
  302. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_partial_failure_cascade.py +0 -0
  303. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_phase_a_behavior.py +0 -0
  304. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_phase_b_headers_footers.py +0 -0
  305. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_phase_c_tables.py +0 -0
  306. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_postproc_cell_format_rewrite.py +0 -0
  307. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_postproc_cell_run_format_rewrite.py +0 -0
  308. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_postproc_ref_restore.py +0 -0
  309. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_pr19766_review_fixes.py +0 -0
  310. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_ptc.py +0 -0
  311. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_python_docx_api_parity.py +0 -0
  312. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_revisions.py +0 -0
  313. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_add_paragraph_style.py +0 -0
  314. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_add_picture.py +0 -0
  315. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_add_run.py +0 -0
  316. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_cell_add_paragraph.py +0 -0
  317. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_comments_add_comment.py +0 -0
  318. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_comments_get.py +0 -0
  319. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_document_audit.py +0 -0
  320. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_document_element.py +0 -0
  321. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_enum_section.py +0 -0
  322. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_font_audit.py +0 -0
  323. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_header_footer.py +0 -0
  324. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_hyperlink.py +0 -0
  325. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_inline_shape.py +0 -0
  326. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_insert_paragraph_before.py +0 -0
  327. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_misc.py +0 -0
  328. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_paragraph_strict.py +0 -0
  329. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_paragraph_style.py +0 -0
  330. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_paragraph_style_strict.py +0 -0
  331. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_parfmt.py +0 -0
  332. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_row_col_cell.py +0 -0
  333. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_run_add_break.py +0 -0
  334. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_run_bool_setters.py +0 -0
  335. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_run_style.py +0 -0
  336. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_run_style_strict.py +0 -0
  337. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_run_text.py +0 -0
  338. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_run_underline.py +0 -0
  339. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_section_audit.py +0 -0
  340. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_section_dimensions.py +0 -0
  341. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_section_onoff.py +0 -0
  342. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_settings.py +0 -0
  343. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_shared_audit.py +0 -0
  344. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_style.py +0 -0
  345. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_styles.py +0 -0
  346. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_table_audit.py +0 -0
  347. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_table_cell.py +0 -0
  348. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_table_dimensions.py +0 -0
  349. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_silent_stub_table_layout.py +0 -0
  350. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_smoke_integration.py +0 -0
  351. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_style_acceptance.py +0 -0
  352. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_style_font.py +0 -0
  353. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_style_setters_contract.py +0 -0
  354. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_table_set_cell_perf.py +0 -0
  355. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_table_style_id_resolution.py +0 -0
  356. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_temporarily_unavailable.py +0 -0
  357. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_validate_find_replace_asset_script.py +0 -0
  358. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_wire_contract.py +0 -0
  359. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_xml_attr_guard.py +0 -0
  360. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/tests/test_zod_wire_contract.py +0 -0
  361. {athena_python_docx-0.16.1 → athena_python_docx-0.17.0}/uv.lock +0 -0
@@ -93,6 +93,21 @@ remaining work* for the exact wire-op shape needed to unblock each.
93
93
  These differ from stock python-docx because the SDK is asset-backed,
94
94
  not file-backed. Each is documented in the relevant docstring.
95
95
 
96
+ - **`add_picture` accepts an image URL or `data:` URI, not just a path
97
+ or stream.** Stock python-docx routes ``image_path_or_stream`` through
98
+ ``docx.image.image.Image.from_file``, which opens a ``str`` as a local
99
+ filesystem path and has no networking — so ``add_picture("https://…")``
100
+ raises ``FileNotFoundError``. Agents (and humans) routinely pass a
101
+ remote image URL, so ``Document.add_picture`` / ``Run.add_picture``
102
+ additionally fetch ``http(s)://`` URLs (via the already-required
103
+ ``requests`` dependency, 30s timeout) and decode ``data:[…;base64],…``
104
+ URIs. Local paths and file-like streams behave exactly as upstream.
105
+ The dispatch lives in ``docx._image_utils.load_image_bytes``; a failed
106
+ fetch/decode raises a ``ValueError`` at the call site rather than a
107
+ bare transport error. This is the only image-input deviation — the
108
+ resulting bytes still flow through the same magic-byte
109
+ ``sniff_content_type`` → base64 ``data:`` URI → ``create.image`` path.
110
+
96
111
  - **Built-in table style friendly names resolve to OOXML styleIds.**
97
112
  Word's ``styles.xml`` ships built-in table styles whose styleIds
98
113
  (``LightGrid-Accent1``, ``MediumShading1-Accent2``, …) differ from
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: athena-python-docx
3
- Version: 0.16.1
3
+ Version: 0.17.0
4
4
  Summary: Drop-in replacement for python-docx that connects to Athena's Superdoc/Keryx collaborative document stack
5
5
  Project-URL: Homepage, https://athenaintelligence.ai
6
6
  Author-email: Athena Intelligence <engineering@athenaintelligence.ai>
@@ -6,7 +6,7 @@ See CLAUDE.md for the API parity contract.
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
- __version__ = "0.16.1"
9
+ __version__ = "0.17.0"
10
10
 
11
11
  from docx.api import Document
12
12
  from docx._buffer import flush_all
@@ -0,0 +1,214 @@
1
+ """Image format / content-type helpers shared by ``Run.add_picture``
2
+ and ``Document.add_picture``.
3
+
4
+ The previous implementations sniffed only by file extension, which
5
+ silently mistyped streams (default ``image/png``) and was wrong on
6
+ files with mismatched extensions (e.g. ``screenshot.png`` containing
7
+ JPEG bytes — common from OS screen-capture flows).
8
+
9
+ We sniff by **magic bytes** for the four formats SuperDoc accepts as
10
+ inline image data URIs (PNG, JPEG, GIF, WebP), with extension as a
11
+ secondary fallback for unknown / off-format streams.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import base64
17
+ from typing import BinaryIO
18
+
19
+ # Magic-byte signatures for the formats SuperDoc accepts inline.
20
+ # (mime, signature_bytes, signature_offset). Most are at offset 0;
21
+ # WebP needs a two-part check (RIFF header + WEBP marker at offset 8).
22
+ _PNG_MAGIC: bytes = b"\x89PNG\r\n\x1a\n"
23
+ _JPEG_MAGIC: bytes = b"\xff\xd8\xff"
24
+ _GIF87_MAGIC: bytes = b"GIF87a"
25
+ _GIF89_MAGIC: bytes = b"GIF89a"
26
+ _WEBP_RIFF: bytes = b"RIFF"
27
+ _WEBP_MARKER: bytes = b"WEBP"
28
+ _BMP_MAGIC: bytes = b"BM"
29
+ _TIFF_LE_MAGIC: bytes = b"II*\x00"
30
+ _TIFF_BE_MAGIC: bytes = b"MM\x00*"
31
+ _SVG_HINT_DECL: bytes = b"<?xml"
32
+ _SVG_HINT_TAG: bytes = b"<svg"
33
+
34
+
35
+ def sniff_content_type(image_bytes: bytes, *, fallback_path: str = "") -> str:
36
+ """Return a SuperDoc-acceptable image MIME for ``image_bytes``.
37
+
38
+ Magic-byte detection in priority order; if no signature matches,
39
+ fall back to the file extension on ``fallback_path``; if that
40
+ also fails, default to ``"image/png"`` (matches the prior
41
+ silent-default behavior so callers that previously got away with
42
+ it keep working).
43
+
44
+ Athena extension beyond python-docx 1.x: also detects SVG, BMP,
45
+ and TIFF. python-docx upstream supports PNG/JPEG/GIF/BMP/TIFF; SVG
46
+ and WEBP are missing from upstream (issues #651, #717, #1399).
47
+ """
48
+ if image_bytes.startswith(_PNG_MAGIC):
49
+ return "image/png"
50
+ if image_bytes.startswith(_JPEG_MAGIC):
51
+ return "image/jpeg"
52
+ if image_bytes.startswith(_GIF87_MAGIC) or image_bytes.startswith(_GIF89_MAGIC):
53
+ return "image/gif"
54
+ if (
55
+ len(image_bytes) >= 12
56
+ and image_bytes.startswith(_WEBP_RIFF)
57
+ and image_bytes[8:12] == _WEBP_MARKER
58
+ ):
59
+ return "image/webp"
60
+ if image_bytes.startswith(_BMP_MAGIC):
61
+ return "image/bmp"
62
+ if image_bytes.startswith(_TIFF_LE_MAGIC) or image_bytes.startswith(_TIFF_BE_MAGIC):
63
+ return "image/tiff"
64
+ # SVG: probe first ~1KB for either an XML declaration or a literal
65
+ # ``<svg`` tag. Case-insensitive on the tag because legitimate SVG
66
+ # files sometimes carry ``<SVG`` after author tools.
67
+ head = image_bytes[:1024]
68
+ if _SVG_HINT_TAG in head or _SVG_HINT_TAG in head.lower():
69
+ return "image/svg+xml"
70
+ if head.startswith(_SVG_HINT_DECL) and b"<svg" in head.lower():
71
+ return "image/svg+xml"
72
+
73
+ if fallback_path:
74
+ lower = fallback_path.lower()
75
+ if lower.endswith((".jpg", ".jpeg")):
76
+ return "image/jpeg"
77
+ if lower.endswith(".gif"):
78
+ return "image/gif"
79
+ if lower.endswith(".webp"):
80
+ return "image/webp"
81
+ if lower.endswith(".png"):
82
+ return "image/png"
83
+ if lower.endswith(".svg"):
84
+ return "image/svg+xml"
85
+ if lower.endswith(".bmp"):
86
+ return "image/bmp"
87
+ if lower.endswith((".tif", ".tiff")):
88
+ return "image/tiff"
89
+
90
+ return "image/png"
91
+
92
+
93
+ # Generous default so large remote images over a slow link still land, while a
94
+ # dead host fails the call instead of hanging the agent's code-exec forever.
95
+ _URL_FETCH_TIMEOUT_SECONDS: float = 30.0
96
+ # Hard cap so a giant (or accidentally non-image) URL can't balloon memory in
97
+ # the document-exec sandbox — the bytes get base64-encoded into the doc next.
98
+ _MAX_REMOTE_IMAGE_BYTES: int = 10 * 1024 * 1024 # 10 MiB
99
+
100
+
101
+ def load_image_bytes(image_path_or_stream: "str | BinaryIO") -> tuple[bytes, str]:
102
+ """Read raw image bytes from a local path, ``http(s)://`` URL, ``data:``
103
+ URI, or binary stream.
104
+
105
+ Returns ``(image_bytes, fallback_path)`` where ``fallback_path`` feeds the
106
+ extension-based MIME fallback in :func:`sniff_content_type` (empty when the
107
+ source carries no usable filename).
108
+
109
+ Athena extension beyond python-docx: upstream ``add_picture`` only accepts a
110
+ local path or file-like object — a ``str`` is always opened as a filesystem
111
+ path. Agents routinely pass an image URL or a ``data:`` URI, so the Athena
112
+ SDK additionally fetches ``http(s)://`` URLs (via ``requests``) and decodes
113
+ ``data:`` URIs here. Local paths and streams behave exactly as in
114
+ python-docx.
115
+
116
+ URL fetching runs inside the document-exec sandbox, which already executes
117
+ arbitrary agent-authored code (hence arbitrary outbound requests), so this
118
+ grants no network capability the caller lacks — it is not an SSRF allowlist
119
+ boundary. It does cap the download at ``_MAX_REMOTE_IMAGE_BYTES`` so an
120
+ oversized response can't exhaust sandbox memory.
121
+ """
122
+ if isinstance(image_path_or_stream, str):
123
+ descriptor = image_path_or_stream
124
+ # URI schemes are case-insensitive (RFC 3986): dispatch on a lowercased
125
+ # scheme, but fetch/open the original value unchanged.
126
+ scheme = descriptor.split(":", 1)[0].lower() if ":" in descriptor else ""
127
+ if scheme in ("http", "https"):
128
+ from urllib.parse import urlsplit
129
+
130
+ # Sniff fallback off the URL *path* only — a signed URL's query
131
+ # string (``?token=…``) would otherwise defeat the extension check.
132
+ return _fetch_image_url(descriptor), urlsplit(descriptor).path
133
+ if scheme == "data":
134
+ return _decode_image_data_uri(descriptor), ""
135
+ with open(descriptor, "rb") as f:
136
+ return f.read(), descriptor
137
+ # Duck-type the stream: python-docx accepts anything with ``.read()`` (it
138
+ # never isinstance-checks), so a BinaryIO that doesn't subclass io.IOBase
139
+ # must work too.
140
+ reader = getattr(image_path_or_stream, "read", None)
141
+ if callable(reader):
142
+ data = reader()
143
+ if not isinstance(data, (bytes, bytearray)):
144
+ raise TypeError(
145
+ f"Image stream .read() returned {type(data).__name__}, expected bytes",
146
+ )
147
+ return bytes(data), ""
148
+ raise TypeError(
149
+ "Expected a path str, http(s) URL, data: URI, or binary stream, got "
150
+ f"{type(image_path_or_stream).__name__}",
151
+ )
152
+
153
+
154
+ def _fetch_image_url(url: str) -> bytes:
155
+ """Download image bytes from an ``http(s)://`` URL, capped at
156
+ ``_MAX_REMOTE_IMAGE_BYTES`` (Athena extension — see
157
+ :func:`load_image_bytes`)."""
158
+ # Lazy import: ``requests`` is already a hard SDK dependency (HTTP transport),
159
+ # but keep this format helper importable without paying for it up front.
160
+ import requests
161
+ from urllib.parse import urlsplit, urlunsplit
162
+
163
+ def _redact(raw: str) -> str:
164
+ # Drop query + fragment so signed-URL tokens don't leak into errors/logs.
165
+ parts = urlsplit(raw)
166
+ return urlunsplit((parts.scheme, parts.netloc, parts.path, "", ""))
167
+
168
+ try:
169
+ with requests.get(url, timeout=_URL_FETCH_TIMEOUT_SECONDS, stream=True) as resp:
170
+ resp.raise_for_status()
171
+ declared = resp.headers.get("content-length")
172
+ if declared is not None and declared.isdigit() and int(declared) > _MAX_REMOTE_IMAGE_BYTES:
173
+ raise ValueError(
174
+ f"add_picture image at {_redact(url)!r} declares {declared} bytes, "
175
+ f"over the {_MAX_REMOTE_IMAGE_BYTES}-byte cap"
176
+ )
177
+ chunks: list[bytes] = []
178
+ total = 0
179
+ for chunk in resp.iter_content(chunk_size=65536):
180
+ if not chunk:
181
+ continue
182
+ total += len(chunk)
183
+ if total > _MAX_REMOTE_IMAGE_BYTES:
184
+ raise ValueError(
185
+ f"add_picture image at {_redact(url)!r} exceeds the "
186
+ f"{_MAX_REMOTE_IMAGE_BYTES}-byte cap"
187
+ )
188
+ chunks.append(chunk)
189
+ return b"".join(chunks)
190
+ except requests.RequestException as exc:
191
+ raise ValueError(f"add_picture could not fetch image URL {_redact(url)!r}: {exc}") from exc
192
+
193
+
194
+ def _decode_image_data_uri(uri: str) -> bytes:
195
+ """Decode a ``data:[<mediatype>][;base64],<payload>`` URI to raw bytes
196
+ (Athena extension — see :func:`load_image_bytes`)."""
197
+ header, sep, payload = uri.partition(",")
198
+ if not sep or not payload:
199
+ raise ValueError("add_picture received a data: URI with no payload")
200
+ # ``;base64`` is a discrete, case-insensitive token (RFC 2397) — match it as
201
+ # a token, not a substring (so ``;notbase64x`` doesn't false-match), and use
202
+ # strict decoding so malformed base64 fails loudly instead of silently.
203
+ is_base64 = any(token.strip().lower() == "base64" for token in header.split(";")[1:])
204
+ try:
205
+ if is_base64:
206
+ return base64.b64decode(payload, validate=True)
207
+ from urllib.parse import unquote_to_bytes
208
+
209
+ return unquote_to_bytes(payload)
210
+ except Exception as exc:
211
+ raise ValueError(f"add_picture could not decode data: URI: {exc}") from exc
212
+
213
+
214
+ __all__ = ["load_image_bytes", "sniff_content_type"]
@@ -15,7 +15,6 @@ Phase 1 supported methods:
15
15
  from __future__ import annotations
16
16
 
17
17
  import base64
18
- import io
19
18
  import sys
20
19
  from contextlib import contextmanager
21
20
  from typing import TYPE_CHECKING, BinaryIO, Generator, Iterator
@@ -1874,26 +1873,20 @@ class Document:
1874
1873
 
1875
1874
  Mirrors python-docx ``Document.add_picture`` — returns the new
1876
1875
  :class:`InlineShape` proxy.
1876
+
1877
+ ``image_path_or_stream`` accepts a local file path, a binary stream
1878
+ (e.g. ``io.BytesIO``), an ``http(s)://`` image URL (fetched
1879
+ server-side), or a ``data:`` URI. The URL and ``data:`` forms are
1880
+ Athena extensions beyond python-docx, which is path/stream-only.
1877
1881
  """
1878
- from docx._image_utils import sniff_content_type
1882
+ from docx._image_utils import load_image_bytes, sniff_content_type
1879
1883
  from docx.shape import InlineShape
1880
1884
  from docx.text.run import _build_inline_shape_info
1881
1885
 
1882
1886
  self._ensure_open()
1883
1887
  self._reset_list_chain()
1884
1888
 
1885
- image_bytes: bytes
1886
- fallback_path: str = ""
1887
- if isinstance(image_path_or_stream, str):
1888
- with open(image_path_or_stream, "rb") as f:
1889
- image_bytes = f.read()
1890
- fallback_path = image_path_or_stream
1891
- elif isinstance(image_path_or_stream, io.IOBase):
1892
- image_bytes = image_path_or_stream.read()
1893
- else:
1894
- raise TypeError(
1895
- f"Expected path str or binary stream, got {type(image_path_or_stream).__name__}",
1896
- )
1889
+ image_bytes, fallback_path = load_image_bytes(image_path_or_stream)
1897
1890
  # An empty payload (closed file, empty BytesIO, truncated stream
1898
1891
  # that's already been read to EOF) would silently produce a
1899
1892
  # ``data:image/png;base64,`` URI — SuperDoc accepts that and
@@ -594,26 +594,18 @@ class Run:
594
594
 
595
595
  Returns an :class:`InlineShape` proxy for the newly-inserted
596
596
  image, matching python-docx ``Run.add_picture``.
597
+
598
+ ``image_path_or_stream`` accepts a local file path, a binary stream
599
+ (e.g. ``io.BytesIO``), an ``http(s)://`` image URL (fetched
600
+ server-side), or a ``data:`` URI. The URL and ``data:`` forms are
601
+ Athena extensions beyond python-docx, which is path/stream-only.
597
602
  """
598
- from docx._image_utils import sniff_content_type
603
+ from docx._image_utils import load_image_bytes, sniff_content_type
599
604
  from docx.document import _emu_to_px
600
605
  from docx.shape import InlineShape
601
606
  import base64
602
- import io
603
-
604
- image_bytes: bytes
605
- fallback_path: str = ""
606
- if isinstance(image_path_or_stream, str):
607
- with open(image_path_or_stream, "rb") as f:
608
- image_bytes = f.read()
609
- fallback_path = image_path_or_stream
610
- elif isinstance(image_path_or_stream, io.IOBase):
611
- image_bytes = image_path_or_stream.read()
612
- else:
613
- raise TypeError(
614
- "Expected path str or binary stream, "
615
- f"got {type(image_path_or_stream).__name__}",
616
- )
607
+
608
+ image_bytes, fallback_path = load_image_bytes(image_path_or_stream)
617
609
  # Empty payload would silently round-trip as
618
610
  # ``data:image/png;base64,`` (broken placeholder image). Fail
619
611
  # at the call site instead of at render time. Matches the
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "athena-python-docx"
7
- version = "0.16.1"
7
+ version = "0.17.0"
8
8
  description = "Drop-in replacement for python-docx that connects to Athena's Superdoc/Keryx collaborative document stack"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -3,9 +3,5 @@
3
3
  "create.paragraph",
4
4
  "create.paragraph",
5
5
  "create.paragraph",
6
- "blocks.list",
7
- "getNodeById",
8
- "getNodeById",
9
- "getNodeById",
10
- "getNodeById"
6
+ "blocks.list"
11
7
  ]
@@ -99,105 +99,5 @@
99
99
  "create.paragraph",
100
100
  "create.heading",
101
101
  "create.paragraph",
102
- "blocks.list",
103
- "getNodeById",
104
- "getNodeById",
105
- "getNodeById",
106
- "getNodeById",
107
- "getNodeById",
108
- "getNodeById",
109
- "getNodeById",
110
- "getNodeById",
111
- "getNodeById",
112
- "getNodeById",
113
- "getNodeById",
114
- "getNodeById",
115
- "getNodeById",
116
- "getNodeById",
117
- "getNodeById",
118
- "getNodeById",
119
- "getNodeById",
120
- "getNodeById",
121
- "getNodeById",
122
- "getNodeById",
123
- "getNodeById",
124
- "getNodeById",
125
- "getNodeById",
126
- "getNodeById",
127
- "getNodeById",
128
- "getNodeById",
129
- "getNodeById",
130
- "getNodeById",
131
- "getNodeById",
132
- "getNodeById",
133
- "getNodeById",
134
- "getNodeById",
135
- "getNodeById",
136
- "getNodeById",
137
- "getNodeById",
138
- "getNodeById",
139
- "getNodeById",
140
- "getNodeById",
141
- "getNodeById",
142
- "getNodeById",
143
- "getNodeById",
144
- "getNodeById",
145
- "getNodeById",
146
- "getNodeById",
147
- "getNodeById",
148
- "getNodeById",
149
- "getNodeById",
150
- "getNodeById",
151
- "getNodeById",
152
- "getNodeById",
153
- "getNodeById",
154
- "getNodeById",
155
- "getNodeById",
156
- "getNodeById",
157
- "getNodeById",
158
- "getNodeById",
159
- "getNodeById",
160
- "getNodeById",
161
- "getNodeById",
162
- "getNodeById",
163
- "getNodeById",
164
- "getNodeById",
165
- "getNodeById",
166
- "getNodeById",
167
- "getNodeById",
168
- "getNodeById",
169
- "getNodeById",
170
- "getNodeById",
171
- "getNodeById",
172
- "getNodeById",
173
- "getNodeById",
174
- "getNodeById",
175
- "getNodeById",
176
- "getNodeById",
177
- "getNodeById",
178
- "getNodeById",
179
- "getNodeById",
180
- "getNodeById",
181
- "getNodeById",
182
- "getNodeById",
183
- "getNodeById",
184
- "getNodeById",
185
- "getNodeById",
186
- "getNodeById",
187
- "getNodeById",
188
- "getNodeById",
189
- "getNodeById",
190
- "getNodeById",
191
- "getNodeById",
192
- "getNodeById",
193
- "getNodeById",
194
- "getNodeById",
195
- "getNodeById",
196
- "getNodeById",
197
- "getNodeById",
198
- "getNodeById",
199
- "getNodeById",
200
- "getNodeById",
201
- "getNodeById",
202
- "getNodeById"
102
+ "blocks.list"
203
103
  ]
@@ -20,23 +20,18 @@
20
20
  "insert",
21
21
  "insert",
22
22
  "blocks.list",
23
- "getNodeById",
24
23
  "format.apply",
25
24
  "format.apply",
26
25
  "format.apply",
27
- "getNodeById",
28
26
  "format.apply",
29
27
  "format.apply",
30
28
  "format.apply",
31
- "getNodeById",
32
29
  "format.apply",
33
30
  "format.apply",
34
31
  "format.apply",
35
- "getNodeById",
36
32
  "format.apply",
37
33
  "format.apply",
38
34
  "format.apply",
39
- "getNodeById",
40
35
  "format.apply",
41
36
  "format.apply",
42
37
  "format.apply"
@@ -69,15 +69,5 @@
69
69
  "getNodeById",
70
70
  "getNodeById",
71
71
  "getNodeById",
72
- "getNodeById",
73
- "getNodeById",
74
- "getNodeById",
75
- "getNodeById",
76
- "getNodeById",
77
- "getNodeById",
78
- "getNodeById",
79
- "getNodeById",
80
- "getNodeById",
81
- "getNodeById",
82
72
  "getNodeById"
83
73
  ]