athena-python-docx 0.32.0__tar.gz → 0.33.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/PKG-INFO +1 -1
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/__init__.py +1 -1
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/text/hyperlink.py +7 -4
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/text/pagebreak.py +65 -18
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/text/paragraph.py +42 -12
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/text/run.py +60 -6
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/pyproject.toml +1 -1
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fixtures/field_reads.json +1 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/live/baseline.json +1 -59
- athena_python_docx-0.33.0/tests/test_rendered_page_breaks.py +196 -0
- athena_python_docx-0.33.0/tests/test_run_unmodeled_toggles.py +86 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/uv.lock +1 -1
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/.gitignore +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/AGENTS.md +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/CLAUDE.md +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/DOCX_EXEC_LAB.md +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/README.md +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/_athena_extension.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/_batching.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/_buffer.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/_capabilities.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/_citations.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/_execution.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/_http.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/_http_doc.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/_image_utils.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/_postproc.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/_ptc.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/_references.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/_run_order.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/_table_styles.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/_timeouts.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/_tracked.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/api.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/blkcntnr.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/bookmarks.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/charts.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/client.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/commands.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/comments.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/document.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/drawing/__init__.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/enum/__init__.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/enum/base.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/enum/dml.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/enum/section.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/enum/shape.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/enum/style.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/enum/table.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/enum/text.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/errors.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/exceptions.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/fields.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/footnotes.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/image/__init__.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/image/exceptions.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/image/image.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/math.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/opc/__init__.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/opc/coreprops.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/oxml/__init__.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/revisions.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/sdt.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/section.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/session.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/settings.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/shape.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/shared.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/styles/__init__.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/styles/_table.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/styles/latent.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/styles/style.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/styles/styles.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/table.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/text/__init__.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/text/font.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/text/parfmt.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/text/tabstops.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/toc.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/docx/typing.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/scripts/docx_exec_lab.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/scripts/docx_exec_lab_examples/fast_table_fill.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/scripts/docx_exec_lab_examples/find_replace_literal.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/scripts/docx_exec_lab_server.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/scripts/dump_wire_fixtures.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/scripts/release.sh +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/scripts/round_trip_smoke.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/scripts/smoke_test_block_not_found.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/scripts/validate_find_replace_asset.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/__init__.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/conftest.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/METHODOLOGY.md +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/README.md +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/__init__.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/ab_probe_cases.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/ab_probe_runner.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/auto_gen_cases.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/binary_round_trip.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/cases.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/complex_cases.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/coverage_report.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/extract.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/extreme_cases.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/fake_session.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/firm_templates/README.md +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/firm_templates/__init__.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/firm_templates/_runner.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/firm_templates/extractor.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/firm_templates/test_pw_corpus.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/firm_templates/test_pw_research_digest.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/local_runner.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/mega_cases.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshot.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/01_basic_paragraph.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/02_multiple_headings.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/03_runs_with_formatting.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/04_font_name_and_size.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/05_font_color_rgb.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/06_font_character_properties.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/07_font_subscript_superscript.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/08_font_highlight.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/09_paragraph_alignment.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/100_table_negative_indexing.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/101_table_cells_flat_iteration.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/102_text_with_embedded_special_chars.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/104_core_properties_datetime.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/105_default_one_section.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/106_heading_paragraph_format.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/107_varying_row_heights.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/10_paragraph_indents.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/11_paragraph_spacing.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/12_paragraph_keep_options.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/13_paragraph_tab_stops.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/14_run_add_tab_and_break.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/15_run_add_break_page.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/16_paragraph_clear_and_insert_before.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/17_table_basic.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/18_table_cell_text.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/19_table_row_column_sizing.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/20_table_cell_vertical_alignment.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/21_table_alignment_and_autofit.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/22_table_cell_paragraphs_iteration.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/24_table_add_row_column.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/25_table_merge_cells.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/26_section_page_setup.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/27_section_margins.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/28_section_add_new.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/29_section_headers_linked.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/30_styles_iteration.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/31_styles_lookup_and_default.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/32_styles_add_paragraph_style.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/33_core_properties_set_and_get.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/34_inline_shapes_iterate_empty.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/35_full_report.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/36_replace_text_in_paragraph.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/37_iterate_runs_and_format_all_bold.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/38_font_all_properties.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/39_large_body_100_paragraphs.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/40_large_table_10x10.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/41_unicode_and_emoji.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/42_very_long_paragraph.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/43_paragraph_text_round_trip.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/44_paragraph_alignment_round_trip.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/45_cell_text_round_trip.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/46_run_text_setter_round_trip.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/47_font_size_round_trip.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/48_font_color_round_trip.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/49_resume_layout.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/50_multi_section_doc.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/52_iterate_everything.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/53_apply_style_to_paragraphs.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/54_empty_everything.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/55_single_character_runs.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/56_everything_in_one.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/57_runs_after_multiple_text_appends.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/58_modify_runs_in_place.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/59_indent_round_trip.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/60_space_round_trip.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/61_cell_paragraph_with_runs.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/62_many_cell_paragraphs.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/63_table_style_round_trip.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/64_many_sections.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/65_20x20_table_formatted.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/66_toc_like_structure.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/67_paragraph_insert_before_chain.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/68_invoice.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/69_newsletter.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/70_add_and_iterate_back.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/71_academic_paper.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/72_legal_contract.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/73_form_with_many_tables.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/74_paragraph_with_10_runs.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/75_paragraph_negative_first_line_indent.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/76_rgbcolor_from_string.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/77_length_unit_conversions.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/78_paragraph_copy_style.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/79_bulk_cell_formatting.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/80_apply_style_after_add_run.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/81_multi_page_with_breaks.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/82_add_text_on_existing_run.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/83_clear_then_repopulate_paragraph.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/84_table_reread_row_count.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/85_header_footer_access.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/86_font_read_unset_returns_none.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/87_500_paragraph_doc.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/88_mixed_content_iteration.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/89_alignment_clear_via_none.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/90_cell_add_paragraph_styled.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/91_many_small_tables.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/92_margins_every_section.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/93_font_bool_reads_after_set.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/94_page_break_before_paragraph.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/95_paragraph_hyperlinks_empty.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/96_paragraph_contains_page_break.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/97_document_styles_by_key.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/98_style_contains_check.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/99_run_add_picture_from_bytes.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex02_unicode_everywhere.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex03_1000_paragraphs.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex04_50x50_table.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex05_long_text_in_cell.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex06_hundred_tiny_runs.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex07_every_font_boolean.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex08_many_continuous_sections.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex09_many_tab_stops.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex10_complex_bom.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex11_banded_rows_formatting.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex12_section_reconfigure.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex13_cell_with_10_paragraphs.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex14_styled_report_table.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex15_paragraph_all_format_props.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex16_runs_interleaved_with_breaks.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex17_all_break_kinds.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex18_read_back_large_doc.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex19_mutate_all_runs.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex20_kitchen_sink_v2.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/mega01_book_chapter.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/mega02_research_proposal.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/mega03_financial_statement.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/mega04_recipe_card.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/mega05_user_manual.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/mega06_complex_newsletter.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/mega07_budget_spreadsheet.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/mega08_product_catalog.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/mega09_signed_contract.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/mega10_api_documentation.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw01_official_quickstart.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw02_paragraph_style_list.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw03_character_formatting.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw04_section_page_setup.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw05_toc_pattern.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw06_meeting_minutes.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw07_dense_formatting_demo.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw08_table_merged_header.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw09_bulk_run_iteration.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw10_colored_grid_table.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw11_header_text.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw12_first_page_footer.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw13_even_page_header.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw15_paragraph_style_instance.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw16_header_footer_tables.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw17_header_letterhead_filled.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw18_header_table_properties.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw19_header_table_rows_columns.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw20_header_table_merges.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/ours_spec.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/parity_crawl.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/parity_diff.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/real_world_cases.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/round_trip_tests.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/stock_spec.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fidelity/test_e2e_against_staging.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fixtures/note_reference_reads.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fixtures/ruby_reads.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/fixtures/symbol_reads.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/live/__init__.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/live/fixture_scripts.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/live/reader.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/live/runner.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/live/sdk_driver.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/live/stock_driver.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/live/test_live_runner.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/parity/README.md +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/parity/__init__.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/parity/baseline_gaps.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/parity/compare.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/parity/intentional_deviations.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/parity/introspect.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/parity/reports/GAP_ANALYSIS.md +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/parity/reports/gap_report.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/parity/run_parity.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/parity/snapshots/athena_latest.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/parity/snapshots/upstream_python_docx_1.2.0.json +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/parity/test_parity_gap.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_add_section.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_add_section_extract_items.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_athena_extension_creates_session_open.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_athena_extensions_contract.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_athena_extensions_registry.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_batch_chunking.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_batching_perf.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_block_not_found_error.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_buffer.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_cell_add_paragraph_wire_shape.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_cell_add_table_not_supported.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_cell_borders_spec.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_cell_fastpath_runs.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_cell_inner_add_hyperlink_stash.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_cell_inner_add_run_via_cell_insert.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_cell_inner_format_stash.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_cell_inner_run_format_stash.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_cell_inner_run_guard.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_cell_merge.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_cell_nested_tables.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_cell_paragraphs_listed.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_cell_text_plain_fastpath.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_cell_text_replace_semantics.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_citations.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_collapsed_range_format.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_color_format_theme.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_command_dataclasses.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_commands.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_comment_paragraphs.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_comments.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_comments_first_read.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_content_control_value.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_core_properties.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_document_asset_id_property.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_document_clear.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_document_create.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_document_create_from_template.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_document_factory_validation.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_docx_exec_lab.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_docx_exec_lab_server.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_drawing_image.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_e2e_partial_failure_cascade.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_empty_hyperlinks.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_enum_parity.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_execution_scope.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_export_docx_clean.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_export_rescue_anchors.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_field_reads_python_docx_parity.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_field_refresh.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_field_runs.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_find_replace_session_open.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_flushed_write_failures.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_http_transport.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_hyperlink_coalescing.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_image_url_data_uri.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_inline_page_break.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_inline_shape_alt_text.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_inline_shape_size.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_inline_shape_type.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_inline_shapes_floating.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_insert_deferred.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_iter_inner_content.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_list_styles.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_merged_cell_secondary_slot.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_merged_cells.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_missing_modules.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_nested_table_refused.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_note_reference_reads_python_docx_parity.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_oxml_shim.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_page_break.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_paragraph_delete.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_paragraph_runs_hyperlinks.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_paragraph_text_len_cache.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_parity_misc.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_parity_round2.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_partial_failure_cascade.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_pdf_export_and_page_renders.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_phase_a_behavior.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_phase_b_headers_footers.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_phase_c_tables.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_positional_cell_id.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_postproc_cell_format_rewrite.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_postproc_cell_run_format_rewrite.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_postproc_ref_restore.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_pr19766_review_fixes.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_ptc.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_python_docx_api_parity.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_read_run_ranges.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_repeated_node_read.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_restart_numbering.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_revisions.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_round_trip_smoke_script.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_ruby_reads_python_docx_parity.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_run_add_picture_anchor.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_run_break_inner_content.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_run_edges.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_run_formatting_wire.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_run_identity.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_run_later_runs.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_run_mark_inheritance.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_run_table_style_objects.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_run_text_python_docx.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_run_text_refreshes_paragraph.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_sdk_reads_served.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_section_read_lengths.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_add_paragraph_style.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_add_picture.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_add_run.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_cell_add_paragraph.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_comments_add_comment.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_comments_get.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_document_audit.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_document_element.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_enum_section.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_font_audit.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_header_footer.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_hyperlink.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_inline_shape.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_insert_paragraph_before.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_misc.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_paragraph_strict.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_paragraph_style.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_paragraph_style_strict.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_parfmt.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_row_col_cell.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_run_add_break.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_run_bool_setters.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_run_style.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_run_style_strict.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_run_text.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_run_underline.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_section_audit.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_section_dimensions.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_section_onoff.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_settings.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_shared_audit.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_style.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_styles.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_table_audit.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_table_cell.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_table_dimensions.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_table_layout.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_smoke_integration.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_style_acceptance.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_style_font.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_style_formatting_writes.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_style_metadata_writes.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_style_names.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_style_setters_contract.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_style_tab_stops_read.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_symbol_reads_python_docx_parity.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_table_anchors.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_table_direction.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_table_read_reuse.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_table_set_cell_perf.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_table_style_id_resolution.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_temporarily_unavailable.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_text_control_characters.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_tracked_revisions_offsets.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_uv_lock_version.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_validate_find_replace_asset_script.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_wire_contract.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_xml_attr_guard.py +0 -0
- {athena_python_docx-0.32.0 → athena_python_docx-0.33.0}/tests/test_zod_wire_contract.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: athena-python-docx
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.33.0
|
|
4
4
|
Summary: Drop-in replacement for python-docx that connects to Athena's DOCX Studio collaborative document stack
|
|
5
5
|
Project-URL: Homepage, https://athenaintelligence.ai
|
|
6
6
|
Author-email: Athena Intelligence <engineering@athenaintelligence.ai>
|
|
@@ -171,13 +171,16 @@ class Hyperlink:
|
|
|
171
171
|
|
|
172
172
|
@property
|
|
173
173
|
def contains_page_break(self) -> bool:
|
|
174
|
-
"""True when
|
|
174
|
+
"""True when a rendered page break (a page Word's last layout began)
|
|
175
|
+
occurs in one of the hyperlink's runs, as python-docx 1.x reads it.
|
|
175
176
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
``Run.contains_page_break`` / ``Paragraph.contains_page_break``).
|
|
177
|
+
docx-studio reads them in the runs (``renderedPageBreaks``); the
|
|
178
|
+
``\\f`` sentinel is an older docx-studio's mark.
|
|
179
179
|
"""
|
|
180
180
|
for run_data, _ in self._segments:
|
|
181
|
+
breaks = run_data.get("renderedPageBreaks")
|
|
182
|
+
if isinstance(breaks, list) and any(isinstance(brk, dict) for brk in breaks):
|
|
183
|
+
return True
|
|
181
184
|
text = run_data.get("text", "")
|
|
182
185
|
if isinstance(text, str) and "\f" in text:
|
|
183
186
|
return True
|
|
@@ -53,15 +53,45 @@ def _warn_pagebreak_fragment(prop: str) -> None:
|
|
|
53
53
|
)
|
|
54
54
|
|
|
55
55
|
|
|
56
|
+
class _ParagraphFragment:
|
|
57
|
+
"""The part of a paragraph before or after one of its rendered page breaks.
|
|
58
|
+
|
|
59
|
+
python-docx returns a ``Paragraph`` divorced from the document body: a
|
|
60
|
+
copy of the paragraph cut at the break, whose changes the document never
|
|
61
|
+
sees. This one reads what text extraction asks of it, its ``text`` and
|
|
62
|
+
``style``, and changes nothing.
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
__slots__ = ("_paragraph", "_text")
|
|
66
|
+
|
|
67
|
+
def __init__(self, *, paragraph: "Paragraph", text: str) -> None:
|
|
68
|
+
self._paragraph = paragraph
|
|
69
|
+
self._text = text
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def text(self) -> str:
|
|
73
|
+
"""The fragment's text, as ``Paragraph.text`` reads it."""
|
|
74
|
+
return self._text
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def style(self):
|
|
78
|
+
"""The paragraph's style: the fragment keeps the paragraph's properties."""
|
|
79
|
+
return self._paragraph.style
|
|
80
|
+
|
|
81
|
+
def __repr__(self) -> str:
|
|
82
|
+
return f"<_ParagraphFragment text={self._text!r}>"
|
|
83
|
+
|
|
84
|
+
|
|
56
85
|
class RenderedPageBreak:
|
|
57
|
-
"""A
|
|
86
|
+
"""A page break Word's last layout put in a paragraph (``w:lastRenderedPageBreak``).
|
|
58
87
|
|
|
59
|
-
Constructed by :meth:`Paragraph.rendered_page_breaks` and yielded
|
|
60
|
-
|
|
61
|
-
|
|
88
|
+
Constructed by :meth:`Paragraph.rendered_page_breaks` and yielded by
|
|
89
|
+
:meth:`Run.iter_inner_content`; not intended for direct user
|
|
90
|
+
instantiation. ``info`` is the break as docx-studio reads it in its run
|
|
91
|
+
(``renderedPageBreaks``): its fragments' text, or no fragment.
|
|
62
92
|
"""
|
|
63
93
|
|
|
64
|
-
__slots__ = ("_paragraph", "_offset", "_preceding_text")
|
|
94
|
+
__slots__ = ("_paragraph", "_offset", "_preceding_text", "_info")
|
|
65
95
|
|
|
66
96
|
def __init__(
|
|
67
97
|
self,
|
|
@@ -69,30 +99,47 @@ class RenderedPageBreak:
|
|
|
69
99
|
paragraph: "Paragraph",
|
|
70
100
|
offset: int = 0,
|
|
71
101
|
preceding_text: str = "",
|
|
102
|
+
info: "dict | None" = None,
|
|
72
103
|
) -> None:
|
|
73
104
|
self._paragraph: "Paragraph" = paragraph
|
|
74
105
|
self._offset: int = offset
|
|
75
106
|
self._preceding_text: str = preceding_text
|
|
107
|
+
self._info: "dict | None" = info
|
|
108
|
+
|
|
109
|
+
def _fragment(self, side: str) -> "_ParagraphFragment | None":
|
|
110
|
+
"""python-docx's fragment on `side` (``preceding``/``following``) of this break."""
|
|
111
|
+
info = self._info
|
|
112
|
+
if info is None:
|
|
113
|
+
_warn_pagebreak_fragment(f"{side}_paragraph_fragment")
|
|
114
|
+
return None
|
|
115
|
+
if side not in info:
|
|
116
|
+
raise ValueError("only defined on first rendered page-break in paragraph")
|
|
117
|
+
text = info[side]
|
|
118
|
+
return (
|
|
119
|
+
None if text is None else _ParagraphFragment(paragraph=self._paragraph, text=str(text))
|
|
120
|
+
)
|
|
76
121
|
|
|
77
122
|
# ---- python-docx canonical surface ----
|
|
78
123
|
@property
|
|
79
|
-
def preceding_paragraph_fragment(self) -> "
|
|
80
|
-
"""The
|
|
81
|
-
*before* the break.
|
|
124
|
+
def preceding_paragraph_fragment(self) -> "_ParagraphFragment | None":
|
|
125
|
+
"""The part of the paragraph before this break, as a paragraph.
|
|
82
126
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
127
|
+
None when no content precedes it (the break precedes all of the
|
|
128
|
+
paragraph's content). A break in a hyperlink puts the whole hyperlink
|
|
129
|
+
in this fragment. Raises ``ValueError`` for a break that is not the
|
|
130
|
+
paragraph's first, as python-docx does.
|
|
86
131
|
"""
|
|
87
|
-
|
|
88
|
-
return None
|
|
132
|
+
return self._fragment("preceding")
|
|
89
133
|
|
|
90
134
|
@property
|
|
91
|
-
def following_paragraph_fragment(self) -> "
|
|
92
|
-
"""The
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
135
|
+
def following_paragraph_fragment(self) -> "_ParagraphFragment | None":
|
|
136
|
+
"""The part of the paragraph after this break, as a paragraph.
|
|
137
|
+
|
|
138
|
+
None when no content follows it. A break in a hyperlink leaves the
|
|
139
|
+
whole hyperlink out of this fragment. Raises ``ValueError`` for a
|
|
140
|
+
break that is not the paragraph's first, as python-docx does.
|
|
141
|
+
"""
|
|
142
|
+
return self._fragment("following")
|
|
96
143
|
|
|
97
144
|
# ---- athena-specific extensions (kept for compat) ----
|
|
98
145
|
@property
|
|
@@ -242,6 +242,30 @@ def _node_text(session: "Session", node_id: str, *, final: bool = False) -> str:
|
|
|
242
242
|
return _extract_text(info, final=final)
|
|
243
243
|
|
|
244
244
|
|
|
245
|
+
def _rendered_page_break_reads(info: object) -> "list[tuple[dict, int]]":
|
|
246
|
+
"""Each rendered page break docx-studio reads in the runs of the paragraph
|
|
247
|
+
whose node info is `info` (``renderedPageBreaks``), its links' included, in
|
|
248
|
+
order, with its offset in the paragraph's text-address space."""
|
|
249
|
+
if not isinstance(info, dict):
|
|
250
|
+
return []
|
|
251
|
+
node: object = info.get("node")
|
|
252
|
+
block: object = (node.get("paragraph") or node.get("heading")) if isinstance(node, dict) else None
|
|
253
|
+
inlines: object = block.get("inlines") if isinstance(block, dict) else None
|
|
254
|
+
reads: list[tuple[dict, int]] = []
|
|
255
|
+
offset = 0
|
|
256
|
+
for inline in inlines if isinstance(inlines, list) else []:
|
|
257
|
+
run: object = inline.get("run") if isinstance(inline, dict) else None
|
|
258
|
+
if not isinstance(run, dict):
|
|
259
|
+
continue
|
|
260
|
+
breaks: object = run.get("renderedPageBreaks")
|
|
261
|
+
for brk in breaks if isinstance(breaks, list) else []:
|
|
262
|
+
if isinstance(brk, dict):
|
|
263
|
+
reads.append((brk, offset + int(brk.get("offset", 0) or 0)))
|
|
264
|
+
text: object = run.get("text")
|
|
265
|
+
offset += len(text) if isinstance(text, str) else 0
|
|
266
|
+
return reads
|
|
267
|
+
|
|
268
|
+
|
|
245
269
|
def _extract_text(info: object, *, final: bool = False) -> str:
|
|
246
270
|
"""Concatenate the text content of a paragraph, mirroring
|
|
247
271
|
python-docx ``Paragraph.text`` semantics:
|
|
@@ -1129,22 +1153,28 @@ class Paragraph:
|
|
|
1129
1153
|
|
|
1130
1154
|
@property
|
|
1131
1155
|
def contains_page_break(self) -> bool:
|
|
1132
|
-
"""python-docx 1.x: True
|
|
1133
|
-
|
|
1156
|
+
"""python-docx 1.x: True when a rendered page break (a page Word's last
|
|
1157
|
+
layout began) occurs in one of the paragraph's runs or its links' runs."""
|
|
1158
|
+
info = self._node_info()
|
|
1159
|
+
return bool(_rendered_page_break_reads(info)) or "\f" in _extract_text(info, final=True)
|
|
1134
1160
|
|
|
1135
1161
|
@property
|
|
1136
1162
|
def rendered_page_breaks(self) -> "list[RenderedPageBreak]":
|
|
1137
|
-
"""
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1163
|
+
"""python-docx 1.x: a :class:`RenderedPageBreak` for each page Word's
|
|
1164
|
+
last layout began in the paragraph's runs and its links' runs
|
|
1165
|
+
(``w:lastRenderedPageBreak``), in document order.
|
|
1166
|
+
|
|
1167
|
+
Each reads python-docx's fragments: the part of the paragraph before
|
|
1168
|
+
and after the break (``preceding_paragraph_fragment``,
|
|
1169
|
+
``following_paragraph_fragment``), defined on the first break only.
|
|
1170
|
+
A paragraph from an older docx-studio marks its breaks with the
|
|
1171
|
+
``\\f`` sentinel in its text instead.
|
|
1146
1172
|
"""
|
|
1147
|
-
|
|
1173
|
+
node_info = self._node_info()
|
|
1174
|
+
reads = _rendered_page_break_reads(node_info)
|
|
1175
|
+
if reads:
|
|
1176
|
+
return [RenderedPageBreak(paragraph=self, offset=offset, info=info) for info, offset in reads]
|
|
1177
|
+
text = _extract_text(node_info)
|
|
1148
1178
|
if "\f" not in text:
|
|
1149
1179
|
return []
|
|
1150
1180
|
out: list[RenderedPageBreak] = []
|
|
@@ -48,11 +48,26 @@ _RUN_MARK_TOGGLES: tuple[str, ...] = (
|
|
|
48
48
|
"outline",
|
|
49
49
|
"rtl",
|
|
50
50
|
)
|
|
51
|
+
# The on/off properties a read reports that no mark holds: ``w:bCs``, ``w:iCs``,
|
|
52
|
+
# ``w:cs``, ``w:noProof``, ``w:snapToGrid``, ``w:webHidden``, ``w:specVanish``
|
|
53
|
+
# and ``w:oMath`` (``math``), which docx-studio keeps among the run's own
|
|
54
|
+
# properties. An older docx-studio reports none of them.
|
|
55
|
+
_RUN_UNMODELED_TOGGLES: tuple[str, ...] = (
|
|
56
|
+
"bCs",
|
|
57
|
+
"iCs",
|
|
58
|
+
"cs",
|
|
59
|
+
"noProof",
|
|
60
|
+
"snapToGrid",
|
|
61
|
+
"webHidden",
|
|
62
|
+
"specVanish",
|
|
63
|
+
"math",
|
|
64
|
+
)
|
|
51
65
|
# Every formatting key of such a read: the toggles, and the value keys
|
|
52
66
|
# (``fontSize`` in points, ``vertAlign``, the character style id ``rStyle``).
|
|
53
67
|
_RUN_MARK_KEYS: frozenset[str] = frozenset(
|
|
54
68
|
(
|
|
55
69
|
*_RUN_MARK_TOGGLES,
|
|
70
|
+
*_RUN_UNMODELED_TOGGLES,
|
|
56
71
|
"color",
|
|
57
72
|
"themeColor",
|
|
58
73
|
"highlight",
|
|
@@ -735,6 +750,37 @@ class Run:
|
|
|
735
750
|
return
|
|
736
751
|
text = _without_ruby(self._raw_text(), self._inline_snapshot)
|
|
737
752
|
font = self._symbol_font() if _SYMBOL_CHARACTERS.search(text) else None
|
|
753
|
+
rendered = self._rendered_page_breaks()
|
|
754
|
+
if rendered and "\f" not in text:
|
|
755
|
+
# Word's rendered page breaks stand between the run's text, each where
|
|
756
|
+
# docx-studio reads it: python-docx yields the text before it, the
|
|
757
|
+
# break, then the text after. A page or column break holding no text
|
|
758
|
+
# reads as "" before them, as the page it begins starts after it.
|
|
759
|
+
from docx.text.paragraph import Paragraph
|
|
760
|
+
|
|
761
|
+
if not text and self._inline_snapshot.get("break") in ("page", "column"):
|
|
762
|
+
yield ""
|
|
763
|
+
paragraph = getattr(self, "_paragraph", None) or Paragraph(session=self._session, node_id=self._block_id)
|
|
764
|
+
# The offsets count the run's text with its ruby base text, which
|
|
765
|
+
# each piece leaves out after it is cut.
|
|
766
|
+
raw = self._raw_text()
|
|
767
|
+
spans = self._inline_snapshot.get("ruby")
|
|
768
|
+
ruby = [s for s in spans if isinstance(s, list) and len(s) == 2] if isinstance(spans, list) else []
|
|
769
|
+
|
|
770
|
+
def piece(start: int, end: int) -> str:
|
|
771
|
+
inside = [[a - start, b - start] for a, b in ruby if isinstance(a, int) and isinstance(b, int) and a >= start and b <= end]
|
|
772
|
+
return _word_text(_without_ruby(raw[start:end], {"ruby": inside}), font)
|
|
773
|
+
|
|
774
|
+
cut = 0
|
|
775
|
+
for info in rendered:
|
|
776
|
+
at = min(max(int(info.get("offset", 0) or 0), cut), len(raw))
|
|
777
|
+
if piece(cut, at):
|
|
778
|
+
yield piece(cut, at)
|
|
779
|
+
yield RenderedPageBreak(paragraph=paragraph, offset=self._range[0] + at, info=info)
|
|
780
|
+
cut = at
|
|
781
|
+
if piece(cut, len(raw)):
|
|
782
|
+
yield piece(cut, len(raw))
|
|
783
|
+
return
|
|
738
784
|
# Fast path — no page breaks, yield the whole run as one string.
|
|
739
785
|
if "\f" not in text:
|
|
740
786
|
if _word_text(text, font):
|
|
@@ -785,6 +831,8 @@ class Run:
|
|
|
785
831
|
f"{value!r}",
|
|
786
832
|
)
|
|
787
833
|
if self._field_part() is not None:
|
|
834
|
+
# python-docx replaces all of the run's content, its rendered page breaks too.
|
|
835
|
+
self._inline_snapshot.pop("renderedPageBreaks", None)
|
|
788
836
|
self._set_field_text(value)
|
|
789
837
|
return
|
|
790
838
|
if self._check_cell_inner("text"):
|
|
@@ -792,6 +840,7 @@ class Run:
|
|
|
792
840
|
# (when present) still reflects reality — keep it.
|
|
793
841
|
return
|
|
794
842
|
self._fastpath_text = None # type: ignore[attr-defined]
|
|
843
|
+
self._inline_snapshot.pop("renderedPageBreaks", None)
|
|
795
844
|
drawing = self._inline_snapshot.get("drawing")
|
|
796
845
|
picture = drawing.get("imageId") if isinstance(drawing, dict) else None
|
|
797
846
|
if isinstance(picture, str) and picture:
|
|
@@ -961,14 +1010,19 @@ class Run:
|
|
|
961
1010
|
|
|
962
1011
|
@property
|
|
963
1012
|
def contains_page_break(self) -> bool:
|
|
964
|
-
"""python-docx 1.x: True
|
|
1013
|
+
"""python-docx 1.x: True when a rendered page break (a page Word's last
|
|
1014
|
+
layout began, ``w:lastRenderedPageBreak``) occurs in this run.
|
|
965
1015
|
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
w:type="page"/>`.
|
|
1016
|
+
An author's hard page break (``w:br w:type="page"``) is not one, as in
|
|
1017
|
+
python-docx. docx-studio reads them in the run (``renderedPageBreaks``);
|
|
1018
|
+
the ``\\f`` sentinel is an older docx-studio's mark.
|
|
970
1019
|
"""
|
|
971
|
-
return "\f" in self.text
|
|
1020
|
+
return bool(self._rendered_page_breaks()) or "\f" in self.text
|
|
1021
|
+
|
|
1022
|
+
def _rendered_page_breaks(self) -> "list[dict]":
|
|
1023
|
+
"""The rendered page breaks docx-studio reads in this run, in order (``renderedPageBreaks``)."""
|
|
1024
|
+
breaks = self._inline_snapshot.get("renderedPageBreaks")
|
|
1025
|
+
return [info for info in breaks if isinstance(info, dict)] if isinstance(breaks, list) else []
|
|
972
1026
|
|
|
973
1027
|
def _continues_own_formatting(self) -> bool:
|
|
974
1028
|
"""True when content appended to this run takes its formatting from
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "athena-python-docx"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.33.0"
|
|
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"
|
|
@@ -270,19 +270,8 @@
|
|
|
270
270
|
"rw20_header_table_merges"
|
|
271
271
|
],
|
|
272
272
|
"gaps": [
|
|
273
|
-
"38_font_all_properties::export::runs.font.snap_to_grid",
|
|
274
|
-
"38_font_all_properties::reads::runs.font.snap_to_grid",
|
|
275
273
|
"abp46_comment_rich_text::export::comments.ids",
|
|
276
274
|
"abp46_comment_rich_text::reads::comments.ids",
|
|
277
|
-
"ex07_every_font_boolean::export::runs.font.complex_script",
|
|
278
|
-
"ex07_every_font_boolean::export::runs.font.cs_bold",
|
|
279
|
-
"ex07_every_font_boolean::export::runs.font.cs_italic",
|
|
280
|
-
"ex07_every_font_boolean::export::runs.font.snap_to_grid",
|
|
281
|
-
"ex07_every_font_boolean::reads::runs.font.complex_script",
|
|
282
|
-
"ex07_every_font_boolean::reads::runs.font.cs_bold",
|
|
283
|
-
"ex07_every_font_boolean::reads::runs.font.cs_italic",
|
|
284
|
-
"ex07_every_font_boolean::reads::runs.font.snap_to_grid",
|
|
285
|
-
"fixture-bidi-rtl::reads::runs.font.cs_bold",
|
|
286
275
|
"fixture-bidi-wrappers::reads::hyperlinks",
|
|
287
276
|
"fixture-bidi-wrappers::reads::hyperlinks.runs",
|
|
288
277
|
"fixture-bidi-wrappers::reads::paragraphs.inner_content",
|
|
@@ -327,12 +316,7 @@
|
|
|
327
316
|
"fixture-comments-links::reads::comments.ids",
|
|
328
317
|
"fixture-comments-point::reads::comments.ids",
|
|
329
318
|
"fixture-comments-replies::reads::comments.ids",
|
|
330
|
-
"fixture-fields-ref-seq-toc::reads::runs.font.no_proof",
|
|
331
|
-
"fixture-fields-toc-entries::reads::hyperlinks.runs",
|
|
332
|
-
"fixture-form-fields::reads::runs.font.no_proof",
|
|
333
319
|
"fixture-hyperlinks-empty-comment-drawing::reads::comments.ids",
|
|
334
|
-
"fixture-index-captions::reads::hyperlinks.runs",
|
|
335
|
-
"fixture-index-captions::reads::runs.font.no_proof",
|
|
336
320
|
"fixture-inline-tags::reads::hyperlinks",
|
|
337
321
|
"fixture-inline-tags::reads::hyperlinks.runs",
|
|
338
322
|
"fixture-inline-tags::reads::paragraphs.inner_content",
|
|
@@ -373,17 +357,7 @@
|
|
|
373
357
|
"fixture-inline-tags::reads::sections.inner_content",
|
|
374
358
|
"fixture-inline-tags::reads::tables.cell_format",
|
|
375
359
|
"fixture-inline-tags::reads::tables.cell_paragraph_content",
|
|
376
|
-
"fixture-inline-tags::reads::tables.cells"
|
|
377
|
-
"fixture-notes-fields-bookmarks::reads::runs.font.no_proof",
|
|
378
|
-
"fixture-permissions-proofing::reads::paragraphs.contains_page_break",
|
|
379
|
-
"fixture-permissions-proofing::reads::paragraphs.rendered_page_breaks",
|
|
380
|
-
"fixture-permissions-proofing::reads::runs.contains_page_break",
|
|
381
|
-
"fixture-permissions-proofing::reads::runs.inner_content",
|
|
382
|
-
"fixture-run-properties-unmodeled::reads::runs.font.snap_to_grid",
|
|
383
|
-
"fixture-smartart-diagram::reads::runs.font.no_proof",
|
|
384
|
-
"fixture-smartart-diagram::reads::runs.inner_content",
|
|
385
|
-
"fixture-text-effects-w14::reads::runs.font.no_proof",
|
|
386
|
-
"fixture-textbox-page-break::reads::runs.font.no_proof"
|
|
360
|
+
"fixture-inline-tags::reads::tables.cells"
|
|
387
361
|
],
|
|
388
362
|
"reasons": [
|
|
389
363
|
{
|
|
@@ -393,43 +367,11 @@
|
|
|
393
367
|
],
|
|
394
368
|
"reason": "Owner question 47 (open): runs inside an inline wrapper (w:dir, w:bdo, w:smartTag, w:customXml) read as the paragraph's runs, where python-docx reads only a w:p's direct w:r and w:hyperlink children, so the runs, their fonts and inner content, the links' runs, the paragraph's text and inner content, and the cells holding them read with the wrapped runs."
|
|
395
369
|
},
|
|
396
|
-
{
|
|
397
|
-
"match": [
|
|
398
|
-
"*::*::runs.font.no_proof",
|
|
399
|
-
"*::*::runs.font.snap_to_grid",
|
|
400
|
-
"*::*::runs.font.cs_bold",
|
|
401
|
-
"*::*::runs.font.cs_italic",
|
|
402
|
-
"*::*::runs.font.complex_script"
|
|
403
|
-
],
|
|
404
|
-
"reason": "R4 (to fix): a run's w:noProof, w:snapToGrid, w:bCs, w:iCs and w:cs are carried by no model mark, so Font.no_proof, snap_to_grid, cs_bold, cs_italic and complex_script read None, and setting snap_to_grid, cs_bold, cs_italic or complex_script does not reach the export."
|
|
405
|
-
},
|
|
406
|
-
{
|
|
407
|
-
"match": [
|
|
408
|
-
"fixture-permissions-proofing::reads::paragraphs.contains_page_break",
|
|
409
|
-
"fixture-permissions-proofing::reads::paragraphs.rendered_page_breaks",
|
|
410
|
-
"fixture-permissions-proofing::reads::runs.contains_page_break",
|
|
411
|
-
"fixture-permissions-proofing::reads::runs.inner_content"
|
|
412
|
-
],
|
|
413
|
-
"reason": "R5 (to fix): w:lastRenderedPageBreak is neither kept nor read, so contains_page_break, rendered_page_breaks and a run's inner content leave out the page break Word last laid out there."
|
|
414
|
-
},
|
|
415
370
|
{
|
|
416
371
|
"match": [
|
|
417
372
|
"*::*::comments.ids"
|
|
418
373
|
],
|
|
419
374
|
"reason": "R6 (to fix): Comment.comment_id returns a str where python-docx returns an int, and the first comment a script adds is numbered 1 where python-docx numbers it 0."
|
|
420
|
-
},
|
|
421
|
-
{
|
|
422
|
-
"match": [
|
|
423
|
-
"fixture-smartart-diagram::reads::runs.inner_content"
|
|
424
|
-
],
|
|
425
|
-
"reason": "R11 (to fix): a SmartArt drawing is left out of its run's inner content: the import moves the diagram into text boxes after the paragraph, and the run's record keeps no trace of the drawing for the read to yield a Drawing (has_picture False) from."
|
|
426
|
-
},
|
|
427
|
-
{
|
|
428
|
-
"match": [
|
|
429
|
-
"fixture-fields-toc-entries::reads::hyperlinks.runs",
|
|
430
|
-
"fixture-index-captions::reads::hyperlinks.runs"
|
|
431
|
-
],
|
|
432
|
-
"reason": "R13 (to fix): a link's runs read no w:webHidden (the tab and page number runs Word writes in a table of contents or a table of figures entry), where python-docx reads web_hidden True; index-captions' entry runs also read no w:noProof (R4)."
|
|
433
375
|
}
|
|
434
376
|
]
|
|
435
377
|
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"""Rendered page breaks (``w:lastRenderedPageBreak``) as python-docx 1.2.0 reads them.
|
|
2
|
+
|
|
3
|
+
docx-studio reads each one in its run (``renderedPageBreaks``): its place in
|
|
4
|
+
the run's text, and the text of python-docx's fragments around the
|
|
5
|
+
paragraph's first break (``preceding`` / ``following``, null for no fragment,
|
|
6
|
+
absent for a break python-docx raises for). ``Run.contains_page_break`` and
|
|
7
|
+
``Run.iter_inner_content`` read them in the run, and
|
|
8
|
+
``Paragraph.rendered_page_breaks`` in the paragraph's runs and its links' runs.
|
|
9
|
+
An author's hard page break is not one.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
import pytest
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@pytest.fixture
|
|
20
|
+
def paragraph_of(mock_session: Any, fake_sd_methods: Any) -> Any:
|
|
21
|
+
"""A paragraph whose read (``get_node_by_id``) holds `inlines`."""
|
|
22
|
+
from docx.text.paragraph import Paragraph
|
|
23
|
+
|
|
24
|
+
def make(inlines: list[dict[str, Any]]) -> Any:
|
|
25
|
+
text = "".join(inline.get("run", {}).get("text", "") for inline in inlines)
|
|
26
|
+
fake_sd_methods.scripted_returns["get_node_by_id"] = {
|
|
27
|
+
"node": {
|
|
28
|
+
"nodeId": "p-1",
|
|
29
|
+
"nodeType": "paragraph",
|
|
30
|
+
"text": text,
|
|
31
|
+
"paragraph": {"inlines": inlines, "runMarks": True},
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return Paragraph(session=mock_session, node_id="p-1", text_len=len(text))
|
|
35
|
+
|
|
36
|
+
return make
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _kinds(items: list[Any]) -> list[Any]:
|
|
40
|
+
return [item if isinstance(item, str) else type(item).__name__ for item in items]
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
FIRST = {"offset": 0, "preceding": "Before, ", "following": "after the break"}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def test_a_run_starting_on_a_new_page_yields_the_break_then_its_text(paragraph_of: Any) -> None:
|
|
47
|
+
paragraph = paragraph_of(
|
|
48
|
+
[
|
|
49
|
+
{"run": {"text": "Before, "}},
|
|
50
|
+
{"run": {"text": "after the break", "renderedPageBreaks": [FIRST]}},
|
|
51
|
+
],
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
runs = paragraph.runs
|
|
55
|
+
|
|
56
|
+
assert [run.contains_page_break for run in runs] == [False, True]
|
|
57
|
+
assert _kinds(list(runs[0].iter_inner_content())) == ["Before, "]
|
|
58
|
+
assert _kinds(list(runs[1].iter_inner_content())) == ["RenderedPageBreak", "after the break"]
|
|
59
|
+
assert runs[1].text == "after the break"
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def test_a_break_inside_a_run_yields_its_text_on_each_side(paragraph_of: Any) -> None:
|
|
63
|
+
paragraph = paragraph_of(
|
|
64
|
+
[
|
|
65
|
+
{
|
|
66
|
+
"run": {
|
|
67
|
+
"text": "abcdef",
|
|
68
|
+
"renderedPageBreaks": [{"offset": 3, "preceding": "abc", "following": "def"}],
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
],
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
assert _kinds(list(paragraph.runs[0].iter_inner_content())) == [
|
|
75
|
+
"abc",
|
|
76
|
+
"RenderedPageBreak",
|
|
77
|
+
"def",
|
|
78
|
+
]
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def test_the_paragraph_lists_its_breaks_and_their_fragments(paragraph_of: Any) -> None:
|
|
82
|
+
paragraph = paragraph_of(
|
|
83
|
+
[
|
|
84
|
+
{"run": {"text": "Before, "}},
|
|
85
|
+
{"run": {"text": "after the break", "renderedPageBreaks": [FIRST]}},
|
|
86
|
+
],
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
breaks = paragraph.rendered_page_breaks
|
|
90
|
+
|
|
91
|
+
assert paragraph.contains_page_break is True
|
|
92
|
+
assert len(breaks) == 1
|
|
93
|
+
assert breaks[0].preceding_paragraph_fragment.text == "Before, "
|
|
94
|
+
assert breaks[0].following_paragraph_fragment.text == "after the break"
|
|
95
|
+
# A run's break reads the same fragments.
|
|
96
|
+
from_run = list(paragraph.runs[1].iter_inner_content())[0]
|
|
97
|
+
assert from_run.preceding_paragraph_fragment.text == "Before, "
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def test_a_fragment_python_docx_has_none_of_is_none(paragraph_of: Any) -> None:
|
|
101
|
+
paragraph = paragraph_of(
|
|
102
|
+
[
|
|
103
|
+
{
|
|
104
|
+
"run": {
|
|
105
|
+
"text": "All on the new page",
|
|
106
|
+
"renderedPageBreaks": [
|
|
107
|
+
{"offset": 0, "preceding": None, "following": "All on the new page"}
|
|
108
|
+
],
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
],
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
[brk] = paragraph.rendered_page_breaks
|
|
115
|
+
|
|
116
|
+
assert brk.preceding_paragraph_fragment is None
|
|
117
|
+
assert brk.following_paragraph_fragment.text == "All on the new page"
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def test_a_later_break_raises_for_its_fragments_as_python_docx_does(paragraph_of: Any) -> None:
|
|
121
|
+
paragraph = paragraph_of(
|
|
122
|
+
[
|
|
123
|
+
{
|
|
124
|
+
"run": {
|
|
125
|
+
"text": "one ",
|
|
126
|
+
"renderedPageBreaks": [{"offset": 2, "preceding": "on", "following": "e two"}],
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
{"run": {"text": "two", "renderedPageBreaks": [{"offset": 1}]}},
|
|
130
|
+
],
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
first, second = paragraph.rendered_page_breaks
|
|
134
|
+
|
|
135
|
+
assert first.preceding_paragraph_fragment.text == "on"
|
|
136
|
+
with pytest.raises(ValueError, match="first rendered page-break"):
|
|
137
|
+
_ = second.preceding_paragraph_fragment
|
|
138
|
+
with pytest.raises(ValueError, match="first rendered page-break"):
|
|
139
|
+
_ = second.following_paragraph_fragment
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def test_a_link_run_s_break_is_the_link_s_and_the_paragraph_s(paragraph_of: Any) -> None:
|
|
143
|
+
link_break = {"offset": 2, "preceding": "See link", "following": " after"}
|
|
144
|
+
paragraph = paragraph_of(
|
|
145
|
+
[
|
|
146
|
+
{"run": {"text": "See "}},
|
|
147
|
+
{
|
|
148
|
+
"run": {
|
|
149
|
+
"text": "link",
|
|
150
|
+
"hyperlink": "https://example.com/",
|
|
151
|
+
"renderedPageBreaks": [link_break],
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
{"run": {"text": " after"}},
|
|
155
|
+
],
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
[link] = paragraph.hyperlinks
|
|
159
|
+
|
|
160
|
+
assert link.contains_page_break is True
|
|
161
|
+
assert [brk.following_paragraph_fragment.text for brk in paragraph.rendered_page_breaks] == [
|
|
162
|
+
" after"
|
|
163
|
+
]
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def test_a_paragraph_without_breaks_reads_none(paragraph_of: Any) -> None:
|
|
167
|
+
paragraph = paragraph_of([{"run": {"text": "Plain"}}, {"run": {"text": "", "break": "page"}}])
|
|
168
|
+
|
|
169
|
+
assert paragraph.contains_page_break is False
|
|
170
|
+
assert paragraph.rendered_page_breaks == []
|
|
171
|
+
assert [run.contains_page_break for run in paragraph.runs] == [False, False]
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def test_a_run_whose_text_is_replaced_holds_its_break_no_more(paragraph_of: Any) -> None:
|
|
175
|
+
"""python-docx's ``run.text = ...`` replaces all of the run's content, its
|
|
176
|
+
rendered page break too (``Run.clear()`` does the same through it)."""
|
|
177
|
+
paragraph = paragraph_of(
|
|
178
|
+
[{"run": {"text": "abcdef", "renderedPageBreaks": [{"offset": 3, "preceding": "abc", "following": "def"}]}}],
|
|
179
|
+
)
|
|
180
|
+
run = paragraph.runs[0]
|
|
181
|
+
|
|
182
|
+
run.text = "new"
|
|
183
|
+
|
|
184
|
+
assert run.contains_page_break is False
|
|
185
|
+
assert "RenderedPageBreak" not in _kinds(list(run.iter_inner_content()))
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def test_a_break_after_ruby_base_text_counts_it(paragraph_of: Any) -> None:
|
|
189
|
+
"""The break's offset counts the run's text with its ruby base text, which
|
|
190
|
+
python-docx's run text leaves out."""
|
|
191
|
+
paragraph = paragraph_of(
|
|
192
|
+
[{"run": {"text": "A\u6f22BC", "ruby": [[1, 2]], "renderedPageBreaks": [{"offset": 2, "preceding": "A", "following": "BC"}]}}],
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
assert _kinds(list(paragraph.runs[0].iter_inner_content())) == ["A", "RenderedPageBreak", "BC"]
|
|
196
|
+
|