athena-python-docx 0.34.0__tar.gz → 0.36.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 (489) hide show
  1. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/AGENTS.md +36 -19
  2. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/PKG-INFO +1 -1
  3. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/__init__.py +1 -1
  4. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_buffer.py +6 -0
  5. athena_python_docx-0.36.0/docx/_proxy.py +109 -0
  6. athena_python_docx-0.36.0/docx/_xml_text.py +46 -0
  7. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/blkcntnr.py +3 -0
  8. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/commands.py +4 -0
  9. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/document.py +4 -0
  10. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/oxml/__init__.py +1 -0
  11. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/section.py +3 -0
  12. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/settings.py +15 -1
  13. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/styles/latent.py +21 -4
  14. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/styles/style.py +94 -28
  15. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/styles/styles.py +5 -1
  16. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/table.py +96 -17
  17. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/text/paragraph.py +42 -6
  18. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/text/parfmt.py +16 -4
  19. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/text/run.py +168 -48
  20. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/text/tabstops.py +26 -3
  21. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/pyproject.toml +1 -1
  22. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/METHODOLOGY.md +9 -1
  23. athena_python_docx-0.36.0/tests/fidelity/ab_probe/__init__.py +15 -0
  24. athena_python_docx-0.36.0/tests/fidelity/ab_probe/agent_documents.py +133 -0
  25. athena_python_docx-0.36.0/tests/fidelity/ab_probe/default_style_run_formatting.py +25 -0
  26. athena_python_docx-0.36.0/tests/fidelity/ab_probe/header_footer_pictures.py +28 -0
  27. athena_python_docx-0.36.0/tests/fidelity/ab_probe/less_used_writes.py +219 -0
  28. athena_python_docx-0.36.0/tests/fidelity/ab_probe/merged_cell_identity.py +31 -0
  29. athena_python_docx-0.36.0/tests/fidelity/ab_probe/paragraph_text_setter.py +57 -0
  30. athena_python_docx-0.36.0/tests/fidelity/ab_probe/picture_runs.py +101 -0
  31. athena_python_docx-0.36.0/tests/fidelity/ab_probe/proxy_equality.py +41 -0
  32. athena_python_docx-0.36.0/tests/fidelity/ab_probe/return_types.py +44 -0
  33. athena_python_docx-0.36.0/tests/fidelity/ab_probe/xml_incompatible_text.py +24 -0
  34. athena_python_docx-0.36.0/tests/fidelity/ab_probe/zero_and_negative_indents.py +26 -0
  35. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/ab_probe_cases.py +196 -0
  36. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/101_table_cells_flat_iteration.json +0 -1
  37. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/99_run_add_picture_from_bytes.json +1 -0
  38. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/live/baseline.json +8 -0
  39. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/live/fixture_scripts.py +17 -0
  40. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/live/runner.py +25 -16
  41. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/live/test_live_runner.py +24 -0
  42. athena_python_docx-0.36.0/tests/test_battery_cases.py +54 -0
  43. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_inner_run_guard.py +5 -7
  44. athena_python_docx-0.36.0/tests/test_document_settings_session_open.py +63 -0
  45. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_drawing_image.py +179 -0
  46. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_enum_parity.py +3 -1
  47. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_latent_style_writes.py +21 -0
  48. athena_python_docx-0.36.0/tests/test_merged_cell_identity.py +104 -0
  49. athena_python_docx-0.36.0/tests/test_paragraph_indent_reads.py +60 -0
  50. athena_python_docx-0.36.0/tests/test_paragraph_text_empty_run.py +44 -0
  51. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_parfmt_clears.py +24 -0
  52. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_parity_misc.py +15 -2
  53. athena_python_docx-0.36.0/tests/test_proxy_equality.py +179 -0
  54. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_run_identity.py +13 -11
  55. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_style_tab_stops.py +77 -0
  56. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_tab_stop_writes.py +21 -0
  57. athena_python_docx-0.36.0/tests/test_unmapped_alignment_reads.py +95 -0
  58. athena_python_docx-0.36.0/tests/test_xml_incompatible_text.py +103 -0
  59. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/uv.lock +1 -1
  60. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/.gitignore +0 -0
  61. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/CLAUDE.md +0 -0
  62. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/DOCX_EXEC_LAB.md +0 -0
  63. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/README.md +0 -0
  64. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_athena_extension.py +0 -0
  65. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_batching.py +0 -0
  66. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_capabilities.py +0 -0
  67. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_citations.py +0 -0
  68. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_execution.py +0 -0
  69. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_http.py +0 -0
  70. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_http_doc.py +0 -0
  71. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_image_utils.py +0 -0
  72. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_postproc.py +0 -0
  73. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_ptc.py +0 -0
  74. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_references.py +0 -0
  75. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_run_order.py +0 -0
  76. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_table_styles.py +0 -0
  77. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_timeouts.py +0 -0
  78. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_tracked.py +0 -0
  79. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/api.py +0 -0
  80. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/bookmarks.py +0 -0
  81. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/charts.py +0 -0
  82. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/client.py +0 -0
  83. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/comments.py +0 -0
  84. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/drawing/__init__.py +0 -0
  85. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/enum/__init__.py +0 -0
  86. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/enum/base.py +0 -0
  87. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/enum/dml.py +0 -0
  88. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/enum/section.py +0 -0
  89. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/enum/shape.py +0 -0
  90. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/enum/style.py +0 -0
  91. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/enum/table.py +0 -0
  92. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/enum/text.py +0 -0
  93. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/errors.py +0 -0
  94. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/exceptions.py +0 -0
  95. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/fields.py +0 -0
  96. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/footnotes.py +0 -0
  97. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/image/__init__.py +0 -0
  98. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/image/exceptions.py +0 -0
  99. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/image/image.py +0 -0
  100. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/math.py +0 -0
  101. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/opc/__init__.py +0 -0
  102. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/opc/coreprops.py +0 -0
  103. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/revisions.py +0 -0
  104. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/sdt.py +0 -0
  105. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/session.py +0 -0
  106. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/shape.py +0 -0
  107. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/shared.py +0 -0
  108. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/styles/__init__.py +0 -0
  109. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/styles/_table.py +0 -0
  110. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/text/__init__.py +0 -0
  111. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/text/font.py +0 -0
  112. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/text/hyperlink.py +0 -0
  113. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/text/pagebreak.py +0 -0
  114. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/toc.py +0 -0
  115. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/typing.py +0 -0
  116. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/scripts/docx_exec_lab.py +0 -0
  117. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/scripts/docx_exec_lab_examples/fast_table_fill.py +0 -0
  118. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/scripts/docx_exec_lab_examples/find_replace_literal.py +0 -0
  119. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/scripts/docx_exec_lab_server.py +0 -0
  120. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/scripts/dump_wire_fixtures.py +0 -0
  121. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/scripts/release.sh +0 -0
  122. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/scripts/round_trip_smoke.py +0 -0
  123. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/scripts/smoke_test_block_not_found.py +0 -0
  124. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/scripts/validate_find_replace_asset.py +0 -0
  125. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/__init__.py +0 -0
  126. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/conftest.py +0 -0
  127. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/README.md +0 -0
  128. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/__init__.py +0 -0
  129. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/ab_probe_runner.py +0 -0
  130. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/auto_gen_cases.py +0 -0
  131. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/binary_round_trip.py +0 -0
  132. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/cases.py +0 -0
  133. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/complex_cases.py +0 -0
  134. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/coverage_report.py +0 -0
  135. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/extract.py +0 -0
  136. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/extreme_cases.py +0 -0
  137. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/fake_session.py +0 -0
  138. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/firm_templates/README.md +0 -0
  139. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/firm_templates/__init__.py +0 -0
  140. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/firm_templates/_runner.py +0 -0
  141. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/firm_templates/extractor.py +0 -0
  142. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/firm_templates/test_pw_corpus.py +0 -0
  143. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/firm_templates/test_pw_research_digest.py +0 -0
  144. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/local_runner.py +0 -0
  145. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/mega_cases.py +0 -0
  146. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshot.py +0 -0
  147. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/01_basic_paragraph.json +0 -0
  148. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/02_multiple_headings.json +0 -0
  149. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/03_runs_with_formatting.json +0 -0
  150. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/04_font_name_and_size.json +0 -0
  151. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/05_font_color_rgb.json +0 -0
  152. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/06_font_character_properties.json +0 -0
  153. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/07_font_subscript_superscript.json +0 -0
  154. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/08_font_highlight.json +0 -0
  155. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/09_paragraph_alignment.json +0 -0
  156. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/100_table_negative_indexing.json +0 -0
  157. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/102_text_with_embedded_special_chars.json +0 -0
  158. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/104_core_properties_datetime.json +0 -0
  159. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/105_default_one_section.json +0 -0
  160. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/106_heading_paragraph_format.json +0 -0
  161. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/107_varying_row_heights.json +0 -0
  162. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/10_paragraph_indents.json +0 -0
  163. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/11_paragraph_spacing.json +0 -0
  164. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/12_paragraph_keep_options.json +0 -0
  165. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/13_paragraph_tab_stops.json +0 -0
  166. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/14_run_add_tab_and_break.json +0 -0
  167. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/15_run_add_break_page.json +0 -0
  168. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/16_paragraph_clear_and_insert_before.json +0 -0
  169. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/17_table_basic.json +0 -0
  170. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/18_table_cell_text.json +0 -0
  171. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/19_table_row_column_sizing.json +0 -0
  172. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/20_table_cell_vertical_alignment.json +0 -0
  173. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/21_table_alignment_and_autofit.json +0 -0
  174. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/22_table_cell_paragraphs_iteration.json +0 -0
  175. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/24_table_add_row_column.json +0 -0
  176. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/25_table_merge_cells.json +0 -0
  177. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/26_section_page_setup.json +0 -0
  178. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/27_section_margins.json +0 -0
  179. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/28_section_add_new.json +0 -0
  180. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/29_section_headers_linked.json +0 -0
  181. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/30_styles_iteration.json +0 -0
  182. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/31_styles_lookup_and_default.json +0 -0
  183. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/32_styles_add_paragraph_style.json +0 -0
  184. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/33_core_properties_set_and_get.json +0 -0
  185. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/34_inline_shapes_iterate_empty.json +0 -0
  186. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/35_full_report.json +0 -0
  187. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/36_replace_text_in_paragraph.json +0 -0
  188. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/37_iterate_runs_and_format_all_bold.json +0 -0
  189. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/38_font_all_properties.json +0 -0
  190. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/39_large_body_100_paragraphs.json +0 -0
  191. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/40_large_table_10x10.json +0 -0
  192. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/41_unicode_and_emoji.json +0 -0
  193. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/42_very_long_paragraph.json +0 -0
  194. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/43_paragraph_text_round_trip.json +0 -0
  195. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/44_paragraph_alignment_round_trip.json +0 -0
  196. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/45_cell_text_round_trip.json +0 -0
  197. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/46_run_text_setter_round_trip.json +0 -0
  198. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/47_font_size_round_trip.json +0 -0
  199. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/48_font_color_round_trip.json +0 -0
  200. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/49_resume_layout.json +0 -0
  201. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/50_multi_section_doc.json +0 -0
  202. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/52_iterate_everything.json +0 -0
  203. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/53_apply_style_to_paragraphs.json +0 -0
  204. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/54_empty_everything.json +0 -0
  205. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/55_single_character_runs.json +0 -0
  206. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/56_everything_in_one.json +0 -0
  207. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/57_runs_after_multiple_text_appends.json +0 -0
  208. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/58_modify_runs_in_place.json +0 -0
  209. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/59_indent_round_trip.json +0 -0
  210. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/60_space_round_trip.json +0 -0
  211. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/61_cell_paragraph_with_runs.json +0 -0
  212. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/62_many_cell_paragraphs.json +0 -0
  213. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/63_table_style_round_trip.json +0 -0
  214. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/64_many_sections.json +0 -0
  215. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/65_20x20_table_formatted.json +0 -0
  216. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/66_toc_like_structure.json +0 -0
  217. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/67_paragraph_insert_before_chain.json +0 -0
  218. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/68_invoice.json +0 -0
  219. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/69_newsletter.json +0 -0
  220. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/70_add_and_iterate_back.json +0 -0
  221. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/71_academic_paper.json +0 -0
  222. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/72_legal_contract.json +0 -0
  223. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/73_form_with_many_tables.json +0 -0
  224. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/74_paragraph_with_10_runs.json +0 -0
  225. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/75_paragraph_negative_first_line_indent.json +0 -0
  226. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/76_rgbcolor_from_string.json +0 -0
  227. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/77_length_unit_conversions.json +0 -0
  228. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/78_paragraph_copy_style.json +0 -0
  229. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/79_bulk_cell_formatting.json +0 -0
  230. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/80_apply_style_after_add_run.json +0 -0
  231. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/81_multi_page_with_breaks.json +0 -0
  232. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/82_add_text_on_existing_run.json +0 -0
  233. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/83_clear_then_repopulate_paragraph.json +0 -0
  234. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/84_table_reread_row_count.json +0 -0
  235. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/85_header_footer_access.json +0 -0
  236. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/86_font_read_unset_returns_none.json +0 -0
  237. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/87_500_paragraph_doc.json +0 -0
  238. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/88_mixed_content_iteration.json +0 -0
  239. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/89_alignment_clear_via_none.json +0 -0
  240. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/90_cell_add_paragraph_styled.json +0 -0
  241. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/91_many_small_tables.json +0 -0
  242. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/92_margins_every_section.json +0 -0
  243. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/93_font_bool_reads_after_set.json +0 -0
  244. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/94_page_break_before_paragraph.json +0 -0
  245. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/95_paragraph_hyperlinks_empty.json +0 -0
  246. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/96_paragraph_contains_page_break.json +0 -0
  247. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/97_document_styles_by_key.json +0 -0
  248. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/98_style_contains_check.json +0 -0
  249. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex02_unicode_everywhere.json +0 -0
  250. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex03_1000_paragraphs.json +0 -0
  251. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex04_50x50_table.json +0 -0
  252. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex05_long_text_in_cell.json +0 -0
  253. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex06_hundred_tiny_runs.json +0 -0
  254. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex07_every_font_boolean.json +0 -0
  255. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex08_many_continuous_sections.json +0 -0
  256. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex09_many_tab_stops.json +0 -0
  257. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex10_complex_bom.json +0 -0
  258. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex11_banded_rows_formatting.json +0 -0
  259. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex12_section_reconfigure.json +0 -0
  260. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex13_cell_with_10_paragraphs.json +0 -0
  261. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex14_styled_report_table.json +0 -0
  262. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex15_paragraph_all_format_props.json +0 -0
  263. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex16_runs_interleaved_with_breaks.json +0 -0
  264. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex17_all_break_kinds.json +0 -0
  265. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex18_read_back_large_doc.json +0 -0
  266. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex19_mutate_all_runs.json +0 -0
  267. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex20_kitchen_sink_v2.json +0 -0
  268. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/mega01_book_chapter.json +0 -0
  269. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/mega02_research_proposal.json +0 -0
  270. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/mega03_financial_statement.json +0 -0
  271. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/mega04_recipe_card.json +0 -0
  272. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/mega05_user_manual.json +0 -0
  273. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/mega06_complex_newsletter.json +0 -0
  274. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/mega07_budget_spreadsheet.json +0 -0
  275. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/mega08_product_catalog.json +0 -0
  276. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/mega09_signed_contract.json +0 -0
  277. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/mega10_api_documentation.json +0 -0
  278. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw01_official_quickstart.json +0 -0
  279. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw02_paragraph_style_list.json +0 -0
  280. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw03_character_formatting.json +0 -0
  281. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw04_section_page_setup.json +0 -0
  282. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw05_toc_pattern.json +0 -0
  283. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw06_meeting_minutes.json +0 -0
  284. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw07_dense_formatting_demo.json +0 -0
  285. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw08_table_merged_header.json +0 -0
  286. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw09_bulk_run_iteration.json +0 -0
  287. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw10_colored_grid_table.json +0 -0
  288. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw11_header_text.json +0 -0
  289. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw12_first_page_footer.json +0 -0
  290. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw13_even_page_header.json +0 -0
  291. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw15_paragraph_style_instance.json +0 -0
  292. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw16_header_footer_tables.json +0 -0
  293. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw17_header_letterhead_filled.json +0 -0
  294. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw18_header_table_properties.json +0 -0
  295. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw19_header_table_rows_columns.json +0 -0
  296. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw20_header_table_merges.json +0 -0
  297. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/ours_spec.json +0 -0
  298. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/parity_crawl.py +0 -0
  299. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/parity_diff.json +0 -0
  300. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/real_world_cases.py +0 -0
  301. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/round_trip_tests.py +0 -0
  302. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/stock_spec.json +0 -0
  303. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/test_e2e_against_staging.py +0 -0
  304. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fixtures/field_reads.json +0 -0
  305. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fixtures/note_reference_reads.json +0 -0
  306. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fixtures/ruby_reads.json +0 -0
  307. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fixtures/symbol_reads.json +0 -0
  308. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/live/__init__.py +0 -0
  309. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/live/reader.py +0 -0
  310. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/live/sdk_driver.py +0 -0
  311. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/live/stock_driver.py +0 -0
  312. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/parity/README.md +0 -0
  313. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/parity/__init__.py +0 -0
  314. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/parity/baseline_gaps.json +0 -0
  315. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/parity/compare.py +0 -0
  316. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/parity/intentional_deviations.json +0 -0
  317. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/parity/introspect.py +0 -0
  318. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/parity/reports/GAP_ANALYSIS.md +0 -0
  319. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/parity/reports/gap_report.json +0 -0
  320. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/parity/run_parity.py +0 -0
  321. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/parity/snapshots/athena_latest.json +0 -0
  322. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/parity/snapshots/upstream_python_docx_1.2.0.json +0 -0
  323. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/parity/test_parity_gap.py +0 -0
  324. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_add_section.py +0 -0
  325. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_add_section_extract_items.py +0 -0
  326. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_alignment_values.py +0 -0
  327. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_athena_extension_creates_session_open.py +0 -0
  328. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_athena_extensions_contract.py +0 -0
  329. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_athena_extensions_registry.py +0 -0
  330. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_batch_chunking.py +0 -0
  331. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_batching_perf.py +0 -0
  332. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_block_not_found_error.py +0 -0
  333. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_buffer.py +0 -0
  334. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_add_paragraph_wire_shape.py +0 -0
  335. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_add_table_not_supported.py +0 -0
  336. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_borders_spec.py +0 -0
  337. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_fastpath_runs.py +0 -0
  338. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_inner_add_hyperlink_stash.py +0 -0
  339. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_inner_add_run_via_cell_insert.py +0 -0
  340. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_inner_format_stash.py +0 -0
  341. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_inner_run_format_stash.py +0 -0
  342. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_merge.py +0 -0
  343. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_nested_tables.py +0 -0
  344. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_paragraphs_listed.py +0 -0
  345. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_text_plain_fastpath.py +0 -0
  346. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_text_replace_semantics.py +0 -0
  347. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_citations.py +0 -0
  348. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_collapsed_range_format.py +0 -0
  349. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_color_format_theme.py +0 -0
  350. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_command_dataclasses.py +0 -0
  351. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_commands.py +0 -0
  352. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_comment_paragraphs.py +0 -0
  353. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_comments.py +0 -0
  354. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_comments_first_read.py +0 -0
  355. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_content_control_value.py +0 -0
  356. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_core_properties.py +0 -0
  357. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_document_asset_id_property.py +0 -0
  358. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_document_clear.py +0 -0
  359. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_document_create.py +0 -0
  360. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_document_create_from_template.py +0 -0
  361. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_document_factory_validation.py +0 -0
  362. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_docx_exec_lab.py +0 -0
  363. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_docx_exec_lab_server.py +0 -0
  364. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_e2e_partial_failure_cascade.py +0 -0
  365. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_empty_hyperlinks.py +0 -0
  366. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_execution_scope.py +0 -0
  367. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_export_docx_clean.py +0 -0
  368. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_export_rescue_anchors.py +0 -0
  369. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_field_reads_python_docx_parity.py +0 -0
  370. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_field_refresh.py +0 -0
  371. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_field_runs.py +0 -0
  372. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_find_replace_session_open.py +0 -0
  373. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_flushed_write_failures.py +0 -0
  374. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_http_transport.py +0 -0
  375. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_hyperlink_coalescing.py +0 -0
  376. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_image_url_data_uri.py +0 -0
  377. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_inline_page_break.py +0 -0
  378. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_inline_shape_alt_text.py +0 -0
  379. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_inline_shape_size.py +0 -0
  380. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_inline_shape_type.py +0 -0
  381. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_inline_shapes_floating.py +0 -0
  382. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_insert_deferred.py +0 -0
  383. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_iter_inner_content.py +0 -0
  384. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_line_clear_break.py +0 -0
  385. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_list_styles.py +0 -0
  386. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_merged_cell_secondary_slot.py +0 -0
  387. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_merged_cells.py +0 -0
  388. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_missing_modules.py +0 -0
  389. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_nested_table_refused.py +0 -0
  390. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_note_reference_reads_python_docx_parity.py +0 -0
  391. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_oxml_shim.py +0 -0
  392. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_page_break.py +0 -0
  393. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_paragraph_delete.py +0 -0
  394. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_paragraph_runs_hyperlinks.py +0 -0
  395. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_paragraph_text_len_cache.py +0 -0
  396. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_parity_round2.py +0 -0
  397. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_partial_failure_cascade.py +0 -0
  398. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_pdf_export_and_page_renders.py +0 -0
  399. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_phase_a_behavior.py +0 -0
  400. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_phase_b_headers_footers.py +0 -0
  401. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_phase_c_tables.py +0 -0
  402. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_positional_cell_id.py +0 -0
  403. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_postproc_cell_format_rewrite.py +0 -0
  404. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_postproc_cell_run_format_rewrite.py +0 -0
  405. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_postproc_ref_restore.py +0 -0
  406. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_pr19766_review_fixes.py +0 -0
  407. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_ptc.py +0 -0
  408. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_python_docx_api_parity.py +0 -0
  409. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_read_run_ranges.py +0 -0
  410. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_rendered_page_breaks.py +0 -0
  411. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_repeated_node_read.py +0 -0
  412. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_restart_numbering.py +0 -0
  413. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_revisions.py +0 -0
  414. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_round_trip_smoke_script.py +0 -0
  415. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_ruby_reads_python_docx_parity.py +0 -0
  416. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_run_add_picture_anchor.py +0 -0
  417. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_run_break_inner_content.py +0 -0
  418. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_run_edges.py +0 -0
  419. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_run_formatting_wire.py +0 -0
  420. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_run_later_runs.py +0 -0
  421. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_run_mark_inheritance.py +0 -0
  422. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_run_page_number_blocks.py +0 -0
  423. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_run_table_style_objects.py +0 -0
  424. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_run_text_python_docx.py +0 -0
  425. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_run_text_refreshes_paragraph.py +0 -0
  426. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_run_unmodeled_toggles.py +0 -0
  427. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_sdk_reads_served.py +0 -0
  428. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_section_read_lengths.py +0 -0
  429. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_add_paragraph_style.py +0 -0
  430. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_add_picture.py +0 -0
  431. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_add_run.py +0 -0
  432. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_cell_add_paragraph.py +0 -0
  433. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_comments_add_comment.py +0 -0
  434. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_comments_get.py +0 -0
  435. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_document_audit.py +0 -0
  436. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_document_element.py +0 -0
  437. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_enum_section.py +0 -0
  438. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_font_audit.py +0 -0
  439. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_header_footer.py +0 -0
  440. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_hyperlink.py +0 -0
  441. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_inline_shape.py +0 -0
  442. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_insert_paragraph_before.py +0 -0
  443. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_misc.py +0 -0
  444. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_paragraph_strict.py +0 -0
  445. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_paragraph_style.py +0 -0
  446. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_paragraph_style_strict.py +0 -0
  447. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_parfmt.py +0 -0
  448. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_row_col_cell.py +0 -0
  449. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_run_add_break.py +0 -0
  450. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_run_bool_setters.py +0 -0
  451. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_run_style.py +0 -0
  452. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_run_style_strict.py +0 -0
  453. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_run_text.py +0 -0
  454. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_run_underline.py +0 -0
  455. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_section_audit.py +0 -0
  456. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_section_dimensions.py +0 -0
  457. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_section_onoff.py +0 -0
  458. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_settings.py +0 -0
  459. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_shared_audit.py +0 -0
  460. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_style.py +0 -0
  461. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_styles.py +0 -0
  462. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_table_audit.py +0 -0
  463. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_table_cell.py +0 -0
  464. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_table_dimensions.py +0 -0
  465. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_table_layout.py +0 -0
  466. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_smoke_integration.py +0 -0
  467. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_style_acceptance.py +0 -0
  468. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_style_delete.py +0 -0
  469. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_style_font.py +0 -0
  470. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_style_formatting_writes.py +0 -0
  471. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_style_metadata_writes.py +0 -0
  472. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_style_names.py +0 -0
  473. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_style_setters_contract.py +0 -0
  474. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_style_tab_stops_read.py +0 -0
  475. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_symbol_reads_python_docx_parity.py +0 -0
  476. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_table_anchors.py +0 -0
  477. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_table_clears.py +0 -0
  478. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_table_direction.py +0 -0
  479. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_table_read_reuse.py +0 -0
  480. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_table_set_cell_perf.py +0 -0
  481. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_table_style_id_resolution.py +0 -0
  482. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_temporarily_unavailable.py +0 -0
  483. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_text_control_characters.py +0 -0
  484. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_tracked_revisions_offsets.py +0 -0
  485. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_uv_lock_version.py +0 -0
  486. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_validate_find_replace_asset_script.py +0 -0
  487. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_wire_contract.py +0 -0
  488. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_xml_attr_guard.py +0 -0
  489. {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_zod_wire_contract.py +0 -0
@@ -121,6 +121,21 @@ pinned by focused tests and documented in
121
121
  `horz_dpi`, `width`, `scaled_dimensions`, …). A picture in a table cell or
