athena-python-docx 0.2.2__tar.gz → 0.2.3__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 (208) hide show
  1. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/PKG-INFO +1 -1
  2. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/__init__.py +1 -1
  3. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/document.py +0 -3
  4. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/section.py +1 -1
  5. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/shape.py +1 -1
  6. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/text/parfmt.py +1 -1
  7. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/pyproject.toml +1 -1
  8. athena_python_docx-0.2.3/scripts/release.sh +80 -0
  9. athena_python_docx-0.2.3/tests/fidelity/auto_gen_cases.py +260 -0
  10. athena_python_docx-0.2.3/tests/fidelity/coverage_report.py +117 -0
  11. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/tests/fidelity/fake_session.py +34 -2
  12. athena_python_docx-0.2.3/tests/fidelity/op_snapshot.py +116 -0
  13. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/01_basic_paragraph.json +3 -0
  14. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/02_multiple_headings.json +9 -0
  15. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/03_runs_with_formatting.json +16 -0
  16. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/04_font_name_and_size.json +7 -0
  17. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/05_font_color_rgb.json +6 -0
  18. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/06_font_character_properties.json +11 -0
  19. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/07_font_subscript_superscript.json +9 -0
  20. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/08_font_highlight.json +6 -0
  21. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/09_paragraph_alignment.json +4 -0
  22. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/100_table_negative_indexing.json +7 -0
  23. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/101_table_cells_flat_iteration.json +33 -0
  24. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/102_text_with_embedded_special_chars.json +3 -0
  25. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/103_cell_tables_enumeration.json +14 -0
  26. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/104_core_properties_datetime.json +1 -0
  27. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/105_default_one_section.json +6 -0
  28. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/106_heading_paragraph_format.json +5 -0
  29. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/107_varying_row_heights.json +53 -0
  30. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/10_paragraph_indents.json +6 -0
  31. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/11_paragraph_spacing.json +7 -0
  32. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/12_paragraph_keep_options.json +7 -0
  33. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/13_paragraph_tab_stops.json +5 -0
  34. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/14_run_add_tab_and_break.json +9 -0
  35. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/15_run_add_break_page.json +6 -0
  36. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/16_paragraph_clear_and_insert_before.json +7 -0
  37. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/17_table_basic.json +5 -0
  38. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/18_table_cell_text.json +27 -0
  39. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/19_table_row_column_sizing.json +25 -0
  40. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/20_table_cell_vertical_alignment.json +12 -0
  41. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/21_table_alignment_and_autofit.json +9 -0
  42. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/22_table_cell_paragraphs_iteration.json +15 -0
  43. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/23_nested_table.json +11 -0
  44. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/24_table_add_row_column.json +21 -0
  45. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/25_table_merge_cells.json +5 -0
  46. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/26_section_page_setup.json +6 -0
  47. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/27_section_margins.json +7 -0
  48. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/28_section_add_new.json +5 -0
  49. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/29_section_headers_linked.json +5 -0
  50. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/30_styles_iteration.json +3 -0
  51. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/31_styles_lookup_and_default.json +4 -0
  52. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/32_styles_add_paragraph_style.json +1 -0
  53. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/33_core_properties_set_and_get.json +1 -0
  54. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/34_inline_shapes_iterate_empty.json +3 -0
  55. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/35_full_report.json +103 -0
  56. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/36_replace_text_in_paragraph.json +5 -0
  57. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/37_iterate_runs_and_format_all_bold.json +9 -0
  58. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/38_font_all_properties.json +23 -0
  59. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/39_large_body_100_paragraphs.json +102 -0
  60. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/40_large_table_10x10.json +403 -0
  61. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/41_unicode_and_emoji.json +6 -0
  62. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/42_very_long_paragraph.json +3 -0
  63. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/43_paragraph_text_round_trip.json +4 -0
  64. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/44_paragraph_alignment_round_trip.json +5 -0
  65. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/45_cell_text_round_trip.json +11 -0
  66. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/46_run_text_setter_round_trip.json +7 -0
  67. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/47_font_size_round_trip.json +7 -0
  68. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/48_font_color_round_trip.json +7 -0
  69. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/49_resume_layout.json +48 -0
  70. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/50_multi_section_doc.json +20 -0
  71. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/51_nested_tables_deep.json +15 -0
  72. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/52_iterate_everything.json +13 -0
  73. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/53_apply_style_to_paragraphs.json +9 -0
  74. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/54_empty_everything.json +6 -0
  75. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/55_single_character_runs.json +18 -0
  76. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/56_everything_in_one.json +111 -0
  77. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/57_runs_after_multiple_text_appends.json +11 -0
  78. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/58_modify_runs_in_place.json +13 -0
  79. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/59_indent_round_trip.json +5 -0
  80. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/60_space_round_trip.json +7 -0
  81. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/61_cell_paragraph_with_runs.json +14 -0
  82. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/62_many_cell_paragraphs.json +26 -0
  83. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/63_table_style_round_trip.json +9 -0
  84. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/64_many_sections.json +28 -0
  85. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/65_20x20_table_formatted.json +3405 -0
  86. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/66_toc_like_structure.json +82 -0
  87. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/67_paragraph_insert_before_chain.json +8 -0
  88. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/68_invoice.json +125 -0
  89. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/69_newsletter.json +67 -0
  90. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/70_add_and_iterate_back.json +11 -0
  91. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/71_academic_paper.json +82 -0
  92. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/72_legal_contract.json +83 -0
  93. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/73_form_with_many_tables.json +194 -0
  94. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/74_paragraph_with_10_runs.json +34 -0
  95. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/75_paragraph_negative_first_line_indent.json +5 -0
  96. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/76_rgbcolor_from_string.json +6 -0
  97. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/77_length_unit_conversions.json +1 -0
  98. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/78_paragraph_copy_style.json +8 -0
  99. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/79_bulk_cell_formatting.json +103 -0
  100. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/80_apply_style_after_add_run.json +7 -0
  101. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/81_multi_page_with_breaks.json +12 -0
  102. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/82_add_text_on_existing_run.json +7 -0
  103. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/83_clear_then_repopulate_paragraph.json +8 -0
  104. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/84_table_reread_row_count.json +21 -0
  105. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/85_header_footer_access.json +5 -0
  106. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/86_font_read_unset_returns_none.json +10 -0
  107. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/87_500_paragraph_doc.json +532 -0
  108. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/88_mixed_content_iteration.json +54 -0
  109. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/89_alignment_clear_via_none.json +6 -0
  110. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/90_cell_add_paragraph_styled.json +9 -0
  111. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/91_many_small_tables.json +453 -0
  112. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/92_margins_every_section.json +21 -0
  113. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/93_font_bool_reads_after_set.json +9 -0
  114. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/94_page_break_before_paragraph.json +4 -0
  115. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/95_paragraph_hyperlinks_empty.json +4 -0
  116. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/96_paragraph_contains_page_break.json +7 -0
  117. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/97_document_styles_by_key.json +8 -0
  118. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/98_style_contains_check.json +5 -0
  119. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/99_run_add_picture_from_bytes.json +5 -0
  120. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/ex01_five_levels_deep_tables.json +23 -0
  121. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/ex02_unicode_everywhere.json +29 -0
  122. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/ex03_1000_paragraphs.json +1002 -0
  123. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/ex04_50x50_table.json +203 -0
  124. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/ex05_long_text_in_cell.json +9 -0
  125. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/ex06_hundred_tiny_runs.json +272 -0
  126. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/ex07_every_font_boolean.json +21 -0
  127. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/ex08_many_continuous_sections.json +32 -0
  128. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/ex09_many_tab_stops.json +13 -0
  129. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/ex10_complex_bom.json +506 -0
  130. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/ex11_banded_rows_formatting.json +805 -0
  131. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/ex12_section_reconfigure.json +17 -0
  132. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/ex13_cell_with_10_paragraphs.json +55 -0
  133. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/ex14_styled_report_table.json +167 -0
  134. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/ex15_paragraph_all_format_props.json +15 -0
  135. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/ex16_runs_interleaved_with_breaks.json +13 -0
  136. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/ex17_all_break_kinds.json +11 -0
  137. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/ex18_read_back_large_doc.json +203 -0
  138. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/ex19_mutate_all_runs.json +48 -0
  139. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/ex20_kitchen_sink_v2.json +812 -0
  140. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/mega01_book_chapter.json +199 -0
  141. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/mega02_research_proposal.json +178 -0
  142. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/mega03_financial_statement.json +167 -0
  143. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/mega04_recipe_card.json +55 -0
  144. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/mega05_user_manual.json +177 -0
  145. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/mega06_complex_newsletter.json +98 -0
  146. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/mega07_budget_spreadsheet.json +231 -0
  147. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/mega08_product_catalog.json +89 -0
  148. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/mega09_signed_contract.json +128 -0
  149. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/mega10_api_documentation.json +322 -0
  150. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/rw01_official_quickstart.json +90 -0
  151. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/rw02_paragraph_style_list.json +7 -0
  152. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/rw03_character_formatting.json +10 -0
  153. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/rw04_section_page_setup.json +11 -0
  154. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/rw05_toc_pattern.json +25 -0
  155. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/rw06_meeting_minutes.json +98 -0
  156. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/rw07_dense_formatting_demo.json +31 -0
  157. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/rw08_table_merged_header.json +35 -0
  158. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/rw09_bulk_run_iteration.json +93 -0
  159. athena_python_docx-0.2.3/tests/fidelity/op_snapshots/rw10_colored_grid_table.json +165 -0
  160. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/tests/fidelity/ours_spec.json +1154 -78
  161. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/tests/fidelity/parity_crawl.py +0 -1
  162. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/tests/fidelity/parity_diff.json +28 -17
  163. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/tests/fidelity/round_trip_tests.py +1 -1
  164. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/tests/fidelity/runner.py +0 -1
  165. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/tests/fidelity/stock_spec.json +16 -16
  166. athena_python_docx-0.2.2/uv.lock +0 -525
  167. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/.gitignore +0 -0
  168. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/CLAUDE.md +0 -0
  169. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/README.md +0 -0
  170. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/_batching.py +0 -0
  171. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/api.py +0 -0
  172. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/client.py +0 -0
  173. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/enum/__init__.py +0 -0
  174. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/enum/section.py +0 -0
  175. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/enum/style.py +0 -0
  176. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/enum/table.py +0 -0
  177. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/enum/text.py +0 -0
  178. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/errors.py +0 -0
  179. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/opc/__init__.py +0 -0
  180. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/opc/coreprops.py +0 -0
  181. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/settings.py +0 -0
  182. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/shared.py +0 -0
  183. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/styles/__init__.py +0 -0
  184. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/styles/style.py +0 -0
  185. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/styles/styles.py +0 -0
  186. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/table.py +0 -0
  187. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/text/__init__.py +0 -0
  188. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/text/hyperlink.py +0 -0
  189. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/text/paragraph.py +0 -0
  190. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/text/run.py +0 -0
  191. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/docx/typing.py +0 -0
  192. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/scripts/publish.sh +0 -0
  193. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/tests/__init__.py +0 -0
  194. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/tests/conftest.py +0 -0
  195. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/tests/fidelity/METHODOLOGY.md +0 -0
  196. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/tests/fidelity/README.md +0 -0
  197. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/tests/fidelity/__init__.py +0 -0
  198. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/tests/fidelity/binary_round_trip.py +0 -0
  199. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/tests/fidelity/cases.py +0 -0
  200. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/tests/fidelity/complex_cases.py +0 -0
  201. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/tests/fidelity/extract.py +0 -0
  202. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/tests/fidelity/extreme_cases.py +0 -0
  203. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/tests/fidelity/local_runner.py +0 -0
  204. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/tests/fidelity/mega_cases.py +0 -0
  205. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/tests/fidelity/real_world_cases.py +0 -0
  206. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/tests/test_commands.py +0 -0
  207. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/tests/test_python_docx_api_parity.py +0 -0
  208. {athena_python_docx-0.2.2 → athena_python_docx-0.2.3}/tests/test_smoke_integration.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: athena-python-docx
