athena-python-docx 0.23.0__tar.gz → 0.24.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 (372) hide show
  1. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/PKG-INFO +1 -1
  2. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/__init__.py +1 -1
  3. athena_python_docx-0.24.0/docx/_run_order.py +217 -0
  4. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/commands.py +19 -2
  5. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/shape.py +89 -12
  6. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/text/paragraph.py +9 -0
  7. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/text/run.py +106 -50
  8. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/pyproject.toml +1 -1
  9. athena_python_docx-0.24.0/tests/test_inline_shape_alt_text.py +230 -0
  10. athena_python_docx-0.24.0/tests/test_run_identity.py +306 -0
  11. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_run_mark_inheritance.py +76 -0
  12. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_wire_contract.py +6 -4
  13. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/.gitignore +0 -0
  14. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/AGENTS.md +0 -0
  15. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/CLAUDE.md +0 -0
  16. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/DOCX_EXEC_LAB.md +0 -0
  17. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/README.md +0 -0
  18. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/_athena_extension.py +0 -0
  19. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/_batching.py +0 -0
  20. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/_buffer.py +0 -0
  21. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/_citations.py +0 -0
  22. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/_execution.py +0 -0
  23. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/_http.py +0 -0
  24. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/_http_doc.py +0 -0
  25. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/_image_utils.py +0 -0
  26. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/_postproc.py +0 -0
  27. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/_ptc.py +0 -0
  28. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/_references.py +0 -0
  29. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/_table_styles.py +0 -0
  30. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/_timeouts.py +0 -0
  31. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/api.py +0 -0
  32. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/bookmarks.py +0 -0
  33. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/charts.py +0 -0
  34. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/client.py +0 -0
  35. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/comments.py +0 -0
  36. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/document.py +0 -0
  37. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/enum/__init__.py +0 -0
  38. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/enum/section.py +0 -0
  39. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/enum/shape.py +0 -0
  40. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/enum/style.py +0 -0
  41. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/enum/table.py +0 -0
  42. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/enum/text.py +0 -0
  43. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/errors.py +0 -0
  44. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/exceptions.py +0 -0
  45. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/fields.py +0 -0
  46. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/footnotes.py +0 -0
  47. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/math.py +0 -0
  48. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/opc/__init__.py +0 -0
  49. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/opc/coreprops.py +0 -0
  50. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/oxml/__init__.py +0 -0
  51. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/revisions.py +0 -0
  52. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/sdt.py +0 -0
  53. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/section.py +0 -0
  54. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/session.py +0 -0
  55. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/settings.py +0 -0
  56. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/shared.py +0 -0
  57. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/styles/__init__.py +0 -0
  58. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/styles/style.py +0 -0
  59. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/styles/styles.py +0 -0
  60. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/table.py +0 -0
  61. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/text/__init__.py +0 -0
  62. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/text/font.py +0 -0
  63. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/text/hyperlink.py +0 -0
  64. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/text/pagebreak.py +0 -0
  65. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/text/parfmt.py +0 -0
  66. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/text/tabstops.py +0 -0
  67. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/toc.py +0 -0
  68. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/docx/typing.py +0 -0
  69. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/scripts/docx_exec_lab.py +0 -0
  70. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/scripts/docx_exec_lab_examples/fast_table_fill.py +0 -0
  71. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/scripts/docx_exec_lab_examples/find_replace_literal.py +0 -0
  72. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/scripts/docx_exec_lab_server.py +0 -0
  73. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/scripts/dump_wire_fixtures.py +0 -0
  74. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/scripts/release.sh +0 -0
  75. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/scripts/round_trip_smoke.py +0 -0
  76. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/scripts/smoke_test_block_not_found.py +0 -0
  77. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/scripts/validate_find_replace_asset.py +0 -0
  78. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/__init__.py +0 -0
  79. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/conftest.py +0 -0
  80. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/METHODOLOGY.md +0 -0
  81. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/README.md +0 -0
  82. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/__init__.py +0 -0
  83. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/ab_probe_cases.py +0 -0
  84. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/ab_probe_runner.py +0 -0
  85. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/auto_gen_cases.py +0 -0
  86. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/binary_round_trip.py +0 -0
  87. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/cases.py +0 -0
  88. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/complex_cases.py +0 -0
  89. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/coverage_report.py +0 -0
  90. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/extract.py +0 -0
  91. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/extreme_cases.py +0 -0
  92. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/fake_session.py +0 -0
  93. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/firm_templates/README.md +0 -0
  94. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/firm_templates/__init__.py +0 -0
  95. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/firm_templates/_runner.py +0 -0
  96. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/firm_templates/extractor.py +0 -0
  97. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/firm_templates/test_pw_corpus.py +0 -0
  98. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/firm_templates/test_pw_research_digest.py +0 -0
  99. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/local_runner.py +0 -0
  100. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/mega_cases.py +0 -0
  101. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshot.py +0 -0
  102. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/01_basic_paragraph.json +0 -0
  103. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/02_multiple_headings.json +0 -0
  104. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/03_runs_with_formatting.json +0 -0
  105. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/04_font_name_and_size.json +0 -0
  106. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/05_font_color_rgb.json +0 -0
  107. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/06_font_character_properties.json +0 -0
  108. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/07_font_subscript_superscript.json +0 -0
  109. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/08_font_highlight.json +0 -0
  110. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/09_paragraph_alignment.json +0 -0
  111. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/100_table_negative_indexing.json +0 -0
  112. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/101_table_cells_flat_iteration.json +0 -0
  113. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/102_text_with_embedded_special_chars.json +0 -0
  114. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/104_core_properties_datetime.json +0 -0
  115. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/105_default_one_section.json +0 -0
  116. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/106_heading_paragraph_format.json +0 -0
  117. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/107_varying_row_heights.json +0 -0
  118. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/10_paragraph_indents.json +0 -0
  119. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/11_paragraph_spacing.json +0 -0
  120. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/12_paragraph_keep_options.json +0 -0
  121. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/13_paragraph_tab_stops.json +0 -0
  122. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/14_run_add_tab_and_break.json +0 -0
  123. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/15_run_add_break_page.json +0 -0
  124. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/16_paragraph_clear_and_insert_before.json +0 -0
  125. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/17_table_basic.json +0 -0
  126. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/18_table_cell_text.json +0 -0
  127. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/19_table_row_column_sizing.json +0 -0
  128. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/20_table_cell_vertical_alignment.json +0 -0
  129. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/21_table_alignment_and_autofit.json +0 -0
  130. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/22_table_cell_paragraphs_iteration.json +0 -0
  131. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/24_table_add_row_column.json +0 -0
  132. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/25_table_merge_cells.json +0 -0
  133. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/26_section_page_setup.json +0 -0
  134. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/27_section_margins.json +0 -0
  135. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/28_section_add_new.json +0 -0
  136. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/29_section_headers_linked.json +0 -0
  137. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/30_styles_iteration.json +0 -0
  138. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/31_styles_lookup_and_default.json +0 -0
  139. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/32_styles_add_paragraph_style.json +0 -0
  140. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/33_core_properties_set_and_get.json +0 -0
  141. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/34_inline_shapes_iterate_empty.json +0 -0
  142. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/35_full_report.json +0 -0
  143. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/36_replace_text_in_paragraph.json +0 -0
  144. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/37_iterate_runs_and_format_all_bold.json +0 -0
  145. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/38_font_all_properties.json +0 -0
  146. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/39_large_body_100_paragraphs.json +0 -0
  147. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/40_large_table_10x10.json +0 -0
  148. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/41_unicode_and_emoji.json +0 -0
  149. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/42_very_long_paragraph.json +0 -0
  150. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/43_paragraph_text_round_trip.json +0 -0
  151. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/44_paragraph_alignment_round_trip.json +0 -0
  152. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/45_cell_text_round_trip.json +0 -0
  153. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/46_run_text_setter_round_trip.json +0 -0
  154. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/47_font_size_round_trip.json +0 -0
  155. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/48_font_color_round_trip.json +0 -0
  156. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/49_resume_layout.json +0 -0
  157. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/50_multi_section_doc.json +0 -0
  158. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/52_iterate_everything.json +0 -0
  159. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/53_apply_style_to_paragraphs.json +0 -0
  160. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/54_empty_everything.json +0 -0
  161. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/55_single_character_runs.json +0 -0
  162. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/56_everything_in_one.json +0 -0
  163. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/57_runs_after_multiple_text_appends.json +0 -0
  164. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/58_modify_runs_in_place.json +0 -0
  165. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/59_indent_round_trip.json +0 -0
  166. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/60_space_round_trip.json +0 -0
  167. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/61_cell_paragraph_with_runs.json +0 -0
  168. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/62_many_cell_paragraphs.json +0 -0
  169. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/63_table_style_round_trip.json +0 -0
  170. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/64_many_sections.json +0 -0
  171. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/65_20x20_table_formatted.json +0 -0
  172. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/66_toc_like_structure.json +0 -0
  173. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/67_paragraph_insert_before_chain.json +0 -0
  174. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/68_invoice.json +0 -0
  175. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/69_newsletter.json +0 -0
  176. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/70_add_and_iterate_back.json +0 -0
  177. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/71_academic_paper.json +0 -0
  178. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/72_legal_contract.json +0 -0
  179. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/73_form_with_many_tables.json +0 -0
  180. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/74_paragraph_with_10_runs.json +0 -0
  181. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/75_paragraph_negative_first_line_indent.json +0 -0
  182. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/76_rgbcolor_from_string.json +0 -0
  183. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/77_length_unit_conversions.json +0 -0
  184. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/78_paragraph_copy_style.json +0 -0
  185. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/79_bulk_cell_formatting.json +0 -0
  186. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/80_apply_style_after_add_run.json +0 -0
  187. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/81_multi_page_with_breaks.json +0 -0
  188. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/82_add_text_on_existing_run.json +0 -0
  189. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/83_clear_then_repopulate_paragraph.json +0 -0
  190. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/84_table_reread_row_count.json +0 -0
  191. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/85_header_footer_access.json +0 -0
  192. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/86_font_read_unset_returns_none.json +0 -0
  193. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/87_500_paragraph_doc.json +0 -0
  194. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/88_mixed_content_iteration.json +0 -0
  195. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/89_alignment_clear_via_none.json +0 -0
  196. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/90_cell_add_paragraph_styled.json +0 -0
  197. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/91_many_small_tables.json +0 -0
  198. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/92_margins_every_section.json +0 -0
  199. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/93_font_bool_reads_after_set.json +0 -0
  200. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/94_page_break_before_paragraph.json +0 -0
  201. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/95_paragraph_hyperlinks_empty.json +0 -0
  202. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/96_paragraph_contains_page_break.json +0 -0
  203. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/97_document_styles_by_key.json +0 -0
  204. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/98_style_contains_check.json +0 -0
  205. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/99_run_add_picture_from_bytes.json +0 -0
  206. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/ex02_unicode_everywhere.json +0 -0
  207. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/ex03_1000_paragraphs.json +0 -0
  208. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/ex04_50x50_table.json +0 -0
  209. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/ex05_long_text_in_cell.json +0 -0
  210. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/ex06_hundred_tiny_runs.json +0 -0
  211. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/ex07_every_font_boolean.json +0 -0
  212. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/ex08_many_continuous_sections.json +0 -0
  213. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/ex09_many_tab_stops.json +0 -0
  214. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/ex10_complex_bom.json +0 -0
  215. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/ex11_banded_rows_formatting.json +0 -0
  216. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/ex12_section_reconfigure.json +0 -0
  217. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/ex13_cell_with_10_paragraphs.json +0 -0
  218. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/ex14_styled_report_table.json +0 -0
  219. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/ex15_paragraph_all_format_props.json +0 -0
  220. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/ex16_runs_interleaved_with_breaks.json +0 -0
  221. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/ex17_all_break_kinds.json +0 -0
  222. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/ex18_read_back_large_doc.json +0 -0
  223. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/ex19_mutate_all_runs.json +0 -0
  224. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/ex20_kitchen_sink_v2.json +0 -0
  225. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/mega01_book_chapter.json +0 -0
  226. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/mega02_research_proposal.json +0 -0
  227. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/mega03_financial_statement.json +0 -0
  228. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/mega04_recipe_card.json +0 -0
  229. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/mega05_user_manual.json +0 -0
  230. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/mega06_complex_newsletter.json +0 -0
  231. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/mega07_budget_spreadsheet.json +0 -0
  232. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/mega08_product_catalog.json +0 -0
  233. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/mega09_signed_contract.json +0 -0
  234. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/mega10_api_documentation.json +0 -0
  235. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/rw01_official_quickstart.json +0 -0
  236. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/rw02_paragraph_style_list.json +0 -0
  237. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/rw03_character_formatting.json +0 -0
  238. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/rw04_section_page_setup.json +0 -0
  239. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/rw05_toc_pattern.json +0 -0
  240. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/rw06_meeting_minutes.json +0 -0
  241. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/rw07_dense_formatting_demo.json +0 -0
  242. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/rw08_table_merged_header.json +0 -0
  243. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/rw09_bulk_run_iteration.json +0 -0
  244. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/rw10_colored_grid_table.json +0 -0
  245. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/rw11_header_text.json +0 -0
  246. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/rw12_first_page_footer.json +0 -0
  247. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/rw13_even_page_header.json +0 -0
  248. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/op_snapshots/rw15_paragraph_style_instance.json +0 -0
  249. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/ours_spec.json +0 -0
  250. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/parity_crawl.py +0 -0
  251. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/parity_diff.json +0 -0
  252. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/real_world_cases.py +0 -0
  253. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/round_trip_tests.py +0 -0
  254. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/stock_spec.json +0 -0
  255. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/fidelity/test_e2e_against_staging.py +0 -0
  256. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/parity/README.md +0 -0
  257. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/parity/__init__.py +0 -0
  258. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/parity/baseline_gaps.json +0 -0
  259. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/parity/compare.py +0 -0
  260. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/parity/intentional_deviations.json +0 -0
  261. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/parity/introspect.py +0 -0
  262. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/parity/reports/GAP_ANALYSIS.md +0 -0
  263. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/parity/reports/gap_report.json +0 -0
  264. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/parity/run_parity.py +0 -0
  265. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/parity/snapshots/athena_latest.json +0 -0
  266. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/parity/snapshots/upstream_python_docx_1.2.0.json +0 -0
  267. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/parity/test_parity_gap.py +0 -0
  268. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_add_section_extract_items.py +0 -0
  269. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_athena_extension_creates_session_open.py +0 -0
  270. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_athena_extensions_contract.py +0 -0
  271. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_athena_extensions_registry.py +0 -0
  272. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_batching_perf.py +0 -0
  273. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_block_not_found_error.py +0 -0
  274. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_buffer.py +0 -0
  275. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_cell_add_paragraph_wire_shape.py +0 -0
  276. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_cell_add_table_not_supported.py +0 -0
  277. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_cell_fastpath_runs.py +0 -0
  278. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_cell_inner_add_hyperlink_stash.py +0 -0
  279. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_cell_inner_add_run_via_cell_insert.py +0 -0
  280. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_cell_inner_format_stash.py +0 -0
  281. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_cell_inner_run_format_stash.py +0 -0
  282. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_cell_inner_run_guard.py +0 -0
  283. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_cell_text_plain_fastpath.py +0 -0
  284. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_cell_text_replace_semantics.py +0 -0
  285. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_citations.py +0 -0
  286. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_collapsed_range_format.py +0 -0
  287. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_command_dataclasses.py +0 -0
  288. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_commands.py +0 -0
  289. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_comments.py +0 -0
  290. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_document_asset_id_property.py +0 -0
  291. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_document_clear.py +0 -0
  292. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_document_create.py +0 -0
  293. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_document_create_from_template.py +0 -0
  294. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_document_factory_validation.py +0 -0
  295. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_docx_exec_lab.py +0 -0
  296. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_docx_exec_lab_server.py +0 -0
  297. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_e2e_partial_failure_cascade.py +0 -0
  298. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_execution_scope.py +0 -0
  299. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_find_replace_session_open.py +0 -0
  300. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_http_transport.py +0 -0
  301. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_hyperlink_coalescing.py +0 -0
  302. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_image_url_data_uri.py +0 -0
  303. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_insert_deferred.py +0 -0
  304. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_iter_inner_content.py +0 -0
  305. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_list_styles.py +0 -0
  306. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_merged_cell_secondary_slot.py +0 -0
  307. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_merged_cells.py +0 -0
  308. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_oxml_shim.py +0 -0
  309. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_paragraph_text_len_cache.py +0 -0
  310. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_parity_misc.py +0 -0
  311. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_parity_round2.py +0 -0
  312. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_partial_failure_cascade.py +0 -0
  313. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_phase_a_behavior.py +0 -0
  314. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_phase_b_headers_footers.py +0 -0
  315. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_phase_c_tables.py +0 -0
  316. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_positional_cell_id.py +0 -0
  317. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_postproc_cell_format_rewrite.py +0 -0
  318. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_postproc_cell_run_format_rewrite.py +0 -0
  319. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_postproc_ref_restore.py +0 -0
  320. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_pr19766_review_fixes.py +0 -0
  321. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_ptc.py +0 -0
  322. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_python_docx_api_parity.py +0 -0
  323. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_revisions.py +0 -0
  324. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_run_add_picture_anchor.py +0 -0
  325. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_add_paragraph_style.py +0 -0
  326. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_add_picture.py +0 -0
  327. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_add_run.py +0 -0
  328. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_cell_add_paragraph.py +0 -0
  329. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_comments_add_comment.py +0 -0
  330. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_comments_get.py +0 -0
  331. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_document_audit.py +0 -0
  332. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_document_element.py +0 -0
  333. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_enum_section.py +0 -0
  334. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_font_audit.py +0 -0
  335. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_header_footer.py +0 -0
  336. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_hyperlink.py +0 -0
  337. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_inline_shape.py +0 -0
  338. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_insert_paragraph_before.py +0 -0
  339. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_misc.py +0 -0
  340. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_paragraph_strict.py +0 -0
  341. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_paragraph_style.py +0 -0
  342. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_paragraph_style_strict.py +0 -0
  343. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_parfmt.py +0 -0
  344. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_row_col_cell.py +0 -0
  345. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_run_add_break.py +0 -0
  346. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_run_bool_setters.py +0 -0
  347. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_run_style.py +0 -0
  348. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_run_style_strict.py +0 -0
  349. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_run_text.py +0 -0
  350. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_run_underline.py +0 -0
  351. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_section_audit.py +0 -0
  352. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_section_dimensions.py +0 -0
  353. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_section_onoff.py +0 -0
  354. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_settings.py +0 -0
  355. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_shared_audit.py +0 -0
  356. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_style.py +0 -0
  357. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_styles.py +0 -0
  358. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_table_audit.py +0 -0
  359. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_table_cell.py +0 -0
  360. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_table_dimensions.py +0 -0
  361. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_silent_stub_table_layout.py +0 -0
  362. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_smoke_integration.py +0 -0
  363. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_style_acceptance.py +0 -0
  364. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_style_font.py +0 -0
  365. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_style_setters_contract.py +0 -0
  366. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_table_set_cell_perf.py +0 -0
  367. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_table_style_id_resolution.py +0 -0
  368. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_temporarily_unavailable.py +0 -0
  369. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_validate_find_replace_asset_script.py +0 -0
  370. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_xml_attr_guard.py +0 -0
  371. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/tests/test_zod_wire_contract.py +0 -0
  372. {athena_python_docx-0.23.0 → athena_python_docx-0.24.0}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: athena-python-docx
3
- Version: 0.23.0
3
+ Version: 0.24.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.23.0"
9
+ __version__ = "0.24.0"
10
10
 
11
11
  from docx.api import Document
12
12
  from docx._buffer import discard_all, flush_all
@@ -0,0 +1,217 @@
1
+ """Run order of a paragraph, as ``Paragraph.add_run`` created its runs.
2
+
3
+ A picture takes no text offset, so two runs can end at the same offset:
4
+ ``r1 = p.add_run("A"); r2 = p.add_run(); r2.add_picture(img)`` puts ``r2`` and
5
+ its picture at offset 1, where ``r1`` ends. The offset alone cannot tell the
6
+ server whether content for ``r1`` goes before or after that picture. The SDK
7
+ knows: ``add_run`` appends each run to the end of its paragraph.
8
+
9
+ This module keeps a record of each such run (its range and the pictures that
10
+ its ``add_picture`` added), in creation order, and gives:
11
+
12
+ - the run identity of a run-end insert (:func:`run_ref`): the first picture
13
+ that a later run holds at the same offset (for a read segment that ends
14
+ inside its run, also the run's own picture there). The server puts the
15
+ content in front of it; without it, after the pictures at the offset.
16
+ - current ranges: when a run grows or shrinks, its pictures and the runs after
17
+ it move (:func:`note_length_change`), and so do the live run proxies. A
18
+ replace cuts every record that it touches.
19
+
20
+ A record lives as long as its paragraph proxy, not as long as its run proxy,
21
+ so ``p.add_run().add_picture(img)`` keeps the picture's place. The records of
22
+ every paragraph proxy of one block (``doc.paragraphs`` makes new ones) are one
23
+ order. A read run (``paragraph.runs``) stands for the recorded run that holds
24
+ its last character; a read run over text that no recorded run holds counts as
25
+ a run before all of them. The order lives in the SDK process only; the
26
+ document stores none of it.
27
+ """
28
+
29
+ from __future__ import annotations
30
+
31
+ import itertools
32
+ import weakref
33
+ from dataclasses import dataclass, field
34
+ from typing import TYPE_CHECKING, Any
35
+
36
+ if TYPE_CHECKING:
37
+ from docx.text.run import Run
38
+
39
+ _SEQ = itertools.count()
40
+
41
+
42
+ @dataclass(eq=False)
43
+ class RunRecord:
44
+ """One run that ``add_run`` created."""
45
+
46
+ seq: int
47
+ range: tuple[int, int]
48
+ run: "weakref.ref[Run]"
49
+ # ``(picture id, offset)`` of each picture that the run's ``add_picture`` added.
50
+ pictures: list[tuple[str, int]] = field(default_factory=list)
51
+
52
+
53
+ # Paragraph proxy -> the records of the runs its ``add_run`` created. A record
54
+ # holds no reference to the paragraph or session, so an entry goes with its
55
+ # paragraph proxy. Keyed by the proxy, not by its id: the first flush moves a
56
+ # new paragraph from its client id to the server id, and the runs created
57
+ # before that keep the client id.
58
+ _ORDERS: "weakref.WeakKeyDictionary[Any, list[RunRecord]]" = weakref.WeakKeyDictionary()
59
+
60
+
61
+ def _records_of(run: "Run") -> list[RunRecord]:
62
+ paragraph = getattr(run, "_paragraph", None)
63
+ ids = {run._block_id}
64
+ if paragraph is not None:
65
+ ids.add(paragraph._node_id)
66
+ records: list[RunRecord] = []
67
+ for owner, owner_records in list(_ORDERS.items()):
68
+ if owner is paragraph or (owner._session is run._session and owner._node_id in ids):
69
+ records.extend(owner_records)
70
+ records.sort(key=lambda record: record.seq)
71
+ return records
72
+
73
+
74
+ def register_run(run: "Run") -> None:
75
+ """Record ``run`` as the last run of its paragraph (``Paragraph.add_run``)."""
76
+ record = RunRecord(seq=next(_SEQ), range=run._range, run=weakref.ref(run))
77
+ _ORDERS.setdefault(run._paragraph, []).append(record)
78
+ run._run_record = record
79
+
80
+
81
+ def forget_paragraph(paragraph: Any) -> None:
82
+ """Drop the order of a paragraph whose runs are gone (``Paragraph.text = ...``)."""
83
+ for owner in list(_ORDERS.keys()):
84
+ if owner is paragraph or (owner._session is paragraph._session and owner._node_id == paragraph._node_id):
85
+ _ORDERS.pop(owner, None)
86
+
87
+
88
+ def _place(
89
+ run: "Run", span: tuple[int, int], records: list[RunRecord] | None = None
90
+ ) -> tuple[RunRecord | None, list[RunRecord]]:
91
+ """The record of ``run`` (over ``span``), if any, and the records after it."""
92
+ if records is None:
93
+ records = _records_of(run)
94
+ # The run itself, or the text that its ``add_text`` returned.
95
+ own = getattr(run, "_run_record", None) or getattr(run, "_owner_record", None)
96
+ for index, record in enumerate(records):
97
+ if record is own:
98
+ return record, records[index + 1 :]
99
+ # ``paragraph.runs`` makes a new proxy of a kept run: over the same range,
100
+ # or over a part of it (a read splits a run at a tab, a break or a change
101
+ # of format). The proxy stands for the run that holds its last character.
102
+ if span[0] != span[1]:
103
+ last = span[1] - 1
104
+ for index, record in enumerate(records):
105
+ if record.range[0] <= last < record.range[1]:
106
+ return record, records[index + 1 :]
107
+ return None, records
108
+
109
+
110
+ def _set_range(record: RunRecord, value: tuple[int, int]) -> None:
111
+ record.range = value
112
+ proxy = record.run()
113
+ if proxy is not None:
114
+ proxy._range = value
115
+
116
+
117
+ def note_length_change(
118
+ run: "Run",
119
+ at: int,
120
+ delta: int,
121
+ *,
122
+ replaced: tuple[int, int] | None = None,
123
+ before: str | None = None,
124
+ ) -> None:
125
+ """``run`` (already over its new range) changed its text by ``delta`` units.
126
+
127
+ Without ``replaced``: an insert of ``delta`` units at ``at`` (the end of
128
+ ``run``), in front of the picture ``before`` when the command named one
129
+ (else after the pictures at ``at``). With ``replaced``: ``Run.text``
130
+ replaced the old range ``replaced``; the server keeps the pictures at its
131
+ start and end and removes the ones inside.
132
+
133
+ The text belongs to the record of ``run`` (see :func:`_place`). Every
134
+ record that the replaced range touches is cut; the records and pictures
135
+ after the change move.
136
+ """
137
+ if delta == 0 and replaced is None:
138
+ return
139
+ records = _records_of(run)
140
+ if replaced is None:
141
+ start = end = at
142
+ inserted = delta
143
+ old_span = (run._range[0], run._range[1] - delta)
144
+ else:
145
+ start, end = replaced
146
+ inserted = (end - start) + delta
147
+ old_span = replaced
148
+ owner = _place(run, old_span, records)[0]
149
+ owner_index = records.index(owner) if owner is not None else -1
150
+ removed = end - start
151
+
152
+ def cut(x: int) -> int:
153
+ return x if x <= start else start if x < end else x - removed
154
+
155
+ # The pictures at ``at`` that an insert goes in front of: ``before`` and
156
+ # the ones after it, in document order (records in order, then the
157
+ # pictures of each record in order).
158
+ moved_at: set[str] = set()
159
+ if replaced is None and before is not None:
160
+ order = [pid for record in records for pid, off in record.pictures if off == at]
161
+ if before in order:
162
+ moved_at = set(order[order.index(before) :])
163
+
164
+ for index, record in enumerate(records):
165
+ rec_start, rec_end = cut(record.range[0]), cut(record.range[1])
166
+ if record is owner:
167
+ rec_end += inserted
168
+ elif index > owner_index and rec_start >= start:
169
+ rec_start, rec_end = rec_start + inserted, rec_end + inserted
170
+ _set_range(record, (rec_start, rec_end))
171
+ pictures: list[tuple[str, int]] = []
172
+ for pid, off in record.pictures:
173
+ if replaced is None:
174
+ pictures.append((pid, off + delta if off > at or pid in moved_at else off))
175
+ elif off <= start:
176
+ pictures.append((pid, off))
177
+ elif off >= end:
178
+ pictures.append((pid, off + delta))
179
+ # The moves keep document order; a stable sort by offset keeps it so.
180
+ pictures.sort(key=lambda item: item[1])
181
+ record.pictures = pictures
182
+
183
+
184
+ def note_picture(run: "Run", picture_id: str, offset: int, *, before: str | None = None) -> None:
185
+ """``run.add_picture`` put the picture ``picture_id`` at ``offset``, in front of ``before``.
186
+
187
+ A record keeps its pictures in document order: the new one goes in front
188
+ of ``before``, else after the pictures at ``offset`` and before the ones
189
+ after it (the server puts a picture after the pictures at its offset).
190
+ """
191
+ record = _place(run, run._range)[0]
192
+ if record is None:
193
+ return
194
+ ids = [pid for pid, _ in record.pictures]
195
+ if before in ids:
196
+ index = ids.index(before)
197
+ else:
198
+ index = next((i for i, (_, off) in enumerate(record.pictures) if off > offset), len(ids))
199
+ record.pictures.insert(index, (picture_id, offset))
200
+
201
+
202
+ def run_ref(run: "Run") -> dict[str, str] | None:
203
+ """``{"beforeImageId": id}``: the picture that an insert at the end of ``run`` goes in front of.
204
+
205
+ The first picture of a later run where ``run`` ends. A read segment that
206
+ ends inside its run (a picture of the run between two of its texts) also
207
+ puts the insert in front of the run's own picture there, right after the
208
+ segment's text.
209
+ """
210
+ end = run._range[1]
211
+ record, later = _place(run, run._range)
212
+ candidates = ([record] if record is not None and end < record.range[1] else []) + later
213
+ for candidate in candidates:
214
+ for picture_id, offset in candidate.pictures:
215
+ if offset == end:
216
+ return {"beforeImageId": picture_id}
217
+ return None
@@ -109,12 +109,19 @@ class CreateTable(Command):
109
109
  client_node_id: str | None = None
