athena-python-docx 0.33.0__tar.gz → 0.34.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 (469) hide show
  1. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/AGENTS.md +133 -29
  2. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/PKG-INFO +1 -1
  3. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/__init__.py +1 -1
  4. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/_capabilities.py +10 -0
  5. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/_http_doc.py +8 -2
  6. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/_postproc.py +10 -1
  7. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/_run_order.py +31 -0
  8. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/commands.py +66 -2
  9. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/enum/base.py +28 -1
  10. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/section.py +9 -24
  11. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/styles/_table.py +6 -4
  12. athena_python_docx-0.34.0/docx/styles/latent.py +337 -0
  13. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/styles/style.py +269 -66
  14. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/styles/styles.py +10 -0
  15. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/table.py +70 -13
  16. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/text/paragraph.py +41 -6
  17. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/text/parfmt.py +70 -41
  18. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/text/run.py +142 -25
  19. athena_python_docx-0.34.0/docx/text/tabstops.py +461 -0
  20. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/pyproject.toml +1 -1
  21. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/ab_probe_cases.py +88 -0
  22. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/fake_session.py +4 -1
  23. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/107_varying_row_heights.json +1 -0
  24. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/13_paragraph_tab_stops.json +1 -0
  25. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/19_table_row_column_sizing.json +1 -0
  26. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/ex09_many_tab_stops.json +1 -0
  27. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/rw18_header_table_properties.json +1 -0
  28. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/live/baseline.json +9 -0
  29. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/live/fixture_scripts.py +50 -0
  30. athena_python_docx-0.34.0/tests/test_alignment_values.py +90 -0
  31. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_field_runs.py +159 -3
  32. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_http_transport.py +1 -1
  33. athena_python_docx-0.34.0/tests/test_latent_style_writes.py +166 -0
  34. athena_python_docx-0.34.0/tests/test_line_clear_break.py +83 -0
  35. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_paragraph_delete.py +1 -0
  36. athena_python_docx-0.34.0/tests/test_parfmt_clears.py +144 -0
  37. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_rendered_page_breaks.py +33 -0
  38. athena_python_docx-0.34.0/tests/test_run_page_number_blocks.py +157 -0
  39. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_parfmt.py +10 -8
  40. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_row_col_cell.py +3 -11
  41. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_section_onoff.py +11 -23
  42. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_table_layout.py +8 -6
  43. athena_python_docx-0.34.0/tests/test_style_delete.py +150 -0
  44. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_style_formatting_writes.py +25 -2
  45. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_style_metadata_writes.py +138 -1
  46. athena_python_docx-0.34.0/tests/test_style_tab_stops.py +207 -0
  47. athena_python_docx-0.34.0/tests/test_tab_stop_writes.py +324 -0
  48. athena_python_docx-0.34.0/tests/test_table_clears.py +128 -0
  49. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_wire_contract.py +8 -0
  50. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/uv.lock +1 -1
  51. athena_python_docx-0.33.0/docx/styles/latent.py +0 -220
  52. athena_python_docx-0.33.0/docx/text/tabstops.py +0 -232
  53. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/.gitignore +0 -0
  54. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/CLAUDE.md +0 -0
  55. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/DOCX_EXEC_LAB.md +0 -0
  56. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/README.md +0 -0
  57. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/_athena_extension.py +0 -0
  58. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/_batching.py +0 -0
  59. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/_buffer.py +0 -0
  60. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/_citations.py +0 -0
  61. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/_execution.py +0 -0
  62. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/_http.py +0 -0
  63. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/_image_utils.py +0 -0
  64. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/_ptc.py +0 -0
  65. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/_references.py +0 -0
  66. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/_table_styles.py +0 -0
  67. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/_timeouts.py +0 -0
  68. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/_tracked.py +0 -0
  69. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/api.py +0 -0
  70. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/blkcntnr.py +0 -0
  71. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/bookmarks.py +0 -0
  72. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/charts.py +0 -0
  73. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/client.py +0 -0
  74. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/comments.py +0 -0
  75. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/document.py +0 -0
  76. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/drawing/__init__.py +0 -0
  77. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/enum/__init__.py +0 -0
  78. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/enum/dml.py +0 -0
  79. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/enum/section.py +0 -0
  80. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/enum/shape.py +0 -0
  81. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/enum/style.py +0 -0
  82. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/enum/table.py +0 -0
  83. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/enum/text.py +0 -0
  84. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/errors.py +0 -0
  85. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/exceptions.py +0 -0
  86. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/fields.py +0 -0
  87. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/footnotes.py +0 -0
  88. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/image/__init__.py +0 -0
  89. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/image/exceptions.py +0 -0
  90. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/image/image.py +0 -0
  91. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/math.py +0 -0
  92. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/opc/__init__.py +0 -0
  93. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/opc/coreprops.py +0 -0
  94. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/oxml/__init__.py +0 -0
  95. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/revisions.py +0 -0
  96. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/sdt.py +0 -0
  97. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/session.py +0 -0
  98. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/settings.py +0 -0
  99. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/shape.py +0 -0
  100. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/shared.py +0 -0
  101. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/styles/__init__.py +0 -0
  102. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/text/__init__.py +0 -0
  103. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/text/font.py +0 -0
  104. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/text/hyperlink.py +0 -0
  105. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/text/pagebreak.py +0 -0
  106. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/toc.py +0 -0
  107. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/docx/typing.py +0 -0
  108. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/scripts/docx_exec_lab.py +0 -0
  109. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/scripts/docx_exec_lab_examples/fast_table_fill.py +0 -0
  110. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/scripts/docx_exec_lab_examples/find_replace_literal.py +0 -0
  111. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/scripts/docx_exec_lab_server.py +0 -0
  112. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/scripts/dump_wire_fixtures.py +0 -0
  113. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/scripts/release.sh +0 -0
  114. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/scripts/round_trip_smoke.py +0 -0
  115. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/scripts/smoke_test_block_not_found.py +0 -0
  116. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/scripts/validate_find_replace_asset.py +0 -0
  117. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/__init__.py +0 -0
  118. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/conftest.py +0 -0
  119. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/METHODOLOGY.md +0 -0
  120. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/README.md +0 -0
  121. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/__init__.py +0 -0
  122. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/ab_probe_runner.py +0 -0
  123. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/auto_gen_cases.py +0 -0
  124. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/binary_round_trip.py +0 -0
  125. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/cases.py +0 -0
  126. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/complex_cases.py +0 -0
  127. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/coverage_report.py +0 -0
  128. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/extract.py +0 -0
  129. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/extreme_cases.py +0 -0
  130. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/firm_templates/README.md +0 -0
  131. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/firm_templates/__init__.py +0 -0
  132. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/firm_templates/_runner.py +0 -0
  133. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/firm_templates/extractor.py +0 -0
  134. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/firm_templates/test_pw_corpus.py +0 -0
  135. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/firm_templates/test_pw_research_digest.py +0 -0
  136. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/local_runner.py +0 -0
  137. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/mega_cases.py +0 -0
  138. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshot.py +0 -0
  139. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/01_basic_paragraph.json +0 -0
  140. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/02_multiple_headings.json +0 -0
  141. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/03_runs_with_formatting.json +0 -0
  142. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/04_font_name_and_size.json +0 -0
  143. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/05_font_color_rgb.json +0 -0
  144. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/06_font_character_properties.json +0 -0
  145. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/07_font_subscript_superscript.json +0 -0
  146. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/08_font_highlight.json +0 -0
  147. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/09_paragraph_alignment.json +0 -0
  148. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/100_table_negative_indexing.json +0 -0
  149. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/101_table_cells_flat_iteration.json +0 -0
  150. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/102_text_with_embedded_special_chars.json +0 -0
  151. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/104_core_properties_datetime.json +0 -0
  152. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/105_default_one_section.json +0 -0
  153. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/106_heading_paragraph_format.json +0 -0
  154. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/10_paragraph_indents.json +0 -0
  155. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/11_paragraph_spacing.json +0 -0
  156. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/12_paragraph_keep_options.json +0 -0
  157. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/14_run_add_tab_and_break.json +0 -0
  158. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/15_run_add_break_page.json +0 -0
  159. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/16_paragraph_clear_and_insert_before.json +0 -0
  160. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/17_table_basic.json +0 -0
  161. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/18_table_cell_text.json +0 -0
  162. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/20_table_cell_vertical_alignment.json +0 -0
  163. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/21_table_alignment_and_autofit.json +0 -0
  164. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/22_table_cell_paragraphs_iteration.json +0 -0
  165. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/24_table_add_row_column.json +0 -0
  166. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/25_table_merge_cells.json +0 -0
  167. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/26_section_page_setup.json +0 -0
  168. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/27_section_margins.json +0 -0
  169. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/28_section_add_new.json +0 -0
  170. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/29_section_headers_linked.json +0 -0
  171. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/30_styles_iteration.json +0 -0
  172. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/31_styles_lookup_and_default.json +0 -0
  173. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/32_styles_add_paragraph_style.json +0 -0
  174. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/33_core_properties_set_and_get.json +0 -0
  175. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/34_inline_shapes_iterate_empty.json +0 -0
  176. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/35_full_report.json +0 -0
  177. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/36_replace_text_in_paragraph.json +0 -0
  178. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/37_iterate_runs_and_format_all_bold.json +0 -0
  179. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/38_font_all_properties.json +0 -0
  180. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/39_large_body_100_paragraphs.json +0 -0
  181. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/40_large_table_10x10.json +0 -0
  182. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/41_unicode_and_emoji.json +0 -0
  183. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/42_very_long_paragraph.json +0 -0
  184. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/43_paragraph_text_round_trip.json +0 -0
  185. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/44_paragraph_alignment_round_trip.json +0 -0
  186. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/45_cell_text_round_trip.json +0 -0
  187. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/46_run_text_setter_round_trip.json +0 -0
  188. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/47_font_size_round_trip.json +0 -0
  189. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/48_font_color_round_trip.json +0 -0
  190. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/49_resume_layout.json +0 -0
  191. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/50_multi_section_doc.json +0 -0
  192. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/52_iterate_everything.json +0 -0
  193. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/53_apply_style_to_paragraphs.json +0 -0
  194. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/54_empty_everything.json +0 -0
  195. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/55_single_character_runs.json +0 -0
  196. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/56_everything_in_one.json +0 -0
  197. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/57_runs_after_multiple_text_appends.json +0 -0
  198. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/58_modify_runs_in_place.json +0 -0
  199. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/59_indent_round_trip.json +0 -0
  200. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/60_space_round_trip.json +0 -0
  201. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/61_cell_paragraph_with_runs.json +0 -0
  202. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/62_many_cell_paragraphs.json +0 -0
  203. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/63_table_style_round_trip.json +0 -0
  204. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/64_many_sections.json +0 -0
  205. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/65_20x20_table_formatted.json +0 -0
  206. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/66_toc_like_structure.json +0 -0
  207. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/67_paragraph_insert_before_chain.json +0 -0
  208. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/68_invoice.json +0 -0
  209. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/69_newsletter.json +0 -0
  210. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/70_add_and_iterate_back.json +0 -0
  211. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/71_academic_paper.json +0 -0
  212. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/72_legal_contract.json +0 -0
  213. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/73_form_with_many_tables.json +0 -0
  214. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/74_paragraph_with_10_runs.json +0 -0
  215. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/75_paragraph_negative_first_line_indent.json +0 -0
  216. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/76_rgbcolor_from_string.json +0 -0
  217. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/77_length_unit_conversions.json +0 -0
  218. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/78_paragraph_copy_style.json +0 -0
  219. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/79_bulk_cell_formatting.json +0 -0
  220. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/80_apply_style_after_add_run.json +0 -0
  221. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/81_multi_page_with_breaks.json +0 -0
  222. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/82_add_text_on_existing_run.json +0 -0
  223. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/83_clear_then_repopulate_paragraph.json +0 -0
  224. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/84_table_reread_row_count.json +0 -0
  225. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/85_header_footer_access.json +0 -0
  226. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/86_font_read_unset_returns_none.json +0 -0
  227. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/87_500_paragraph_doc.json +0 -0
  228. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/88_mixed_content_iteration.json +0 -0
  229. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/89_alignment_clear_via_none.json +0 -0
  230. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/90_cell_add_paragraph_styled.json +0 -0
  231. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/91_many_small_tables.json +0 -0
  232. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/92_margins_every_section.json +0 -0
  233. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/93_font_bool_reads_after_set.json +0 -0
  234. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/94_page_break_before_paragraph.json +0 -0
  235. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/95_paragraph_hyperlinks_empty.json +0 -0
  236. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/96_paragraph_contains_page_break.json +0 -0
  237. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/97_document_styles_by_key.json +0 -0
  238. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/98_style_contains_check.json +0 -0
  239. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/99_run_add_picture_from_bytes.json +0 -0
  240. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/ex02_unicode_everywhere.json +0 -0
  241. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/ex03_1000_paragraphs.json +0 -0
  242. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/ex04_50x50_table.json +0 -0
  243. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/ex05_long_text_in_cell.json +0 -0
  244. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/ex06_hundred_tiny_runs.json +0 -0
  245. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/ex07_every_font_boolean.json +0 -0
  246. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/ex08_many_continuous_sections.json +0 -0
  247. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/ex10_complex_bom.json +0 -0
  248. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/ex11_banded_rows_formatting.json +0 -0
  249. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/ex12_section_reconfigure.json +0 -0
  250. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/ex13_cell_with_10_paragraphs.json +0 -0
  251. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/ex14_styled_report_table.json +0 -0
  252. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/ex15_paragraph_all_format_props.json +0 -0
  253. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/ex16_runs_interleaved_with_breaks.json +0 -0
  254. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/ex17_all_break_kinds.json +0 -0
  255. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/ex18_read_back_large_doc.json +0 -0
  256. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/ex19_mutate_all_runs.json +0 -0
  257. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/ex20_kitchen_sink_v2.json +0 -0
  258. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/mega01_book_chapter.json +0 -0
  259. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/mega02_research_proposal.json +0 -0
  260. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/mega03_financial_statement.json +0 -0
  261. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/mega04_recipe_card.json +0 -0
  262. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/mega05_user_manual.json +0 -0
  263. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/mega06_complex_newsletter.json +0 -0
  264. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/mega07_budget_spreadsheet.json +0 -0
  265. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/mega08_product_catalog.json +0 -0
  266. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/mega09_signed_contract.json +0 -0
  267. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/mega10_api_documentation.json +0 -0
  268. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/rw01_official_quickstart.json +0 -0
  269. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/rw02_paragraph_style_list.json +0 -0
  270. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/rw03_character_formatting.json +0 -0
  271. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/rw04_section_page_setup.json +0 -0
  272. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/rw05_toc_pattern.json +0 -0
  273. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/rw06_meeting_minutes.json +0 -0
  274. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/rw07_dense_formatting_demo.json +0 -0
  275. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/rw08_table_merged_header.json +0 -0
  276. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/rw09_bulk_run_iteration.json +0 -0
  277. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/rw10_colored_grid_table.json +0 -0
  278. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/rw11_header_text.json +0 -0
  279. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/rw12_first_page_footer.json +0 -0
  280. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/rw13_even_page_header.json +0 -0
  281. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/rw15_paragraph_style_instance.json +0 -0
  282. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/rw16_header_footer_tables.json +0 -0
  283. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/rw17_header_letterhead_filled.json +0 -0
  284. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/rw19_header_table_rows_columns.json +0 -0
  285. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/op_snapshots/rw20_header_table_merges.json +0 -0
  286. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/ours_spec.json +0 -0
  287. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/parity_crawl.py +0 -0
  288. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/parity_diff.json +0 -0
  289. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/real_world_cases.py +0 -0
  290. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/round_trip_tests.py +0 -0
  291. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/stock_spec.json +0 -0
  292. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fidelity/test_e2e_against_staging.py +0 -0
  293. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fixtures/field_reads.json +0 -0
  294. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fixtures/note_reference_reads.json +0 -0
  295. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fixtures/ruby_reads.json +0 -0
  296. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/fixtures/symbol_reads.json +0 -0
  297. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/live/__init__.py +0 -0
  298. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/live/reader.py +0 -0
  299. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/live/runner.py +0 -0
  300. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/live/sdk_driver.py +0 -0
  301. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/live/stock_driver.py +0 -0
  302. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/live/test_live_runner.py +0 -0
  303. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/parity/README.md +0 -0
  304. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/parity/__init__.py +0 -0
  305. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/parity/baseline_gaps.json +0 -0
  306. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/parity/compare.py +0 -0
  307. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/parity/intentional_deviations.json +0 -0
  308. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/parity/introspect.py +0 -0
  309. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/parity/reports/GAP_ANALYSIS.md +0 -0
  310. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/parity/reports/gap_report.json +0 -0
  311. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/parity/run_parity.py +0 -0
  312. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/parity/snapshots/athena_latest.json +0 -0
  313. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/parity/snapshots/upstream_python_docx_1.2.0.json +0 -0
  314. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/parity/test_parity_gap.py +0 -0
  315. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_add_section.py +0 -0
  316. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_add_section_extract_items.py +0 -0
  317. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_athena_extension_creates_session_open.py +0 -0
  318. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_athena_extensions_contract.py +0 -0
  319. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_athena_extensions_registry.py +0 -0
  320. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_batch_chunking.py +0 -0
  321. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_batching_perf.py +0 -0
  322. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_block_not_found_error.py +0 -0
  323. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_buffer.py +0 -0
  324. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_cell_add_paragraph_wire_shape.py +0 -0
  325. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_cell_add_table_not_supported.py +0 -0
  326. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_cell_borders_spec.py +0 -0
  327. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_cell_fastpath_runs.py +0 -0
  328. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_cell_inner_add_hyperlink_stash.py +0 -0
  329. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_cell_inner_add_run_via_cell_insert.py +0 -0
  330. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_cell_inner_format_stash.py +0 -0
  331. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_cell_inner_run_format_stash.py +0 -0
  332. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_cell_inner_run_guard.py +0 -0
  333. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_cell_merge.py +0 -0
  334. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_cell_nested_tables.py +0 -0
  335. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_cell_paragraphs_listed.py +0 -0
  336. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_cell_text_plain_fastpath.py +0 -0
  337. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_cell_text_replace_semantics.py +0 -0
  338. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_citations.py +0 -0
  339. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_collapsed_range_format.py +0 -0
  340. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_color_format_theme.py +0 -0
  341. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_command_dataclasses.py +0 -0
  342. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_commands.py +0 -0
  343. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_comment_paragraphs.py +0 -0
  344. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_comments.py +0 -0
  345. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_comments_first_read.py +0 -0
  346. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_content_control_value.py +0 -0
  347. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_core_properties.py +0 -0
  348. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_document_asset_id_property.py +0 -0
  349. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_document_clear.py +0 -0
  350. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_document_create.py +0 -0
  351. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_document_create_from_template.py +0 -0
  352. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_document_factory_validation.py +0 -0
  353. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_docx_exec_lab.py +0 -0
  354. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_docx_exec_lab_server.py +0 -0
  355. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_drawing_image.py +0 -0
  356. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_e2e_partial_failure_cascade.py +0 -0
  357. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_empty_hyperlinks.py +0 -0
  358. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_enum_parity.py +0 -0
  359. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_execution_scope.py +0 -0
  360. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_export_docx_clean.py +0 -0
  361. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_export_rescue_anchors.py +0 -0
  362. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_field_reads_python_docx_parity.py +0 -0
  363. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_field_refresh.py +0 -0
  364. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_find_replace_session_open.py +0 -0
  365. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_flushed_write_failures.py +0 -0
  366. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_hyperlink_coalescing.py +0 -0
  367. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_image_url_data_uri.py +0 -0
  368. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_inline_page_break.py +0 -0
  369. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_inline_shape_alt_text.py +0 -0
  370. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_inline_shape_size.py +0 -0
  371. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_inline_shape_type.py +0 -0
  372. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_inline_shapes_floating.py +0 -0
  373. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_insert_deferred.py +0 -0
  374. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_iter_inner_content.py +0 -0
  375. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_list_styles.py +0 -0
  376. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_merged_cell_secondary_slot.py +0 -0
  377. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_merged_cells.py +0 -0
  378. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_missing_modules.py +0 -0
  379. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_nested_table_refused.py +0 -0
  380. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_note_reference_reads_python_docx_parity.py +0 -0
  381. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_oxml_shim.py +0 -0
  382. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_page_break.py +0 -0
  383. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_paragraph_runs_hyperlinks.py +0 -0
  384. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_paragraph_text_len_cache.py +0 -0
  385. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_parity_misc.py +0 -0
  386. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_parity_round2.py +0 -0
  387. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_partial_failure_cascade.py +0 -0
  388. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_pdf_export_and_page_renders.py +0 -0
  389. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_phase_a_behavior.py +0 -0
  390. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_phase_b_headers_footers.py +0 -0
  391. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_phase_c_tables.py +0 -0
  392. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_positional_cell_id.py +0 -0
  393. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_postproc_cell_format_rewrite.py +0 -0
  394. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_postproc_cell_run_format_rewrite.py +0 -0
  395. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_postproc_ref_restore.py +0 -0
  396. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_pr19766_review_fixes.py +0 -0
  397. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_ptc.py +0 -0
  398. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_python_docx_api_parity.py +0 -0
  399. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_read_run_ranges.py +0 -0
  400. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_repeated_node_read.py +0 -0
  401. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_restart_numbering.py +0 -0
  402. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_revisions.py +0 -0
  403. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_round_trip_smoke_script.py +0 -0
  404. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_ruby_reads_python_docx_parity.py +0 -0
  405. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_run_add_picture_anchor.py +0 -0
  406. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_run_break_inner_content.py +0 -0
  407. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_run_edges.py +0 -0
  408. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_run_formatting_wire.py +0 -0
  409. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_run_identity.py +0 -0
  410. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_run_later_runs.py +0 -0
  411. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_run_mark_inheritance.py +0 -0
  412. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_run_table_style_objects.py +0 -0
  413. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_run_text_python_docx.py +0 -0
  414. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_run_text_refreshes_paragraph.py +0 -0
  415. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_run_unmodeled_toggles.py +0 -0
  416. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_sdk_reads_served.py +0 -0
  417. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_section_read_lengths.py +0 -0
  418. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_add_paragraph_style.py +0 -0
  419. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_add_picture.py +0 -0
  420. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_add_run.py +0 -0
  421. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_cell_add_paragraph.py +0 -0
  422. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_comments_add_comment.py +0 -0
  423. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_comments_get.py +0 -0
  424. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_document_audit.py +0 -0
  425. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_document_element.py +0 -0
  426. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_enum_section.py +0 -0
  427. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_font_audit.py +0 -0
  428. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_header_footer.py +0 -0
  429. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_hyperlink.py +0 -0
  430. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_inline_shape.py +0 -0
  431. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_insert_paragraph_before.py +0 -0
  432. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_misc.py +0 -0
  433. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_paragraph_strict.py +0 -0
  434. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_paragraph_style.py +0 -0
  435. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_paragraph_style_strict.py +0 -0
  436. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_run_add_break.py +0 -0
  437. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_run_bool_setters.py +0 -0
  438. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_run_style.py +0 -0
  439. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_run_style_strict.py +0 -0
  440. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_run_text.py +0 -0
  441. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_run_underline.py +0 -0
  442. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_section_audit.py +0 -0
  443. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_section_dimensions.py +0 -0
  444. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_settings.py +0 -0
  445. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_shared_audit.py +0 -0
  446. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_style.py +0 -0
  447. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_styles.py +0 -0
  448. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_table_audit.py +0 -0
  449. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_table_cell.py +0 -0
  450. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_silent_stub_table_dimensions.py +0 -0
  451. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_smoke_integration.py +0 -0
  452. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_style_acceptance.py +0 -0
  453. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_style_font.py +0 -0
  454. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_style_names.py +0 -0
  455. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_style_setters_contract.py +0 -0
  456. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_style_tab_stops_read.py +0 -0
  457. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_symbol_reads_python_docx_parity.py +0 -0
  458. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_table_anchors.py +0 -0
  459. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_table_direction.py +0 -0
  460. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_table_read_reuse.py +0 -0
  461. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_table_set_cell_perf.py +0 -0
  462. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_table_style_id_resolution.py +0 -0
  463. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_temporarily_unavailable.py +0 -0
  464. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_text_control_characters.py +0 -0
  465. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_tracked_revisions_offsets.py +0 -0
  466. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_uv_lock_version.py +0 -0
  467. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_validate_find_replace_asset_script.py +0 -0
  468. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_xml_attr_guard.py +0 -0
  469. {athena_python_docx-0.33.0 → athena_python_docx-0.34.0}/tests/test_zod_wire_contract.py +0 -0
