athena-python-docx 0.11.0__tar.gz → 0.11.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.
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/PKG-INFO +1 -1
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/__init__.py +1 -1
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/_http_doc.py +25 -10
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/table.py +40 -28
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/pyproject.toml +1 -1
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/22_table_cell_paragraphs_iteration.json +3 -1
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/62_many_cell_paragraphs.json +15 -5
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/69_newsletter.json +13 -5
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/90_cell_add_paragraph_styled.json +3 -1
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/ex13_cell_with_10_paragraphs.json +30 -10
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/mega01_book_chapter.json +18 -6
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_block_not_found_error.py +69 -0
- athena_python_docx-0.11.1/tests/test_cell_add_paragraph_wire_shape.py +133 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/.gitignore +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/CLAUDE.md +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/README.md +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/_athena_extension.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/_batching.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/_buffer.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/_http.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/_image_utils.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/_ptc.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/_table_styles.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/api.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/bookmarks.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/charts.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/client.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/commands.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/comments.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/document.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/enum/__init__.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/enum/section.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/enum/style.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/enum/table.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/enum/text.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/errors.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/exceptions.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/fields.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/footnotes.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/math.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/opc/__init__.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/opc/coreprops.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/oxml/__init__.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/revisions.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/sdt.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/section.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/settings.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/shape.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/shared.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/styles/__init__.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/styles/style.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/styles/styles.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/text/__init__.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/text/font.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/text/hyperlink.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/text/pagebreak.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/text/paragraph.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/text/parfmt.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/text/run.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/text/tabstops.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/toc.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/docx/typing.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/scripts/publish.sh +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/scripts/release.sh +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/scripts/round_trip_smoke.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/scripts/smoke_test_block_not_found.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/__init__.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/conftest.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/METHODOLOGY.md +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/README.md +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/__init__.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/ab_probe_cases.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/ab_probe_runner.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/auto_gen_cases.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/binary_round_trip.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/cases.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/complex_cases.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/coverage_report.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/extract.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/extreme_cases.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/fake_session.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/firm_templates/README.md +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/firm_templates/__init__.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/firm_templates/_runner.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/firm_templates/extractor.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/firm_templates/test_pw_corpus.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/firm_templates/test_pw_research_digest.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/local_runner.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/mega_cases.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshot.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/01_basic_paragraph.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/02_multiple_headings.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/03_runs_with_formatting.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/04_font_name_and_size.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/05_font_color_rgb.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/06_font_character_properties.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/07_font_subscript_superscript.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/08_font_highlight.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/09_paragraph_alignment.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/100_table_negative_indexing.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/101_table_cells_flat_iteration.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/102_text_with_embedded_special_chars.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/103_cell_tables_enumeration.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/104_core_properties_datetime.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/105_default_one_section.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/106_heading_paragraph_format.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/107_varying_row_heights.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/10_paragraph_indents.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/11_paragraph_spacing.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/12_paragraph_keep_options.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/13_paragraph_tab_stops.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/14_run_add_tab_and_break.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/15_run_add_break_page.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/16_paragraph_clear_and_insert_before.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/17_table_basic.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/18_table_cell_text.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/19_table_row_column_sizing.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/20_table_cell_vertical_alignment.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/21_table_alignment_and_autofit.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/23_nested_table.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/24_table_add_row_column.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/25_table_merge_cells.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/26_section_page_setup.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/27_section_margins.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/28_section_add_new.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/29_section_headers_linked.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/30_styles_iteration.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/31_styles_lookup_and_default.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/32_styles_add_paragraph_style.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/33_core_properties_set_and_get.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/34_inline_shapes_iterate_empty.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/35_full_report.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/36_replace_text_in_paragraph.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/37_iterate_runs_and_format_all_bold.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/38_font_all_properties.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/39_large_body_100_paragraphs.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/40_large_table_10x10.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/41_unicode_and_emoji.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/42_very_long_paragraph.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/43_paragraph_text_round_trip.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/44_paragraph_alignment_round_trip.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/45_cell_text_round_trip.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/46_run_text_setter_round_trip.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/47_font_size_round_trip.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/48_font_color_round_trip.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/49_resume_layout.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/50_multi_section_doc.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/51_nested_tables_deep.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/52_iterate_everything.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/53_apply_style_to_paragraphs.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/54_empty_everything.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/55_single_character_runs.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/56_everything_in_one.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/57_runs_after_multiple_text_appends.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/58_modify_runs_in_place.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/59_indent_round_trip.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/60_space_round_trip.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/61_cell_paragraph_with_runs.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/63_table_style_round_trip.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/64_many_sections.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/65_20x20_table_formatted.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/66_toc_like_structure.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/67_paragraph_insert_before_chain.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/68_invoice.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/70_add_and_iterate_back.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/71_academic_paper.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/72_legal_contract.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/73_form_with_many_tables.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/74_paragraph_with_10_runs.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/75_paragraph_negative_first_line_indent.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/76_rgbcolor_from_string.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/77_length_unit_conversions.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/78_paragraph_copy_style.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/79_bulk_cell_formatting.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/80_apply_style_after_add_run.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/81_multi_page_with_breaks.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/82_add_text_on_existing_run.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/83_clear_then_repopulate_paragraph.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/84_table_reread_row_count.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/85_header_footer_access.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/86_font_read_unset_returns_none.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/87_500_paragraph_doc.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/88_mixed_content_iteration.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/89_alignment_clear_via_none.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/91_many_small_tables.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/92_margins_every_section.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/93_font_bool_reads_after_set.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/94_page_break_before_paragraph.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/95_paragraph_hyperlinks_empty.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/96_paragraph_contains_page_break.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/97_document_styles_by_key.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/98_style_contains_check.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/99_run_add_picture_from_bytes.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/ex01_five_levels_deep_tables.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/ex02_unicode_everywhere.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/ex03_1000_paragraphs.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/ex04_50x50_table.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/ex05_long_text_in_cell.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/ex06_hundred_tiny_runs.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/ex07_every_font_boolean.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/ex08_many_continuous_sections.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/ex09_many_tab_stops.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/ex10_complex_bom.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/ex11_banded_rows_formatting.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/ex12_section_reconfigure.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/ex14_styled_report_table.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/ex15_paragraph_all_format_props.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/ex16_runs_interleaved_with_breaks.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/ex17_all_break_kinds.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/ex18_read_back_large_doc.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/ex19_mutate_all_runs.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/ex20_kitchen_sink_v2.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/mega02_research_proposal.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/mega03_financial_statement.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/mega04_recipe_card.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/mega05_user_manual.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/mega06_complex_newsletter.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/mega07_budget_spreadsheet.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/mega08_product_catalog.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/mega09_signed_contract.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/mega10_api_documentation.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/rw01_official_quickstart.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/rw02_paragraph_style_list.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/rw03_character_formatting.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/rw04_section_page_setup.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/rw05_toc_pattern.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/rw06_meeting_minutes.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/rw07_dense_formatting_demo.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/rw08_table_merged_header.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/rw09_bulk_run_iteration.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/rw10_colored_grid_table.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/rw11_header_text.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/rw12_first_page_footer.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/rw13_even_page_header.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/rw14_nested_cell_table.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/op_snapshots/rw15_paragraph_style_instance.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/ours_spec.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/parity_crawl.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/parity_diff.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/real_world_cases.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/round_trip_tests.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/runner.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/stock_spec.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/fidelity/test_e2e_against_staging.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/parity/README.md +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/parity/__init__.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/parity/baseline_gaps.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/parity/compare.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/parity/intentional_deviations.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/parity/introspect.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/parity/reports/GAP_ANALYSIS.md +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/parity/reports/gap_report.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/parity/run_parity.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/parity/snapshots/athena_latest.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/parity/snapshots/upstream_python_docx_1.2.0.json +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/parity/test_parity_gap.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_athena_extensions_contract.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_athena_extensions_registry.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_batching_perf.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_buffer.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_cell_text_plain_fastpath.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_collapsed_range_format.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_command_dataclasses.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_commands.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_comments.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_document_asset_id_property.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_document_create.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_document_create_from_template.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_document_factory_validation.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_e2e_partial_failure_cascade.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_http_transport.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_hyperlink_coalescing.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_insert_deferred.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_iter_inner_content.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_list_styles.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_merged_cell_secondary_slot.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_merged_cells.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_oxml_shim.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_paragraph_text_len_cache.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_parity_misc.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_parity_round2.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_partial_failure_cascade.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_phase_a_behavior.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_phase_b_headers_footers.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_phase_c_tables.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_pr19766_review_fixes.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_ptc.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_python_docx_api_parity.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_revisions.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_add_paragraph_style.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_add_picture.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_add_run.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_cell_add_paragraph.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_comments_add_comment.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_comments_get.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_document_audit.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_document_element.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_enum_section.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_font_audit.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_header_footer.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_hyperlink.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_inline_shape.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_insert_paragraph_before.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_misc.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_paragraph_strict.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_paragraph_style.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_paragraph_style_strict.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_parfmt.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_row_col_cell.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_run_add_break.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_run_bool_setters.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_run_style.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_run_style_strict.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_run_text.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_run_underline.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_section_audit.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_section_dimensions.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_section_onoff.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_settings.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_shared_audit.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_style.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_styles.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_table_audit.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_table_cell.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_table_dimensions.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_silent_stub_table_layout.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_smoke_integration.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_style_acceptance.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_style_font.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_style_setters_contract.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_table_set_cell_perf.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_table_style_id_resolution.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_temporarily_unavailable.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_wire_contract.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/tests/test_zod_wire_contract.py +0 -0
- {athena_python_docx-0.11.0 → athena_python_docx-0.11.1}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: athena-python-docx
|
|
3
|
-
Version: 0.11.
|
|
3
|
+
Version: 0.11.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>
|
|
@@ -186,22 +186,32 @@ _NOT_FOUND_ERROR_NAMES: frozenset[str] = frozenset(
|
|
|
186
186
|
|
|
187
187
|
|
|
188
188
|
def _looks_like_block_not_found(err_obj: dict) -> bool:
|
|
189
|
-
"""Detect SuperDoc's
|
|
189
|
+
"""Detect SuperDoc's cell-inner-paragraph addressing failures.
|
|
190
190
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
191
|
+
SuperDoc emits two shapes for the same underlying gap
|
|
192
|
+
(``SUPERDOC_UPSTREAM_REQUESTS.md`` § 13):
|
|
193
|
+
|
|
194
|
+
* ``Block "paragraph:<uuid>" was not found.`` — older "not found" form.
|
|
195
|
+
* ``INVALID_TARGET - Expected paragraph:<uuid> but found tableCell:<id>.``
|
|
196
|
+
— newer type-mismatch form, surfaced when the supplied paragraph
|
|
197
|
+
anchor resolves to its containing ``tableCell`` instead.
|
|
198
|
+
|
|
199
|
+
Both surface as :class:`BlockNotFoundError` so agent code can route
|
|
200
|
+
them through the same cell-paragraph hint path.
|
|
195
201
|
"""
|
|
196
202
|
msg = err_obj.get("message")
|
|
197
203
|
if not isinstance(msg, str):
|
|
198
204
|
return False
|
|
199
205
|
lower = msg.lower()
|
|
200
|
-
if "not found"
|
|
201
|
-
return
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
206
|
+
if "not found" in lower:
|
|
207
|
+
return 'block "' in lower or (
|
|
208
|
+
'block ' in lower and ' was not found' in lower
|
|
209
|
+
)
|
|
210
|
+
if "invalid_target" in lower or "invalid target" in lower:
|
|
211
|
+
# "Expected paragraph:<id> but found tableCell:<id>" — the new
|
|
212
|
+
# variant of the § 13 cell-inner-paragraph addressing gap.
|
|
213
|
+
return "but found tablecell" in lower
|
|
214
|
+
return False
|
|
205
215
|
|
|
206
216
|
|
|
207
217
|
# Commands that target a paragraph block (or its inline range) and
|
|
@@ -239,6 +249,11 @@ _PARAGRAPH_TARGETING_COMMANDS: frozenset[str] = frozenset(
|
|
|
239
249
|
"Replace",
|
|
240
250
|
"InsertLineBreak",
|
|
241
251
|
"InsertTab",
|
|
252
|
+
# Create-* anchor-into-cell-inner-paragraph variant of § 13.
|
|
253
|
+
"CreateParagraph",
|
|
254
|
+
"CreateHeading",
|
|
255
|
+
"CreateTable",
|
|
256
|
+
"CreateImage",
|
|
242
257
|
}
|
|
243
258
|
)
|
|
244
259
|
|
|
@@ -1345,23 +1345,24 @@ class _Cell:
|
|
|
1345
1345
|
only ``str`` was honored and passing a ``ParagraphStyle`` got
|
|
1346
1346
|
``repr()``'d into the style id slot, silently producing a
|
|
1347
1347
|
paragraph with a garbage style reference.
|
|
1348
|
+
|
|
1349
|
+
Routes through ``doc.insert`` with the cell itself as the
|
|
1350
|
+
target and ``placement: 'insideEnd'`` — mirroring the wire
|
|
1351
|
+
path that ``_Cell.text`` uses. SuperDoc 1.8.1 cannot resolve a
|
|
1352
|
+
``create.paragraph`` ``at`` anchor that points at a cell-inner
|
|
1353
|
+
paragraph (SUPERDOC_UPSTREAM_REQUESTS.md § 13); attempting it
|
|
1354
|
+
raises ``INVALID_TARGET - Expected paragraph:<id> but found
|
|
1355
|
+
tableCell:<id>``.
|
|
1348
1356
|
"""
|
|
1349
1357
|
from docx.document import _extract_inserted_node_id
|
|
1350
1358
|
from docx.styles.style import ParagraphStyle
|
|
1351
1359
|
from docx.text.paragraph import Paragraph
|
|
1352
1360
|
|
|
1353
|
-
# python-docx 1.x: ``text`` is ``str`` (lxml TypeErrors on
|
|
1354
|
-
# non-str). Was: any value flowed straight to the wire
|
|
1355
|
-
# ``text`` field — SuperDoc's permissive parser swallowed or
|
|
1356
|
-
# rejected silently.
|
|
1357
1361
|
if not isinstance(text, str):
|
|
1358
1362
|
raise TypeError(
|
|
1359
1363
|
f"_Cell.add_paragraph text requires str; got "
|
|
1360
1364
|
f"{type(text).__name__} {text!r}",
|
|
1361
1365
|
)
|
|
1362
|
-
# ``style`` is ``str | ParagraphStyle | None``. Was: catch-all
|
|
1363
|
-
# ``str(style)`` shipped garbage like ``"<MyStyle object at
|
|
1364
|
-
# 0x...>"`` as a style id — Word silently fell back to Normal.
|
|
1365
1366
|
style_id: str | None
|
|
1366
1367
|
if style is None:
|
|
1367
1368
|
style_id = None
|
|
@@ -1376,38 +1377,49 @@ class _Cell:
|
|
|
1376
1377
|
f"{type(style).__name__} {style!r}",
|
|
1377
1378
|
)
|
|
1378
1379
|
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
"
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
else:
|
|
1390
|
-
# No paragraphs yet — create one inside the cell (sibling of cell
|
|
1391
|
-
# is invalid; fall back to documentEnd and accept degraded placement).
|
|
1392
|
-
anchor = {"kind": "documentEnd"}
|
|
1380
|
+
fragment: dict = {
|
|
1381
|
+
"kind": "paragraph",
|
|
1382
|
+
"paragraph": {
|
|
1383
|
+
"inlines": (
|
|
1384
|
+
[{"kind": "run", "run": {"text": text}}]
|
|
1385
|
+
if text
|
|
1386
|
+
else []
|
|
1387
|
+
),
|
|
1388
|
+
},
|
|
1389
|
+
}
|
|
1393
1390
|
|
|
1391
|
+
session = self._table._session
|
|
1392
|
+
cell_id = self._cell_id()
|
|
1394
1393
|
result: object = run_sync(
|
|
1395
|
-
|
|
1396
|
-
{
|
|
1394
|
+
session.doc.insert(
|
|
1395
|
+
{
|
|
1396
|
+
"target": {
|
|
1397
|
+
"kind": "block",
|
|
1398
|
+
"nodeType": "tableCell",
|
|
1399
|
+
"nodeId": cell_id,
|
|
1400
|
+
},
|
|
1401
|
+
"placement": "insideEnd",
|
|
1402
|
+
"content": fragment,
|
|
1403
|
+
},
|
|
1397
1404
|
),
|
|
1398
1405
|
)
|
|
1406
|
+
|
|
1407
|
+
node_id: str = ""
|
|
1399
1408
|
if isinstance(result, dict):
|
|
1400
|
-
node_id
|
|
1409
|
+
node_id = _extract_inserted_node_id(
|
|
1401
1410
|
result, expected_type="paragraph",
|
|
1402
1411
|
)
|
|
1403
|
-
|
|
1404
|
-
|
|
1412
|
+
if not node_id:
|
|
1413
|
+
ids = self._inner_paragraph_ids()
|
|
1414
|
+
if ids:
|
|
1415
|
+
node_id = ids[-1]
|
|
1405
1416
|
if not node_id:
|
|
1406
1417
|
raise RuntimeError(
|
|
1407
|
-
f"
|
|
1418
|
+
f"docx-studio did not return nodeId for "
|
|
1419
|
+
f"_Cell.add_paragraph (cell={cell_id!r}): {result!r}",
|
|
1408
1420
|
)
|
|
1409
1421
|
para = Paragraph(
|
|
1410
|
-
session=
|
|
1422
|
+
session=session,
|
|
1411
1423
|
node_id=node_id,
|
|
1412
1424
|
node_type="paragraph",
|
|
1413
1425
|
)
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "athena-python-docx"
|
|
7
|
-
version = "0.11.
|
|
7
|
+
version = "0.11.1"
|
|
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"
|
|
@@ -2,24 +2,34 @@
|
|
|
2
2
|
"create.table",
|
|
3
3
|
"tables.get",
|
|
4
4
|
"tables.getCells",
|
|
5
|
+
"insert",
|
|
6
|
+
"tables.get",
|
|
7
|
+
"tables.getCells",
|
|
5
8
|
"getNodeById",
|
|
6
|
-
"
|
|
9
|
+
"tables.get",
|
|
10
|
+
"tables.getCells",
|
|
11
|
+
"insert",
|
|
7
12
|
"tables.get",
|
|
8
13
|
"tables.getCells",
|
|
9
14
|
"getNodeById",
|
|
10
|
-
"
|
|
15
|
+
"tables.get",
|
|
16
|
+
"tables.getCells",
|
|
17
|
+
"insert",
|
|
11
18
|
"tables.get",
|
|
12
19
|
"tables.getCells",
|
|
13
20
|
"getNodeById",
|
|
14
|
-
"
|
|
21
|
+
"tables.get",
|
|
22
|
+
"tables.getCells",
|
|
23
|
+
"insert",
|
|
15
24
|
"tables.get",
|
|
16
25
|
"tables.getCells",
|
|
17
26
|
"getNodeById",
|
|
18
|
-
"
|
|
27
|
+
"tables.get",
|
|
28
|
+
"tables.getCells",
|
|
29
|
+
"insert",
|
|
19
30
|
"tables.get",
|
|
20
31
|
"tables.getCells",
|
|
21
32
|
"getNodeById",
|
|
22
|
-
"create.paragraph",
|
|
23
33
|
"tables.get",
|
|
24
34
|
"tables.getCells",
|
|
25
35
|
"getNodeById",
|
|
@@ -38,20 +38,28 @@
|
|
|
38
38
|
"tables.setStyle",
|
|
39
39
|
"tables.get",
|
|
40
40
|
"tables.getCells",
|
|
41
|
+
"insert",
|
|
42
|
+
"tables.get",
|
|
43
|
+
"tables.getCells",
|
|
41
44
|
"getNodeById",
|
|
42
|
-
"create.paragraph",
|
|
43
45
|
"getNodeById",
|
|
44
46
|
"format.apply",
|
|
45
47
|
"tables.get",
|
|
46
48
|
"tables.getCells",
|
|
47
|
-
"
|
|
48
|
-
"create.paragraph",
|
|
49
|
+
"insert",
|
|
49
50
|
"tables.get",
|
|
50
51
|
"tables.getCells",
|
|
51
52
|
"getNodeById",
|
|
52
|
-
"
|
|
53
|
+
"tables.get",
|
|
54
|
+
"tables.getCells",
|
|
55
|
+
"insert",
|
|
53
56
|
"tables.get",
|
|
54
57
|
"tables.getCells",
|
|
55
58
|
"getNodeById",
|
|
56
|
-
"
|
|
59
|
+
"tables.get",
|
|
60
|
+
"tables.getCells",
|
|
61
|
+
"insert",
|
|
62
|
+
"tables.get",
|
|
63
|
+
"tables.getCells",
|
|
64
|
+
"getNodeById"
|
|
57
65
|
]
|
|
@@ -3,52 +3,72 @@
|
|
|
3
3
|
"tables.setStyle",
|
|
4
4
|
"tables.get",
|
|
5
5
|
"tables.getCells",
|
|
6
|
+
"insert",
|
|
7
|
+
"tables.get",
|
|
8
|
+
"tables.getCells",
|
|
6
9
|
"getNodeById",
|
|
7
|
-
"create.paragraph",
|
|
8
10
|
"format.paragraph.setAlignment",
|
|
9
11
|
"tables.get",
|
|
10
12
|
"tables.getCells",
|
|
13
|
+
"insert",
|
|
14
|
+
"tables.get",
|
|
15
|
+
"tables.getCells",
|
|
11
16
|
"getNodeById",
|
|
12
|
-
"create.paragraph",
|
|
13
17
|
"format.paragraph.setAlignment",
|
|
14
18
|
"tables.get",
|
|
15
19
|
"tables.getCells",
|
|
20
|
+
"insert",
|
|
21
|
+
"tables.get",
|
|
22
|
+
"tables.getCells",
|
|
16
23
|
"getNodeById",
|
|
17
|
-
"create.paragraph",
|
|
18
24
|
"format.paragraph.setAlignment",
|
|
19
25
|
"tables.get",
|
|
20
26
|
"tables.getCells",
|
|
27
|
+
"insert",
|
|
28
|
+
"tables.get",
|
|
29
|
+
"tables.getCells",
|
|
21
30
|
"getNodeById",
|
|
22
|
-
"create.paragraph",
|
|
23
31
|
"format.paragraph.setAlignment",
|
|
24
32
|
"tables.get",
|
|
25
33
|
"tables.getCells",
|
|
34
|
+
"insert",
|
|
35
|
+
"tables.get",
|
|
36
|
+
"tables.getCells",
|
|
26
37
|
"getNodeById",
|
|
27
|
-
"create.paragraph",
|
|
28
38
|
"format.paragraph.setAlignment",
|
|
29
39
|
"tables.get",
|
|
30
40
|
"tables.getCells",
|
|
41
|
+
"insert",
|
|
42
|
+
"tables.get",
|
|
43
|
+
"tables.getCells",
|
|
31
44
|
"getNodeById",
|
|
32
|
-
"create.paragraph",
|
|
33
45
|
"format.paragraph.setAlignment",
|
|
34
46
|
"tables.get",
|
|
35
47
|
"tables.getCells",
|
|
48
|
+
"insert",
|
|
49
|
+
"tables.get",
|
|
50
|
+
"tables.getCells",
|
|
36
51
|
"getNodeById",
|
|
37
|
-
"create.paragraph",
|
|
38
52
|
"format.paragraph.setAlignment",
|
|
39
53
|
"tables.get",
|
|
40
54
|
"tables.getCells",
|
|
55
|
+
"insert",
|
|
56
|
+
"tables.get",
|
|
57
|
+
"tables.getCells",
|
|
41
58
|
"getNodeById",
|
|
42
|
-
"create.paragraph",
|
|
43
59
|
"format.paragraph.setAlignment",
|
|
44
60
|
"tables.get",
|
|
45
61
|
"tables.getCells",
|
|
62
|
+
"insert",
|
|
63
|
+
"tables.get",
|
|
64
|
+
"tables.getCells",
|
|
46
65
|
"getNodeById",
|
|
47
|
-
"create.paragraph",
|
|
48
66
|
"format.paragraph.setAlignment",
|
|
49
67
|
"tables.get",
|
|
50
68
|
"tables.getCells",
|
|
69
|
+
"insert",
|
|
70
|
+
"tables.get",
|
|
71
|
+
"tables.getCells",
|
|
51
72
|
"getNodeById",
|
|
52
|
-
"create.paragraph",
|
|
53
73
|
"format.paragraph.setAlignment"
|
|
54
74
|
]
|
|
@@ -45,8 +45,10 @@
|
|
|
45
45
|
"tables.setCell",
|
|
46
46
|
"tables.get",
|
|
47
47
|
"tables.getCells",
|
|
48
|
+
"insert",
|
|
49
|
+
"tables.get",
|
|
50
|
+
"tables.getCells",
|
|
48
51
|
"getNodeById",
|
|
49
|
-
"create.paragraph",
|
|
50
52
|
"getNodeById",
|
|
51
53
|
"getNodeById",
|
|
52
54
|
"format.apply",
|
|
@@ -54,8 +56,10 @@
|
|
|
54
56
|
"format.apply",
|
|
55
57
|
"tables.get",
|
|
56
58
|
"tables.getCells",
|
|
59
|
+
"insert",
|
|
60
|
+
"tables.get",
|
|
61
|
+
"tables.getCells",
|
|
57
62
|
"getNodeById",
|
|
58
|
-
"create.paragraph",
|
|
59
63
|
"getNodeById",
|
|
60
64
|
"getNodeById",
|
|
61
65
|
"format.apply",
|
|
@@ -63,8 +67,10 @@
|
|
|
63
67
|
"format.apply",
|
|
64
68
|
"tables.get",
|
|
65
69
|
"tables.getCells",
|
|
70
|
+
"insert",
|
|
71
|
+
"tables.get",
|
|
72
|
+
"tables.getCells",
|
|
66
73
|
"getNodeById",
|
|
67
|
-
"create.paragraph",
|
|
68
74
|
"getNodeById",
|
|
69
75
|
"getNodeById",
|
|
70
76
|
"format.apply",
|
|
@@ -72,8 +78,10 @@
|
|
|
72
78
|
"format.apply",
|
|
73
79
|
"tables.get",
|
|
74
80
|
"tables.getCells",
|
|
81
|
+
"insert",
|
|
82
|
+
"tables.get",
|
|
83
|
+
"tables.getCells",
|
|
75
84
|
"getNodeById",
|
|
76
|
-
"create.paragraph",
|
|
77
85
|
"getNodeById",
|
|
78
86
|
"getNodeById",
|
|
79
87
|
"format.apply",
|
|
@@ -81,8 +89,10 @@
|
|
|
81
89
|
"format.apply",
|
|
82
90
|
"tables.get",
|
|
83
91
|
"tables.getCells",
|
|
92
|
+
"insert",
|
|
93
|
+
"tables.get",
|
|
94
|
+
"tables.getCells",
|
|
84
95
|
"getNodeById",
|
|
85
|
-
"create.paragraph",
|
|
86
96
|
"getNodeById",
|
|
87
97
|
"getNodeById",
|
|
88
98
|
"format.apply",
|
|
@@ -90,8 +100,10 @@
|
|
|
90
100
|
"format.apply",
|
|
91
101
|
"tables.get",
|
|
92
102
|
"tables.getCells",
|
|
103
|
+
"insert",
|
|
104
|
+
"tables.get",
|
|
105
|
+
"tables.getCells",
|
|
93
106
|
"getNodeById",
|
|
94
|
-
"create.paragraph",
|
|
95
107
|
"getNodeById",
|
|
96
108
|
"getNodeById",
|
|
97
109
|
"format.apply",
|
|
@@ -263,6 +263,75 @@ def test_generic_not_found_still_raises_notfounderror() -> None:
|
|
|
263
263
|
)
|
|
264
264
|
|
|
265
265
|
|
|
266
|
+
def test_invalid_target_tablecell_routes_through_block_not_found() -> None:
|
|
267
|
+
"""SuperDoc's newer cell-paragraph addressing-error shape
|
|
268
|
+
|
|
269
|
+
``INVALID_TARGET - Expected paragraph:<uuid> but found tableCell:<id>.``
|
|
270
|
+
|
|
271
|
+
must surface as :class:`BlockNotFoundError` with the cell-paragraph
|
|
272
|
+
hint, same as the older ``Block "paragraph:<uuid>" was not found``
|
|
273
|
+
form. Both error shapes share the same root cause (SUPERDOC_UPSTREAM_
|
|
274
|
+
REQUESTS § 13) — agents shouldn't have to learn which variant fired
|
|
275
|
+
to find the recovery path."""
|
|
276
|
+
|
|
277
|
+
def _capture(url: str, **kwargs: Any) -> _FakeResponse: # noqa: ARG001
|
|
278
|
+
return _FakeResponse(
|
|
279
|
+
status_code=207,
|
|
280
|
+
body=_partial_failure_body(
|
|
281
|
+
cmd_type="SetParagraphAlignment",
|
|
282
|
+
message=(
|
|
283
|
+
"INVALID_TARGET - Expected paragraph:"
|
|
284
|
+
"2d58567b-e933-4f72-bfde-674e7b552f8a but found "
|
|
285
|
+
"tableCell:cell-auto-38f799d7."
|
|
286
|
+
),
|
|
287
|
+
),
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
client = HttpClient(base_url="https://example.com", api_key="bg_key")
|
|
291
|
+
|
|
292
|
+
with patch.object(client._session, "post", side_effect=_capture):
|
|
293
|
+
with pytest.raises(BlockNotFoundError) as exc_info:
|
|
294
|
+
_execute_setalignment(client)
|
|
295
|
+
|
|
296
|
+
msg = str(exc_info.value)
|
|
297
|
+
assert "cell.text" in msg, (
|
|
298
|
+
"INVALID_TARGET ... but found tableCell is the new variant of "
|
|
299
|
+
"the cell-paragraph addressing gap (SUPERDOC_UPSTREAM_REQUESTS "
|
|
300
|
+
"§ 13). The hint MUST fire here just like the older 'Block "
|
|
301
|
+
"not found' form."
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
def test_invalid_target_create_paragraph_routes_through_block_not_found() -> None:
|
|
306
|
+
"""``CreateParagraph`` against a cell-inner paragraph anchor (the
|
|
307
|
+
pre-0.11.x ``_Cell.add_paragraph`` shape) raises the INVALID_TARGET
|
|
308
|
+
form. ``_Cell.add_paragraph`` now routes through ``doc.insert``
|
|
309
|
+
instead, but other call sites that build a Create with a cell-inner
|
|
310
|
+
target should still get the hint instead of a generic DocxError."""
|
|
311
|
+
|
|
312
|
+
def _capture(url: str, **kwargs: Any) -> _FakeResponse: # noqa: ARG001
|
|
313
|
+
return _FakeResponse(
|
|
314
|
+
status_code=207,
|
|
315
|
+
body=_partial_failure_body(
|
|
316
|
+
cmd_type="CreateParagraph",
|
|
317
|
+
message=(
|
|
318
|
+
"INVALID_TARGET - Expected paragraph:"
|
|
319
|
+
"2d58567b-e933-4f72-bfde-674e7b552f8a but found "
|
|
320
|
+
"tableCell:cell-auto-38f799d7."
|
|
321
|
+
),
|
|
322
|
+
),
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
client = HttpClient(base_url="https://example.com", api_key="bg_key")
|
|
326
|
+
|
|
327
|
+
with patch.object(client._session, "post", side_effect=_capture):
|
|
328
|
+
with pytest.raises(BlockNotFoundError) as exc_info:
|
|
329
|
+
_execute_setalignment(client)
|
|
330
|
+
|
|
331
|
+
msg = str(exc_info.value)
|
|
332
|
+
assert "cell.text" in msg
|
|
333
|
+
|
|
334
|
+
|
|
266
335
|
def test_transport_error_unchanged() -> None:
|
|
267
336
|
"""A genuine 5xx or validation error must NOT be reclassified as
|
|
268
337
|
:class:`BlockNotFoundError`. Only the "Block ... not found" shape
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"""Wire-shape lock-in for ``_Cell.add_paragraph``.
|
|
2
|
+
|
|
3
|
+
Pre-fix: the SDK anchored ``create.paragraph`` after the cell's last
|
|
4
|
+
inner paragraph (``at: {kind: "after", target: paragraph(<inner-id>)}``).
|
|
5
|
+
SuperDoc 1.8.1 cannot resolve that anchor for cell-inner paragraphs
|
|
6
|
+
and raises ``INVALID_TARGET - Expected paragraph:<id> but found
|
|
7
|
+
tableCell:<id>``. See ``docx-studio/SUPERDOC_UPSTREAM_REQUESTS.md`` § 13.
|
|
8
|
+
|
|
9
|
+
Post-fix: the SDK routes through ``doc.insert`` with the cell itself
|
|
10
|
+
as target and ``placement: "insideEnd"`` — the same wire path that
|
|
11
|
+
``_Cell.text`` already uses successfully.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
from typing import Any
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _make_cell(mock_session: Any, fake_sd_methods: Any) -> Any:
|
|
20
|
+
from docx.table import Table, _Cell
|
|
21
|
+
|
|
22
|
+
fake_sd_methods.scripted_returns["tables.get_cells"] = {
|
|
23
|
+
"cells": [
|
|
24
|
+
{
|
|
25
|
+
"nodeId": "cell-auto-abc123",
|
|
26
|
+
"rowIndex": 0,
|
|
27
|
+
"columnIndex": 0,
|
|
28
|
+
"text": "existing content",
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
}
|
|
32
|
+
fake_sd_methods.scripted_returns["get_node_by_id"] = {
|
|
33
|
+
"node": {
|
|
34
|
+
"kind": "tableCell",
|
|
35
|
+
"id": "cell-auto-abc123",
|
|
36
|
+
"tableCell": {
|
|
37
|
+
"paragraphs": [
|
|
38
|
+
{"kind": "paragraph", "id": "para-existing-1"},
|
|
39
|
+
{"kind": "paragraph", "id": "para-new-2"},
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
table = Table(session=mock_session, node_id="tbl-1")
|
|
46
|
+
return _Cell(table=table, row=0, col=0)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def test_cell_add_paragraph_routes_through_insert(
|
|
50
|
+
mock_session: Any, fake_sd_methods: Any
|
|
51
|
+
) -> None:
|
|
52
|
+
"""``cell.add_paragraph('hi')`` MUST NOT call ``create.paragraph``
|
|
53
|
+
with a cell-inner-paragraph anchor.
|
|
54
|
+
|
|
55
|
+
The pre-fix wire shape was:
|
|
56
|
+
create.paragraph({
|
|
57
|
+
text: "hi",
|
|
58
|
+
at: {kind: "after",
|
|
59
|
+
target: {nodeType: "paragraph", nodeId: <inner-id>}},
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
That shape provokes SuperDoc 1.8.1's INVALID_TARGET error on every
|
|
63
|
+
cell loaded from a real .docx (every such cell has at least one
|
|
64
|
+
inner paragraph). The post-fix shape uses ``doc.insert`` against
|
|
65
|
+
the cell with ``placement: insideEnd``.
|
|
66
|
+
"""
|
|
67
|
+
cell = _make_cell(mock_session, fake_sd_methods)
|
|
68
|
+
|
|
69
|
+
cell.add_paragraph("hi")
|
|
70
|
+
|
|
71
|
+
insert_calls = [c for c in fake_sd_methods.calls if c[0] == "insert"]
|
|
72
|
+
assert insert_calls, (
|
|
73
|
+
"Expected _Cell.add_paragraph to call doc.insert, but only saw "
|
|
74
|
+
f"{[c[0] for c in fake_sd_methods.calls]}"
|
|
75
|
+
)
|
|
76
|
+
_, params = insert_calls[-1]
|
|
77
|
+
assert params["target"] == {
|
|
78
|
+
"kind": "block",
|
|
79
|
+
"nodeType": "tableCell",
|
|
80
|
+
"nodeId": "cell-auto-abc123",
|
|
81
|
+
}, f"target must be the cell itself, not its inner paragraph; got {params['target']!r}"
|
|
82
|
+
assert params["placement"] == "insideEnd"
|
|
83
|
+
content = params["content"]
|
|
84
|
+
assert isinstance(content, dict)
|
|
85
|
+
assert content["kind"] == "paragraph"
|
|
86
|
+
inlines = content["paragraph"]["inlines"]
|
|
87
|
+
assert inlines == [{"kind": "run", "run": {"text": "hi"}}]
|
|
88
|
+
|
|
89
|
+
create_para_calls = [
|
|
90
|
+
c for c in fake_sd_methods.calls if c[0] == "create.paragraph"
|
|
91
|
+
]
|
|
92
|
+
for _, p in create_para_calls:
|
|
93
|
+
at = p.get("at") or {}
|
|
94
|
+
target = at.get("target") or {}
|
|
95
|
+
assert target.get("nodeType") != "paragraph" or not str(
|
|
96
|
+
target.get("nodeId", "")
|
|
97
|
+
).startswith("para-"), (
|
|
98
|
+
"create.paragraph must not anchor to a cell-inner "
|
|
99
|
+
f"paragraph (got at={at!r})"
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def test_cell_add_paragraph_empty_text_emits_empty_inlines(
|
|
104
|
+
mock_session: Any, fake_sd_methods: Any
|
|
105
|
+
) -> None:
|
|
106
|
+
"""``cell.add_paragraph()`` (no text) inserts a paragraph fragment
|
|
107
|
+
with an empty inlines list — the same shape ``_Cell.text = ''``
|
|
108
|
+
produces."""
|
|
109
|
+
cell = _make_cell(mock_session, fake_sd_methods)
|
|
110
|
+
|
|
111
|
+
cell.add_paragraph()
|
|
112
|
+
|
|
113
|
+
insert_calls = [c for c in fake_sd_methods.calls if c[0] == "insert"]
|
|
114
|
+
assert insert_calls
|
|
115
|
+
_, params = insert_calls[-1]
|
|
116
|
+
assert params["content"]["paragraph"]["inlines"] == []
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def test_cell_add_paragraph_returns_paragraph_with_node_id(
|
|
120
|
+
mock_session: Any, fake_sd_methods: Any
|
|
121
|
+
) -> None:
|
|
122
|
+
"""The returned ``Paragraph`` proxy must carry a real node_id so
|
|
123
|
+
follow-up operations (``para.style = ...``, ``para.add_run(...)``)
|
|
124
|
+
address the new paragraph rather than its containing cell.
|
|
125
|
+
"""
|
|
126
|
+
cell = _make_cell(mock_session, fake_sd_methods)
|
|
127
|
+
|
|
128
|
+
para = cell.add_paragraph("hi")
|
|
129
|
+
|
|
130
|
+
from docx.text.paragraph import Paragraph
|
|
131
|
+
|
|
132
|
+
assert isinstance(para, Paragraph)
|
|
133
|
+
assert para._node_id, "Paragraph proxy must carry a non-empty node_id"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|