110
110
 
111
111
 
112
+ # Run identity of a run-end insert (``Run.add_text`` / ``add_tab`` /
113
+ # ``add_break`` / ``add_picture``, ``Run.text`` on an empty run):
114
+ # ``{"beforeImageId": <picture id>}``, the first picture that a later run
115
+ # holds at the same offset (see ``docx._run_order``). The server puts the
116
+ # content in front of it. ``None`` (not sent): after the pictures there.
117
+ # ``Insert``, ``InsertTab`` and ``InsertLineBreak`` carry it too.
112
118
  @dataclass
113
119
  class CreateImage(Command):
114
120
  src: str
115
121
  size: dict[str, Any]
116
122
  at: dict[str, Any]
117
123
  client_node_id: str | None = None
124
+ run: dict[str, Any] | None = None
118
125
 
119
126
 
120
127
  @dataclass
@@ -142,6 +149,7 @@ class Insert(Command):
142
149
  inherit_marks: bool | None = None
143
150
  placement: str | None = None
144
151
  content: dict[str, Any] | None = None
152
+ run: dict[str, Any] | None = None
145
153
 
146
154
 
147
155
  @dataclass
@@ -181,12 +189,14 @@ class Replace(Command):
181
189
  class InsertLineBreak(Command):
182
190
  block_id: str
183
191
  offset: int
192
+ run: dict[str, Any] | None = None
184
193
 
185
194
 
186
195
  @dataclass
187
196
  class InsertTab(Command):
188
197
  block_id: str
189
198
  offset: int
199
+ run: dict[str, Any] | None = None
190
200
 
191
201
 
192
202
  @dataclass
@@ -490,10 +500,15 @@ class SetImageSize(Command):
490
500
  class SetImageAltText(Command):
491
501
  """Set alt-text on an inline image. Mirrors DOCX Studio's
492
502
  ``doc.images.setAltText``. Used by accessibility flows that need
493
- a text alternative for screen readers."""
503
+ a text alternative for screen readers.
504
+
505
+ ``alt_text`` is Word's description (``wp:docPr/@descr``). ``title`` is
506
+ Word's title (``wp:docPr/@title``); ``None`` leaves it unchanged, and an
507
+ older docx-studio ignores the field."""
494
508
 
495
509
  image_id: str
496
510
  alt_text: str
511
+ title: str | None = None
497
512
 
498
513
 
499
514
  @dataclass
@@ -551,7 +566,9 @@ class GetNode(Command):
551
566
 
552
567
  @dataclass
553
568
  class ImagesList(Command):
554
- pass
569
+ # ``False`` leaves out each picture's ``src`` (a data URI can be MBs); an
570
+ # older docx-studio ignores the field and sends ``src``.
571
+ include_src: bool | None = None
555
572
 
556
573
 
557
574
  @dataclass
@@ -65,6 +65,19 @@ def _strip_data_uri(src: str) -> tuple[bytes, str | None]:
65
65
  return b"", mime
66
66
 
67
67
 
68
+ def _picture_id_parts(node_id: str) -> tuple[str, str, str | None]:
69
+ """``(paraId, fingerprint, persisted id)`` of a picture id.
70
+
71
+ A picture id is ``<paraId>:<index>:<fingerprint>``, with a fourth part
72
+ ``:<persisted id>`` when the room stores one; an older docx-studio gives
73
+ only ``<paraId>`` or ``<paraId>:<index>``.
74
+ """
75
+ parts = node_id.split(":")
76
+ fingerprint = parts[2] if len(parts) > 2 else ""
77
+ persisted = parts[3] if len(parts) > 3 else None
78
+ return parts[0], fingerprint, persisted
79
+
80
+
68
81
  class InlineShape:
69
82
  """An inline image/shape in the document."""
70
83
 
@@ -177,15 +190,75 @@ class InlineShape:
177
190
  @alt_text.setter
178
191
  @athena_extension(issue="PR#1530", description="InlineShape.alt_text setter.")
179
192
  def alt_text(self, value: str | None) -> None:
193
+ text = "" if value is None else str(value)
194
+ if self._can_address(stacklevel=3):
195
+ self._send_alt_text(alt_text=text, title=None)
196
+ self._info["altText"] = text
197
+
198
+ def _can_address(self, *, stacklevel: int) -> bool:
199
+ """``False`` (with a warning) for a shape that has no id.
200
+
201
+ A listed picture on an older docx-studio, whose ``ImagesList`` sends
202
+ no ``nodeId``, cannot be addressed, and an empty ``imageId`` fails the
203
+ whole batch there. The setter then sends nothing and keeps the old
204
+ value, so the shape does not report a change that the document does
205
+ not have.
206
+ """
207
+ from docx.errors import DocxUnsupportedCommandWarning
208
+
209
+ if self._node_id:
210
+ return True
211
+ warnings.warn(
212
+ "InlineShape alt text / title / decorative was not set: this picture has "
213
+ "no id. Read the shape again from doc.inline_shapes after "
214
+ "docx-studio is updated.",
215
+ DocxUnsupportedCommandWarning,
216
+ stacklevel=stacklevel + 1,
217
+ )
218
+ return False
219
+
220
+ def _send_alt_text(self, *, alt_text: str, title: str | None) -> None:
180
221
  from docx.commands import SetImageAltText
181
222
 
182
- text = "" if value is None else str(value)
183
223
  run_sync(
184
224
  self._session.send_command(
185
- SetImageAltText(image_id=self._node_id, alt_text=text),
225
+ SetImageAltText(image_id=self._node_id, alt_text=alt_text, title=title),
186
226
  ),
187
227
  )
188
- self._info["altText"] = text
228
+
229
+ def _stored_alt_text(self) -> str:
230
+ """The description that the document stores for this picture now.
231
+
232
+ Another shape for the same picture can change the description after
233
+ this shape read it. ``ImagesList`` gives the current value, without
234
+ the image data; the cached value is the fallback when the list does
235
+ not name the picture (an older docx-studio). The read flushes pending
236
+ commands first, so a client id is the real id after it.
237
+ """
238
+ rows = InlineShapes(session=self._session)._items(include_src=False)
239
+ node_id = self._node_id
240
+ para_id, fingerprint, persisted = _picture_id_parts(node_id)
241
+ same: list[dict] = []
242
+ for row in rows:
243
+ row_id = str(row.get("nodeId") or "")
244
+ if row_id == node_id:
245
+ same = [row]
246
+ break
247
+ row_para, row_fingerprint, row_persisted = _picture_id_parts(row_id)
248
+ # A persisted id names one picture, in any paragraph and position.
249
+ if persisted is not None and row_persisted is not None:
250
+ if row_persisted == persisted:
251
+ same = [row]
252
+ break
253
+ continue
254
+ # A room without persisted ids (an older editor removed them):
255
+ # the paragraph and the fingerprint, as the server does.
256
+ if row_para != para_id:
257
+ continue
258
+ if ":" not in node_id or (fingerprint and row_fingerprint == fingerprint):
259
+ same.append(row)
260
+ stored = same[0].get("altText") if len(same) == 1 else None
261
+ return stored if isinstance(stored, str) else self.alt_text
189
262
 
190
263
  @property
191
264
  @athena_extension(issue="PR#1530", description="InlineShape.title — image title.")
@@ -202,14 +275,15 @@ class InlineShape:
202
275
  @title.setter
203
276
  @athena_extension(issue="PR#1530", description="InlineShape.title setter.")
204
277
  def title(self, value: str | None) -> None:
205
- from docx.commands import SetImageAltText
206
-
207
278
  text = "" if value is None else str(value)
208
- run_sync(
209
- self._session.send_command(
210
- SetImageAltText(image_id=self._node_id, alt_text=text),
211
- ),
212
- )
279
+ if not self._can_address(stacklevel=3):
280
+ return
281
+ # The command always carries the description: an older docx-studio
282
+ # requires ``altText`` and ignores ``title``. Sending the stored
283
+ # description keeps it; before, the title text replaced it.
284
+ alt_text = self._stored_alt_text()
285
+ self._send_alt_text(alt_text=alt_text, title=text)
286
+ self._info["altText"] = alt_text
213
287
  self._info["title"] = text
214
288
 
215
289
  @property
@@ -228,6 +302,8 @@ class InlineShape:
228
302
  def decorative(self, value: bool) -> None:
229
303
  from docx.commands import SetImageDecorative
230
304
 
305
+ if not self._can_address(stacklevel=3):
306
+ return
231
307
  run_sync(
232
308
  self._session.send_command(
233
309
  SetImageDecorative(image_id=self._node_id, decorative=bool(value)),
@@ -283,8 +359,9 @@ class InlineShapes:
283
359
  def __init__(self, *, session: "Session") -> None:
284
360
  self._session: "Session" = session
285
361
 
286
- def _items(self) -> list[dict]:
287
- info: object = run_sync(self._session.doc.images.list({}))
362
+ def _items(self, *, include_src: bool = True) -> list[dict]:
363
+ params: dict = {} if include_src else {"includeSrc": False}
364
+ info: object = run_sync(self._session.doc.images.list(params))
288
365
  if isinstance(info, dict):
289
366
  items: object = info.get("items") or info.get("images") or []
290
367
  if isinstance(items, list):
@@ -7,6 +7,7 @@ from typing import TYPE_CHECKING, Any
7
7
 
8
8
  from docx._athena_extension import athena_extension
9
9
  from docx._batching import run_sync
10
+ from docx._run_order import forget_paragraph, register_run
10
11
 
11
12
  if TYPE_CHECKING:
12
13
  from docx._references import AssetReference
@@ -431,6 +432,8 @@ class Paragraph:
431
432
  # We just replaced the entire paragraph contents with ``value``;
432
433
  # the new text-address length is simply ``len(value)``.
433
434
  self._text_len = len(value)
435
+ # The runs of the paragraph are gone, as in python-docx.
436
+ forget_paragraph(self)
434
437
  # Content changed — drop the prefetched snapshot so a follow-up
435
438
  # ``.text`` / ``.runs`` read reflects the replacement.
436
439
  self._invalidate_node_info()
@@ -1232,6 +1235,12 @@ class Paragraph:
1232
1235
  in_cell=self._in_cell,
1233
1236
  cell_ooxml_address=self._cell_ooxml_address,
1234
1237
  )
1238
+ # The paragraph's run order, so a run-end insert at an offset that two
1239
+ # runs share goes to the right run (see ``docx._run_order``).
1240
+ register_run(run_obj)
1241
+ # A new empty run has no formatting of its own yet: its first text
1242
+ # does not take the formatting of the run before it.
1243
+ run_obj._fresh = not text_str
1235
1244
  if style is not None:
1236
1245
  style_id: str = (
1237
1246
  style.style_id if isinstance(style, CharacterStyle) else style