@@ -85,16 +85,30 @@ pinned by focused tests and documented in
85
85
  `quick_style`, `unhide_when_used`, `base_style`,
86
86
  `next_paragraph_style`) write the style's definition
87
87
  (`SetStyleMetadata`), `Styles.add_style` adds one (`CreateStyle`), and
88
- a paragraph or character style's formatting (`style.font.*`,
89
- `style.paragraph_format.*`) is written too (`SetStyleFormatting`); each
88
+ a paragraph, character or table style's formatting (`style.font.*`,
89
+ `style.paragraph_format.*`; a table style's on a docx-studio that reports
90
+ `tableStyleFormatting`, which a room imported before its cells resolved
91
+ table styles does not) is written too (`SetStyleFormatting`); each
90
92
  reads back from the style table, whose `metadata` / `font` /
91
93
  `paragraphFormat` entries are the capability signal
92
94
  (`tests/test_style_metadata_writes.py`,
93
- `tests/test_style_formatting_writes.py`). `style_id`, `delete()`, a
94
- table style's formatting and base, a style's tab stops, and every style write on
95
- a docx-studio without that signal emit `PendingStyleMutationWarning`
96
- (or its paragraph-format / registry variant) and stash on
97
- `_overrides` (`tests/test_style_setters_contract.py`).
95
+ `tests/test_style_formatting_writes.py`), a paragraph style's
96
+ `tab_stops` (each mutation sends the style's whole `w:tabs` as python-docx's
97
+ `TabStops` leaves it, on a docx-studio that reports `styleTabStops`; each
98
+ tab stop object is its place in that list, which a write to another moves,
99
+ so of two equal stops each writes itself, and one removed writes nothing;
100
+ `tests/test_style_tab_stops.py`). `delete()` removes a paragraph
101
+ or character style's definition (`DeleteStyle`, on a docx-studio that
102
+ reports `deleteStyle`; `tests/test_style_delete.py`): its content keeps the
103
+ style's name and shows the default style, as in Word. A table style's
104
+ `delete()`, `base_style` and `style_id` are sent where docx-studio also
105
+ reports `tableStyleRestyles` (it draws the style's tables again), and its
106
+ font and paragraph format where it reports `tableStyleFormatting`; a room
107
+ imported before its cells resolved table styles reports neither. A
108
+ numbering style's `style_id` and deletion, and every style write on a
109
+ docx-studio without that signal emit
110
+ `PendingStyleMutationWarning` (or its delete / paragraph-format / registry
111
+ variant) and stash on `_overrides` (`tests/test_style_setters_contract.py`).
98
112
  - **A picture is a run, and `Run.iter_inner_content()` yields its
99
113
  `docx.drawing.Drawing`.** As python-docx reads a `w:r` holding a
100
114
  `w:drawing`, `Paragraph.runs` and `iter_inner_content()` hold a run with
@@ -116,10 +130,15 @@ pinned by focused tests and documented in
116
130
  - **`Styles.latent_styles`** (`docx.styles.latent.LatentStyles`) reads
117
131
  the document's `<w:latentStyles>` (defaults and each `w:lsdException`)
118
132
  from docx-studio's `Info` (`includeStyles` → `latentStyles`), as python-docx
119
- reads them. Writing them is not supported: a setter, `add_latent_style`
120
- and `_LatentStyle.delete` emit `PendingLatentStylesWriteWarning` and
121
- change nothing. A docx-studio that predates the read (or a document
122
- without a source copy) reads as empty, with
133
+ reads them, and writes them as python-docx does: each setter,
134
+ `add_latent_style` and `_LatentStyle.delete` sends one `EditLatentStyles`
135
+ to a docx-studio that reports `latentStyleWrites`
136
+ (`tests/test_latent_style_writes.py`); an older one keeps the value, with
137
+ `PendingLatentStylesWriteWarning`. A `_LatentStyle` addresses its exception
138
+ by name and `occurrence` (which of that name's exceptions it is), moved
139
+ when an earlier one is deleted, so one `add_latent_style` returns beside an
140
+ exception of the same name writes to itself, as python-docx's element does. A docx-studio that predates the read (or
141
+ a document without a source copy) reads as empty, with
123
142
  `PendingLatentStylesReadWarning`.
124
143
 
125
144
  ### Intentional deviations (additions / different semantics)
@@ -169,6 +188,22 @@ not file-backed. Each is documented in the relevant docstring.
169
188
  cells stay. ``table.style = None`` removes an existing table's style as
170
189
  python-docx does (``DOCX_STUDIO_LIMITATIONS.md`` § 25).
171
190
 
191
+ - **Table, row and cell properties set to None, and row height parts**, as
192
+ python-docx 1.2.0 writes them on a docx-studio that reports
193
+ ``tableClears`` (``tests/test_table_clears.py``): ``Table.alignment =
194
+ None`` removes ``w:jc`` (a header or footer table's too),
195
+ ``_Cell.vertical_alignment = None`` removes
196
+ ``w:vAlign``, and ``_Row.height`` / ``_Row.height_rule`` each write their
197
+ own part of ``w:trHeight``, None removing it (``<w:trHeight
198
+ w:hRule="exact"/>``); a height set without a rule is the value alone.
199
+ ``_Cell.width = None`` raises ``TypeError`` and ``Table.autofit = None``
200
+ changes nothing, as in python-docx. An older docx-studio keeps the
201
+ ``PendingTableClearWarning`` and sends a rule (at least) with each height.
202
+ ``_Column.width = None`` still warns: a ``w:gridCol`` without a width
203
+ needs the layout to size the column from its cells. An invalid height or
204
+ rule is refused before the capability read, whose ``Info`` would send the
205
+ edits still buffered.
206
+
172
207
  - **`Document.create(name=, base_url=, api_key=, parent_folder_id=, workspace_id=, docx=, agora_base_url=)`**
173
208
  classmethod. Stock python-docx returns a blank in-memory document
174
209
  for `Document(None)`; we can't fabricate a Word document asset
@@ -921,10 +956,26 @@ architecture or a DOCX Studio constraint:
921
956
  string DOCX Studio's commands carry for a member (`"center"`, `"wavy"`,
922
957
  the `w:` XML value, …) where upstream rejects strings. The SDK sends
923
958
  `member.to_docx_studio()` and reads with `from_docx_studio()`, never
924
- `.value`. Members DOCX Studio can't apply are sent as their closest
925
- value with `PendingEnumCoercionWarning` (distributed / kashida / Thai
926
- justification → `"justify"`; `LIST`/`CLEAR`/`END`/`NUM`/`START` tabs →
927
- `"left"`); `WD_ALIGN_VERTICAL.BOTH` goes as `"center"`. `INHERITED`
959
+ `.value`. A paragraph's alignment and tab stops go as python-docx writes
960
+ them (distributed / kashida / Thai justification, `LIST`/`CLEAR`/`END`/
961
+ `NUM`/`START` tabs) to a DOCX Studio that reports `alignmentValues`
962
+ (`tests/test_alignment_values.py`); to an older one, as their closest
963
+ value (`"justify"`, `"left"`) with `PendingEnumCoercionWarning`.
964
+ `TabStops.add_tab_stop` keeps a stop already at its position and goes in
965
+ after it, as python-docx's `insert_tab_in_order` puts it
966
+ (`SetParagraphTabStop` with `insert`, sent to a DOCX Studio that reports
967
+ `tabStopInserts`; an older one replaces that stop). A stop's `alignment`
968
+ and `leader` change it in place, and its `position` moves it where
969
+ python-docx moves its `w:tab` (`tests/test_tab_stop_writes.py`). A
970
+ `TabStop` is its place in the paragraph's list, which a write through any
971
+ other moves (the live stops of each paragraph are held weakly per
972
+ session), as python-docx's proxy holds its `w:tab`: two stops at one
973
+ position are each their own, and two objects of one stop both write it.
974
+ One the paragraph no longer holds takes a value and writes nothing; its
975
+ `position` raises `AttributeError`, except for one `clear_all` took out,
976
+ as python-docx's do. An add reads nothing unless a stop of the paragraph
977
+ holds a place: the next read finds where it went.
978
+ `WD_ALIGN_VERTICAL.BOTH` goes as `"center"`. `INHERITED`
928
979
  raises `ValueError` ("has no XML representation") as upstream's
929
980
  `to_xml` does, and a bool is its int value (`True` is the member valued
930
981
  1), as upstream reads it. `Table.alignment`
@@ -1009,7 +1060,10 @@ architecture or a DOCX Studio constraint:
1009
1060
  docx-studio finds the table by those paragraphs, so a table an edit moved (a
1010
1061
  row added above a table nested in a cell, a table added before it, a merge
1011
1062
  moving a nested table into the merged cell) is still the one read and
1012
- written, as python-docx's proxies follow the elements they hold. When no
1063
+ written, as python-docx's proxies follow the elements they hold. A write
1064
+ that replaces one of those paragraphs (`cell.text = …` on the first or last
1065
+ cell) leaves its paraId on the table as an alias (`anchorAliases`), so the
1066
+ proxy reaches the table in later batches on any docx-studio replica. When no
1013
1067
  table holds them (the table was deleted, or the cell holding it had its
1014
1068
  text replaced, which removes the tables it held), docx-studio refuses the
1015
1069
  batch and the SDK raises `StaleTableError`: "the table this proxy named is
@@ -1069,11 +1123,16 @@ architecture or a DOCX Studio constraint:
1069
1123
  exported paragraph as `annotation text`. Owner decision, 2026-10-12.
1070
1124
  Recorded in `tests/parity/intentional_deviations.json` (`live_deviations`).
1071
1125
 
1072
- - **`ParagraphFormat.line_spacing_rule = None` warns-and-preserves on a
1073
- clear** rather than raising (upstream accepts `None` to clear, but DOCX
1074
- Studio's merging mutation ops have no single-attribute clear). It emits a
1075
- `Pending…ClearWarning` and leaves the value intact instead of
1076
- destructively clearing the whole block. The `Section` dimension setters
1126
+ - **A `ParagraphFormat` setter given `None` clears that property alone**, as
1127
+ upstream does, on a docx-studio that reports `paragraphFormatClears`:
1128
+ `space_before`, `space_after`, `line_spacing` (the line with its rule) and
1129
+ `line_spacing_rule` (the rule alone) send `ClearParagraphSpacing.only`;
1130
+ `left_indent`, `right_indent` and `first_line_indent` send
1131
+ `ClearParagraphIndentation.only`; `keep_with_next`, `keep_together` and
1132
+ `widow_control` send `SetParagraphKeepOptions.clear…`. On an older one a
1133
+ spacing or indent `None` clears all of the paragraph's spacing or indents,
1134
+ as before, and the keep options and `line_spacing_rule` warn
1135
+ (`PendingParfmtClearWarning`) and keep the value. The `Section` dimension setters
1077
1136
  remove the attribute for `None`, as upstream does (`null` on the wire),
1078
1137
  on a docx-studio whose section read reports `clearsDimensions`; on an
1079
1138
  older one they warn (`PendingSectionDimensionClearWarning`) and keep the
@@ -1156,18 +1215,37 @@ architecture or a DOCX Studio constraint:
1156
1215
  field's result changed (through another read's run, or by a
1157
1216
  collaborator) raises `FieldRunWriteError` rather than write over that
1158
1217
  change, where python-docx's run is live;
1159
- - formatting a result run formats the field's whole result (`FormatApply`
1160
- with a `field` target), from its source formatting, where python-docx
1161
- formats that run alone;
1218
+ - formatting a field's one result run formats the field's whole result
1219
+ (`FormatApply` with a `field` target), from its source formatting, as
1220
+ python-docx formats that run, and in a body paragraph docx-studio writes
1221
+ the run's own `w:rPr` with it (a caption's number keeps its `w:noProof`
1222
+ and takes nothing of the Caption style); of a result of several runs, it formats that
1223
+ run alone, as python-docx does, against a docx-studio that reports
1224
+ `capabilities.fieldRunFormats` (an older one formats the whole result).
1225
+ The SDK names that run by its place among the result's runs and the text
1226
+ it was read with, and renumbers the result runs a read holds when a write
1227
+ through one of them empties it (docx-studio writes no emptied result
1228
+ run): a run that no longer has a place, or holds other text, is not
1229
+ formatted alone. The SDK warns (`PendingFieldRunFormatWarning`), or
1230
+ docx-studio refuses the format, so it never lands on another run;
1162
1231
  - `.text` (and `clear()`) on a field character or field code run raises