122
122
  a header has no id to read its image by, so `.image` raises `ValueError`;
123
123
  an older docx-studio does not report pictures, so they are not runs there.
124
+ `Run.add_picture` puts the picture in that run, as python-docx appends the
125
+ `w:drawing` to its `w:r`: after what the run holds, and text `add_text`
126
+ adds goes after it. Against a docx-studio that reports
127
+ `capabilities.pictureRuns`, `CreateImage` carries `runEdge: "append"` (the
128
+ run's identity as `add_text` names it), the run's record holds the picture
129
+ (`pictureRun`), and the run reads as one run whose pictures stand at their
130
+ places in its text (`pictures`), so `iter_inner_content()` yields its text
131
+ and each `Drawing` in order (with Word's rendered page breaks where the read
132
+ places them among the pictures, `afterPictures`), a whole-run format takes
133
+ its pictures too, and `run.text = ...` takes every one of them out
134
+ (`wholeRun`). A picture's run (no text) formats its picture at once, named
135
+ by its identity (`laterRuns`), so `r = p.add_run(); r.bold = True;
136
+ r.add_picture(img)` writes the bold `w:rPr` beside the `w:drawing`. An older
137
+ docx-studio puts the picture in a run of its own (`tests/test_drawing_image.py`,
138
+ battery `ab_probe/picture_runs.py`).
124
139
  - **A run holding only a page or column break yields `""` from
125
140
  `Run.iter_inner_content()`,** as python-docx reads a `w:br` of type `page`
126
141
  or `column` as empty text; an empty run (a comment reference's) yields
@@ -1255,31 +1270,33 @@ architecture or a DOCX Studio constraint:
1255
1270
  exported file. Against a docx-studio that predates `fieldRun` reads, a
1256
1271
  field reads as no runs and no text, as before (`tests/test_field_runs.py`).
1257
1272
 
1258
- - **A run that holds a page number block refuses two whole-run formats.** A
1259
- page number block (`w:pgNum`) reads as a run with no text, and a run that
1260
- holds text and blocks (or two blocks) reads as python-docx's one run. A
1261
- whole-run format (`run.bold = True`, `run.font.*`, a format of a block's
1262
- run) formats every piece of it, as python-docx formats its `w:rPr`. Two
1263
- formats are refused while a block of the run has a node. A link's block
1264
- has none, and takes both as the run's text does. The first is a tracked
1265
- format (`track_revisions`), which raises `DocxError` naming
1266
- `TrackedChangesUnsupported`, because docx-studio records no tracked change
1267
- on a block. The second is the on/off properties no editor mark holds
1273
+ - **A run that holds a page number block refuses a tracked whole-run format
1274
+ and two text writes.** A page number block (`w:pgNum`) reads as a run with
1275
+ no text, and a run that holds text and blocks (or two blocks) reads as
1276
+ python-docx's one run. A whole-run format (`run.bold = True`, `run.font.*`,
1277
+ a format of a block's run) formats every piece of it, as python-docx formats
1278
+ its `w:rPr`, the on/off properties no editor mark holds included
1268
1279
  (`font.no_proof`, `snap_to_grid`, `web_hidden`, `spec_vanish`, `math`,
1269
- `complex_script`, `cs_bold`, `cs_italic`), in any format that reaches a
1270
- block, which warn (`DocxUnsupportedCommandWarning`), because a block keeps
1271
- its source run's.
1272
- python-docx writes both into the run's `w:rPr`. Made on the run's text
1273
- alone, either would leave the run half formatted and split it in two
1280
+ `complex_script`, `cs_bold`, `cs_italic`). A tracked format
1281
+ (`track_revisions`) is refused while a block of the run has a node, and
1282
+ raises `DocxError` naming `TrackedChangesUnsupported`, because docx-studio
1283
+ records no tracked change on a block. A link's block has none, and takes it
1284
+ as the run's text does. In a document imported before docx-studio gave a
1285
+ block's node its run's properties (in October 2026, between the release that
1286
+ first read `w:pgNum` and the next), and in a comment, the on/off properties
1287
+ are refused too, in any format that reaches a block, and warn
1288
+ (`DocxUnsupportedCommandWarning`), because there a block keeps its source
1289
+ run's. python-docx writes both into the run's `w:rPr`. Made on the run's
1290
+ text alone, either would leave the run half formatted and split it in two
1274
1291
  (`DOCX_STUDIO_LIMITATIONS.md` § 27). `run.text = …` and `clear()` replace
1275
1292
  all of such a run, its blocks too, as upstream does: the SDK declares
1276
1293
  `wholeRunPieces`, and renumbers the field runs it holds of the paragraph,
1277
1294
  since each field after the blocks is numbered one lower for each
1278
1295
  (`tests/test_run_page_number_blocks.py`). Two text writes are refused and
1279
- warn (`DocxUnsupportedCommandWarning`), where upstream replaces the
1280
- blocks: text written to a block's run (a run of blocks alone, or a lone
1281
- block), which would move the text offsets the SDK keeps, and the text of a
1282
- link's run that holds a block, which has no node to take out.
1296
+ warn (`DocxUnsupportedCommandWarning`), where upstream replaces the blocks:
1297
+ text written to a block's run (a run of blocks alone, or a lone block),
1298
+ which would move the text offsets the SDK keeps, and the text of a link's
1299
+ run that holds a block, which has no node to take out.
1283
1300
 