3
- Version: 0.2.2
3
+ Version: 0.2.3
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.2.2"
9
+ __version__ = "0.2.3"
10
10
 
11
11
  from docx.api import Document
12
12
  # Re-exports python-docx ships at docx top-level for convenience.
@@ -115,7 +115,6 @@ class Document:
115
115
  @property
116
116
  def sections(self):
117
117
  """Return the document's sections collection."""
118
- from docx.section import Sections
119
118
 
120
119
  self._ensure_open()
121
120
  return Sections(session=self._session)
@@ -397,8 +396,6 @@ class Document:
397
396
  Mirrors python-docx: creating a section adds a trailing empty
398
397
  paragraph that marks the section boundary.
399
398
  """
400
- from docx.enum.section import WD_SECTION_START
401
- from docx.section import Section
402
399
 
403
400
  self._ensure_open()
404
401
  # python-docx always inserts an anchor paragraph at the section break
@@ -14,7 +14,7 @@ from __future__ import annotations
14
14
  from typing import TYPE_CHECKING
15
15
 
16
16
  from docx._batching import run_sync
17
- from docx.shared import Emu, Length, Pt
17
+ from docx.shared import Length, Pt
18
18
 
19
19
  if TYPE_CHECKING:
20
20
  from docx.client import Session
@@ -10,7 +10,7 @@ from __future__ import annotations
10
10
  from typing import TYPE_CHECKING
11
11
 
12
12
  from docx._batching import run_sync
13
- from docx.shared import Emu, Length, Pt
13
+ from docx.shared import Length, Pt
14
14
 
15
15
  if TYPE_CHECKING:
16
16
  from docx.client import Session
@@ -14,7 +14,7 @@ from __future__ import annotations
14
14
  from typing import TYPE_CHECKING
15
15
 
16
16
  from docx._batching import run_sync
17
- from docx.shared import Length, Pt, Twips
17
+ from docx.shared import Length, Twips
18
18
 
19
19
  if TYPE_CHECKING:
20
20
  from docx.enum.text import WD_ALIGN_PARAGRAPH, WD_LINE_SPACING
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "athena-python-docx"
7
- version = "0.2.2"
7
+ version = "0.2.3"
8
8
  description = "Drop-in replacement for python-docx that connects to Athena's Superdoc/Keryx collaborative document stack"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env bash
2
+ # Tag + push a new athena-python-docx release. CI handles the rest:
3
+ # PyPI publish, Docker image rebuild, Daytona snapshot creation, Doppler
4
+ # flip in agora dev + stg. See
5
+ # .github/workflows/athena-python-docx-release.yml for the full flow.
6
+ #
7
+ # Usage:
8
+ # ./scripts/release.sh <version>
9
+ #
10
+ # e.g. ./scripts/release.sh 0.2.3 — releases athena-python-docx==0.2.3
11
+ # by:
12
+ # 1. Updating pyproject.toml + docx/__init__.py
13
+ # 2. Committing the version bump
14
+ # 3. Tagging athena-python-docx-v<version>
15
+ # 4. Pushing the commit + tag to origin
16
+ #
17
+ # CI trigger fires on the tag push and runs the full release pipeline.
18
+
19
+ set -euo pipefail
20
+
21
+ if [ $# -ne 1 ]; then
22
+ echo "Usage: $0 <version> (e.g., 0.2.3)" >&2
23
+ exit 1
24
+ fi
25
+
26
+ VERSION="$1"
27
+ if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(\.(dev|rc|a|b)[0-9]+)?$ ]]; then
28
+ echo "ERROR: version '$VERSION' is not a valid semver-ish" >&2
29
+ exit 1
30
+ fi
31
+
32
+ SDK_DIR="$(cd "$(dirname "$0")/.." && pwd)"
33
+ REPO_ROOT="$(git -C "$SDK_DIR" rev-parse --show-toplevel)"
34
+
35
+ # Require clean working tree so the commit captures only the version bump.
36
+ if ! git -C "$REPO_ROOT" diff --quiet || ! git -C "$REPO_ROOT" diff --cached --quiet; then
37
+ echo "ERROR: working tree is dirty. Commit or stash first." >&2
38
+ git -C "$REPO_ROOT" status --short >&2
39
+ exit 1
40
+ fi
41
+
42
+ # Bump pyproject.toml
43
+ sed -i.bak "s/^version = \".*\"/version = \"$VERSION\"/" "$SDK_DIR/pyproject.toml"
44
+ rm -f "$SDK_DIR/pyproject.toml.bak"
45
+
46
+ # Bump docx/__init__.py
47
+ sed -i.bak "s/^__version__ = \".*\"/__version__ = \"$VERSION\"/" "$SDK_DIR/docx/__init__.py"
48
+ rm -f "$SDK_DIR/docx/__init__.py.bak"
49
+
50
+ # Show the diff so the operator sees what will be committed.
51
+ echo "=== Version bump diff ==="
52
+ git -C "$REPO_ROOT" diff "$SDK_DIR/pyproject.toml" "$SDK_DIR/docx/__init__.py"
53
+ echo "========================="
54
+
55
+ TAG="athena-python-docx-v$VERSION"
56
+
57
+ # Commit + tag + push.
58
+ git -C "$REPO_ROOT" add "$SDK_DIR/pyproject.toml" "$SDK_DIR/docx/__init__.py"
59
+ git -C "$REPO_ROOT" commit -m "chore(docx-sdk): bump version to $VERSION"
60
+ git -C "$REPO_ROOT" tag "$TAG"
61
+ git -C "$REPO_ROOT" push
62
+ git -C "$REPO_ROOT" push origin "$TAG"
63
+
64
+ cat <<EOF
65
+
66
+ Tagged $TAG and pushed. CI is now running the full release pipeline:
67
+
68
+ 1. PyPI publish → https://pypi.org/project/athena-python-docx/$VERSION/
69
+ 2. Docker image rebuild → athenaintel/daytona-document:$VERSION
70
+ 3. Daytona snapshot → document-exec:$VERSION
71
+ 4. Doppler flip → agora/dev + agora/stg
72
+
73
+ Watch the run:
74
+ https://github.com/Athena-Intel/demo-app-monorepo/actions/workflows/athena-python-docx-release.yml
75
+
76
+ For prd rollout, after canary verification:
77
+ doppler secrets set --project agora --config prd \\
78
+ DAYTONA_DOCUMENT_EXEC_SNAPSHOT=document-exec:$VERSION
79
+
80
+ EOF
@@ -0,0 +1,260 @@
1
+ """Auto-generate test cases from python-docx's public API surface.
2
+
3
+ For every `(ClassName, method_or_property)` pair python-docx exposes that
4
+ our SDK claims to support, emit a minimum-viable test case that:
5
+ - constructs the relevant object (via a small set of hand-written fixtures)
6
+ - invokes the method / sets the property
7
+ - asserts no exception is raised
8
+
9
+ The generated cases live in memory; run via `auto_gen_cases.run_all`.
10
+ Complements hand-written cases by guaranteeing every surface has at least
11
+ one exercise path.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import argparse
17
+ import sys
18
+ import traceback
19
+ from pathlib import Path
20
+ from typing import Any, Callable
21
+
22
+ _SDK_ROOT = Path(__file__).resolve().parents[2]
23
+ sys.path.insert(0, str(_SDK_ROOT))
24
+
25
+ from tests.fidelity.fake_session import install_fake_session # noqa: E402
26
+
27
+
28
+ # ── Representative values per type ───────────────────────────────────
29
+
30
+
31
+ def _rep_value(param_name: str, param_type: str, obj_context: str) -> Any:
32
+ """Pick a representative value for a parameter name+type hint."""
33
+ from docx.enum.table import (
34
+ WD_ROW_HEIGHT_RULE,
35
+ )
36
+ from docx.enum.text import (
37
+ WD_ALIGN_PARAGRAPH,
38
+ WD_COLOR_INDEX,
39
+ )
40
+ from docx.enum.section import WD_ORIENTATION, WD_SECTION_START
41
+ from docx.shared import Inches, Pt, RGBColor
42
+
43
+ name = param_name.lower()
44
+ type_str = param_type.lower()
45
+ # Booleans
46
+ if "bool" in type_str or name in ("bold", "italic", "underline", "active"):
47
+ return True
48
+ # String literals
49
+ if "str" in type_str or name in ("text", "name", "style", "id", "label"):
50
+ return "sample"
51
+ # Lengths
52
+ if "length" in type_str or "emu" in type_str or "inches" in type_str or "pt " in type_str:
53
+ return Inches(1)
54
+ if name in ("width", "height", "size") and "int" in type_str:
55
+ return Pt(12)
56
+ if "rgb" in type_str or "color" in name:
57
+ return RGBColor(0, 0, 0)
58
+ if "int" in type_str or "number" in type_str:
59
+ if "level" in name:
60
+ return 1
61
+ if name in ("rows", "cols", "rowindex", "columnindex"):
62
+ return 2
63
+ return 1
64
+ # Enums
65
+ if "alignment" in name:
66
+ return WD_ALIGN_PARAGRAPH.CENTER
67
+ if "orientation" in name:
68
+ return WD_ORIENTATION.PORTRAIT
69
+ if "start_type" in name or "break_type" in name:
70
+ return WD_SECTION_START.NEW_PAGE
71
+ if "highlight" in name:
72
+ return WD_COLOR_INDEX.YELLOW
73
+ if "rule" in name:
74
+ return WD_ROW_HEIGHT_RULE.AT_LEAST
75
+ return None
76
+
77
+
78
+ # ── Fixtures ──────────────────────────────────────────────────────────
79
+
80
+
81
+ def _fixture_new_doc() -> Any:
82
+ install_fake_session()
83
+ from docx import Document
84
+ return Document("asset_fake")
85
+
86
+
87
+ _FIXTURES: dict[str, Callable[[Any], Any]] = {
88
+ "Document": lambda doc: doc,
89
+ "Paragraph": lambda doc: doc.add_paragraph("auto-gen"),
90
+ "Run": lambda doc: doc.add_paragraph().add_run("auto-gen"),
91
+ "Font": lambda doc: doc.add_paragraph().add_run("auto-gen").font,
92
+ "ParagraphFormat": lambda doc: doc.add_paragraph("auto-gen").paragraph_format,
93
+ "Table": lambda doc: doc.add_table(rows=2, cols=2),
94
+ "_Cell": lambda doc: doc.add_table(rows=1, cols=1).cell(0, 0),
95
+ "_Row": lambda doc: doc.add_table(rows=1, cols=1).rows[0],
96
+ "_Column": lambda doc: doc.add_table(rows=1, cols=1).columns[0],
97
+ "Section": lambda doc: doc.sections[0],
98
+ "Styles": lambda doc: doc.styles,
99
+ "CoreProperties": lambda doc: doc.core_properties,
100
+ "InlineShapes": lambda doc: doc.inline_shapes,
101
+ "Sections": lambda doc: doc.sections,
102
+ }
103
+
104
+
105
+ _PROPERTY_VALUES: dict[tuple[str, str], Any] = {} # populated lazily
106
+
107
+
108
+ def _property_value(cls_name: str, prop: str) -> Any:
109
+ from docx.enum.table import WD_ALIGN_VERTICAL, WD_ROW_HEIGHT_RULE, WD_TABLE_ALIGNMENT
110
+ from docx.enum.text import WD_ALIGN_PARAGRAPH, WD_COLOR_INDEX
111
+ from docx.enum.section import WD_ORIENTATION
112
+ from docx.shared import Inches, Pt
113
+
114
+ # Hand-tuned per (class, property) — most important ones.
115
+ mapping = {
116
+ ("Paragraph", "text"): "text",
117
+ ("Paragraph", "style"): "Normal",
118
+ ("Paragraph", "alignment"): WD_ALIGN_PARAGRAPH.CENTER,
119
+ ("Run", "text"): "text",
120
+ ("Run", "bold"): True,
121
+ ("Run", "italic"): True,
122
+ ("Run", "underline"): True,
123
+ ("Run", "style"): "Emphasis",
124
+ ("Font", "name"): "Arial",
125
+ ("Font", "size"): Pt(12),
126
+ ("Font", "bold"): True,
127
+ ("Font", "italic"): True,
128
+ ("Font", "strike"): True,
129
+ ("Font", "double_strike"): True,
130
+ ("Font", "all_caps"): True,
131
+ ("Font", "small_caps"): True,
132
+ ("Font", "shadow"): True,
133
+ ("Font", "outline"): True,
134
+ ("Font", "emboss"): True,
135
+ ("Font", "imprint"): True,
136
+ ("Font", "hidden"): True,
137
+ ("Font", "subscript"): True,
138
+ ("Font", "superscript"): True,
139
+ ("Font", "highlight_color"): WD_COLOR_INDEX.YELLOW,
140
+ ("ParagraphFormat", "alignment"): WD_ALIGN_PARAGRAPH.CENTER,
141
+ ("ParagraphFormat", "left_indent"): Inches(0.5),
142
+ ("ParagraphFormat", "right_indent"): Inches(0.25),
143
+ ("ParagraphFormat", "first_line_indent"): Inches(0.25),
144
+ ("ParagraphFormat", "space_before"): Pt(12),
145
+ ("ParagraphFormat", "space_after"): Pt(6),
146
+ ("ParagraphFormat", "line_spacing"): 1.5,
147
+ ("ParagraphFormat", "keep_together"): True,
148
+ ("ParagraphFormat", "keep_with_next"): True,
149
+ ("ParagraphFormat", "widow_control"): True,
150
+ ("ParagraphFormat", "page_break_before"): True,
151
+ ("Table", "style"): "TableGrid",
152
+ ("Table", "alignment"): WD_TABLE_ALIGNMENT.CENTER,
153
+ ("Table", "autofit"): True,
154
+ ("_Cell", "text"): "cell body",
155
+ ("_Cell", "vertical_alignment"): WD_ALIGN_VERTICAL.CENTER,
156
+ ("_Cell", "width"): Inches(1),
157
+ ("_Row", "height"): Pt(20),
158
+ ("_Row", "height_rule"): WD_ROW_HEIGHT_RULE.AT_LEAST,
159
+ ("_Column", "width"): Inches(1),
160
+ ("Section", "page_width"): Inches(8.5),
161
+ ("Section", "page_height"): Inches(11),
162
+ ("Section", "orientation"): WD_ORIENTATION.PORTRAIT,
163
+ ("Section", "left_margin"): Inches(1),
164
+ ("Section", "right_margin"): Inches(1),
165
+ ("Section", "top_margin"): Inches(1),
166
+ ("Section", "bottom_margin"): Inches(1),
167
+ }
168
+ return mapping.get((cls_name, prop))
169
+
170
+
171
+ # ── Test runner ───────────────────────────────────────────────────────
172
+
173
+
174
+ def run_all() -> tuple[int, int, list[tuple[str, str]]]:
175
+ """Run auto-generated tests; return (passed, total, failures)."""
176
+ failures: list[tuple[str, str]] = []
177
+ total = 0
178
+ passed = 0
179
+ for cls_name, fix in _FIXTURES.items():
180
+ # Per-class: iterate known (class, property) pairs
181
+ for (cname, prop), val in list(_PROPERTY_VALUES.items()):
182
+ if cname != cls_name:
183
+ continue
184
+ # Use _property_value mapping: iterate all keys matching this class
185
+ from docx.enum.table import WD_ALIGN_VERTICAL # noqa: F401 — keeps import list alive
186
+ mapping_keys = _collect_property_keys(cls_name)
187
+ for prop in mapping_keys:
188
+ val = _property_value(cls_name, prop)
189
+ if val is None:
190
+ continue
191
+ total += 1
192
+ doc = _fixture_new_doc()
193
+ try:
194
+ target = fix(doc)
195
+ _set_nested(target, prop, val)
196
+ # Round-trip read (best effort; skip if getter raises)
197
+ try:
198
+ _ = _get_nested(target, prop)
199
+ except Exception:
200
+ pass
201
+ passed += 1
202
+ except Exception as e: # noqa: BLE001
203
+ failures.append((f"{cls_name}.{prop}", f"{type(e).__name__}: {e}"))
204
+ finally:
205
+ try:
206
+ doc.close()
207
+ except Exception:
208
+ pass
209
+ return passed, total, failures
210
+
211
+
212
+ def _collect_property_keys(cls_name: str) -> list[str]:
213
+ """Pull properties we have values for."""
214
+ # Use introspection on the _property_value mapping: easiest way
215
+ # without duplicating data is to call it with each key and filter.
216
+ all_keys = [
217
+ "text", "style", "alignment", "bold", "italic", "underline",
218
+ "name", "size", "strike", "double_strike", "all_caps", "small_caps",
219
+ "shadow", "outline", "emboss", "imprint", "hidden", "subscript",
220
+ "superscript", "highlight_color", "left_indent", "right_indent",
221
+ "first_line_indent", "space_before", "space_after", "line_spacing",
222
+ "keep_together", "keep_with_next", "widow_control", "page_break_before",
223
+ "autofit", "vertical_alignment", "width", "height", "height_rule",
224
+ "page_width", "page_height", "orientation", "left_margin",
225
+ "right_margin", "top_margin", "bottom_margin",
226
+ ]
227
+ return [k for k in all_keys if _property_value(cls_name, k) is not None]
228
+
229
+
230
+ def _set_nested(obj: Any, path: str, value: Any) -> None:
231
+ parts = path.split(".")
232
+ for p in parts[:-1]:
233
+ obj = getattr(obj, p)
234
+ setattr(obj, parts[-1], value)
235
+
236
+
237
+ def _get_nested(obj: Any, path: str) -> Any:
238
+ for p in path.split("."):
239
+ obj = getattr(obj, p)
240
+ return obj
241
+
242
+
243
+ def main() -> int:
244
+ parser = argparse.ArgumentParser()
245
+ parser.add_argument("--verbose", action="store_true")
246
+ args = parser.parse_args()
247
+ passed, total, failures = run_all()
248
+ for name, err in failures:
249
+ print(f" ❌ {name:45} — {err}")
250
+ if args.verbose:
251
+ traceback.print_exc()
252
+ print()
253
+ print(f"Auto-generated fidelity: {passed}/{total} passed")
254
+ if failures:
255
+ print(f"Failures: {len(failures)}")
256
+ return 0 if not failures else 1
257
+
258
+
259
+ if __name__ == "__main__":
260
+ sys.exit(main())
@@ -0,0 +1,117 @@
1
+ """Parity coverage scorecard.
2
+
3
+ Combines layers L1-L6 into a single `coverage.json` + human scorecard:
4
+
5
+ - L1 (import parity) — from parity_crawl --ours output
6
+ - L2 (signature match) — from parity_diff
7
+ - L3 (enum value parity) — from parity_diff
8
+ - L6 (property round-trip)— from round_trip_tests
9
+
10
+ The output looks like:
11
+
12
+ python-docx coverage scorecard (0.2.2)
13
+ =====================================
14
+ Classes 27/30 (90%) ✅
15
+ Properties 210/225 (93%) ✅
16
+ Methods 122/142 (86%) ⚠️
17
+ Enum values 68/73 (93%) ✅
18
+
19
+ Intended as a CI gate: any decrease fails the job.
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ import json
25
+ import sys
26
+ from pathlib import Path
27
+
28
+ _SDK_ROOT = Path(__file__).resolve().parents[2]
29
+
30
+
31
+ def _load(path: Path) -> dict:
32
+ if not path.exists():
33
+ return {}
34
+ return json.loads(path.read_text())
35
+
36
+
37
+ def _count_in_stock(stock: dict) -> dict[str, int]:
38
+ classes = 0
39
+ properties = 0
40
+ methods = 0
41
+ enum_values = 0
42
+ for mod_path, entries in stock.items():
43
+ for qual, entry in entries.items():
44
+ if not isinstance(entry, dict):
45
+ continue
46
+ if entry.get("kind") == "class":
47
+ classes += 1
48
+ # Enum detection: a class whose bases include Enum-ish
49
+ is_enum = any(
50
+ b in ("Enum", "IntEnum", "BaseXmlEnum") for b in entry.get("bases", [])
51
+ )
52
+ for m_name, m_entry in entry.get("members", {}).items():
53
+ if not isinstance(m_entry, dict):
54
+ continue
55
+ kind = m_entry.get("kind")
56
+ if kind == "property":
57
+ properties += 1
58
+ elif kind == "method":
59
+ methods += 1
60
+ elif kind == "attribute" and is_enum:
61
+ enum_values += 1
62
+ return {"classes": classes, "properties": properties, "methods": methods, "enum_values": enum_values}
63
+
64
+
65
+ def _count_diff_missing(diff: dict) -> dict[str, int]:
66
+ missing = {"classes": len(diff.get("missing_classes", [])), "properties": 0, "methods": 0, "enum_values": 0}
67
+ # missing_members are a flat list; we can't tell property/method from there
68
+ # without cross-ref to stock. For now, lump them under "methods" as a rough
69
+ # signal — the scorecard will be approximate but still useful.
70
+ missing["methods"] += len(diff.get("missing_members", []))
71
+ return missing
72
+
73
+
74
+ def main() -> int:
75
+ stock = _load(_SDK_ROOT / "tests/fidelity/stock_spec.json")
76
+ diff = _load(_SDK_ROOT / "tests/fidelity/parity_diff.json")
77
+ if not stock or not diff:
78
+ print("run parity_crawl.py --stock / --ours / --diff first")
79
+ return 1
80
+ totals = _count_in_stock(stock)
81
+ missing = _count_diff_missing(diff)
82
+
83
+ implemented = {
84
+ k: max(totals[k] - missing.get(k, 0), 0)
85
+ for k in totals
86
+ }
87
+
88
+ version = _get_sdk_version()
89
+
90
+ print()
91
+ print(f"python-docx coverage scorecard (athena-python-docx {version})")
92
+ print("=" * 60)
93
+ for key, label in [("classes", "Classes"), ("properties", "Properties"), ("methods", "Methods"), ("enum_values", "Enum values")]:
94
+ t = totals[key]
95
+ i = implemented[key]
96
+ pct = (i * 100 // t) if t else 100
97
+ icon = "✅" if pct >= 90 else ("⚠️" if pct >= 75 else "❌")
98
+ print(f" {label:14} {i:4}/{t:<4} ({pct:>3}%) {icon}")
99
+ print()
100
+
101
+ # Round-trip scorecard (L6)
102
+ rt_path = _SDK_ROOT / "tests/fidelity/round_trip_tests.py"
103
+ if rt_path.exists():
104
+ print("Property round-trips: run `.venv/bin/python tests/fidelity/round_trip_tests.py` for details")
105
+
106
+ return 0
107
+
108
+
109
+ def _get_sdk_version() -> str:
110
+ init = (_SDK_ROOT / "docx/__init__.py").read_text()
111
+ import re
112
+ m = re.search(r'__version__ = "([^"]+)"', init)
113
+ return m.group(1) if m else "?"
114
+
115
+
116
+ if __name__ == "__main__":
117
+ sys.exit(main())
@@ -364,16 +364,31 @@ class FakeDocState:
364
364
  if target.get("kind") == "block" and target.get("nodeType") == "tableCell":
365
365
  cell_nid = target.get("nodeId")
366
366
  content = params.get("content") or {}
367
- # Extract text from prosemirror paragraph fragment.
367
+ # Extract text from either a prosemirror `{type:"paragraph",
368
+ # content:[{type:"text",text:"…"}]}` fragment OR a Superdoc
369
+ # native `{kind:"paragraph", paragraph:{inlines:[{run:...}]}}`
370
+ # fragment.
368
371
  appended: str = ""
369
372
  if isinstance(content, dict):
370
- inline_list = content.get("content") or []
373
+ inline_list = content.get("content")
371
374
  if isinstance(inline_list, list):
372
375
  for inl in inline_list:
373
376
  if isinstance(inl, dict) and inl.get("type") == "text":
374
377
  t = inl.get("text")
375
378
  if isinstance(t, str):
376
379
  appended += t
380
+ # Superdoc native shape
381
+ para = content.get("paragraph")
382
+ if isinstance(para, dict):
383
+ inlines = para.get("inlines") or []
384
+ if isinstance(inlines, list):
385
+ for inl in inlines:
386
+ if isinstance(inl, dict):
387
+ run = inl.get("run")
388
+ if isinstance(run, dict):
389
+ t = run.get("text")
390
+ if isinstance(t, str):
391
+ appended += t
377
392
  # Find cell and append to its first paragraph.
378
393
  for t in self.tables:
379
394
  for r_idx, row in enumerate(t.cells):
@@ -391,6 +406,23 @@ class FakeDocState:
391
406
  )
392
407
  return {"ok": True}
393
408
 
409
+ # markdown_to_fragment: return a minimal-valid Superdoc fragment.
410
+ if op == "markdownToFragment":
411
+ md = params.get("markdown", "")
412
+ return {
413
+ "fragment": {
414
+ "kind": "paragraph",
415
+ "paragraph": {
416
+ "inlines": (
417
+ [{"kind": "run", "run": {"text": md}}]
418
+ if md else []
419
+ ),
420
+ },
421
+ },
422
+ "lossy": False,
423
+ "diagnostics": [],
424
+ }
425
+
394
426
  if op == "insertLineBreak":
395
427
  blk_id = params.get("blockId")
396
428
  if blk_id: