athena-python-docx 0.6.0__tar.gz → 0.6.1__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 (302) hide show
  1. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/PKG-INFO +1 -1
  2. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/__init__.py +1 -1
  3. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/comments.py +20 -0
  4. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/document.py +31 -6
  5. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/enum/section.py +18 -0
  6. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/enum/text.py +27 -0
  7. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/section.py +87 -20
  8. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/shape.py +26 -0
  9. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/table.py +118 -19
  10. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/text/paragraph.py +163 -8
  11. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/text/run.py +172 -8
  12. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/pyproject.toml +1 -1
  13. athena_python_docx-0.6.0/tests/fidelity/op_snapshots/37_iterate_runs_and_format_all_bold.json → athena_python_docx-0.6.1/tests/fidelity/op_snapshots/03_runs_with_formatting.json +4 -4
  14. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/04_font_name_and_size.json +0 -1
  15. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/05_font_color_rgb.json +0 -1
  16. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/06_font_character_properties.json +0 -1
  17. athena_python_docx-0.6.1/tests/fidelity/op_snapshots/07_font_subscript_superscript.json +7 -0
  18. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/08_font_highlight.json +0 -1
  19. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/102_text_with_embedded_special_chars.json +0 -1
  20. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/14_run_add_tab_and_break.json +0 -1
  21. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/15_run_add_break_page.json +0 -1
  22. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/16_paragraph_clear_and_insert_before.json +0 -1
  23. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/35_full_report.json +0 -4
  24. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/36_replace_text_in_paragraph.json +0 -1
  25. athena_python_docx-0.6.0/tests/fidelity/op_snapshots/07_font_subscript_superscript.json → athena_python_docx-0.6.1/tests/fidelity/op_snapshots/37_iterate_runs_and_format_all_bold.json +3 -3
  26. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/38_font_all_properties.json +0 -1
  27. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/46_run_text_setter_round_trip.json +0 -1
  28. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/47_font_size_round_trip.json +0 -1
  29. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/48_font_color_round_trip.json +0 -1
  30. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/49_resume_layout.json +0 -7
  31. athena_python_docx-0.6.1/tests/fidelity/op_snapshots/54_empty_everything.json +4 -0
  32. athena_python_docx-0.6.0/tests/fidelity/op_snapshots/03_runs_with_formatting.json → athena_python_docx-0.6.1/tests/fidelity/op_snapshots/55_single_character_runs.json +2 -5
  33. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/56_everything_in_one.json +0 -6
  34. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/57_runs_after_multiple_text_appends.json +0 -3
  35. athena_python_docx-0.6.0/tests/fidelity/op_snapshots/55_single_character_runs.json → athena_python_docx-0.6.1/tests/fidelity/op_snapshots/58_modify_runs_in_place.json +3 -6
  36. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/68_invoice.json +0 -1
  37. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/69_newsletter.json +0 -9
  38. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/71_academic_paper.json +0 -2
  39. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/72_legal_contract.json +0 -6
  40. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/74_paragraph_with_10_runs.json +0 -10
  41. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/76_rgbcolor_from_string.json +0 -1
  42. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/80_apply_style_after_add_run.json +0 -1
  43. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/82_add_text_on_existing_run.json +0 -1
  44. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/83_clear_then_repopulate_paragraph.json +0 -2
  45. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/86_font_read_unset_returns_none.json +0 -1
  46. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/93_font_bool_reads_after_set.json +0 -1
  47. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/96_paragraph_contains_page_break.json +0 -1
  48. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/99_run_add_picture_from_bytes.json +0 -1
  49. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex02_unicode_everywhere.json +0 -3
  50. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex06_hundred_tiny_runs.json +0 -100
  51. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex07_every_font_boolean.json +0 -1
  52. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex16_runs_interleaved_with_breaks.json +0 -4
  53. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex17_all_break_kinds.json +0 -3
  54. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex19_mutate_all_runs.json +0 -15
  55. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex20_kitchen_sink_v2.json +0 -22
  56. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/mega01_book_chapter.json +0 -8
  57. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/mega02_research_proposal.json +0 -4
  58. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/mega03_financial_statement.json +0 -1
  59. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/mega04_recipe_card.json +0 -3
  60. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/mega05_user_manual.json +0 -3
  61. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/mega06_complex_newsletter.json +0 -17
  62. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/mega08_product_catalog.json +0 -15
  63. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/mega09_signed_contract.json +0 -11
  64. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/mega10_api_documentation.json +0 -7
  65. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw01_official_quickstart.json +0 -3
  66. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw03_character_formatting.json +0 -2
  67. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw06_meeting_minutes.json +0 -4
  68. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw07_dense_formatting_demo.json +0 -6
  69. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw09_bulk_run_iteration.json +0 -30
  70. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/parity/introspect.py +14 -0
  71. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/parity/reports/GAP_ANALYSIS.md +1 -1
  72. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/parity/reports/gap_report.json +297 -285
  73. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/parity/snapshots/athena_latest.json +287 -976
  74. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/parity/snapshots/upstream_python_docx_1.2.0.json +4046 -3115
  75. athena_python_docx-0.6.1/tests/test_collapsed_range_format.py +190 -0
  76. athena_python_docx-0.6.1/tests/test_paragraph_text_len_cache.py +161 -0
  77. athena_python_docx-0.6.1/tests/test_silent_stub_add_paragraph_style.py +67 -0
  78. athena_python_docx-0.6.1/tests/test_silent_stub_add_run.py +90 -0
  79. athena_python_docx-0.6.1/tests/test_silent_stub_cell_add_paragraph.py +47 -0
  80. athena_python_docx-0.6.1/tests/test_silent_stub_comments_add_comment.py +71 -0
  81. athena_python_docx-0.6.1/tests/test_silent_stub_enum_section.py +83 -0
  82. athena_python_docx-0.6.1/tests/test_silent_stub_inline_shape.py +105 -0
  83. athena_python_docx-0.6.1/tests/test_silent_stub_insert_paragraph_before.py +61 -0
  84. athena_python_docx-0.6.1/tests/test_silent_stub_paragraph_strict.py +170 -0
  85. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_paragraph_style.py +17 -9
  86. athena_python_docx-0.6.1/tests/test_silent_stub_paragraph_style_strict.py +93 -0
  87. athena_python_docx-0.6.1/tests/test_silent_stub_row_col_cell.py +181 -0
  88. athena_python_docx-0.6.1/tests/test_silent_stub_run_add_break.py +82 -0
  89. athena_python_docx-0.6.1/tests/test_silent_stub_run_style.py +57 -0
  90. athena_python_docx-0.6.1/tests/test_silent_stub_run_style_strict.py +71 -0
  91. athena_python_docx-0.6.1/tests/test_silent_stub_run_text.py +71 -0
  92. athena_python_docx-0.6.1/tests/test_silent_stub_run_underline.py +123 -0
  93. athena_python_docx-0.6.1/tests/test_silent_stub_section_dimensions.py +96 -0
  94. athena_python_docx-0.6.1/tests/test_silent_stub_section_onoff.py +83 -0
  95. athena_python_docx-0.6.1/tests/test_silent_stub_table_layout.py +153 -0
  96. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/uv.lock +1 -1
  97. athena_python_docx-0.6.0/tests/fidelity/op_snapshots/54_empty_everything.json +0 -6
  98. athena_python_docx-0.6.0/tests/fidelity/op_snapshots/58_modify_runs_in_place.json +0 -18
  99. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/.gitignore +0 -0
  100. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/CLAUDE.md +0 -0
  101. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/README.md +0 -0
  102. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/_batching.py +0 -0
  103. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/_buffer.py +0 -0
  104. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/_http.py +0 -0
  105. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/_http_doc.py +0 -0
  106. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/_image_utils.py +0 -0
  107. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/_ptc.py +0 -0
  108. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/api.py +0 -0
  109. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/client.py +0 -0
  110. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/commands.py +0 -0
  111. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/enum/__init__.py +0 -0
  112. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/enum/style.py +0 -0
  113. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/enum/table.py +0 -0
  114. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/errors.py +0 -0
  115. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/exceptions.py +0 -0
  116. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/opc/__init__.py +0 -0
  117. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/opc/coreprops.py +0 -0
  118. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/revisions.py +0 -0
  119. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/settings.py +0 -0
  120. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/shared.py +0 -0
  121. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/styles/__init__.py +0 -0
  122. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/styles/style.py +0 -0
  123. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/styles/styles.py +0 -0
  124. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/text/__init__.py +0 -0
  125. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/text/font.py +0 -0
  126. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/text/hyperlink.py +0 -0
  127. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/text/pagebreak.py +0 -0
  128. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/text/parfmt.py +0 -0
  129. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/text/tabstops.py +0 -0
  130. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/typing.py +0 -0
  131. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/scripts/publish.sh +0 -0
  132. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/scripts/release.sh +0 -0
  133. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/scripts/round_trip_smoke.py +0 -0
  134. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/__init__.py +0 -0
  135. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/conftest.py +0 -0
  136. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/METHODOLOGY.md +0 -0
  137. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/README.md +0 -0
  138. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/__init__.py +0 -0
  139. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/ab_probe_cases.py +0 -0
  140. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/ab_probe_runner.py +0 -0
  141. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/auto_gen_cases.py +0 -0
  142. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/binary_round_trip.py +0 -0
  143. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/cases.py +0 -0
  144. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/complex_cases.py +0 -0
  145. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/coverage_report.py +0 -0
  146. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/extract.py +0 -0
  147. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/extreme_cases.py +0 -0
  148. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/fake_session.py +0 -0
  149. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/local_runner.py +0 -0
  150. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/mega_cases.py +0 -0
  151. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshot.py +0 -0
  152. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/01_basic_paragraph.json +0 -0
  153. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/02_multiple_headings.json +0 -0
  154. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/09_paragraph_alignment.json +0 -0
  155. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/100_table_negative_indexing.json +0 -0
  156. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/101_table_cells_flat_iteration.json +0 -0
  157. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/103_cell_tables_enumeration.json +0 -0
  158. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/104_core_properties_datetime.json +0 -0
  159. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/105_default_one_section.json +0 -0
  160. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/106_heading_paragraph_format.json +0 -0
  161. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/107_varying_row_heights.json +0 -0
  162. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/10_paragraph_indents.json +0 -0
  163. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/11_paragraph_spacing.json +0 -0
  164. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/12_paragraph_keep_options.json +0 -0
  165. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/13_paragraph_tab_stops.json +0 -0
  166. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/17_table_basic.json +0 -0
  167. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/18_table_cell_text.json +0 -0
  168. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/19_table_row_column_sizing.json +0 -0
  169. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/20_table_cell_vertical_alignment.json +0 -0
  170. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/21_table_alignment_and_autofit.json +0 -0
  171. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/22_table_cell_paragraphs_iteration.json +0 -0
  172. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/23_nested_table.json +0 -0
  173. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/24_table_add_row_column.json +0 -0
  174. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/25_table_merge_cells.json +0 -0
  175. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/26_section_page_setup.json +0 -0
  176. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/27_section_margins.json +0 -0
  177. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/28_section_add_new.json +0 -0
  178. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/29_section_headers_linked.json +0 -0
  179. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/30_styles_iteration.json +0 -0
  180. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/31_styles_lookup_and_default.json +0 -0
  181. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/32_styles_add_paragraph_style.json +0 -0
  182. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/33_core_properties_set_and_get.json +0 -0
  183. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/34_inline_shapes_iterate_empty.json +0 -0
  184. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/39_large_body_100_paragraphs.json +0 -0
  185. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/40_large_table_10x10.json +0 -0
  186. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/41_unicode_and_emoji.json +0 -0
  187. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/42_very_long_paragraph.json +0 -0
  188. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/43_paragraph_text_round_trip.json +0 -0
  189. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/44_paragraph_alignment_round_trip.json +0 -0
  190. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/45_cell_text_round_trip.json +0 -0
  191. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/50_multi_section_doc.json +0 -0
  192. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/51_nested_tables_deep.json +0 -0
  193. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/52_iterate_everything.json +0 -0
  194. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/53_apply_style_to_paragraphs.json +0 -0
  195. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/59_indent_round_trip.json +0 -0
  196. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/60_space_round_trip.json +0 -0
  197. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/61_cell_paragraph_with_runs.json +0 -0
  198. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/62_many_cell_paragraphs.json +0 -0
  199. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/63_table_style_round_trip.json +0 -0
  200. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/64_many_sections.json +0 -0
  201. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/65_20x20_table_formatted.json +0 -0
  202. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/66_toc_like_structure.json +0 -0
  203. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/67_paragraph_insert_before_chain.json +0 -0
  204. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/70_add_and_iterate_back.json +0 -0
  205. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/73_form_with_many_tables.json +0 -0
  206. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/75_paragraph_negative_first_line_indent.json +0 -0
  207. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/77_length_unit_conversions.json +0 -0
  208. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/78_paragraph_copy_style.json +0 -0
  209. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/79_bulk_cell_formatting.json +0 -0
  210. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/81_multi_page_with_breaks.json +0 -0
  211. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/84_table_reread_row_count.json +0 -0
  212. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/85_header_footer_access.json +0 -0
  213. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/87_500_paragraph_doc.json +0 -0
  214. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/88_mixed_content_iteration.json +0 -0
  215. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/89_alignment_clear_via_none.json +0 -0
  216. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/90_cell_add_paragraph_styled.json +0 -0
  217. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/91_many_small_tables.json +0 -0
  218. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/92_margins_every_section.json +0 -0
  219. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/94_page_break_before_paragraph.json +0 -0
  220. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/95_paragraph_hyperlinks_empty.json +0 -0
  221. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/97_document_styles_by_key.json +0 -0
  222. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/98_style_contains_check.json +0 -0
  223. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex01_five_levels_deep_tables.json +0 -0
  224. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex03_1000_paragraphs.json +0 -0
  225. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex04_50x50_table.json +0 -0
  226. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex05_long_text_in_cell.json +0 -0
  227. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex08_many_continuous_sections.json +0 -0
  228. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex09_many_tab_stops.json +0 -0
  229. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex10_complex_bom.json +0 -0
  230. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex11_banded_rows_formatting.json +0 -0
  231. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex12_section_reconfigure.json +0 -0
  232. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex13_cell_with_10_paragraphs.json +0 -0
  233. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex14_styled_report_table.json +0 -0
  234. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex15_paragraph_all_format_props.json +0 -0
  235. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex18_read_back_large_doc.json +0 -0
  236. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/mega07_budget_spreadsheet.json +0 -0
  237. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw02_paragraph_style_list.json +0 -0
  238. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw04_section_page_setup.json +0 -0
  239. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw05_toc_pattern.json +0 -0
  240. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw08_table_merged_header.json +0 -0
  241. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw10_colored_grid_table.json +0 -0
  242. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw11_header_text.json +0 -0
  243. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw12_first_page_footer.json +0 -0
  244. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw13_even_page_header.json +0 -0
  245. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw14_nested_cell_table.json +0 -0
  246. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw15_paragraph_style_instance.json +0 -0
  247. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/ours_spec.json +0 -0
  248. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/parity_crawl.py +0 -0
  249. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/parity_diff.json +0 -0
  250. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/real_world_cases.py +0 -0
  251. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/round_trip_tests.py +0 -0
  252. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/runner.py +0 -0
  253. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/stock_spec.json +0 -0
  254. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/parity/README.md +0 -0
  255. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/parity/__init__.py +0 -0
  256. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/parity/baseline_gaps.json +0 -0
  257. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/parity/compare.py +0 -0
  258. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/parity/intentional_deviations.json +0 -0
  259. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/parity/run_parity.py +0 -0
  260. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/parity/test_parity_gap.py +0 -0
  261. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_batching_perf.py +0 -0
  262. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_buffer.py +0 -0
  263. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_command_dataclasses.py +0 -0
  264. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_commands.py +0 -0
  265. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_comments.py +0 -0
  266. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_document_create.py +0 -0
  267. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_http_transport.py +0 -0
  268. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_iter_inner_content.py +0 -0
  269. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_merged_cells.py +0 -0
  270. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_parity_misc.py +0 -0
  271. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_parity_round2.py +0 -0
  272. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_phase_a_behavior.py +0 -0
  273. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_phase_b_headers_footers.py +0 -0
  274. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_phase_c_tables.py +0 -0
  275. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_pr19766_review_fixes.py +0 -0
  276. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_ptc.py +0 -0
  277. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_python_docx_api_parity.py +0 -0
  278. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_revisions.py +0 -0
  279. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_add_picture.py +0 -0
  280. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_comments_get.py +0 -0
  281. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_document_audit.py +0 -0
  282. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_document_element.py +0 -0
  283. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_font_audit.py +0 -0
  284. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_header_footer.py +0 -0
  285. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_hyperlink.py +0 -0
  286. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_misc.py +0 -0
  287. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_parfmt.py +0 -0
  288. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_run_bool_setters.py +0 -0
  289. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_section_audit.py +0 -0
  290. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_settings.py +0 -0
  291. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_shared_audit.py +0 -0
  292. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_style.py +0 -0
  293. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_styles.py +0 -0
  294. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_table_audit.py +0 -0
  295. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_table_cell.py +0 -0
  296. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_table_dimensions.py +0 -0
  297. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_smoke_integration.py +0 -0
  298. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_style_acceptance.py +0 -0
  299. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_style_font.py +0 -0
  300. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_style_setters_contract.py +0 -0
  301. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_wire_contract.py +0 -0
  302. {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_zod_wire_contract.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: athena-python-docx
3
- Version: 0.6.0
3
+ Version: 0.6.1
4
4
  Summary: Drop-in replacement for python-docx that connects to Athena's Superdoc/Keryx collaborative document stack
5
5
  Project-URL: Homepage, https://athenaintelligence.ai
6
6
  Author-email: Athena Intelligence <engineering@athenaintelligence.ai>
@@ -6,7 +6,7 @@ See CLAUDE.md for the API parity contract.
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
- __version__ = "0.6.0"
9
+ __version__ = "0.6.1"
10
10
 
11
11
  from docx.api import Document
12
12
  from docx._buffer import flush_all
@@ -314,6 +314,26 @@ class Comments:
314
314
  Use :meth:`Document.add_comment` to thread a run-anchored
315
315
  target — this method creates an unanchored comment.
316
316
  """
317
+ # python-docx 1.x routes ``text`` / ``author`` / ``initials``
318
+ # through lxml's element setters which TypeError on non-str.
319
+ # Was: any value shipped to wire (text) or stashed as-is on
320
+ # the local info dict (author/initials) — caller's intent was
321
+ # lost when they passed a wrong type.
322
+ if not isinstance(text, str):
323
+ raise TypeError(
324
+ f"Comments.add_comment text requires str; got "
325
+ f"{type(text).__name__} {text!r}",
326
+ )
327
+ if not isinstance(author, str):
328
+ raise TypeError(
329
+ f"Comments.add_comment author requires str; got "
330
+ f"{type(author).__name__} {author!r}",
331
+ )
332
+ if initials is not None and not isinstance(initials, str):
333
+ raise TypeError(
334
+ f"Comments.add_comment initials requires str or None; "
335
+ f"got {type(initials).__name__} {initials!r}",
336
+ )
317
337
  result: object = run_sync(
318
338
  self._session.doc.comments.create({"text": text}),
319
339
  )
@@ -596,9 +596,24 @@ class Document:
596
596
 
597
597
  # Coerce ParagraphStyle instances to their style id so the rest
598
598
  # of this method can treat `style` as an Optional[str].
599
- style_str: str | None = (
600
- style.style_id if isinstance(style, ParagraphStyle) else style
601
- )
599
+ # python-docx 1.x accepts ``str | ParagraphStyle | None`` and
600
+ # raises ``TypeError`` at the style-lookup layer for anything
601
+ # else. Mirror that — the previous code accepted ``style`` as
602
+ # the literal value when it wasn't a ParagraphStyle, so e.g.
603
+ # ``add_paragraph(style=42)`` shipped ``42`` as the style id.
604
+ style_str: str | None
605
+ if style is None:
606
+ style_str = None
607
+ elif isinstance(style, ParagraphStyle):
608
+ style_str = style.style_id
609
+ elif isinstance(style, str):
610
+ style_str = style
611
+ else:
612
+ raise TypeError(
613
+ f"Document.add_paragraph style requires str, "
614
+ f"ParagraphStyle, or None; got "
615
+ f"{type(style).__name__} {style!r}",
616
+ )
602
617
 
603
618
  # Use Superdoc's canonical primitive `doc.create.paragraph`. It
604
619
  # accepts an `at` anchor and a `text` body; an empty `text` creates
@@ -624,8 +639,9 @@ class Document:
624
639
  # heavy lifting.
625
640
  normalized: str = self._normalize_text(text)
626
641
  has_control_chars = any(ch in "\t\n\r" for ch in normalized)
642
+ wire_text: str = "" if has_control_chars else normalized
627
643
  params: dict = {
628
- "text": "" if has_control_chars else normalized,
644
+ "text": wire_text,
629
645
  "at": {"kind": "documentEnd"},
630
646
  }
631
647
  # When inside ``with doc.batch():`` we pre-assign a client UUID
@@ -650,8 +666,13 @@ class Document:
650
666
  raise RuntimeError(
651
667
  f"Superdoc did not return a nodeId for add_paragraph: {result!r}",
652
668
  )
669
+ # Seed the text-length cache so the next ``p.add_run(...)``
670
+ # call can skip its ``get_node_by_id`` HTTP round-trip.
653
671
  para = Paragraph(
654
- session=self._session, node_id=node_id, node_type="paragraph",
672
+ session=self._session,
673
+ node_id=node_id,
674
+ node_type="paragraph",
675
+ text_len=len(wire_text),
655
676
  )
656
677
  if client_node_id is not None:
657
678
  self._register_proxy_for_batch(client_node_id, para)
@@ -722,6 +743,7 @@ class Document:
722
743
  session=self._session,
723
744
  node_id=node_id,
724
745
  node_type="paragraph",
746
+ text_len=len(wire_text),
725
747
  )
726
748
  if client_node_id is not None:
727
749
  self._register_proxy_for_batch(client_node_id, paragraph)
@@ -753,7 +775,10 @@ class Document:
753
775
  f"Superdoc did not return a nodeId for add_heading: {result!r}",
754
776
  )
755
777
  heading = Paragraph(
756
- session=self._session, node_id=node_id, node_type="heading",
778
+ session=self._session,
779
+ node_id=node_id,
780
+ node_type="heading",
781
+ text_len=len(wire_text),
757
782
  )
758
783
  if client_node_id is not None:
759
784
  self._register_proxy_for_batch(client_node_id, heading)
@@ -4,6 +4,17 @@ from __future__ import annotations
4
4
 
5
5
  from enum import Enum
6
6
 
7
+ from docx.enum.text import _warn_enum_coercion
8
+
9
+ __all__ = [
10
+ "WD_HEADER_FOOTER",
11
+ "WD_HEADER_FOOTER_INDEX",
12
+ "WD_ORIENT",
13
+ "WD_ORIENTATION",
14
+ "WD_SECTION",
15
+ "WD_SECTION_START",
16
+ ]
17
+
7
18
 
8
19
  class WD_ORIENTATION(Enum):
9
20
  PORTRAIT = "portrait"
@@ -31,6 +42,13 @@ class WD_SECTION_START(Enum):
31
42
  return "evenPage"
32
43
  if self == WD_SECTION_START.ODD_PAGE:
33
44
  return "oddPage"
45
+ if self == WD_SECTION_START.NEW_PAGE:
46
+ return "nextPage"
47
+ # NEW_COLUMN — SuperDoc 1.8 doesn't have a column-break section
48
+ # type, so we collapse to "nextPage" but emit
49
+ # PendingEnumCoercionWarning so callers don't silently get a
50
+ # page break when they asked for a column break.
51
+ _warn_enum_coercion(self, "nextPage")
34
52
  return "nextPage"
35
53
 
36
54
 
@@ -13,6 +13,19 @@ import warnings
13
13
  from enum import Enum
14
14
 
15
15
 
16
+ _INT_TO_ALIGN: "dict[int, str]" = {
17
+ 0: "LEFT",
18
+ 1: "CENTER",
19
+ 2: "RIGHT",
20
+ 3: "JUSTIFY",
21
+ 4: "DISTRIBUTE",
22
+ 5: "JUSTIFY_MED",
23
+ 7: "JUSTIFY_HI",
24
+ 8: "JUSTIFY_LOW",
25
+ 9: "THAI_JUSTIFY",
26
+ }
27
+
28
+
16
29
  class PendingEnumCoercionWarning(UserWarning):
17
30
  """Emitted when an enum member's :meth:`to_superdoc` collapses the
18
31
  value to a different SuperDoc-supported primitive.
@@ -58,6 +71,20 @@ class WD_ALIGN_PARAGRAPH(Enum):
58
71
  JUSTIFY_LOW = "justifyLow"
59
72
  THAI_JUSTIFY = "thaiJustify"
60
73
 
74
+ @classmethod
75
+ def from_int(cls, value: int) -> "WD_ALIGN_PARAGRAPH | None":
76
+ """Coerce a python-docx-style int alignment to the enum.
77
+
78
+ python-docx 1.x's ``WD_ALIGN_PARAGRAPH`` is keyed on int (its
79
+ ``BaseXmlEnum`` mapping: LEFT=0, CENTER=1, RIGHT=2, JUSTIFY=3,
80
+ DISTRIBUTE=4, JUSTIFY_MED=5, JUSTIFY_HI=7, JUSTIFY_LOW=8,
81
+ THAI_JUSTIFY=9). Callers passing ``paragraph.alignment = 1``
82
+ get CENTER. We mirror that without changing our enum's
83
+ string-valued definition.
84
+ """
85
+ name = _INT_TO_ALIGN.get(value)
86
+ return getattr(cls, name) if name is not None else None
87
+
61
88
  def to_superdoc(self) -> str:
62
89
  # Superdoc only supports left/center/right/justify; coerce the
63
90
  # distributed/thai variants to "justify" so set_alignment doesn't
@@ -83,6 +83,66 @@ def _emu_to_pt(emu: int) -> float:
83
83
  return emu / 12700.0
84
84
 
85
85
 
86
+ def _reject_none_dimension(prop: str, value: object) -> None:
87
+ """Raise ``TypeError`` if ``value`` is None for a dimension setter
88
+ that python-docx 1.2.0 doesn't accept None for.
89
+
90
+ Upstream ``Section.page_width = None`` (and every margin /
91
+ header_distance / footer_distance / gutter setter) routes through
92
+ ``Emu(value).twips`` which raises ``TypeError`` on ``None``. Our
93
+ setters previously early-returned silently, swallowing the
94
+ intent. Raise to match upstream behavior — callers who actually
95
+ want a clear must pass ``Inches(0)`` (or similar) explicitly.
96
+ """
97
+ if value is None:
98
+ raise TypeError(
99
+ f"Section.{prop} = None is not supported. python-docx "
100
+ f"1.2.0 raises TypeError here too — its Emu(None).twips "
101
+ f"fails with the same shape. Pass an explicit Length "
102
+ f"(e.g. Inches(0)) if you want to zero the dimension."
103
+ )
104
+
105
+
106
+ class PendingSectionOnOffClearWarning(UserWarning):
107
+ """Emitted when ``Section.different_first_page_header_footer = None``.
108
+
109
+ python-docx 1.x semantics: ``None`` clears the OOXML
110
+ ``<w:titlePg/>`` element back to inherited. SuperDoc 1.8's
111
+ ``sections.set_title_page`` only accepts ``enabled: bool`` — the
112
+ wire can't represent the clear-intent. The warning surfaces
113
+ silent-divergence. Tracked in
114
+ ``docx-studio/SUPERDOC_UPSTREAM_REQUESTS.md``.
115
+ """
116
+
117
+
118
+ def _warn_section_onoff_clear(prop: str) -> None:
119
+ warnings.warn(
120
+ f"Section.{prop} = None was IGNORED — SuperDoc 1.8 has no "
121
+ f"clear-op for this OnOff property. The section keeps its "
122
+ f"previous value. Tracked in "
123
+ f"docx-studio/SUPERDOC_UPSTREAM_REQUESTS.md.",
124
+ PendingSectionOnOffClearWarning,
125
+ stacklevel=3,
126
+ )
127
+
128
+
129
+ def _require_section_bool(prop: str, value: object) -> bool:
130
+ """Reject non-bool input on Section OnOff setters.
131
+
132
+ python-docx 1.x's ``_OnOff`` typed-attribute setter raises
133
+ ``ValueError`` for non-bool input. Our previous ``bool(value)``
134
+ coercion silently turned ``"yes"`` / ``1`` / ``[]`` into True/False
135
+ without surfacing the type mismatch.
136
+ """
137
+ if not isinstance(value, bool):
138
+ raise TypeError(
139
+ f"Section.{prop} requires bool or None; got "
140
+ f"{type(value).__name__} {value!r}. python-docx 1.x's "
141
+ f"``_OnOff`` setter rejects truthy non-bool here too.",
142
+ )
143
+ return value
144
+
145
+
86
146
  class Section:
87
147
  """A document section — page size, margins, headers/footers, break type."""
88
148
 
@@ -124,8 +184,7 @@ class Section:
124
184
 
125
185
  @page_width.setter
126
186
  def page_width(self, value: "Length | int | None") -> None:
127
- if value is None:
128
- return
187
+ _reject_none_dimension("page_width", value)
129
188
  pt = _emu_to_pt(_emu_from(value))
130
189
  self._set_page_setup(width=pt)
131
190
 
@@ -140,8 +199,7 @@ class Section:
140
199
 
141
200
  @page_height.setter
142
201
  def page_height(self, value: "Length | int | None") -> None:
143
- if value is None:
144
- return
202
+ _reject_none_dimension("page_height", value)
145
203
  pt = _emu_to_pt(_emu_from(value))
146
204
  self._set_page_setup(height=pt)
147
205
 
@@ -201,8 +259,7 @@ class Section:
201
259
 
202
260
  @left_margin.setter
203
261
  def left_margin(self, value: "Length | int | None") -> None:
204
- if value is None:
205
- return
262
+ _reject_none_dimension("left_margin", value)
206
263
  self._set_margins(left=_emu_to_pt(_emu_from(value)))
207
264
 
208
265
  @property
@@ -211,8 +268,7 @@ class Section:
211
268
 
212
269
  @right_margin.setter
213
270
  def right_margin(self, value: "Length | int | None") -> None:
214
- if value is None:
215
- return
271
+ _reject_none_dimension("right_margin", value)
216
272
  self._set_margins(right=_emu_to_pt(_emu_from(value)))
217
273
 
218
274
  @property
@@ -221,8 +277,7 @@ class Section:
221
277
 
222
278
  @top_margin.setter
223
279
  def top_margin(self, value: "Length | int | None") -> None:
224
- if value is None:
225
- return
280
+ _reject_none_dimension("top_margin", value)
226
281
  self._set_margins(top=_emu_to_pt(_emu_from(value)))
227
282
 
228
283
  @property
@@ -231,8 +286,7 @@ class Section:
231
286
 
232
287
  @bottom_margin.setter
233
288
  def bottom_margin(self, value: "Length | int | None") -> None:
234
- if value is None:
235
- return
289
+ _reject_none_dimension("bottom_margin", value)
236
290
  self._set_margins(bottom=_emu_to_pt(_emu_from(value)))
237
291
 
238
292
  @property
@@ -241,8 +295,7 @@ class Section:
241
295
 
242
296
  @gutter.setter
243
297
  def gutter(self, value: "Length | int | None") -> None:
244
- if value is None:
245
- return
298
+ _reject_none_dimension("gutter", value)
246
299
  self._set_margins(gutter=_emu_to_pt(_emu_from(value)))
247
300
 
248
301
  @property
@@ -256,8 +309,7 @@ class Section:
256
309
 
257
310
  @header_distance.setter
258
311
  def header_distance(self, value: "Length | int | None") -> None:
259
- if value is None:
260
- return
312
+ _reject_none_dimension("header_distance", value)
261
313
  run_sync(
262
314
  self._session.doc.sections.set_header_footer_margins(
263
315
  {"target": self._address, "header": _emu_to_pt(_emu_from(value))},
@@ -275,8 +327,7 @@ class Section:
275
327
 
276
328
  @footer_distance.setter
277
329
  def footer_distance(self, value: "Length | int | None") -> None:
278
- if value is None:
279
- return
330
+ _reject_none_dimension("footer_distance", value)
280
331
  run_sync(
281
332
  self._session.doc.sections.set_header_footer_margins(
282
333
  {"target": self._address, "footer": _emu_to_pt(_emu_from(value))},
@@ -335,14 +386,18 @@ class Section:
335
386
  @different_first_page_header_footer.setter
336
387
  def different_first_page_header_footer(self, value: bool | None) -> None:
337
388
  if value is None:
389
+ _warn_section_onoff_clear("different_first_page_header_footer")
338
390
  return
391
+ enabled = _require_section_bool(
392
+ "different_first_page_header_footer", value
393
+ )
339
394
  run_sync(
340
395
  self._session.doc.sections.set_title_page(
341
396
  # SuperDoc's wire field is ``enabled`` (DocSectionsSet
342
397
  # TitlePageParams). The earlier ``titlePage`` name was
343
398
  # rejected silently because the apps/api applier punts
344
399
  # SuperDoc's strict types via ``AnyDoc``.
345
- {"target": self._address, "enabled": bool(value)},
400
+ {"target": self._address, "enabled": enabled},
346
401
  ),
347
402
  )
348
403
 
@@ -622,8 +677,20 @@ class _HeaderFooter:
622
677
  style_str = None
623
678
  elif isinstance(style, ParagraphStyle):
624
679
  style_str = style.style_id
680
+ elif isinstance(style, str):
681
+ style_str = style
625
682
  else:
626
- style_str = str(style)
683
+ # python-docx 1.x's ``add_paragraph(style=...)`` accepts
684
+ # ``str | ParagraphStyle | None`` and raises ``TypeError``
685
+ # at the style-lookup layer for anything else. The
686
+ # previous ``str(style)`` silently shipped garbage like
687
+ # ``<MyStyle object at 0x...>`` as a style id, which
688
+ # SuperDoc would swallow or reject without a clear signal.
689
+ raise TypeError(
690
+ f"_HeaderFooter.add_paragraph style requires str, "
691
+ f"ParagraphStyle, or None; got "
692
+ f"{type(style).__name__} {style!r}",
693
+ )
627
694
 
628
695
  result: object = run_sync(
629
696
  self._section._session.doc.create.paragraph(
@@ -7,6 +7,7 @@ to image binary / metadata round-trips through `doc.images.get`.
7
7
  from __future__ import annotations
8
8
 
9
9
  import base64
10
+ import warnings
10
11
  from typing import TYPE_CHECKING
11
12
 
12
13
  from docx._batching import run_sync
@@ -16,6 +17,29 @@ if TYPE_CHECKING:
16
17
  from docx.client import Session
17
18
 
18
19
 
20
+ class PendingInlineShapeClearWarning(UserWarning):
21
+ """Emitted when ``InlineShape.width`` or ``.height`` is set to
22
+ ``None`` (python-docx semantics: "revert to natural sizing").
23
+
24
+ SuperDoc 1.8 has no clear-op for image dimensions — its
25
+ ``images.setSize`` requires explicit ``width`` and ``height``. The
26
+ SDK can't represent a "revert to natural" intent on the wire, so
27
+ ``image.width = None`` is a no-op. The warning surfaces the
28
+ silent-divergence pattern so agent runs see the gap. Tracked in
29
+ ``docx-studio/SUPERDOC_UPSTREAM_REQUESTS.md``.
30
+ """
31
+
32
+
33
+ def _warn_inline_shape_clear(prop: str) -> None:
34
+ warnings.warn(
35
+ f"InlineShape.{prop} = None was IGNORED — SuperDoc 1.8 has no "
36
+ f"clear-op for image dimensions. The image keeps its previous "
37
+ f"size. Tracked in docx-studio/SUPERDOC_UPSTREAM_REQUESTS.md.",
38
+ PendingInlineShapeClearWarning,
39
+ stacklevel=3,
40
+ )
41
+
42
+
19
43
  def _strip_data_uri(src: str) -> tuple[bytes, str | None]:
20
44
  """If ``src`` is a ``data:`` URI, return (decoded_bytes, mime).
21
45
  Otherwise return ``(b"", None)``."""
@@ -63,6 +87,7 @@ class InlineShape:
63
87
  @width.setter
64
88
  def width(self, value: "Length | int | None") -> None:
65
89
  if value is None:
90
+ _warn_inline_shape_clear("width")
66
91
  return
67
92
  pt: float = value.pt if isinstance(value, Length) else float(value) / 12700.0
68
93
  h = self.height
@@ -92,6 +117,7 @@ class InlineShape:
92
117
  @height.setter
93
118
  def height(self, value: "Length | int | None") -> None:
94
119
  if value is None:
120
+ _warn_inline_shape_clear("height")
95
121
  return
96
122
  pt: float = value.pt if isinstance(value, Length) else float(value) / 12700.0
97
123
  w = self.width
@@ -3,12 +3,41 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import sys
6
+ import warnings
6
7
  from typing import TYPE_CHECKING
7
8
 
8
9
  from docx._batching import run_sync
9
10
  from docx.errors import ValidationError
10
11
  from docx.shared import Length, Pt
11
12
 
13
+
14
+ class PendingTableClearWarning(UserWarning):
15
+ """Emitted when a ``Table`` / ``_Row`` / ``_Column`` / ``_Cell``
16
+ setter is asked to clear a property (``None`` assignment) that
17
+ python-docx 1.x supports but SuperDoc 1.8 has no clear-op for.
18
+
19
+ Covers: ``Table.alignment / direction / autofit``,
20
+ ``_Row.height / height_rule``, ``_Column.width``,
21
+ ``_Cell.width / vertical_alignment``. SuperDoc's
22
+ ``tables.set_layout`` / ``set_row_height`` / ``set_column_width``
23
+ / ``set_cell_properties`` require explicit values — the wire
24
+ can't represent the python-docx "revert to inherited" intent.
25
+ The warning surfaces the silent-divergence so agent runs see
26
+ the gap. Tracked in
27
+ ``docx-studio/SUPERDOC_UPSTREAM_REQUESTS.md``.
28
+ """
29
+
30
+
31
+ def _warn_table_clear(prop: str, *, cls: str = "Table") -> None:
32
+ warnings.warn(
33
+ f"{cls}.{prop} = None was IGNORED — SuperDoc 1.8 has no "
34
+ f"clear-op for this property. The {cls.lower()} keeps its "
35
+ f"previous value. Tracked in "
36
+ f"docx-studio/SUPERDOC_UPSTREAM_REQUESTS.md.",
37
+ PendingTableClearWarning,
38
+ stacklevel=3,
39
+ )
40
+
12
41
  if TYPE_CHECKING:
13
42
  from docx.client import Session
14
43
  from docx.enum.table import (
@@ -420,12 +449,28 @@ class Table:
420
449
  from docx.enum.table import WD_TABLE_ALIGNMENT
421
450
 
422
451
  if value is None:
452
+ _warn_table_clear("alignment")
423
453
  return
424
- v: str = (
425
- value.to_superdoc()
426
- if isinstance(value, WD_TABLE_ALIGNMENT)
427
- else str(value).lower()
428
- )
454
+ if isinstance(value, WD_TABLE_ALIGNMENT):
455
+ v: str = value.to_superdoc()
456
+ elif isinstance(value, str):
457
+ # python-docx coerces strings through the enum and raises
458
+ # ``ValueError`` for non-member values. Mirror that here
459
+ # instead of shipping bogus ``str(value).lower()`` to
460
+ # SuperDoc, which would silently swallow unknowns.
461
+ try:
462
+ v = WD_TABLE_ALIGNMENT(value).to_superdoc()
463
+ except (ValueError, KeyError) as exc:
464
+ raise ValueError(
465
+ f"Table.alignment = {value!r}: not a valid "
466
+ f"WD_TABLE_ALIGNMENT. Expected one of "
467
+ f"{[m.value for m in WD_TABLE_ALIGNMENT]}."
468
+ ) from exc
469
+ else:
470
+ raise TypeError(
471
+ f"Table.alignment requires WD_TABLE_ALIGNMENT, str, "
472
+ f"or None; got {type(value).__name__}",
473
+ )
429
474
  # SuperDoc 1.8.1: alignment is a setLayout field, not a
430
475
  # setTableOptions field. The earlier setTableOptions call
431
476
  # silently dropped the value (Zod validated, AnyDoc punt let
@@ -456,12 +501,24 @@ class Table:
456
501
  from docx.enum.table import WD_TABLE_DIRECTION
457
502
 
458
503
  if value is None:
504
+ _warn_table_clear("direction")
459
505
  return
460
- v: str = (
461
- value.to_superdoc()
462
- if isinstance(value, WD_TABLE_DIRECTION)
463
- else str(value).lower()
464
- )
506
+ if isinstance(value, WD_TABLE_DIRECTION):
507
+ v: str = value.to_superdoc()
508
+ elif isinstance(value, str):
509
+ try:
510
+ v = WD_TABLE_DIRECTION(value).to_superdoc()
511
+ except (ValueError, KeyError) as exc:
512
+ raise ValueError(
513
+ f"Table.direction = {value!r}: not a valid "
514
+ f"WD_TABLE_DIRECTION. Expected one of "
515
+ f"{[m.value for m in WD_TABLE_DIRECTION]}."
516
+ ) from exc
517
+ else:
518
+ raise TypeError(
519
+ f"Table.direction requires WD_TABLE_DIRECTION, str, "
520
+ f"or None; got {type(value).__name__}",
521
+ )
465
522
  # SuperDoc's setLayout takes ``tableDirection`` (not
466
523
  # ``direction``). Same diagnostic as alignment above —
467
524
  # setTableOptions silently swallowed the field.
@@ -488,7 +545,15 @@ class Table:
488
545
  @autofit.setter
489
546
  def autofit(self, value: bool | None) -> None:
490
547
  if value is None:
548
+ _warn_table_clear("autofit")
491
549
  return
550
+ if not isinstance(value, bool):
551
+ raise TypeError(
552
+ f"Table.autofit requires bool or None; got "
553
+ f"{type(value).__name__} {value!r}. python-docx 1.x "
554
+ f"is a ``_OnOff`` setter and rejects truthy non-bool "
555
+ f"here too.",
556
+ )
492
557
  run_sync(
493
558
  self._session.doc.tables.set_layout(
494
559
  {
@@ -614,6 +679,7 @@ class _Row:
614
679
  @height.setter
615
680
  def height(self, value: "Length | int | None") -> None:
616
681
  if value is None:
682
+ _warn_table_clear("height", cls="_Row")
617
683
  return
618
684
  # Mirror python-docx: row height is stored as unsigned twips
619
685
  # (``ST_TwipsMeasure``), so negative inputs raise ``ValueError``
@@ -663,12 +729,27 @@ class _Row:
663
729
  from docx.enum.table import WD_ROW_HEIGHT_RULE
664
730
 
665
731
  if value is None:
732
+ _warn_table_clear("height_rule", cls="_Row")
666
733
  return
667
- rule: str = (
668
- value.to_superdoc()
669
- if isinstance(value, WD_ROW_HEIGHT_RULE)
670
- else str(value)
671
- )
734
+ if isinstance(value, WD_ROW_HEIGHT_RULE):
735
+ rule: str = value.to_superdoc()
736
+ elif isinstance(value, str):
737
+ # python-docx coerces strings through the enum and raises
738
+ # on misses. Was: ``str(value)`` shipped any value to the
739
+ # wire (SuperDoc swallowed unknowns silently).
740
+ try:
741
+ rule = WD_ROW_HEIGHT_RULE(value).to_superdoc()
742
+ except (ValueError, KeyError) as exc:
743
+ raise ValueError(
744
+ f"_Row.height_rule = {value!r}: not a valid "
745
+ f"WD_ROW_HEIGHT_RULE. Expected one of "
746
+ f"{[m.value for m in WD_ROW_HEIGHT_RULE]}."
747
+ ) from exc
748
+ else:
749
+ raise TypeError(
750
+ f"_Row.height_rule requires WD_ROW_HEIGHT_RULE, str, "
751
+ f"or None; got {type(value).__name__}",
752
+ )
672
753
  h = self.height
673
754
  h_pt: float = float(h.pt) if isinstance(h, Length) else 12.0
674
755
  run_sync(
@@ -719,6 +800,7 @@ class _Column:
719
800
  @width.setter
720
801
  def width(self, value: "Length | int | None") -> None:
721
802
  if value is None:
803
+ _warn_table_clear("width", cls="_Column")
722
804
  return
723
805
  # Mirror python-docx: width must be non-negative. Upstream
724
806
  # uses Emu which raises ``ValueError`` for negatives. Previously
@@ -1038,16 +1120,31 @@ class _Cell:
1038
1120
  from docx.styles.style import ParagraphStyle
1039
1121
  from docx.text.paragraph import Paragraph
1040
1122
 
1041
- # Normalize style ParagraphStyle → style_id, str str, None → None.
1042
- # Any other type lands as ``str(style)`` which Word will then
1043
- # treat as an unknown style id (Word falls back to Normal).
1123
+ # python-docx 1.x: ``text`` is ``str`` (lxml TypeErrors on
1124
+ # non-str). Was: any value flowed straight to the wire
1125
+ # ``text`` field SuperDoc's permissive parser swallowed or
1126
+ # rejected silently.
1127
+ if not isinstance(text, str):
1128
+ raise TypeError(
1129
+ f"_Cell.add_paragraph text requires str; got "
1130
+ f"{type(text).__name__} {text!r}",
1131
+ )
1132
+ # ``style`` is ``str | ParagraphStyle | None``. Was: catch-all
1133
+ # ``str(style)`` shipped garbage like ``"<MyStyle object at
1134
+ # 0x...>"`` as a style id — Word silently fell back to Normal.
1044
1135
  style_id: str | None
1045
1136
  if style is None:
1046
1137
  style_id = None
1047
1138
  elif isinstance(style, ParagraphStyle):
1048
1139
  style_id = style.style_id
1140
+ elif isinstance(style, str):
1141
+ style_id = style
1049
1142
  else:
1050
- style_id = str(style)
1143
+ raise TypeError(
1144
+ f"_Cell.add_paragraph style requires str, "
1145
+ f"ParagraphStyle, or None; got "
1146
+ f"{type(style).__name__} {style!r}",
1147
+ )
1051
1148
 
1052
1149
  ids = self._inner_paragraph_ids()
1053
1150
  if ids:
@@ -1266,6 +1363,7 @@ class _Cell:
1266
1363
  from docx.enum.table import WD_ALIGN_VERTICAL
1267
1364
 
1268
1365
  if value is None:
1366
+ _warn_table_clear("vertical_alignment", cls="_Cell")
1269
1367
  return
1270
1368
  if isinstance(value, WD_ALIGN_VERTICAL):
1271
1369
  v: str = value.to_superdoc()
@@ -1301,6 +1399,7 @@ class _Cell:
1301
1399
  @width.setter
1302
1400
  def width(self, value: "Length | int | None") -> None:
1303
1401
  if value is None:
1402
+ _warn_table_clear("width", cls="_Cell")
1304
1403
  return
1305
1404
  # Mirror python-docx + ``_Column.width``: cell width is unsigned
1306
1405
  # twips; negative widths previously round-tripped to the wire