athena-python-docx 0.21.1__tar.gz → 0.21.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.
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/PKG-INFO +1 -1
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/__init__.py +1 -1
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/_buffer.py +6 -4
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/_citations.py +5 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/table.py +87 -32
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/pyproject.toml +1 -1
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/firm_templates/test_pw_corpus.py +2 -14
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_citations.py +1 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_positional_cell_id.py +142 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_ptc.py +35 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/uv.lock +1 -1
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/.gitignore +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/CLAUDE.md +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/DOCX_EXEC_LAB.md +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/README.md +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/_athena_extension.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/_batching.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/_execution.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/_http.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/_http_doc.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/_image_utils.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/_postproc.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/_ptc.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/_references.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/_table_styles.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/_timeouts.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/api.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/bookmarks.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/charts.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/client.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/commands.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/comments.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/document.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/enum/__init__.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/enum/section.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/enum/shape.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/enum/style.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/enum/table.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/enum/text.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/errors.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/exceptions.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/fields.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/footnotes.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/math.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/opc/__init__.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/opc/coreprops.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/oxml/__init__.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/revisions.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/sdt.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/section.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/session.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/settings.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/shape.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/shared.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/styles/__init__.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/styles/style.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/styles/styles.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/text/__init__.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/text/font.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/text/hyperlink.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/text/pagebreak.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/text/paragraph.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/text/parfmt.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/text/run.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/text/tabstops.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/toc.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/docx/typing.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/scripts/docx_exec_lab.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/scripts/docx_exec_lab_examples/fast_table_fill.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/scripts/docx_exec_lab_examples/find_replace_literal.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/scripts/docx_exec_lab_server.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/scripts/dump_wire_fixtures.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/scripts/publish.sh +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/scripts/release.sh +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/scripts/round_trip_smoke.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/scripts/smoke_test_block_not_found.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/scripts/validate_find_replace_asset.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/__init__.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/conftest.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/METHODOLOGY.md +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/README.md +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/__init__.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/ab_probe_cases.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/ab_probe_runner.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/auto_gen_cases.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/binary_round_trip.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/cases.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/complex_cases.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/coverage_report.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/extract.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/extreme_cases.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/fake_session.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/firm_templates/README.md +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/firm_templates/__init__.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/firm_templates/_runner.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/firm_templates/extractor.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/firm_templates/test_pw_research_digest.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/local_runner.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/mega_cases.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshot.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/01_basic_paragraph.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/02_multiple_headings.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/03_runs_with_formatting.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/04_font_name_and_size.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/05_font_color_rgb.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/06_font_character_properties.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/07_font_subscript_superscript.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/08_font_highlight.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/09_paragraph_alignment.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/100_table_negative_indexing.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/101_table_cells_flat_iteration.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/102_text_with_embedded_special_chars.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/104_core_properties_datetime.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/105_default_one_section.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/106_heading_paragraph_format.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/107_varying_row_heights.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/10_paragraph_indents.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/11_paragraph_spacing.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/12_paragraph_keep_options.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/13_paragraph_tab_stops.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/14_run_add_tab_and_break.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/15_run_add_break_page.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/16_paragraph_clear_and_insert_before.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/17_table_basic.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/18_table_cell_text.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/19_table_row_column_sizing.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/20_table_cell_vertical_alignment.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/21_table_alignment_and_autofit.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/22_table_cell_paragraphs_iteration.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/24_table_add_row_column.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/25_table_merge_cells.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/26_section_page_setup.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/27_section_margins.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/28_section_add_new.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/29_section_headers_linked.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/30_styles_iteration.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/31_styles_lookup_and_default.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/32_styles_add_paragraph_style.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/33_core_properties_set_and_get.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/34_inline_shapes_iterate_empty.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/35_full_report.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/36_replace_text_in_paragraph.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/37_iterate_runs_and_format_all_bold.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/38_font_all_properties.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/39_large_body_100_paragraphs.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/40_large_table_10x10.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/41_unicode_and_emoji.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/42_very_long_paragraph.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/43_paragraph_text_round_trip.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/44_paragraph_alignment_round_trip.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/45_cell_text_round_trip.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/46_run_text_setter_round_trip.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/47_font_size_round_trip.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/48_font_color_round_trip.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/49_resume_layout.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/50_multi_section_doc.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/52_iterate_everything.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/53_apply_style_to_paragraphs.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/54_empty_everything.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/55_single_character_runs.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/56_everything_in_one.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/57_runs_after_multiple_text_appends.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/58_modify_runs_in_place.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/59_indent_round_trip.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/60_space_round_trip.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/61_cell_paragraph_with_runs.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/62_many_cell_paragraphs.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/63_table_style_round_trip.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/64_many_sections.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/65_20x20_table_formatted.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/66_toc_like_structure.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/67_paragraph_insert_before_chain.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/68_invoice.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/69_newsletter.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/70_add_and_iterate_back.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/71_academic_paper.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/72_legal_contract.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/73_form_with_many_tables.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/74_paragraph_with_10_runs.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/75_paragraph_negative_first_line_indent.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/76_rgbcolor_from_string.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/77_length_unit_conversions.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/78_paragraph_copy_style.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/79_bulk_cell_formatting.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/80_apply_style_after_add_run.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/81_multi_page_with_breaks.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/82_add_text_on_existing_run.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/83_clear_then_repopulate_paragraph.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/84_table_reread_row_count.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/85_header_footer_access.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/86_font_read_unset_returns_none.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/87_500_paragraph_doc.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/88_mixed_content_iteration.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/89_alignment_clear_via_none.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/90_cell_add_paragraph_styled.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/91_many_small_tables.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/92_margins_every_section.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/93_font_bool_reads_after_set.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/94_page_break_before_paragraph.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/95_paragraph_hyperlinks_empty.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/96_paragraph_contains_page_break.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/97_document_styles_by_key.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/98_style_contains_check.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/99_run_add_picture_from_bytes.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/ex02_unicode_everywhere.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/ex03_1000_paragraphs.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/ex04_50x50_table.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/ex05_long_text_in_cell.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/ex06_hundred_tiny_runs.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/ex07_every_font_boolean.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/ex08_many_continuous_sections.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/ex09_many_tab_stops.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/ex10_complex_bom.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/ex11_banded_rows_formatting.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/ex12_section_reconfigure.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/ex13_cell_with_10_paragraphs.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/ex14_styled_report_table.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/ex15_paragraph_all_format_props.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/ex16_runs_interleaved_with_breaks.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/ex17_all_break_kinds.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/ex18_read_back_large_doc.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/ex19_mutate_all_runs.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/ex20_kitchen_sink_v2.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/mega01_book_chapter.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/mega02_research_proposal.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/mega03_financial_statement.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/mega04_recipe_card.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/mega05_user_manual.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/mega06_complex_newsletter.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/mega07_budget_spreadsheet.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/mega08_product_catalog.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/mega09_signed_contract.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/mega10_api_documentation.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/rw01_official_quickstart.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/rw02_paragraph_style_list.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/rw03_character_formatting.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/rw04_section_page_setup.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/rw05_toc_pattern.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/rw06_meeting_minutes.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/rw07_dense_formatting_demo.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/rw08_table_merged_header.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/rw09_bulk_run_iteration.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/rw10_colored_grid_table.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/rw11_header_text.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/rw12_first_page_footer.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/rw13_even_page_header.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/op_snapshots/rw15_paragraph_style_instance.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/ours_spec.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/parity_crawl.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/parity_diff.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/real_world_cases.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/round_trip_tests.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/stock_spec.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/fidelity/test_e2e_against_staging.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/parity/README.md +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/parity/__init__.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/parity/baseline_gaps.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/parity/compare.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/parity/intentional_deviations.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/parity/introspect.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/parity/reports/GAP_ANALYSIS.md +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/parity/reports/gap_report.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/parity/run_parity.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/parity/snapshots/athena_latest.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/parity/snapshots/upstream_python_docx_1.2.0.json +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/parity/test_parity_gap.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_add_section_extract_items.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_athena_extensions_contract.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_athena_extensions_registry.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_batching_perf.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_block_not_found_error.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_buffer.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_cell_add_paragraph_wire_shape.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_cell_add_table_not_supported.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_cell_inner_add_hyperlink_stash.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_cell_inner_add_run_via_cell_insert.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_cell_inner_format_stash.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_cell_inner_run_format_stash.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_cell_inner_run_guard.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_cell_text_plain_fastpath.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_cell_text_replace_semantics.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_collapsed_range_format.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_command_dataclasses.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_commands.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_comments.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_document_asset_id_property.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_document_clear.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_document_create.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_document_create_from_template.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_document_factory_validation.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_docx_exec_lab.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_docx_exec_lab_server.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_e2e_partial_failure_cascade.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_execution_scope.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_find_replace_session_open.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_http_transport.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_hyperlink_coalescing.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_image_url_data_uri.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_insert_deferred.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_iter_inner_content.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_list_styles.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_merged_cell_secondary_slot.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_merged_cells.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_oxml_shim.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_paragraph_text_len_cache.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_parity_misc.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_parity_round2.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_partial_failure_cascade.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_phase_a_behavior.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_phase_b_headers_footers.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_phase_c_tables.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_postproc_cell_format_rewrite.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_postproc_cell_run_format_rewrite.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_postproc_ref_restore.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_pr19766_review_fixes.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_python_docx_api_parity.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_revisions.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_add_paragraph_style.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_add_picture.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_add_run.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_cell_add_paragraph.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_comments_add_comment.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_comments_get.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_document_audit.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_document_element.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_enum_section.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_font_audit.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_header_footer.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_hyperlink.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_inline_shape.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_insert_paragraph_before.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_misc.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_paragraph_strict.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_paragraph_style.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_paragraph_style_strict.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_parfmt.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_row_col_cell.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_run_add_break.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_run_bool_setters.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_run_style.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_run_style_strict.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_run_text.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_run_underline.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_section_audit.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_section_dimensions.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_section_onoff.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_settings.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_shared_audit.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_style.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_styles.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_table_audit.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_table_cell.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_table_dimensions.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_silent_stub_table_layout.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_smoke_integration.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_style_acceptance.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_style_font.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_style_setters_contract.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_table_set_cell_perf.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_table_style_id_resolution.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_temporarily_unavailable.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_validate_find_replace_asset_script.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_wire_contract.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_xml_attr_guard.py +0 -0
- {athena_python_docx-0.21.1 → athena_python_docx-0.21.3}/tests/test_zod_wire_contract.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: athena-python-docx
|
|
3
|
-
Version: 0.21.
|
|
3
|
+
Version: 0.21.3
|
|
4
4
|
Summary: Drop-in replacement for python-docx that connects to Athena's DOCX Studio collaborative document stack
|
|
5
5
|
Project-URL: Homepage, https://athenaintelligence.ai
|
|
6
6
|
Author-email: Athena Intelligence <engineering@athenaintelligence.ai>
|
|
@@ -124,10 +124,12 @@ if TYPE_CHECKING:
|
|
|
124
124
|
# HTTP POST to agora (see ``_ptc._send``), so emitting one card per low-level
|
|
125
125
|
# mutation produces hundreds of sub-cards per script and pays full network
|
|
126
126
|
# RTT on every one. The allow-list keeps the per-action signal — one card
|
|
127
|
-
# per logical block creation
|
|
128
|
-
#
|
|
129
|
-
#
|
|
130
|
-
_PTC_EMIT_TOOLS: frozenset[str] = frozenset(
|
|
127
|
+
# per logical block/citation creation — without the spam or the cumulative
|
|
128
|
+
# latency. Asset-level creation events (``CreateDocument``) are emitted from
|
|
129
|
+
# ``Document.create`` directly, not through this buffer path.
|
|
130
|
+
_PTC_EMIT_TOOLS: frozenset[str] = frozenset(
|
|
131
|
+
{"CreateParagraph", "CreateHeading", "CreateTable", "AddCitation"}
|
|
132
|
+
)
|
|
131
133
|
|
|
132
134
|
|
|
133
135
|
def _should_emit_ptc(cmd: Command) -> bool:
|
|
@@ -53,6 +53,11 @@ def normalize_citation_string(citation_string: str) -> str:
|
|
|
53
53
|
|
|
54
54
|
if not parsed.scheme and value.startswith("/"):
|
|
55
55
|
relative = urlparse(value)
|
|
56
|
+
if relative.netloc:
|
|
57
|
+
raise ValueError(
|
|
58
|
+
"protocol-relative Athena Spaces citation URLs are not allowed; "
|
|
59
|
+
"use an absolute Athena host"
|
|
60
|
+
)
|
|
56
61
|
if relative.path.rstrip("/") == "/dashboard/spaces":
|
|
57
62
|
asset_ids = parse_qs(relative.query).get("asset_ids")
|
|
58
63
|
if asset_ids and asset_ids[0]:
|
|
@@ -108,6 +108,37 @@ def _normalize_border_spec(spec: "dict | str | None", *, edge: str) -> "dict | N
|
|
|
108
108
|
)
|
|
109
109
|
|
|
110
110
|
|
|
111
|
+
def _table_node_id_from_item(item: object) -> str | None:
|
|
112
|
+
if not isinstance(item, dict):
|
|
113
|
+
return None
|
|
114
|
+
addr = item.get("address")
|
|
115
|
+
if isinstance(addr, dict):
|
|
116
|
+
nid = addr.get("nodeId")
|
|
117
|
+
if isinstance(nid, str) and nid:
|
|
118
|
+
return nid
|
|
119
|
+
nid = item.get("nodeId")
|
|
120
|
+
if isinstance(nid, str) and nid:
|
|
121
|
+
return nid
|
|
122
|
+
return None
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _table_items_from_blocks_list_result(result: object) -> list[dict]:
|
|
126
|
+
if isinstance(result, dict):
|
|
127
|
+
blocks_obj: object = result.get("blocks", [])
|
|
128
|
+
blocks = blocks_obj if isinstance(blocks_obj, list) else []
|
|
129
|
+
elif isinstance(result, list):
|
|
130
|
+
blocks = result
|
|
131
|
+
else:
|
|
132
|
+
blocks = []
|
|
133
|
+
return [
|
|
134
|
+
block
|
|
135
|
+
for block in blocks
|
|
136
|
+
if isinstance(block, dict)
|
|
137
|
+
and block.get("nodeType") == "table"
|
|
138
|
+
and _table_node_id_from_item(block)
|
|
139
|
+
]
|
|
140
|
+
|
|
141
|
+
|
|
111
142
|
if TYPE_CHECKING:
|
|
112
143
|
from docx.client import Session
|
|
113
144
|
from docx.enum.table import (
|
|
@@ -474,25 +505,33 @@ class Table:
|
|
|
474
505
|
return self._node_id, info
|
|
475
506
|
except Exception:
|
|
476
507
|
pass
|
|
477
|
-
# Fallback: scan top-level tables
|
|
478
|
-
#
|
|
479
|
-
#
|
|
480
|
-
#
|
|
481
|
-
#
|
|
482
|
-
#
|
|
483
|
-
#
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
508
|
+
# Fallback: scan top-level tables in document order. Prefer
|
|
509
|
+
# ``blocks.list`` because docx-editor supports it on the same engine
|
|
510
|
+
# path used by ``Document.tables``; ``doc.find({"type": "table"})`` is
|
|
511
|
+
# not implemented by older docx-editor appliers and caused immediate
|
|
512
|
+
# failures when agents styled a freshly-created table cell. Keep
|
|
513
|
+
# ``doc.find`` only as a compatibility fallback for transports that
|
|
514
|
+
# do not expose ``blocks.list``.
|
|
515
|
+
items: list = []
|
|
516
|
+
try:
|
|
517
|
+
blocks_result: object = run_sync(
|
|
518
|
+
self._session.doc.blocks.list(
|
|
519
|
+
{"nodeTypes": ["table"], "includeText": False},
|
|
520
|
+
),
|
|
521
|
+
)
|
|
522
|
+
items = _table_items_from_blocks_list_result(blocks_result)
|
|
523
|
+
except Exception as exc: # noqa: BLE001
|
|
524
|
+
_log_debug(f"table rotation lookup via blocks.list failed: {type(exc).__name__}: {exc}")
|
|
525
|
+
if not items:
|
|
526
|
+
find_result: object = run_sync(
|
|
527
|
+
self._session.doc.find({"type": "table"}),
|
|
528
|
+
)
|
|
529
|
+
items_obj: object = find_result.get("items", []) if isinstance(find_result, dict) else []
|
|
530
|
+
raw_items: list = items_obj if isinstance(items_obj, list) else []
|
|
531
|
+
items = [item for item in raw_items if isinstance(item, dict)]
|
|
491
532
|
for item in items:
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
addr = item.get("address", {})
|
|
495
|
-
if isinstance(addr, dict) and addr.get("nodeId") == self._node_id:
|
|
533
|
+
nid = _table_node_id_from_item(item)
|
|
534
|
+
if nid == self._node_id:
|
|
496
535
|
info_obj = run_sync(
|
|
497
536
|
self._session.doc.tables.get({"nodeId": self._node_id}),
|
|
498
537
|
)
|
|
@@ -522,17 +561,15 @@ class Table:
|
|
|
522
561
|
):
|
|
523
562
|
pos = len(items) - session_count + self._doc_index
|
|
524
563
|
cand = items[pos]
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
rotated_addr = ca
|
|
564
|
+
cand_id = _table_node_id_from_item(cand)
|
|
565
|
+
if cand_id:
|
|
566
|
+
rotated_addr = {"nodeId": cand_id}
|
|
529
567
|
elif len(items) == 1:
|
|
530
568
|
# Unambiguous: only one table in the doc.
|
|
531
569
|
cand = items[0]
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
rotated_addr = ca
|
|
570
|
+
cand_id = _table_node_id_from_item(cand)
|
|
571
|
+
if cand_id:
|
|
572
|
+
rotated_addr = {"nodeId": cand_id}
|
|
536
573
|
else:
|
|
537
574
|
# Multi-table doc, ``_doc_index`` unknown (proxy resolved
|
|
538
575
|
# via iteration / find rather than ``Document.add_table``)
|
|
@@ -1504,11 +1541,13 @@ class _Cell:
|
|
|
1504
1541
|
|
|
1505
1542
|
Reads the proxy's stored ``_node_id`` with NO round-trip. DOCX Studio
|
|
1506
1543
|
tables carry real (non-``t:N``) node ids → returns ``None`` so the
|
|
1507
|
-
caller queries (DOCX Studio is pooled, so that read is cheap anyway).
|
|
1508
|
-
freshly-created docx-editor table still holds a client UUID until its
|
|
1509
|
-
create flushes
|
|
1510
|
-
|
|
1511
|
-
|
|
1544
|
+
caller queries (DOCX Studio is pooled, so that read is cheap anyway).
|
|
1545
|
+
A freshly-created docx-editor table still holds a client UUID until its
|
|
1546
|
+
create flushes. For docx-editor, :meth:`Document.add_table` already
|
|
1547
|
+
knows the table's eventual document-order index, so SDK-created body
|
|
1548
|
+
tables can fast-path before a fragile first ``tables.get_cells`` query.
|
|
1549
|
+
We first try to flush the pending create so DOCX Studio's non-positional
|
|
1550
|
+
table ids can still fall back to the query path after the id rewrite.
|
|
1512
1551
|
|
|
1513
1552
|
Gated to a **known uniform grid**: the table must have been created
|
|
1514
1553
|
via :meth:`Document.add_table` (so ``_doc_index`` is set and the full
|
|
@@ -1520,11 +1559,27 @@ class _Cell:
|
|
|
1520
1559
|
fall back to the query path to stay address-correct.
|
|
1521
1560
|
"""
|
|
1522
1561
|
table = self._table
|
|
1523
|
-
|
|
1562
|
+
doc_index = getattr(table, "_doc_index", None)
|
|
1563
|
+
if doc_index is None or getattr(table, "_has_merges", False):
|
|
1524
1564
|
return None
|
|
1525
1565
|
nid = getattr(table, "_node_id", None)
|
|
1526
1566
|
if isinstance(nid, str) and nid.startswith("t:") and nid[2:].isdigit():
|
|
1527
1567
|
return f"tc:{nid[2:]}:{self._row}:{self._col}"
|
|
1568
|
+
if (
|
|
1569
|
+
isinstance(nid, str)
|
|
1570
|
+
and nid.startswith("t_")
|
|
1571
|
+
and getattr(table, "_header_footer_ref_id", None) is None
|
|
1572
|
+
):
|
|
1573
|
+
handle = getattr(table._session, "_doc_handle", None)
|
|
1574
|
+
buf = getattr(handle, "buffer", None) if handle is not None else None
|
|
1575
|
+
if buf is not None:
|
|
1576
|
+
buf.flush()
|
|
1577
|
+
nid = getattr(table, "_node_id", None)
|
|
1578
|
+
if isinstance(nid, str) and nid.startswith("t:") and nid[2:].isdigit():
|
|
1579
|
+
return f"tc:{nid[2:]}:{self._row}:{self._col}"
|
|
1580
|
+
if not (isinstance(nid, str) and nid.startswith("t_")):
|
|
1581
|
+
return None
|
|
1582
|
+
return f"tc:{doc_index}:{self._row}:{self._col}"
|
|
1528
1583
|
return None
|
|
1529
1584
|
|
|
1530
1585
|
def _cell_id(self) -> str:
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "athena-python-docx"
|
|
7
|
-
version = "0.21.
|
|
7
|
+
version = "0.21.3"
|
|
8
8
|
description = "Drop-in replacement for python-docx that connects to Athena's DOCX Studio collaborative document stack"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -52,8 +52,7 @@ class CorpusDoc:
|
|
|
52
52
|
|
|
53
53
|
# Per-doc captured scorecards. Captured 2026-05-17 from the corpus
|
|
54
54
|
# source files via ``extractor.py``; these values pin the round-trip
|
|
55
|
-
# output too (the bytes-in == bytes-out guarantee for everything
|
|
56
|
-
# except Purchase_Agreement, which is xfailed below).
|
|
55
|
+
# output too (the bytes-in == bytes-out guarantee for everything).
|
|
57
56
|
CORPUS: list[CorpusDoc] = [
|
|
58
57
|
CorpusDoc(
|
|
59
58
|
label="AI_Research_Digest",
|
|
@@ -246,15 +245,6 @@ CORPUS: list[CorpusDoc] = [
|
|
|
246
245
|
paragraph_style_defs=119, character_style_defs=54,
|
|
247
246
|
table_style_defs=2, custom_style_defs=118, image_files=0,
|
|
248
247
|
),
|
|
249
|
-
xfail_reason=(
|
|
250
|
-
"DOCX Studio § 18 strips REF field codes on import: 1989 → 1974 "
|
|
251
|
-
"bookmarks (15 _9kMxxx co-author bookmarks dropped) AND every "
|
|
252
|
-
"REF cross-reference's visible result text disappears, leaving "
|
|
253
|
-
'definitions like "Estimated Cash shall have the meaning set forth in" '
|
|
254
|
-
"without their trailing Section reference. Pinned strict so a DOCX Studio "
|
|
255
|
-
"fix surfaces as UNEXPECTED PASS. See docs/PW_CORPUS_FIDELITY_ASSESSMENT.md "
|
|
256
|
-
"§ 3 and DOCX_STUDIO_LIMITATIONS.md § 18."
|
|
257
|
-
),
|
|
258
248
|
),
|
|
259
249
|
]
|
|
260
250
|
|
|
@@ -335,9 +325,7 @@ def test_round_trip_preserves_scorecard(
|
|
|
335
325
|
) -> None:
|
|
336
326
|
"""The DOCX Studio round-trip must preserve the per-doc scorecard.
|
|
337
327
|
|
|
338
|
-
Docs in the ``xfail_reason`` regime are marked ``xfail(strict=True)
|
|
339
|
-
— currently only the Harvey Purchase Agreement, which loses all 301
|
|
340
|
-
REF field result texts (see DOCX Studio upstream § 18).
|
|
328
|
+
Docs in the ``xfail_reason`` regime are marked ``xfail(strict=True)``.
|
|
341
329
|
"""
|
|
342
330
|
# Make sure bun + corpus are available; otherwise skip with a clean
|
|
343
331
|
# reason. ``require_case`` raises a pytest.skip on missing source.
|
|
@@ -279,6 +279,7 @@ def test_add_citation_rejects_non_reference_source() -> None:
|
|
|
279
279
|
"mailto:source@example.com",
|
|
280
280
|
"https://",
|
|
281
281
|
"https://example.com/dashboard/spaces/?asset_ids=asset_pdf",
|
|
282
|
+
"//evil.com/dashboard/spaces/?asset_ids=asset_pdf",
|
|
282
283
|
):
|
|
283
284
|
with pytest.raises(ValueError, match="citation_string|asset_ids|Athena host"):
|
|
284
285
|
paragraph.add_citation(source) # type: ignore[arg-type]
|
|
@@ -19,6 +19,15 @@ address-correct.
|
|
|
19
19
|
from __future__ import annotations
|
|
20
20
|
|
|
21
21
|
|
|
22
|
+
class _RecordingSession:
|
|
23
|
+
def __init__(self) -> None:
|
|
24
|
+
self.commands: list[object] = []
|
|
25
|
+
|
|
26
|
+
async def send_command(self, command: object) -> dict:
|
|
27
|
+
self.commands.append(command)
|
|
28
|
+
return {}
|
|
29
|
+
|
|
30
|
+
|
|
22
31
|
class _CountingGetCells:
|
|
23
32
|
"""Async ``tables.get_cells`` stub that counts invocations."""
|
|
24
33
|
|
|
@@ -31,6 +40,42 @@ class _CountingGetCells:
|
|
|
31
40
|
return {"cells": [{"nodeId": self._cell_id, "colspan": 1, "rowspan": 1}]}
|
|
32
41
|
|
|
33
42
|
|
|
43
|
+
class _CountingTablesGet:
|
|
44
|
+
"""Async ``tables.get`` stub that records node-id lookups."""
|
|
45
|
+
|
|
46
|
+
def __init__(self, table_info_by_id: dict[str, dict] | None = None) -> None:
|
|
47
|
+
self.calls: list[dict] = []
|
|
48
|
+
self._table_info_by_id = table_info_by_id or {}
|
|
49
|
+
|
|
50
|
+
async def __call__(self, params: dict) -> dict:
|
|
51
|
+
self.calls.append(params)
|
|
52
|
+
node_id = params.get("nodeId")
|
|
53
|
+
if isinstance(node_id, str):
|
|
54
|
+
return self._table_info_by_id.get(node_id, {})
|
|
55
|
+
return {}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class _CountingBlocksList:
|
|
59
|
+
"""Async ``blocks.list`` stub used by table rotation fallback tests."""
|
|
60
|
+
|
|
61
|
+
def __init__(self, blocks: list[dict]) -> None:
|
|
62
|
+
self.calls: list[dict] = []
|
|
63
|
+
self._blocks = blocks
|
|
64
|
+
|
|
65
|
+
async def __call__(self, params: dict) -> dict:
|
|
66
|
+
self.calls.append(params)
|
|
67
|
+
return {"blocks": list(self._blocks)}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class _FailingFind:
|
|
71
|
+
def __init__(self) -> None:
|
|
72
|
+
self.calls = 0
|
|
73
|
+
|
|
74
|
+
async def __call__(self, params: dict) -> dict: # noqa: ARG002
|
|
75
|
+
self.calls += 1
|
|
76
|
+
raise AssertionError("doc.find should not be used when blocks.list resolves tables")
|
|
77
|
+
|
|
78
|
+
|
|
34
79
|
class _TableStub:
|
|
35
80
|
def __init__(
|
|
36
81
|
self,
|
|
@@ -53,6 +98,17 @@ class _TableStub:
|
|
|
53
98
|
return self._node_id
|
|
54
99
|
|
|
55
100
|
|
|
101
|
+
class _RewritingBuffer:
|
|
102
|
+
def __init__(self, table: _TableStub, real_node_id: str) -> None:
|
|
103
|
+
self.calls = 0
|
|
104
|
+
self._table = table
|
|
105
|
+
self._real_node_id = real_node_id
|
|
106
|
+
|
|
107
|
+
def flush(self) -> None:
|
|
108
|
+
self.calls += 1
|
|
109
|
+
self._table._node_id = self._real_node_id
|
|
110
|
+
|
|
111
|
+
|
|
56
112
|
def test_docx_editor_cell_id_is_positional_with_no_query() -> None:
|
|
57
113
|
from docx.table import _Cell
|
|
58
114
|
|
|
@@ -79,6 +135,32 @@ def test_docx_editor_cell_address_shape_no_query() -> None:
|
|
|
79
135
|
assert gc.calls == 0
|
|
80
136
|
|
|
81
137
|
|
|
138
|
+
def test_fresh_client_id_table_uses_known_doc_index_no_query() -> None:
|
|
139
|
+
from docx.table import _Cell
|
|
140
|
+
|
|
141
|
+
gc = _CountingGetCells()
|
|
142
|
+
table = _TableStub("t_client_abc", gc, doc_index=4)
|
|
143
|
+
cell = _Cell(table=table, row=1, col=1) # type: ignore[arg-type]
|
|
144
|
+
|
|
145
|
+
assert cell._cell_id() == "tc:4:1:1"
|
|
146
|
+
assert gc.calls == 0
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def test_fresh_client_id_table_flushes_buffer_then_uses_rewritten_positional_id() -> None:
|
|
150
|
+
from docx.table import _Cell
|
|
151
|
+
|
|
152
|
+
gc = _CountingGetCells()
|
|
153
|
+
table = _TableStub("t_client_abc", gc, doc_index=4)
|
|
154
|
+
buffer = _RewritingBuffer(table, "t:8")
|
|
155
|
+
table._session._doc_handle = type("_Handle", (), {"buffer": buffer})()
|
|
156
|
+
cell = _Cell(table=table, row=1, col=1) # type: ignore[arg-type]
|
|
157
|
+
|
|
158
|
+
assert cell._cell_id() == "tc:8:1:1"
|
|
159
|
+
assert table._node_id == "t:8"
|
|
160
|
+
assert buffer.calls == 1
|
|
161
|
+
assert gc.calls == 0
|
|
162
|
+
|
|
163
|
+
|
|
82
164
|
def test_docx_studio_cell_id_falls_back_to_query() -> None:
|
|
83
165
|
from docx.table import _Cell
|
|
84
166
|
|
|
@@ -117,3 +199,63 @@ def test_read_loaded_table_falls_back_to_query() -> None:
|
|
|
117
199
|
|
|
118
200
|
assert cell._cell_id() == "tc:0:0:1"
|
|
119
201
|
assert gc.calls >= 1
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def test_unflushed_client_table_uses_doc_index_not_find_for_cell_id() -> None:
|
|
205
|
+
from docx.table import Table, _Cell
|
|
206
|
+
|
|
207
|
+
get_cells = _CountingGetCells(cell_id="tc:0:0:0")
|
|
208
|
+
tables_get = _CountingTablesGet(
|
|
209
|
+
table_info_by_id={
|
|
210
|
+
"t:0": {"nodeId": "t:0", "rows": 2, "columns": 2},
|
|
211
|
+
},
|
|
212
|
+
)
|
|
213
|
+
blocks_list = _CountingBlocksList(
|
|
214
|
+
blocks=[
|
|
215
|
+
{"nodeType": "table", "nodeId": "t:0"},
|
|
216
|
+
],
|
|
217
|
+
)
|
|
218
|
+
failing_find = _FailingFind()
|
|
219
|
+
doc = type(
|
|
220
|
+
"_Doc",
|
|
221
|
+
(),
|
|
222
|
+
{
|
|
223
|
+
"tables": type(
|
|
224
|
+
"_Tables",
|
|
225
|
+
(),
|
|
226
|
+
{"get": tables_get, "get_cells": get_cells},
|
|
227
|
+
)(),
|
|
228
|
+
"blocks": type("_Blocks", (), {"list": blocks_list})(),
|
|
229
|
+
"find": failing_find,
|
|
230
|
+
},
|
|
231
|
+
)()
|
|
232
|
+
session = type("_S", (), {"doc": doc})()
|
|
233
|
+
table = Table(session=session, node_id="t_client_uuid", rows=2, columns=2, doc_index=0)
|
|
234
|
+
cell = _Cell(table=table, row=0, col=0)
|
|
235
|
+
|
|
236
|
+
assert cell._cell_id() == "tc:0:0:0"
|
|
237
|
+
assert table._node_id == "t_client_uuid"
|
|
238
|
+
assert blocks_list.calls == []
|
|
239
|
+
assert failing_find.calls == 0
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def test_set_shading_uses_positional_cell_target_without_query() -> None:
|
|
243
|
+
from docx.table import Table, _Cell
|
|
244
|
+
|
|
245
|
+
session = _RecordingSession()
|
|
246
|
+
table = Table(session=session, node_id="t:2", rows=2, columns=2, doc_index=2)
|
|
247
|
+
cell = _Cell(table=table, row=0, col=1)
|
|
248
|
+
|
|
249
|
+
cell.set_shading(fill="1F497D")
|
|
250
|
+
|
|
251
|
+
assert len(session.commands) == 1
|
|
252
|
+
command = session.commands[0]
|
|
253
|
+
assert command.to_dict() == {
|
|
254
|
+
"type": "SetCellShading",
|
|
255
|
+
"target": {
|
|
256
|
+
"kind": "block",
|
|
257
|
+
"nodeType": "tableCell",
|
|
258
|
+
"nodeId": "tc:2:0:1",
|
|
259
|
+
},
|
|
260
|
+
"fill": "1F497D",
|
|
261
|
+
}
|
|
@@ -524,6 +524,41 @@ def test_buffer_emits_for_create_table(monkeypatch: Any) -> None:
|
|
|
524
524
|
assert calls["end"][0]["is_error"] is False
|
|
525
525
|
|
|
526
526
|
|
|
527
|
+
def test_buffer_emits_for_add_citation(monkeypatch: Any) -> None:
|
|
528
|
+
"""``AddCitation`` is allow-listed so agent-authored citations are
|
|
529
|
+
visible as PTC sub-tool-cards instead of silently only updating the
|
|
530
|
+
Athena citation layer."""
|
|
531
|
+
from docx._buffer import CommandBuffer
|
|
532
|
+
from docx.commands import AddCitation
|
|
533
|
+
|
|
534
|
+
calls = _stub_ptc(monkeypatch)
|
|
535
|
+
client = _FakeHttpClient()
|
|
536
|
+
buf = CommandBuffer(client, asset_id="asset-1", auto_flush_seconds=0)
|
|
537
|
+
|
|
538
|
+
buf.call(
|
|
539
|
+
AddCitation(
|
|
540
|
+
destination_anchor={"type": "pm_node", "nodeId": "p_1"},
|
|
541
|
+
citation_string="/dashboard/spaces/?asset_ids=asset_pdf&type=pdf&page=2",
|
|
542
|
+
citation_id="citation_abc",
|
|
543
|
+
excerpt="20,049 total vulnerabilities",
|
|
544
|
+
display_value="Vulnerability total",
|
|
545
|
+
)
|
|
546
|
+
)
|
|
547
|
+
|
|
548
|
+
assert len(calls["begin"]) == 1
|
|
549
|
+
assert calls["begin"][0][0] == "AddCitation"
|
|
550
|
+
assert calls["begin"][0][1]["citationString"] == (
|
|
551
|
+
"/dashboard/spaces/?asset_ids=asset_pdf&type=pdf&page=2"
|
|
552
|
+
)
|
|
553
|
+
assert calls["begin"][0][3] == "asset-1"
|
|
554
|
+
assert len(calls["end"]) == 0
|
|
555
|
+
|
|
556
|
+
buf.flush()
|
|
557
|
+
assert len(calls["end"]) == 1
|
|
558
|
+
assert calls["end"][0]["tool_name"] == "AddCitation"
|
|
559
|
+
assert calls["end"][0]["is_error"] is False
|
|
560
|
+
|
|
561
|
+
|
|
527
562
|
def test_buffer_skips_ptc_for_non_body_creates(monkeypatch: Any) -> None:
|
|
528
563
|
"""Allow-listed creates that target a non-body story (header/footer/
|
|
529
564
|
footnote via ``in_``) do NOT emit a PTC card: the frontend locate
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|