athena-python-docx 0.31.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.31.0 → athena_python_docx-0.33.0}/AGENTS.md +6 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/PKG-INFO +1 -1
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/__init__.py +1 -1
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/_run_order.py +39 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/commands.py +20 -4
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/drawing/__init__.py +7 -2
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/settings.py +12 -2
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/table.py +33 -19
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/text/hyperlink.py +7 -4
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/text/pagebreak.py +65 -18
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/text/paragraph.py +50 -13
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/text/run.py +214 -20
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/pyproject.toml +1 -1
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/complex_cases.py +1 -1
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/fake_session.py +2 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/21_table_alignment_and_autofit.json +1 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fixtures/field_reads.json +1 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/live/baseline.json +5 -106
- athena_python_docx-0.33.0/tests/live/fixture_scripts.py +188 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_drawing_image.py +38 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_enum_parity.py +4 -2
- athena_python_docx-0.33.0/tests/test_rendered_page_breaks.py +196 -0
- athena_python_docx-0.33.0/tests/test_run_break_inner_content.py +121 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_run_edges.py +25 -0
- athena_python_docx-0.33.0/tests/test_run_later_runs.py +580 -0
- athena_python_docx-0.33.0/tests/test_run_unmodeled_toggles.py +86 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_settings.py +33 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_table_layout.py +8 -6
- athena_python_docx-0.33.0/tests/test_table_direction.py +102 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/uv.lock +1 -1
- athena_python_docx-0.31.0/tests/live/fixture_scripts.py +0 -68
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/.gitignore +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/CLAUDE.md +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/DOCX_EXEC_LAB.md +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/README.md +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/_athena_extension.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/_batching.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/_buffer.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/_capabilities.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/_citations.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/_execution.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/_http.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/_http_doc.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/_image_utils.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/_postproc.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/_ptc.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/_references.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/_table_styles.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/_timeouts.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/_tracked.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/api.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/blkcntnr.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/bookmarks.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/charts.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/client.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/comments.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/document.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/enum/__init__.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/enum/base.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/enum/dml.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/enum/section.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/enum/shape.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/enum/style.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/enum/table.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/enum/text.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/errors.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/exceptions.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/fields.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/footnotes.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/image/__init__.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/image/exceptions.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/image/image.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/math.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/opc/__init__.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/opc/coreprops.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/oxml/__init__.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/revisions.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/sdt.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/section.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/session.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/shape.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/shared.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/styles/__init__.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/styles/_table.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/styles/latent.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/styles/style.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/styles/styles.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/text/__init__.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/text/font.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/text/parfmt.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/text/tabstops.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/toc.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/docx/typing.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/scripts/docx_exec_lab.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/scripts/docx_exec_lab_examples/fast_table_fill.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/scripts/docx_exec_lab_examples/find_replace_literal.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/scripts/docx_exec_lab_server.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/scripts/dump_wire_fixtures.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/scripts/release.sh +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/scripts/round_trip_smoke.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/scripts/smoke_test_block_not_found.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/scripts/validate_find_replace_asset.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/__init__.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/conftest.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/METHODOLOGY.md +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/README.md +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/__init__.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/ab_probe_cases.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/ab_probe_runner.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/auto_gen_cases.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/binary_round_trip.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/cases.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/coverage_report.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/extract.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/extreme_cases.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/firm_templates/README.md +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/firm_templates/__init__.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/firm_templates/_runner.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/firm_templates/extractor.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/firm_templates/test_pw_corpus.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/firm_templates/test_pw_research_digest.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/local_runner.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/mega_cases.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshot.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/01_basic_paragraph.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/02_multiple_headings.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/03_runs_with_formatting.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/04_font_name_and_size.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/05_font_color_rgb.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/06_font_character_properties.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/07_font_subscript_superscript.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/08_font_highlight.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/09_paragraph_alignment.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/100_table_negative_indexing.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/101_table_cells_flat_iteration.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/102_text_with_embedded_special_chars.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/104_core_properties_datetime.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/105_default_one_section.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/106_heading_paragraph_format.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/107_varying_row_heights.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/10_paragraph_indents.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/11_paragraph_spacing.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/12_paragraph_keep_options.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/13_paragraph_tab_stops.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/14_run_add_tab_and_break.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/15_run_add_break_page.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/16_paragraph_clear_and_insert_before.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/17_table_basic.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/18_table_cell_text.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/19_table_row_column_sizing.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/20_table_cell_vertical_alignment.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/22_table_cell_paragraphs_iteration.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/24_table_add_row_column.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/25_table_merge_cells.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/26_section_page_setup.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/27_section_margins.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/28_section_add_new.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/29_section_headers_linked.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/30_styles_iteration.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/31_styles_lookup_and_default.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/32_styles_add_paragraph_style.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/33_core_properties_set_and_get.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/34_inline_shapes_iterate_empty.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/35_full_report.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/36_replace_text_in_paragraph.json +0 -0
- {athena_python_docx-0.31.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.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/38_font_all_properties.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/39_large_body_100_paragraphs.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/40_large_table_10x10.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/41_unicode_and_emoji.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/42_very_long_paragraph.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/43_paragraph_text_round_trip.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/44_paragraph_alignment_round_trip.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/45_cell_text_round_trip.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/46_run_text_setter_round_trip.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/47_font_size_round_trip.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/48_font_color_round_trip.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/49_resume_layout.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/50_multi_section_doc.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/52_iterate_everything.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/53_apply_style_to_paragraphs.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/54_empty_everything.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/55_single_character_runs.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/56_everything_in_one.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/57_runs_after_multiple_text_appends.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/58_modify_runs_in_place.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/59_indent_round_trip.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/60_space_round_trip.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/61_cell_paragraph_with_runs.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/62_many_cell_paragraphs.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/63_table_style_round_trip.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/64_many_sections.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/65_20x20_table_formatted.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/66_toc_like_structure.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/67_paragraph_insert_before_chain.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/68_invoice.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/69_newsletter.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/70_add_and_iterate_back.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/71_academic_paper.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/72_legal_contract.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/73_form_with_many_tables.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/74_paragraph_with_10_runs.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/75_paragraph_negative_first_line_indent.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/76_rgbcolor_from_string.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/77_length_unit_conversions.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/78_paragraph_copy_style.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/79_bulk_cell_formatting.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/80_apply_style_after_add_run.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/81_multi_page_with_breaks.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/82_add_text_on_existing_run.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/83_clear_then_repopulate_paragraph.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/84_table_reread_row_count.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/85_header_footer_access.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/86_font_read_unset_returns_none.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/87_500_paragraph_doc.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/88_mixed_content_iteration.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/89_alignment_clear_via_none.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/90_cell_add_paragraph_styled.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/91_many_small_tables.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/92_margins_every_section.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/93_font_bool_reads_after_set.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/94_page_break_before_paragraph.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/95_paragraph_hyperlinks_empty.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/96_paragraph_contains_page_break.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/97_document_styles_by_key.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/98_style_contains_check.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/99_run_add_picture_from_bytes.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex02_unicode_everywhere.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex03_1000_paragraphs.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex04_50x50_table.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex05_long_text_in_cell.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex06_hundred_tiny_runs.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex07_every_font_boolean.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex08_many_continuous_sections.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex09_many_tab_stops.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex10_complex_bom.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex11_banded_rows_formatting.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex12_section_reconfigure.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex13_cell_with_10_paragraphs.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex14_styled_report_table.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex15_paragraph_all_format_props.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex16_runs_interleaved_with_breaks.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex17_all_break_kinds.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex18_read_back_large_doc.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex19_mutate_all_runs.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/ex20_kitchen_sink_v2.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/mega01_book_chapter.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/mega02_research_proposal.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/mega03_financial_statement.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/mega04_recipe_card.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/mega05_user_manual.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/mega06_complex_newsletter.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/mega07_budget_spreadsheet.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/mega08_product_catalog.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/mega09_signed_contract.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/mega10_api_documentation.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw01_official_quickstart.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw02_paragraph_style_list.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw03_character_formatting.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw04_section_page_setup.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw05_toc_pattern.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw06_meeting_minutes.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw07_dense_formatting_demo.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw08_table_merged_header.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw09_bulk_run_iteration.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw10_colored_grid_table.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw11_header_text.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw12_first_page_footer.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw13_even_page_header.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw15_paragraph_style_instance.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw16_header_footer_tables.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw17_header_letterhead_filled.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw18_header_table_properties.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw19_header_table_rows_columns.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/op_snapshots/rw20_header_table_merges.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/ours_spec.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/parity_crawl.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/parity_diff.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/real_world_cases.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/round_trip_tests.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/stock_spec.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fidelity/test_e2e_against_staging.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fixtures/note_reference_reads.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fixtures/ruby_reads.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/fixtures/symbol_reads.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/live/__init__.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/live/reader.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/live/runner.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/live/sdk_driver.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/live/stock_driver.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/live/test_live_runner.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/parity/README.md +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/parity/__init__.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/parity/baseline_gaps.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/parity/compare.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/parity/intentional_deviations.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/parity/introspect.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/parity/reports/GAP_ANALYSIS.md +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/parity/reports/gap_report.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/parity/run_parity.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/parity/snapshots/athena_latest.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/parity/snapshots/upstream_python_docx_1.2.0.json +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/parity/test_parity_gap.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_add_section.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_add_section_extract_items.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_athena_extension_creates_session_open.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_athena_extensions_contract.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_athena_extensions_registry.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_batch_chunking.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_batching_perf.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_block_not_found_error.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_buffer.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_cell_add_paragraph_wire_shape.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_cell_add_table_not_supported.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_cell_borders_spec.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_cell_fastpath_runs.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_cell_inner_add_hyperlink_stash.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_cell_inner_add_run_via_cell_insert.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_cell_inner_format_stash.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_cell_inner_run_format_stash.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_cell_inner_run_guard.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_cell_merge.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_cell_nested_tables.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_cell_paragraphs_listed.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_cell_text_plain_fastpath.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_cell_text_replace_semantics.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_citations.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_collapsed_range_format.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_color_format_theme.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_command_dataclasses.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_commands.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_comment_paragraphs.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_comments.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_comments_first_read.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_content_control_value.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_core_properties.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_document_asset_id_property.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_document_clear.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_document_create.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_document_create_from_template.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_document_factory_validation.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_docx_exec_lab.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_docx_exec_lab_server.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_e2e_partial_failure_cascade.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_empty_hyperlinks.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_execution_scope.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_export_docx_clean.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_export_rescue_anchors.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_field_reads_python_docx_parity.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_field_refresh.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_field_runs.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_find_replace_session_open.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_flushed_write_failures.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_http_transport.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_hyperlink_coalescing.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_image_url_data_uri.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_inline_page_break.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_inline_shape_alt_text.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_inline_shape_size.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_inline_shape_type.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_inline_shapes_floating.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_insert_deferred.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_iter_inner_content.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_list_styles.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_merged_cell_secondary_slot.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_merged_cells.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_missing_modules.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_nested_table_refused.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_note_reference_reads_python_docx_parity.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_oxml_shim.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_page_break.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_paragraph_delete.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_paragraph_runs_hyperlinks.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_paragraph_text_len_cache.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_parity_misc.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_parity_round2.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_partial_failure_cascade.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_pdf_export_and_page_renders.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_phase_a_behavior.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_phase_b_headers_footers.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_phase_c_tables.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_positional_cell_id.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_postproc_cell_format_rewrite.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_postproc_cell_run_format_rewrite.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_postproc_ref_restore.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_pr19766_review_fixes.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_ptc.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_python_docx_api_parity.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_read_run_ranges.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_repeated_node_read.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_restart_numbering.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_revisions.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_round_trip_smoke_script.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_ruby_reads_python_docx_parity.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_run_add_picture_anchor.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_run_formatting_wire.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_run_identity.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_run_mark_inheritance.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_run_table_style_objects.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_run_text_python_docx.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_run_text_refreshes_paragraph.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_sdk_reads_served.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_section_read_lengths.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_add_paragraph_style.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_add_picture.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_add_run.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_cell_add_paragraph.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_comments_add_comment.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_comments_get.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_document_audit.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_document_element.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_enum_section.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_font_audit.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_header_footer.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_hyperlink.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_inline_shape.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_insert_paragraph_before.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_misc.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_paragraph_strict.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_paragraph_style.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_paragraph_style_strict.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_parfmt.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_row_col_cell.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_run_add_break.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_run_bool_setters.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_run_style.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_run_style_strict.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_run_text.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_run_underline.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_section_audit.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_section_dimensions.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_section_onoff.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_shared_audit.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_style.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_styles.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_table_audit.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_table_cell.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_silent_stub_table_dimensions.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_smoke_integration.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_style_acceptance.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_style_font.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_style_formatting_writes.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_style_metadata_writes.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_style_names.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_style_setters_contract.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_style_tab_stops_read.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_symbol_reads_python_docx_parity.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_table_anchors.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_table_read_reuse.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_table_set_cell_perf.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_table_style_id_resolution.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_temporarily_unavailable.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_text_control_characters.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_tracked_revisions_offsets.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_uv_lock_version.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_validate_find_replace_asset_script.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_wire_contract.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_xml_attr_guard.py +0 -0
- {athena_python_docx-0.31.0 → athena_python_docx-0.33.0}/tests/test_zod_wire_contract.py +0 -0
|
@@ -107,6 +107,12 @@ pinned by focused tests and documented in
|
|
|
107
107
|
`horz_dpi`, `width`, `scaled_dimensions`, …). A picture in a table cell or
|
|
108
108
|
a header has no id to read its image by, so `.image` raises `ValueError`;
|
|
109
109
|
an older docx-studio does not report pictures, so they are not runs there.
|
|
110
|
+
- **A run holding only a page or column break yields `""` from
|
|
111
|
+
`Run.iter_inner_content()`,** as python-docx reads a `w:br` of type `page`
|
|
112
|
+
or `column` as empty text; an empty run (a comment reference's) yields
|
|
113
|
+
nothing. docx-studio's read marks such a run with `break`, and
|
|
114
|
+
`Run.add_break` marks the run it adds one to. Against an older docx-studio,
|
|
115
|
+
which sends no `break`, a re-read run yields nothing.
|
|
110
116
|
- **`Styles.latent_styles`** (`docx.styles.latent.LatentStyles`) reads
|
|
111
117
|
the document's `<w:latentStyles>` (defaults and each `w:lsdException`)
|
|
112
118
|
from docx-studio's `Info` (`includeStyles` → `latentStyles`), as python-docx
|
|
@@ -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>
|
|
@@ -332,6 +332,45 @@ def note_picture(run: "Run", picture_id: str, offset: int, *, before: str | None
|
|
|
332
332
|
record.pictures.insert(index, (picture_id, offset))
|
|
333
333
|
|
|
334
334
|
|
|
335
|
+
def read_stamp() -> int:
|
|
336
|
+
"""The moment a read gives its runs (``Paragraph.runs``): a run ``add_run``
|
|
337
|
+
creates after it has a higher ``seq``."""
|
|
338
|
+
return next(_SEQ)
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
def later_runs_at_end(run: "Run") -> int | None:
|
|
342
|
+
"""How many runs after ``run`` end where it does, by which docx-studio
|
|
343
|
+
tells ``run`` from them (``run.laterRuns``) where the offset cannot: an
|
|
344
|
+
empty run ``add_run()`` made after it, or one of breaks alone, ends there
|
|
345
|
+
too.
|
|
346
|
+
|
|
347
|
+
For a run ``add_run`` created, the runs it created after it; for a run a
|
|
348
|
+
read gave (``Paragraph.runs``), the later runs of that read and the runs
|
|
349
|
+
``add_run`` created since. Each where it ends now, not where it ended at
|
|
350
|
+
the read: a write through a run moves the live proxies (:func:`track_run`),
|
|
351
|
+
as clearing a run of text after a run of a break leaves an empty run that
|
|
352
|
+
ends where the break's run does. A read run holds the next run of its
|
|
353
|
+
read (``_next_read``), so the later ones stay live, and current, while it
|
|
354
|
+
is. None for a run proxy that is neither, which the SDK cannot tell from
|
|
355
|
+
the runs around it.
|
|
356
|
+
"""
|
|
357
|
+
end = run._range[1]
|
|
358
|
+
records = _records_of(run)
|
|
359
|
+
own = getattr(run, "_run_record", None) or getattr(run, "_owner_record", None)
|
|
360
|
+
if own is not None and own in records:
|
|
361
|
+
return sum(1 for other in records[records.index(own) + 1 :] if other.range[1] == end)
|
|
362
|
+
read_seq = getattr(run, "_read_seq", None)
|
|
363
|
+
if read_seq is None:
|
|
364
|
+
return None
|
|
365
|
+
later = 0
|
|
366
|
+
following: Run | None = getattr(run, "_next_read", None)
|
|
367
|
+
while following is not None:
|
|
368
|
+
if following._range[1] == end:
|
|
369
|
+
later += 1
|
|
370
|
+
following = getattr(following, "_next_read", None)
|
|
371
|
+
return later + sum(1 for other in records if other.seq > read_seq and other.range[1] == end)
|
|
372
|
+
|
|
373
|
+
|
|
335
374
|
def ends_last_at_its_end(run: "Run") -> bool:
|
|
336
375
|
"""True when no run ``add_run`` created after ``run`` ends where it does.
|
|
337
376
|
|
|
@@ -223,6 +223,10 @@ class Replace(Command):
|
|
|
223
223
|
# …``), whose own properties docx-studio keeps for the new text; an older
|
|
224
224
|
# docx-studio ignores it.
|
|
225
225
|
whole_run: bool | None = None
|
|
226
|
+
# An empty run's identity among the runs at its place (``{"laterRuns": n}``,
|
|
227
|
+
# as ``Insert.run``), sent to a docx-studio reporting
|
|
228
|
+
# ``capabilities.runIdentity``.
|
|
229
|
+
run: dict[str, Any] | None = None
|
|
226
230
|
|
|
227
231
|
|
|
228
232
|
@dataclass
|
|
@@ -233,13 +237,17 @@ class InsertLineBreak(Command):
|
|
|
233
237
|
# ``True`` gives the break the formatting of the run it ends
|
|
234
238
|
# (``Run.add_break``); an older docx-studio ignores it.
|
|
235
239
|
inherit_marks: bool | None = None
|
|
236
|
-
# ``"column"``: a column break (``Run.add_break(WD_BREAK.COLUMN)``),
|
|
237
|
-
#
|
|
238
|
-
#
|
|
239
|
-
# break.
|
|
240
|
+
# ``"column"``: a column break (``Run.add_break(WD_BREAK.COLUMN)``),
|
|
241
|
+
# outside the paragraph's text-address space: with ``inline``, at the end
|
|
242
|
+
# of the run, in it; otherwise after the paragraph's content. An older
|
|
243
|
+
# docx-studio ignores it and inserts a line break.
|
|
240
244
|
break_type: str | None = None
|
|
241
245
|
# As ``Insert.run_edge``.
|
|
242
246
|
run_edge: str | None = None
|
|
247
|
+
# ``True`` with ``break_type="column"``: the break at the end of the run,
|
|
248
|
+
# in it, as python-docx writes it. Sent only to a docx-studio reporting
|
|
249
|
+
# ``capabilities.inlineColumnBreak``; an older one ignores it.
|
|
250
|
+
inline: bool | None = None
|
|
243
251
|
|
|
244
252
|
|
|
245
253
|
@dataclass
|
|
@@ -261,6 +269,10 @@ class FormatApply(Command):
|
|
|
261
269
|
# (``run.bold = True``), which docx-studio keeps apart with their new
|
|
262
270
|
# formatting; an older docx-studio ignores it.
|
|
263
271
|
whole_run: bool | None = None
|
|
272
|
+
# The identity of an empty run that holds a page or column break
|
|
273
|
+
# (``{"laterRuns": n}``, as ``Insert.run``): its breaks take the
|
|
274
|
+
# formatting. Sent to a docx-studio reporting ``capabilities.runIdentity``.
|
|
275
|
+
run: dict[str, Any] | None = None
|
|
264
276
|
|
|
265
277
|
|
|
266
278
|
@dataclass
|
|
@@ -725,6 +737,10 @@ class Info(Command):
|
|
|
725
737
|
# ``docProps/core.xml``. An older docx-studio ignores the field, which
|
|
726
738
|
# tells the SDK it has no ``SetCoreProperties``.
|
|
727
739
|
include_core_properties: bool | None = None
|
|
740
|
+
# ``True`` also returns ``settings``: ``evenAndOddHeaders``, the
|
|
741
|
+
# document's ``w:evenAndOddHeaders`` in ``word/settings.xml``. An older
|
|
742
|
+
# docx-studio ignores the field and sends none.
|
|
743
|
+
include_settings: bool | None = None
|
|
728
744
|
|
|
729
745
|
|
|
730
746
|
@dataclass
|
|
@@ -29,9 +29,12 @@ class Drawing:
|
|
|
29
29
|
def has_picture(self) -> bool:
|
|
30
30
|
"""True when `drawing` contains an embedded picture.
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
As python-docx: False for a drawing whose graphic is not a picture (a
|
|
33
|
+
chart, a diagram, a group), which docx-studio reports with
|
|
34
|
+
``hasPicture: false``. An older docx-studio reports none, and every
|
|
35
|
+
drawing it reports reads as a picture.
|
|
33
36
|
"""
|
|
34
|
-
return
|
|
37
|
+
return self._info.get("hasPicture") is not False
|
|
35
38
|
|
|
36
39
|
@property
|
|
37
40
|
def image(self) -> "Image":
|
|
@@ -44,6 +47,8 @@ class Drawing:
|
|
|
44
47
|
from docx.image.image import Image
|
|
45
48
|
from docx.shape import _strip_data_uri
|
|
46
49
|
|
|
50
|
+
if not self.has_picture:
|
|
51
|
+
raise ValueError("drawing does not contain a picture")
|
|
47
52
|
image_id = self._info.get("imageId")
|
|
48
53
|
if not isinstance(image_id, str) or not image_id:
|
|
49
54
|
raise ValueError("drawing image cannot be read: docx-studio reported no id for it")
|
|
@@ -4,8 +4,9 @@ Most Word app settings are not surfaced by DOCX Studio, so this proxy is
|
|
|
4
4
|
intentionally minimal. The fields that ARE exposed have one-to-one
|
|
5
5
|
DOCX Studio semantics:
|
|
6
6
|
|
|
7
|
-
* ``odd_and_even_pages_header_footer`` —
|
|
8
|
-
``<w:evenAndOddHeaders/>`` flag
|
|
7
|
+
* ``odd_and_even_pages_header_footer`` — reads the document-level
|
|
8
|
+
``<w:evenAndOddHeaders/>`` flag from ``Info`` (``includeSettings``) and
|
|
9
|
+
toggles it via DOCX Studio 1.8.1's
|
|
9
10
|
``doc.sections.setOddEvenHeadersFooters`` (doc-level despite its
|
|
10
11
|
namespace — see ``commands.SetSectionsOddEvenHeadersFooters``).
|
|
11
12
|
* ``track_revisions`` — alias for :attr:`docx.document.Document.track_revisions`.
|
|
@@ -50,6 +51,15 @@ class Settings:
|
|
|
50
51
|
|
|
51
52
|
@property
|
|
52
53
|
def odd_and_even_pages_header_footer(self) -> bool:
|
|
54
|
+
"""The document's ``w:evenAndOddHeaders`` in ``word/settings.xml``, as
|
|
55
|
+
python-docx reads it (False when absent or off). A docx-studio that
|
|
56
|
+
does not report it (``Info`` without ``settings``) gives the value this
|
|
57
|
+
proxy last set."""
|
|
58
|
+
info: object = run_sync(self._session.doc.info({"includeSettings": True}))
|
|
59
|
+
settings: object = info.get("settings") if isinstance(info, dict) else None
|
|
60
|
+
reported: object = settings.get("evenAndOddHeaders") if isinstance(settings, dict) else None
|
|
61
|
+
if isinstance(reported, bool):
|
|
62
|
+
return reported
|
|
53
63
|
return self._odd_and_even_pages_header_footer
|
|
54
64
|
|
|
55
65
|
@odd_and_even_pages_header_footer.setter
|
|
@@ -23,9 +23,11 @@ class PendingTableClearWarning(UserWarning):
|
|
|
23
23
|
setter is asked to clear a property (``None`` assignment) that
|
|
24
24
|
python-docx 1.x supports but DOCX Studio 1.8 has no clear-op for.
|
|
25
25
|
|
|
26
|
-
Covers: ``Table.alignment /
|
|
26
|
+
Covers: ``Table.alignment / autofit``,
|
|
27
27
|
``_Row.height / height_rule``, ``_Column.width``,
|
|
28
|
-
``_Cell.width / vertical_alignment
|
|
28
|
+
``_Cell.width / vertical_alignment``, and any ``Table.table_direction``
|
|
29
|
+
write to a docx-studio that does not report
|
|
30
|
+
``capabilities.tableDirection`` (one that does writes None too). DOCX Studio's
|
|
29
31
|
``tables.set_layout`` / ``set_row_height`` / ``set_column_width``
|
|
30
32
|
/ ``set_cell_properties`` require explicit values — the wire
|
|
31
33
|
can't represent the python-docx "revert to inherited" intent.
|
|
@@ -1241,36 +1243,48 @@ class Table:
|
|
|
1241
1243
|
)
|
|
1242
1244
|
|
|
1243
1245
|
@property
|
|
1244
|
-
def
|
|
1245
|
-
|
|
1246
|
-
|
|
1246
|
+
def table_direction(self) -> "WD_TABLE_DIRECTION | None":
|
|
1247
|
+
"""The table's ``w:bidiVisual`` as python-docx 1.2.0 reads it: ``True``
|
|
1248
|
+
(right to left), ``False`` (an explicit left to right) or None (none),
|
|
1249
|
+
the ``bool`` python-docx returns behind its ``WD_TABLE_DIRECTION`` hint
|
|
1250
|
+
(``True == WD_TABLE_DIRECTION.RTL``)."""
|
|
1247
1251
|
info: object = run_sync(
|
|
1248
1252
|
self._session.doc.tables.get_properties({"nodeId": self._fresh_node_id()}),
|
|
1249
1253
|
)
|
|
1250
|
-
if isinstance(info, dict)
|
|
1251
|
-
|
|
1254
|
+
direction: object = info.get("direction") if isinstance(info, dict) else None
|
|
1255
|
+
if direction == "rtl":
|
|
1256
|
+
return cast("WD_TABLE_DIRECTION", True)
|
|
1257
|
+
if direction == "ltr":
|
|
1258
|
+
return cast("WD_TABLE_DIRECTION", False)
|
|
1252
1259
|
return None
|
|
1253
1260
|
|
|
1254
|
-
@
|
|
1255
|
-
def
|
|
1261
|
+
@table_direction.setter
|
|
1262
|
+
def table_direction(self, value: "WD_TABLE_DIRECTION | int | str | None") -> None:
|
|
1263
|
+
"""As python-docx 1.2.0: RTL writes ``w:bidiVisual``, LTR writes
|
|
1264
|
+
``w:bidiVisual w:val="0"`` and None removes it. A docx-studio that does
|
|
1265
|
+
not report ``capabilities.tableDirection`` drops the write, so the SDK
|
|
1266
|
+
sends none there and warns (``PendingTableClearWarning``)."""
|
|
1267
|
+
from docx._capabilities import server_takes
|
|
1268
|
+
from docx.commands import NULL
|
|
1256
1269
|
from docx.enum.table import WD_TABLE_DIRECTION
|
|
1257
1270
|
|
|
1258
|
-
|
|
1259
|
-
|
|
1271
|
+
# None goes on the wire as JSON null (``NULL``): a ``None`` field is left off it.
|
|
1272
|
+
wire: object = NULL if value is None else WD_TABLE_DIRECTION._wire(value, "Table.table_direction")
|
|
1273
|
+
if not server_takes(self._session, "tableDirection"):
|
|
1274
|
+
warnings.warn(
|
|
1275
|
+
"Table.table_direction was IGNORED: this DOCX Studio does not write a table's "
|
|
1276
|
+
"direction (w:bidiVisual); the table keeps its previous direction.",
|
|
1277
|
+
PendingTableClearWarning,
|
|
1278
|
+
stacklevel=2,
|
|
1279
|
+
)
|
|
1260
1280
|
return
|
|
1261
|
-
|
|
1262
|
-
# DOCX Studio's setLayout takes ``tableDirection`` (not
|
|
1263
|
-
# ``direction``). Same diagnostic as alignment above —
|
|
1264
|
-
# setTableOptions silently swallowed the field.
|
|
1281
|
+
# DOCX Studio's setLayout takes ``tableDirection`` (not ``direction``).
|
|
1265
1282
|
run_sync(
|
|
1266
1283
|
self._session.doc.tables.set_layout(
|
|
1267
|
-
{"nodeId": self._fresh_node_id(), "tableDirection":
|
|
1284
|
+
{"nodeId": self._fresh_node_id(), "tableDirection": wire},
|
|
1268
1285
|
),
|
|
1269
1286
|
)
|
|
1270
1287
|
|
|
1271
|
-
# python-docx aliases
|
|
1272
|
-
table_direction = direction
|
|
1273
|
-
|
|
1274
1288
|
@property
|
|
1275
1289
|
def autofit(self) -> bool:
|
|
1276
1290
|
info: object = run_sync(
|
|
@@ -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
|
|
@@ -9,7 +9,7 @@ from typing import TYPE_CHECKING, Any
|
|
|
9
9
|
from docx._athena_extension import athena_extension
|
|
10
10
|
from docx._batching import run_sync
|
|
11
11
|
from docx._buffer import writes_unapplied
|
|
12
|
-
from docx._run_order import forget_paragraph, register_run
|
|
12
|
+
from docx._run_order import forget_paragraph, read_stamp, register_run
|
|
13
13
|
from docx._tracked import tracking
|
|
14
14
|
|
|
15
15
|
#: The session attribute ``Paragraph.delete`` bumps, after which every
|
|
@@ -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:
|
|
@@ -818,6 +842,13 @@ class Paragraph:
|
|
|
818
842
|
# cache for free (avoids a follow-up ``get_node_by_id`` if the
|
|
819
843
|
# caller does ``p.runs[...]; p.add_run(...)``).
|
|
820
844
|
self._text_len = offset
|
|
845
|
+
# Each run holds the next one of this read: docx-studio tells it from
|
|
846
|
+
# the later ones that end where it does when content goes to it, by
|
|
847
|
+
# where they end then (``docx._run_order.later_runs_at_end``).
|
|
848
|
+
stamp = read_stamp()
|
|
849
|
+
for index, run_obj in enumerate(runs):
|
|
850
|
+
run_obj._next_read = runs[index + 1] if index + 1 < len(runs) else None
|
|
851
|
+
run_obj._read_seq = stamp
|
|
821
852
|
return runs
|
|
822
853
|
|
|
823
854
|
@property
|
|
@@ -1122,22 +1153,28 @@ class Paragraph:
|
|
|
1122
1153
|
|
|
1123
1154
|
@property
|
|
1124
1155
|
def contains_page_break(self) -> bool:
|
|
1125
|
-
"""python-docx 1.x: True
|
|
1126
|
-
|
|
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)
|
|
1127
1160
|
|
|
1128
1161
|
@property
|
|
1129
1162
|
def rendered_page_breaks(self) -> "list[RenderedPageBreak]":
|
|
1130
|
-
"""
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
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.
|
|
1139
1172
|
"""
|
|
1140
|
-
|
|
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)
|
|
1141
1178
|
if "\f" not in text:
|
|
1142
1179
|
return []
|
|
1143
1180
|
out: list[RenderedPageBreak] = []
|