1163
1232
  `docx.errors.FieldRunWriteError` naming the field: python-docx replaces
1164
1233
  the run's `w:fldChar` or `w:instrText` with the text, which breaks the
1165
1234
  field;
1166
- - formatting set on a field character or field code run is not applied and
1167
- emits `PendingFieldRunFormatWarning` (those runs show nothing; docx-studio
1168
- has no command that writes their own `w:rPr`), where python-docx writes
1169
- it, so `for run in p.runs: run.bold = True` formats the text and the
1170
- field's result and warns for the rest;
1235
+ - formatting set on a field character or field code run, a table of
1236
+ contents' own runs among them, is written to that run's `w:rPr` as
1237
+ python-docx writes it, so `for run in p.runs: run.bold = True` formats
1238
+ every run, against a docx-studio that reports
1239
+ `capabilities.fieldRunFormats` (the SDK names the run: its `part`, with its
1240
+ field's index and which run of that part it is, or which of the
1241
+ paragraph's field runs no field node stands for it is). It is refused and
1242
+ warns (`DocxUnsupportedCommandWarning`) for a run of a field `add_field`
1243
+ added since the import, whose runs docx-studio writes from its node, and
1244
+ of a paragraph a field was added to or taken out of since; a tracked
1245
+ format raises naming `TrackedChangesUnsupported`. An older docx-studio has
1246
+ no command that writes those runs' `w:rPr`: there the setter changes
1247
+ nothing and emits `PendingFieldRunFormatWarning`
1248
+ (`tests/test_field_runs.py`, `DOCX_STUDIO_LIMITATIONS.md` § 27);
1171
1249
  - `add_text`, `add_tab`, `add_break`, `add_picture`, `add_field`,
1172
1250
  `add_footnote`, `add_endnote`, `add_math` and `add_cross_reference` on
1173
1251
  any of a field's runs raise `FieldRunWriteError`; python-docx appends to
@@ -1177,6 +1255,32 @@ architecture or a DOCX Studio constraint:
1177
1255
  exported file. Against a docx-studio that predates `fieldRun` reads, a
1178
1256
  field reads as no runs and no text, as before (`tests/test_field_runs.py`).
1179
1257
 
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
1268
+ (`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
1274
+ (`DOCX_STUDIO_LIMITATIONS.md` § 27). `run.text = …` and `clear()` replace
1275
+ all of such a run, its blocks too, as upstream does: the SDK declares
1276
+ `wholeRunPieces`, and renumbers the field runs it holds of the paragraph,
1277
+ since each field after the blocks is numbered one lower for each
1278
+ (`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.
1283
+
1180
1284
  - **`Font.name = "…"` also clears the theme fonts of the two slots it
1181
1285
  sets.** python-docx writes the name to `w:rFonts`' `w:ascii` and `w:hAnsi`
1182
1286
  and leaves a `w:asciiTheme` / `w:hAnsiTheme` beside them; Word reads a
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: athena-python-docx
3
- Version: 0.33.0
3
+ Version: 0.34.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.33.0"
9
+ __version__ = "0.34.0"
10
10
 
11
11
  from docx.api import Document
12
12
  from docx._buffer import discard_all, flush_all
@@ -22,6 +22,16 @@ from docx._batching import run_sync
22
22
  # An older docx-studio gives none, so the SDK needs no check.
23
23
  TABLE_ANCHORS_CLIENT_CAPABILITY = "tableAnchors"
24
24
 
25
+ # What this SDK declares in ``client.capabilities``: it renumbers the field
26
+ # runs it holds once a whole run's text write (``run.text = …``, ``clear()``)
27
+ # took out the page number blocks (``w:pgNum``) of a run docx-studio cut at
28
+ # them, whose read lists their field indices (``pageNumberBlocks``). Such a
29
+ # write then replaces all of the run, its blocks too, as python-docx replaces
30
+ # its ``w:r``'s content, and each field after the blocks is numbered one lower
31
+ # for each. An older docx-studio lists no blocks and keeps them, so the SDK
32
+ # renumbers nothing.
33
+ WHOLE_RUN_PIECES_CLIENT_CAPABILITY = "wholeRunPieces"
34
+
25
35
  # Session -> the capabilities its server reported, read once.
26
36
  _capabilities: "weakref.WeakKeyDictionary[Any, dict[str, Any]]" = weakref.WeakKeyDictionary()
27
37
 
@@ -44,7 +44,7 @@ from urllib3.util.retry import Retry
44
44
  from docx._batching import call_abandoned, note_progress
45
45
  from docx._buffer import CommandBuffer, keep_reported_message
46
46
  from docx._tracked import TRACKED_AUTHORING_CAPABILITY, TRACKED_MINIMAL_PARAGRAPH_TEXT_CAPABILITY
47
- from docx._capabilities import TABLE_ANCHORS_CLIENT_CAPABILITY
47
+ from docx._capabilities import TABLE_ANCHORS_CLIENT_CAPABILITY, WHOLE_RUN_PIECES_CLIENT_CAPABILITY
48
48
  from docx._timeouts import (
49
49
  DEFAULT_OP_TIMEOUT_SECONDS,
50
50
  LONG_RUNNING_COMMAND_TIMEOUT_SECONDS,
@@ -87,6 +87,8 @@ from docx.commands import (
87
87
  CreateParagraph,
88
88
  CreateSectionBreak,
89
89
  CreateStyle,
90
+ EditLatentStyles,
91
+ DeleteStyle,
90
92
  CreateTable,
91
93
  CreateTOC,
92
94
  CreateWatermark,
@@ -1209,11 +1211,13 @@ class HttpClient:
1209
1211
  "version": _sdk_version(),
1210
1212
  # Keeps its offsets as a tracked edit moves them, and reads a
1211
1213
  # paragraph's length back after a tracked ``paragraph.text``
1212
- # (``docx._tracked``); holds anchored table ids (``docx.table``).
1214
+ # (``docx._tracked``); holds anchored table ids (``docx.table``);
1215
+ # renumbers its field runs after a cut run's whole write (``docx._run_order``).
1213
1216
  "capabilities": [
1214
1217
  TRACKED_AUTHORING_CAPABILITY,
1215
1218
  TRACKED_MINIMAL_PARAGRAPH_TEXT_CAPABILITY,
1216
1219
  TABLE_ANCHORS_CLIENT_CAPABILITY,
1220
+ WHOLE_RUN_PIECES_CLIENT_CAPABILITY,
1217
1221
  ],
1218
1222
  },
1219
1223
  "commands": [
@@ -1374,6 +1378,8 @@ _OP_TO_COMMAND: dict[str, type[Command]] = {
1374
1378
  "styles.set_formatting": SetStyleFormatting,
1375
1379
  "styles.set_metadata": SetStyleMetadata,
1376
1380
  "styles.create": CreateStyle,
1381
+ "styles.edit_latent": EditLatentStyles,
1382
+ "styles.delete": DeleteStyle,
1377
1383
  "core_properties.set": SetCoreProperties,
1378
1384
  # Sections
1379
1385
  "sections.set_page_margins": SetSectionPageMargins,
@@ -2897,6 +2897,15 @@ def _replace_flag(
2897
2897
  elem.set(f"{W_NS}val", "0")
2898
2898
 
2899
2899
 
2900
+ # The other ``w:jc`` justifications python-docx writes, by their lower case.
2901
+ _JUSTIFICATIONS_BY_LOWER = {
2902
+ "mediumkashida": "mediumKashida",
2903
+ "highkashida": "highKashida",
2904
+ "lowkashida": "lowKashida",
2905
+ "thaidistribute": "thaiDistribute",
2906
+ }
2907
+
2908
+
2900
2909
  def normalize_alignment(value: Any) -> str | None:
2901
2910
  """Convert a python-docx ``WD_ALIGN_PARAGRAPH`` value (or string) to
2902
2911
  the OOXML ``w:jc`` value (``left`` / ``center`` / ``right`` /
@@ -2919,7 +2928,7 @@ def normalize_alignment(value: Any) -> str | None:
2919
2928
  return "both"
2920
2929
  if s in {"distribute"}:
2921
2930
  return "distribute"
2922
- return None
2931
+ return _JUSTIFICATIONS_BY_LOWER.get(s)
2923
2932
 
2924
2933
  # WD_ALIGN_PARAGRAPH enum values (int-like).
2925
2934
  name = getattr(value, "name", None)
@@ -29,6 +29,7 @@ document stores none of it.
29
29
 
30
30
  from __future__ import annotations
31
31
 
32
+ import bisect
32
33
  import itertools
33
34
  import weakref
34
35
  from dataclasses import dataclass, field
@@ -105,6 +106,36 @@ def _live_runs(run: "Run") -> list["Run"]:
105
106
  return [proxy for block_id in ids for proxy in list(blocks.get(block_id, ()))]
106
107
 
107
108
 
109
+ def page_number_blocks_gone(run: "Run", gone: list[int], *, taken_out: bool) -> None:
110
+ """The page number blocks ``gone`` (their field indices) are no run's of
111
+ ``run``'s paragraph now: a whole run's text write took them out
112
+ (``taken_out``), or, with tracking on, deleted them, where they keep
113
+ their place and their numbers.
114
+
115
+ No live run proxy of the paragraph, read or created, lists them
116
+ (``pageNumberBlocks``). Taken out, each field after them is numbered one
117
+ lower for each, as docx-studio numbers them, so every proxy names its
118
+ field (``fieldIndex``) and the blocks it holds by the new numbers.
119
+ """
120
+ removed = sorted(set(gone))
121
+
122
+ def renumbered(index: int) -> int:
123
+ return index - bisect.bisect_left(removed, index) if taken_out else index
124
+
125
+ for proxy in _live_runs(run):
126
+ snapshot: object = getattr(proxy, "_inline_snapshot", None)
127
+ if not isinstance(snapshot, dict):
128
+ continue
129
+ index: object = snapshot.get("fieldIndex")
130
+ if isinstance(index, int) and not isinstance(index, bool):
131
+ snapshot["fieldIndex"] = renumbered(index)
132
+ blocks: object = snapshot.get("pageNumberBlocks")
133
+ if isinstance(blocks, list):
134
+ snapshot["pageNumberBlocks"] = [
135
+ renumbered(block) for block in blocks if isinstance(block, int) and block not in removed
136
+ ]
137
+
138
+
108
139
  def _move_live_runs(
109
140
  run: "Run",
110
141
  old_span: tuple[int, int],
@@ -248,6 +248,12 @@ class InsertLineBreak(Command):
248
248
  # in it, as python-docx writes it. Sent only to a docx-studio reporting
249
249
  # ``capabilities.inlineColumnBreak``; an older one ignores it.
250
250
  inline: bool | None = None
251
+ # ``"left"``, ``"right"`` or ``"all"``: a clearing line break
252
+ # (``Run.add_break(WD_BREAK.LINE_CLEAR_LEFT)`` and the rest), written as
253
+ # ``<w:br w:type="textWrapping" w:clear="…"/>``. Sent only to a
254
+ # docx-studio reporting ``capabilities.lineBreakClear``; an older one
255
+ # ignores it and inserts a line break.
256
+ clear: str | None = None
251
257
 
252
258
 
253
259
  @dataclass
@@ -304,6 +310,12 @@ class SetParagraphIndentation(Command):
304
310
  @dataclass
305
311
  class ClearParagraphIndentation(Command):
306
312
  target: dict[str, Any]
313
+ # Only these of the paragraph's own indents ("left", "right", "firstLine":
314
+ # the first-line or hanging indent), as python-docx's ``left_indent`` /
315
+ # ``right_indent`` / ``first_line_indent = None`` each clear their own.
316
+ # Without it, all of them. Sent only to a docx-studio reporting
317
+ # ``paragraphFormatClears``; an older one drops it and clears all.
318
+ only: list[str] | None = None
307
319
 
308
320
 
309
321
  @dataclass
@@ -318,6 +330,12 @@ class SetParagraphSpacing(Command):
318
330
  @dataclass
319
331
  class ClearParagraphSpacing(Command):
320
332
  target: dict[str, Any]
333
+ # Only these of the paragraph's own spacing ("before", "after", "line":
334
+ # the line spacing with its rule, "lineRule": the rule alone), as
335
+ # python-docx's ``space_before`` / ``space_after`` / ``line_spacing`` /
336
+ # ``line_spacing_rule = None`` each clear their own. Without it, all of
337
+ # them. Sent only to a docx-studio reporting ``paragraphFormatClears``.
338
+ only: list[str] | None = None
321
339
 
322
340
 
323
341
  @dataclass
@@ -326,6 +344,12 @@ class SetParagraphKeepOptions(Command):
326
344
  keep_next: bool | None = None
327
345
  keep_lines: bool | None = None
328
346
  widow_control: bool | None = None
347
+ # ``keep_with_next`` / ``keep_together`` / ``widow_control = None``: the
348
+ # paragraph's own value goes, and it takes its style's again. Sent only to
349
+ # a docx-studio reporting ``paragraphFormatClears``.
350
+ clear_keep_next: bool | None = None
351
+ clear_keep_lines: bool | None = None
352
+ clear_widow_control: bool | None = None
329
353
 
330
354
 
331
355
  @dataclass
@@ -347,6 +371,10 @@ class SetParagraphTabStop(Command):
347
371
  position: float
348
372
  alignment: str | None = None
349
373
  leader: str | None = None
374
+ # python-docx's ``add_tab_stop``: the stop goes in after any at its
375
+ # position, which stays (``insert_tab_in_order``). An older docx-studio
376
+ # drops the key and replaces that stop.
377
+ insert: bool | None = None
350
378
 
351
379
 
352
380
  @dataclass
@@ -381,6 +409,30 @@ class CreateStyle(Command):
381
409
  builtin: bool | None = None
382
410
 
383
411
 
412
+ @dataclass
413
+ class EditLatentStyles(Command):
414
+ """One python-docx write to ``styles.xml``'s ``w:latentStyles``:
415
+ ``defaults`` (``LatentStyles`` setters), ``add`` (``add_latent_style``,
416
+ the styles.xml name) or ``exception`` (``{"name", "attrs"}`` for a
417
+ ``_LatentStyle`` setter, ``{"name", "delete": True}`` for ``delete()``).
418
+ Sent only to a docx-studio reporting ``latentStyleWrites``."""
419
+
420
+ defaults: dict[str, Any] | None = None
421
+ add: str | None = None
422
+ exception: dict[str, Any] | None = None
423
+
424
+
425
+ @dataclass
426
+ class DeleteStyle(Command):
427
+ """A style's ``w:style`` removed from ``styles.xml``, as python-docx's
428
+ ``BaseStyle.delete()`` removes it: ``style_id`` names it, as for
429
+ ``SetStyleMetadata``. Sent only to a docx-studio reporting
430
+ ``deleteStyle``."""
431
+
432
+ style_id: str
433
+ style_type: str | None = None
434
+
435
+
384
436
  @dataclass
385
437
  class SetStyleMetadata(Command):
386
438
  """A style's metadata in ``styles.xml``, as python-docx's ``BaseStyle``
@@ -599,10 +651,15 @@ class TablesSetColumnWidth(Command):
599
651
 
600
652
  @dataclass
601
653
  class TablesSetRowHeight(Command):
654
+ """A row's ``w:trHeight``: ``height_pt`` its value and ``rule`` its
655
+ ``w:hRule`` (``"auto"`` | ``"exact"`` | ``"atLeast"``), each left as it is
656
+ when not given; ``NULL`` removes it, on a docx-studio that reports
657
+ ``tableClears``."""
658
+
602
659
  node_id: str
603
660
  row_index: int
604
- height_pt: float
605
- rule: str | None = None # "auto" | "exact" | "atLeast"
661
+ height_pt: float | None = None
662
+ rule: str | None = None
606
663
 
607
664
 
608
665
  @dataclass
@@ -2051,6 +2108,11 @@ def is_response_bearing(cmd: Command) -> bool:
2051
2108
  if isinstance(cmd, CreateSectionBreak):
2052
2109
  # ``Document.add_section`` returns the section the answer names.
2053
2110
  return cmd.new_section is True
2111
+ if isinstance(cmd, SetStyleMetadata):
2112
+ # ``BaseStyle.style_id = …`` takes the new id once docx-studio renamed
2113
+ # the style: a refused rename raises at the call, and the style keeps
2114
+ # the id the document holds.
2115
+ return "id" in (cmd.metadata or {})
2054
2116
  return cmd.type in _RESPONSE_BEARING_TYPES
2055
2117
 
2056
2118
 
@@ -2188,6 +2250,8 @@ __all__ = [
2188
2250
  "ClearParagraphTabStops",
2189
2251
  "SetStyleFormatting",
2190
2252
  "CreateStyle",
2253
+ "EditLatentStyles",
2254
+ "DeleteStyle",
2191
2255
  "SetStyleMetadata",
2192
2256
  "SetCoreProperties",
2193
2257
  # Sections
@@ -62,6 +62,33 @@ class _DocxStudioWire:
62
62
  """``value`` as ``owner`` sends it: ``TypeError`` for a non-int,
63
63
  non-str value and ``ValueError`` for one naming no member, before
64
64
  anything reaches the wire."""
65
+ return cls._member_for(value, owner).to_docx_studio()
66
+
67
+ @classmethod
68
+ def _wire_for(cls, value: object, owner: str, session: Any, capability: str) -> str:
69
+ """``value`` as ``owner`` sends it to ``session``'s docx-studio: the
70
+ member's own string where an older docx-studio takes it too, or where
71
+ this one reports ``capability``; else :meth:`_wire`'s closest value,
72
+ with its warning. Only a value an older docx-studio collapses asks
73
+ docx-studio what it takes."""
74
+ import warnings
75
+
76
+ member = cls._member_for(value, owner)
77
+ exact = _wire_value(member)
78
+ with warnings.catch_warnings():
79
+ warnings.simplefilter("ignore")
80
+ collapsed = member.to_docx_studio()
81
+ if exact is None or exact == collapsed:
82
+ return collapsed
83
+ from docx._capabilities import server_takes
84
+
85
+ if session is not None and server_takes(session, capability):
86
+ return exact
87
+ return member.to_docx_studio()
88
+
89
+ @classmethod
90
+ def _member_for(cls, value: object, owner: str) -> Any:
91
+ """The member ``value`` names for ``owner``, validated as :meth:`_wire` says."""
65
92
  if not isinstance(value, (int, str)):
66
93
  raise TypeError(
67
94
  f"{owner} requires {cls.__name__}, int, or str; "
@@ -75,7 +102,7 @@ class _DocxStudioWire:
75
102
  f"{owner} = {value!r}: not a valid {cls.__name__}. "
76
103
  f"Expected a member or one of {[m.value for m in members]}."
77
104
  ) from exc
78
- return member.to_docx_studio()
105
+ return member
79
106
 
80
107
 
81
108
  class BaseEnum(_DocxStudioWire, int, enum.Enum):
@@ -242,28 +242,12 @@ def _warn_section_dimension_clear(prop: str) -> None:
242
242
 
243
243
 
244
244
  class PendingSectionOnOffClearWarning(UserWarning):
245
- """Emitted when ``Section.different_first_page_header_footer = None``.
246
-
247
- python-docx 1.x semantics: ``None`` clears the OOXML
248
- ``<w:titlePg/>`` element back to inherited. DOCX Studio 1.8's
249
- ``sections.set_title_page`` only accepts ``enabled: bool`` — the
250
- wire can't represent the clear-intent. The warning surfaces
251
- silent-divergence. Tracked in
252
- ``docx-studio/DOCX_STUDIO_LIMITATIONS.md``.
245
+ """No longer emitted: ``Section.different_first_page_header_footer =
246
+ None`` removes ``<w:titlePg/>`` as ``False`` does, as python-docx 1.x
247
+ does. Kept so code that filters or imports it keeps working.
253
248
  """
254
249
 
255
250
 
256
- def _warn_section_onoff_clear(prop: str) -> None:
257
- warnings.warn(
258
- f"Section.{prop} = None was IGNORED — DOCX Studio 1.8 has no "
259
- f"clear-op for this OnOff property. The section keeps its "
260
- f"previous value. Tracked in "
261
- f"docx-studio/DOCX_STUDIO_LIMITATIONS.md.",
262
- PendingSectionOnOffClearWarning,
263
- stacklevel=3,
264
- )
265
-
266
-
267
251
  def _require_section_bool(prop: str, value: object) -> bool:
268
252
  """Reject non-bool input on Section OnOff setters.
269
253
 
@@ -592,11 +576,12 @@ class Section:
592
576
 
593
577
  @different_first_page_header_footer.setter
594
578
  def different_first_page_header_footer(self, value: bool | None) -> None:
595
- if value is None:
596
- _warn_section_onoff_clear("different_first_page_header_footer")
597
- return
598
- enabled = _require_section_bool(
599
- "different_first_page_header_footer", value
579
+ # python-docx removes ``w:titlePg`` for ``None`` as for ``False``
580
+ # (``CT_SectPr.titlePg_val``), and so does docx-studio for ``False``.
581
+ enabled = (
582
+ False
583
+ if value is None
584
+ else _require_section_bool("different_first_page_header_footer", value)
600
585
  )
601
586
  run_sync(
602
587
  self._session.doc.sections.set_title_page(
@@ -204,11 +204,13 @@ def style_table(session: Any) -> tuple[StyleRecord, ...] | None:
204
204
  # same session): what an earlier read reported is no longer current.
205
205
  _latent.pop(session, None)
206
206
  _stale.discard(session)
207
- _writes_style_formatting[session] = bool(table) and any(
208
- record.font is not None for record in table
207
+ # A server that showed it writes styles still does once deletes leave its
208
+ # table without the entries that told: the signal holds for the session.
209
+ _writes_style_formatting[session] = _writes_style_formatting.get(session, False) or (
210
+ bool(table) and any(record.font is not None for record in table)
209
211
  )
210
- _writes_style_metadata[session] = bool(table) and any(
211
- record.metadata is not None for record in table
212
+ _writes_style_metadata[session] = _writes_style_metadata.get(session, False) or (
213
+ bool(table) and any(record.metadata is not None for record in table)
212
214
  )
213
215
  return table
214
216