1284
1301
  - **`Font.name = "…"` also clears the theme fonts of the two slots it
1285
1302
  sets.** python-docx writes the name to `w:rFonts`' `w:ascii` and `w:hAnsi`
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: athena-python-docx
3
- Version: 0.34.0
3
+ Version: 0.36.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.34.0"
9
+ __version__ = "0.36.0"
10
10
 
11
11
  from docx.api import Document
12
12
  from docx._buffer import discard_all, flush_all
@@ -43,6 +43,7 @@ from docx._execution import (
43
43
  is_stale_execution,
44
44
  )
45
45
  from docx._timeouts import timeout_for_commands
46
+ from docx._xml_text import check_command_text
46
47
  from docx.commands import (
47
48
  Command,
48
49
  GetNodeById,
@@ -596,6 +597,11 @@ class CommandBuffer:
596
597
  proxy's ``_node_id`` in-place.
597
598
  """
598
599
  self.ensure_usable()
600
+ # A write whose text holds a character XML does not allow raises
601
+ # python-docx's ValueError here, before anything is sent: every command
602
+ # comes through, a path-proxy op's and a direct ``send_command``'s.
603
+ if not is_query(cmd):
604
+ check_command_text(cmd.to_dict())
599
605
 
600
606
  # A read of the node the last command read, with nothing sent or
601
607
  # buffered since and within READ_REUSE_SECONDS of it, answers from
@@ -0,0 +1,109 @@
1
+ """python-docx's ``ElementProxy`` equality, for the SDK's proxies of the
2
+ objects python-docx wraps in one: styles, the styles part, settings, a
3
+ paragraph's or a style's paragraph format, a run's or a style's font, tab
4
+ stops and the latent styles."""
5
+
6
+ from __future__ import annotations
7
+
8
+ import weakref
9
+ from collections.abc import Iterator
10
+ from typing import Any, Generic, TypeVar
11
+
12
+ _T = TypeVar("_T")
13
+
14
+
15
+ class IdentityWeakSet(Generic[_T]):
16
+ """A set of objects held weakly, by identity: a ``weakref.WeakSet`` hashes
17
+ its members, and a proxy that compares by its element
18
+ (:class:`ElementProxyEquality`) is not hashable, as in python-docx."""
19
+
20
+ __slots__ = ("_members",)
21
+
22
+ def __init__(self) -> None:
23
+ self._members: "weakref.WeakValueDictionary[int, _T]" = weakref.WeakValueDictionary()
24
+
25
+ def add(self, item: _T) -> None:
26
+ self._members[id(item)] = item
27
+
28
+ def __iter__(self) -> Iterator[_T]:
29
+ return iter(list(self._members.values()))
30
+
31
+ def __len__(self) -> int:
32
+ return len(self._members)
33
+
34
+
35
+ class ElementProxyEquality:
36
+ """python-docx's ``docx.shared.ElementProxy`` equality: two proxies of the
37
+ same element are equal (``paragraph.style == doc.styles["Heading 1"]``),
38
+ a proxy of another element or anything else is not, and, as python-docx
39
+ defines ``__eq__`` there, a proxy is not hashable.
40
+
41
+ The element is :meth:`_proxy_element`: the docx-studio object it stands
42
+ for, named as the XML element python-docx's proxy wraps (a style's
43
+ ``w:style``, so a style, its font and its paragraph format are equal, as
44
+ they are in python-docx).
45
+ """
46
+
47
+ __slots__ = ()
48
+
49
+ def _proxy_element(self) -> tuple[object, ...]:
50
+ raise NotImplementedError
51
+
52
+ def __eq__(self, other: object) -> bool:
53
+ if not isinstance(other, ElementProxyEquality):
54
+ return False
55
+ return self._proxy_element() == other._proxy_element()
56
+
57
+ def __ne__(self, other: object) -> bool:
58
+ return not self.__eq__(other)
59
+
60
+ __hash__ = None # type: ignore[assignment]
61
+
62
+
63
+ # Session -> style id -> the style definition that id names in the session's
64
+ # document now (:func:`style_definition`). Held weakly by session, as the
65
+ # run order is (``docx._run_order``); the document stores none of it.
66
+ _STYLE_DEFINITIONS: "weakref.WeakKeyDictionary[Any, dict[str, object]]" = weakref.WeakKeyDictionary()
67
+
68
+
69
+ def _definitions(session: object) -> "dict[str, object] | None":
70
+ if session is None:
71
+ return None
72
+ try:
73
+ return _STYLE_DEFINITIONS.setdefault(session, {})
74
+ except TypeError: # a session that takes no weak reference
75
+ return None
76
+
77
+
78
+ def style_definition(session: object, style_id: str) -> object:
79
+ """The style definition (its ``w:style`` element) that ``style_id`` names in
80
+ ``session``'s document now, which a style proxy holds from its first read:
81
+ the same one after a rename (:func:`style_renamed`), another for a style
82
+ made after one of that id was deleted (:func:`style_deleted`)."""
83
+ definitions = _definitions(session)
84
+ if definitions is None:
85
+ return ("w:styleId", style_id)
86
+ return definitions.setdefault(style_id, object())
87
+
88
+
89
+ def style_renamed(session: object, old: str, new: str) -> None:
90
+ """``style_id`` renamed the definition ``old`` named to ``new``."""
91
+ definitions = _definitions(session)
92
+ if definitions is not None:
93
+ definitions[new] = definitions.pop(old, None) or object()
94
+
95
+
96
+ def style_deleted(session: object, style_id: str) -> None:
97
+ """``delete`` removed the definition ``style_id`` named."""
98
+ definitions = _definitions(session)
99
+ if definitions is not None:
100
+ definitions.pop(style_id, None)
101
+
102
+
103
+ def style_element(style: object) -> tuple[object, ...]:
104
+ """The ``w:style`` element of ``style`` (a ``BaseStyle``): its document and
105
+ its definition (:func:`style_definition`), which a rename keeps."""
106
+ definition = getattr(style, "_definition", None)
107
+ if definition is None:
108
+ definition = ("w:styleId", getattr(style, "_style_id", None))
109
+ return ("w:style", getattr(style, "_session", None), definition)
@@ -0,0 +1,46 @@
1
+ """What lxml refuses in XML text and attribute values, where python-docx meets it.
2
+
3
+ python-docx writes every string it is given into an lxml element, and lxml
4
+ raises ``ValueError`` for a character XML does not allow: C0 controls other
5
+ than tab, LF and CR, the noncharacters U+FFFE / U+FFFF, and lone surrogates.
6
+ So ``run.text = "a\\x0bb"`` (a vertical tab, Word's line break in its object
7
+ model) raises there, before anything is written. docx-studio would take the
8
+ text, and a part holding it is one Word refuses to open.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import re
14
+ from typing import Any
15
+
16
+ XML_INCOMPATIBLE_CHARACTER = re.compile(r"[\x00-\x08\x0b\x0c\x0e-\x1f\ud800-\udfff￾￿]")
17
+ XML_INCOMPATIBLE_MESSAGE = (
18
+ "All strings must be XML compatible: Unicode or ASCII, no NULL bytes or control characters"
19
+ )
20
+
21
+
22
+ def check_xml_compatible(value: Any) -> None:
23
+ """Raise python-docx's ``ValueError`` (lxml's) when a string in ``value``,
24
+ a command's params (strings, lists, dicts), holds a character XML does
25
+ not allow."""
26
+ if isinstance(value, str):
27
+ if XML_INCOMPATIBLE_CHARACTER.search(value):
28
+ raise ValueError(XML_INCOMPATIBLE_MESSAGE)
29
+ elif isinstance(value, dict):
30
+ for item in value.values():
31
+ check_xml_compatible(item)
32
+ elif isinstance(value, (list, tuple)):
33
+ for item in value:
34
+ check_xml_compatible(item)
35
+
36
+
37
+ #: Fields of a write that name text to find, not text to write
38
+ #: (``FindReplace.pattern``): a pattern may match what a document already holds.
39
+ _SEARCH_FIELDS: frozenset[str] = frozenset({"pattern"})
40
+
41
+
42
+ def check_command_text(command: dict[str, Any]) -> None:
43
+ """:func:`check_xml_compatible` over a write's wire fields (a command's
44
+ ``to_dict()``), but for the text it searches for (``_SEARCH_FIELDS``)."""
45
+ check_xml_compatible({key: value for key, value in command.items() if key not in _SEARCH_FIELDS})
46
+
@@ -9,6 +9,8 @@ docx-studio; ``isinstance(cell, BlockItemContainer)`` holds as in python-docx.
9
9
 
10
10
  from __future__ import annotations
11
11
 
12
+ from docx._xml_text import check_xml_compatible
13
+
12
14
  from typing import TYPE_CHECKING, Iterator
13
15
 
14
16
  if TYPE_CHECKING:
@@ -30,6 +32,7 @@ class BlockItemContainer:
30
32
  self, text: str = "", style: "str | ParagraphStyle | None" = None
31
33
  ) -> "Paragraph":
32
34
  """Return paragraph newly added to the end of the content in this container."""
35
+ check_xml_compatible(text)
33
36
  raise NotImplementedError(f"{type(self).__name__} holds no paragraphs")
34
37
 
35
38
  def add_table(self, rows: int, cols: int, width: "Length") -> "Table":
@@ -140,6 +140,10 @@ class CreateImage(Command):
140
140
  at: dict[str, Any]
141
141
  client_node_id: str | None = None
142
142
  run: dict[str, Any] | None = None
143
+ # ``"append"`` (``Run.add_picture`` against a docx-studio that reports
144
+ # ``capabilities.pictureRuns``): the picture ends the run that ends at the
145
+ # anchor's offset, in that run's ``w:r``, as python-docx appends it.
146
+ run_edge: str | None = None
143
147
 
144
148
 
145
149
  @dataclass
@@ -14,6 +14,8 @@ Phase 1 supported methods:
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
+ from docx._xml_text import check_xml_compatible
18
+
17
19
  import base64
18
20
  import os
19
21
  import re
@@ -1789,6 +1791,7 @@ class Document:
1789
1791
  Returns:
1790
1792
  The newly-created Paragraph.
1791
1793
  """
1794
+ check_xml_compatible(text)
1792
1795
  from docx.styles._table import paragraph_style_name
1793
1796
  from docx.styles.style import ParagraphStyle
1794
1797
  from docx.text.paragraph import Paragraph
@@ -2033,6 +2036,7 @@ class Document:
2033
2036
  level: int = 1,
2034
2037
  ) -> "Paragraph":
2035
2038
  """Append a heading via DOCX Studio's canonical `doc.create.heading`."""
2039
+ check_xml_compatible(text)
2036
2040
  from docx.text.paragraph import Paragraph
2037
2041
 
2038
2042
  self._ensure_open()
@@ -92,6 +92,7 @@ _XML_ELEMENT_ATTRS: frozenset[str] = frozenset(
92
92
  "_tc", # _Cell._tc
93
93
  "_tbl", # Table._tbl
94
94
  "_tr", # _Row._tr
95
+ "_t", # _Text._t (the ``w:t`` Run.add_text added)
95
96
  "element", # Run.element / Paragraph.element / Document.element
96
97
  "_element", # private alias used by some python-docx forks
97
98
  },
@@ -11,6 +11,8 @@ or twip values depending on the op).
11
11
 
12
12
  from __future__ import annotations
13
13
 
14
+ from docx._xml_text import check_xml_compatible
15
+
14
16
  import warnings
15
17
  from collections.abc import Sequence
16
18
  from typing import TYPE_CHECKING
@@ -986,6 +988,7 @@ class _HeaderFooter(BlockItemContainer):
986
988
  server turns tabs and line breaks in ``text`` into ``<w:tab/>`` /
987
989
  ``<w:br/>``, as python-docx's ``Run.text`` does.
988
990
  """
991
+ check_xml_compatible(text)
989
992
  from docx.styles.style import ParagraphStyle
990
993
 
991
994
  style_str: str | None
@@ -21,6 +21,7 @@ from __future__ import annotations
21
21
  from typing import TYPE_CHECKING
22
22
 
23
23
  from docx._batching import run_sync
24
+ from docx._proxy import ElementProxyEquality
24
25
 
25
26
  if TYPE_CHECKING:
26
27
  from docx.client import Session
@@ -38,7 +39,7 @@ class PendingSettingsMutationWarning(UserWarning):
38
39
  """
39
40
 
40
41
 
41
- class Settings:
42
+ class Settings(ElementProxyEquality):
42
43
  def __init__(
43
44
  self,
44
45
  *,
@@ -49,12 +50,16 @@ class Settings:
49
50
  self._document: "Document | None" = document
50
51
  self._odd_and_even_pages_header_footer: bool = False
51
52
 
53
+ def _proxy_element(self) -> tuple[object, ...]:
54
+ return ("w:settings", self._session)
55
+
52
56
  @property
53
57
  def odd_and_even_pages_header_footer(self) -> bool:
54
58
  """The document's ``w:evenAndOddHeaders`` in ``word/settings.xml``, as
55
59
  python-docx reads it (False when absent or off). A docx-studio that
56
60
  does not report it (``Info`` without ``settings``) gives the value this
57
61
  proxy last set."""
62
+ self._open()
58
63
  info: object = run_sync(self._session.doc.info({"includeSettings": True}))
59
64
  settings: object = info.get("settings") if isinstance(info, dict) else None
60
65
  reported: object = settings.get("evenAndOddHeaders") if isinstance(settings, dict) else None
@@ -65,6 +70,7 @@ class Settings:
65
70
  @odd_and_even_pages_header_footer.setter
66
71
  def odd_and_even_pages_header_footer(self, value: bool) -> None:
67
72
  enabled = bool(value)
73
+ self._open()
68
74
  run_sync(
69
75
  self._session.doc.sections.set_odd_even_headers_footers(
70
76
  {"enabled": enabled},
@@ -72,6 +78,14 @@ class Settings:
72
78
  )
73
79
  self._odd_and_even_pages_header_footer = enabled
74
80
 
81
+ def _open(self) -> None:
82
+ """Open the document's session before a read or write of it, as every
83
+ member of ``Document`` that touches it does (``Document.create()``
84
+ returns before it opens). ``track_revisions`` needs no session: it
85
+ stays a local flag until one opens."""
86
+ if self._document is not None:
87
+ self._document._ensure_open()
88
+
75
89
  # --- Track changes alias (Athena: forwards to Document.track_revisions) ---
76
90
 
77
91
  @property
@@ -23,6 +23,7 @@ import warnings
23
23
  import weakref
24
24
  from typing import TYPE_CHECKING, Any, Iterator
25
25
 
26
+ from docx._proxy import ElementProxyEquality, IdentityWeakSet
26
27
  from docx.styles import BabelFish
27
28
 
28
29
  if TYPE_CHECKING:
@@ -52,12 +53,12 @@ _XML_INCOMPATIBLE_MESSAGE = (
52
53
  # Session -> every live ``_LatentStyle``, read or added: deleting one moves the
53
54
  # others of its name after it up one place (:func:`_removed`), as python-docx's
54
55
  # are elements a deletion elsewhere does not move. The sets hold them weakly.
55
- _LIVE: "weakref.WeakKeyDictionary[Any, weakref.WeakSet[_LatentStyle]]" = weakref.WeakKeyDictionary()
56
+ _LIVE: "weakref.WeakKeyDictionary[Any, IdentityWeakSet[_LatentStyle]]" = weakref.WeakKeyDictionary()
56
57
 
57
58
 
58
59
  def _track(latent_style: "_LatentStyle") -> None:
59
60
  try:
60
- _LIVE.setdefault(latent_style._session, weakref.WeakSet()).add(latent_style)
61
+ _LIVE.setdefault(latent_style._session, IdentityWeakSet()).add(latent_style)
61
62
  except TypeError: # no session, or one that takes no weak reference
62
63
  return
63
64
 
@@ -67,6 +68,7 @@ def _removed(deleted: "_LatentStyle", name: Any) -> None:
67
68
  that name after it move up one place, and another object of the same
68
69
  exception is out of the document, writing nothing to it, as python-docx's
69
70
  removed element is."""
71
+ deleted._element = removed = object()
70
72
  try:
71
73
  live = _LIVE.get(deleted._session)
72
74
  except TypeError:
@@ -78,6 +80,7 @@ def _removed(deleted: "_LatentStyle", name: Any) -> None:
78
80
  continue
79
81
  if other._occurrence == deleted._occurrence:
80
82
  other._detached = True
83
+ other._element = removed
81
84
  elif other._occurrence > deleted._occurrence:
82
85
  other._occurrence -= 1
83
86
 
@@ -140,13 +143,17 @@ def _int(text: object) -> int | None:
140
143
  return None
141
144
 
142
145
 
143
- class LatentStyles:
146
+ class LatentStyles(ElementProxyEquality):
144
147
  """The default behaviors for latent styles in this document, and the
145
148
  |_LatentStyle| objects that override them for a named latent style."""
146
149
 
147
150
  def __init__(self, *, session: "Session | None" = None) -> None:
148
151
  self._session: "Session | None" = session
149
152
 
153
+ def _proxy_element(self) -> tuple[object, ...]:
154
+ # python-docx's LatentStyles wraps the styles part's w:latentStyles.
155
+ return ("w:latentStyles", self._session)
156
+
150
157
  def _read(self, prop: str | None) -> dict[str, Any]:
151
158
  """The latent styles docx-studio reports; a read of ``prop`` from one
152
159
  that reports none warns (iterating, an empty collection, does not)."""
@@ -246,7 +253,7 @@ class LatentStyles:
246
253
  self._set_default("load_count", "count", None if value is None else int(value))
247
254
 
248
255
 
249
- class _LatentStyle:
256
+ class _LatentStyle(ElementProxyEquality):
250
257
  """A ``w:lsdException``: display behaviors for a built-in style the
251
258
  document does not define yet, overriding the |LatentStyles| defaults."""
252
259
 
@@ -260,8 +267,18 @@ class _LatentStyle:
260
267
  #: Removed through another object of the same exception: like
261
268
  #: python-docx's element out of the part, it writes nothing to the document.
262
269
  self._detached = False
270
+ #: The exception it held once removed, which its other objects hold too.
271
+ self._element: object | None = None
263
272
  _track(self)
264
273
 
274
+ def _proxy_element(self) -> tuple[object, ...]:
275
+ # python-docx's _LatentStyle wraps its w:lsdException: the exception
276
+ # of its name at its place among them, or, removed, that exception, as
277
+ # its other objects are.
278
+ if self._detached or self._exception is None:
279
+ return ("w:lsdException", self._element if self._element is not None else id(self))
280
+ return ("w:lsdException", self._session, self._exception.get("name"), self._occurrence)
281
+
265
282
  def _target(self) -> dict[str, Any]:
266
283
  """The exception's address in ``EditLatentStyles``."""
267
284
  name = self._exception.get("name")