athena-python-docx 0.33.0__tar.gz → 0.35.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.33.0 → athena_python_docx-0.35.0}/AGENTS.md +135 -29
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/PKG-INFO +1 -1
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/__init__.py +1 -1
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/_buffer.py +6 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/_capabilities.py +10 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/_http_doc.py +8 -2
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/_postproc.py +10 -1
- athena_python_docx-0.35.0/docx/_proxy.py +85 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/_run_order.py +31 -0
- athena_python_docx-0.35.0/docx/_xml_text.py +46 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/blkcntnr.py +3 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/commands.py +66 -2
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/document.py +4 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/enum/base.py +28 -1
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/section.py +12 -24
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/settings.py +15 -1
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/styles/_table.py +6 -4
- athena_python_docx-0.35.0/docx/styles/latent.py +337 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/styles/style.py +319 -69
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/styles/styles.py +15 -1
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/table.py +158 -26
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/text/paragraph.py +74 -9
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/text/parfmt.py +86 -45
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/text/run.py +163 -27
- athena_python_docx-0.35.0/docx/text/tabstops.py +461 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/pyproject.toml +1 -1
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/METHODOLOGY.md +9 -1
- athena_python_docx-0.35.0/tests/fidelity/ab_probe/__init__.py +15 -0
- athena_python_docx-0.35.0/tests/fidelity/ab_probe/default_style_run_formatting.py +25 -0
- athena_python_docx-0.35.0/tests/fidelity/ab_probe/header_footer_pictures.py +28 -0
- athena_python_docx-0.35.0/tests/fidelity/ab_probe/less_used_writes.py +219 -0
- athena_python_docx-0.35.0/tests/fidelity/ab_probe/merged_cell_identity.py +31 -0
- athena_python_docx-0.35.0/tests/fidelity/ab_probe/paragraph_text_setter.py +57 -0
- athena_python_docx-0.35.0/tests/fidelity/ab_probe/proxy_equality.py +41 -0
- athena_python_docx-0.35.0/tests/fidelity/ab_probe/xml_incompatible_text.py +24 -0
- athena_python_docx-0.35.0/tests/fidelity/ab_probe/zero_and_negative_indents.py +26 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/ab_probe_cases.py +284 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/fake_session.py +4 -1
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/101_table_cells_flat_iteration.json +0 -1
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/107_varying_row_heights.json +1 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/13_paragraph_tab_stops.json +1 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/19_table_row_column_sizing.json +1 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/ex09_many_tab_stops.json +1 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/rw18_header_table_properties.json +1 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/live/baseline.json +17 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/live/fixture_scripts.py +67 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/live/runner.py +25 -16
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/live/test_live_runner.py +24 -0
- athena_python_docx-0.35.0/tests/test_alignment_values.py +90 -0
- athena_python_docx-0.35.0/tests/test_battery_cases.py +54 -0
- athena_python_docx-0.35.0/tests/test_document_settings_session_open.py +63 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_field_runs.py +159 -3
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_http_transport.py +1 -1
- athena_python_docx-0.35.0/tests/test_latent_style_writes.py +166 -0
- athena_python_docx-0.35.0/tests/test_line_clear_break.py +83 -0
- athena_python_docx-0.35.0/tests/test_merged_cell_identity.py +104 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_paragraph_delete.py +1 -0
- athena_python_docx-0.35.0/tests/test_paragraph_indent_reads.py +60 -0
- athena_python_docx-0.35.0/tests/test_paragraph_text_empty_run.py +44 -0
- athena_python_docx-0.35.0/tests/test_parfmt_clears.py +168 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_parity_misc.py +15 -2
- athena_python_docx-0.35.0/tests/test_proxy_equality.py +179 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_rendered_page_breaks.py +33 -0
- athena_python_docx-0.35.0/tests/test_run_page_number_blocks.py +157 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_parfmt.py +10 -8
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_row_col_cell.py +3 -11
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_section_onoff.py +11 -23
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_table_layout.py +8 -6
- athena_python_docx-0.35.0/tests/test_style_delete.py +150 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_style_formatting_writes.py +25 -2
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_style_metadata_writes.py +138 -1
- athena_python_docx-0.35.0/tests/test_style_tab_stops.py +249 -0
- athena_python_docx-0.35.0/tests/test_tab_stop_writes.py +324 -0
- athena_python_docx-0.35.0/tests/test_table_clears.py +128 -0
- athena_python_docx-0.35.0/tests/test_unmapped_alignment_reads.py +95 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_wire_contract.py +8 -0
- athena_python_docx-0.35.0/tests/test_xml_incompatible_text.py +103 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/uv.lock +1 -1
- athena_python_docx-0.33.0/docx/styles/latent.py +0 -220
- athena_python_docx-0.33.0/docx/text/tabstops.py +0 -232
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/.gitignore +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/CLAUDE.md +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/DOCX_EXEC_LAB.md +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/README.md +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/_athena_extension.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/_batching.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/_citations.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/_execution.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/_http.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/_image_utils.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/_ptc.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/_references.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/_table_styles.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/_timeouts.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/_tracked.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/api.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/bookmarks.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/charts.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/client.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/comments.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/drawing/__init__.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/enum/__init__.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/enum/dml.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/enum/section.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/enum/shape.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/enum/style.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/enum/table.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/enum/text.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/errors.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/exceptions.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/fields.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/footnotes.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/image/__init__.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/image/exceptions.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/image/image.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/math.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/opc/__init__.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/opc/coreprops.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/oxml/__init__.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/revisions.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/sdt.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/session.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/shape.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/shared.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/styles/__init__.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/text/__init__.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/text/font.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/text/hyperlink.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/text/pagebreak.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/toc.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/docx/typing.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/scripts/docx_exec_lab.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/scripts/docx_exec_lab_examples/fast_table_fill.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/scripts/docx_exec_lab_examples/find_replace_literal.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/scripts/docx_exec_lab_server.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/scripts/dump_wire_fixtures.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/scripts/release.sh +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/scripts/round_trip_smoke.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/scripts/smoke_test_block_not_found.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/scripts/validate_find_replace_asset.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/__init__.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/conftest.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/README.md +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/__init__.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/ab_probe_runner.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/auto_gen_cases.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/binary_round_trip.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/cases.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/complex_cases.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/coverage_report.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/extract.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/extreme_cases.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/firm_templates/README.md +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/firm_templates/__init__.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/firm_templates/_runner.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/firm_templates/extractor.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/firm_templates/test_pw_corpus.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/firm_templates/test_pw_research_digest.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/local_runner.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/mega_cases.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshot.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/01_basic_paragraph.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/02_multiple_headings.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/03_runs_with_formatting.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/04_font_name_and_size.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/05_font_color_rgb.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/06_font_character_properties.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/07_font_subscript_superscript.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/08_font_highlight.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/09_paragraph_alignment.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/100_table_negative_indexing.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/102_text_with_embedded_special_chars.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/104_core_properties_datetime.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/105_default_one_section.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/106_heading_paragraph_format.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/10_paragraph_indents.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/11_paragraph_spacing.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/12_paragraph_keep_options.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/14_run_add_tab_and_break.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/15_run_add_break_page.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/16_paragraph_clear_and_insert_before.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/17_table_basic.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/18_table_cell_text.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/20_table_cell_vertical_alignment.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/21_table_alignment_and_autofit.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/22_table_cell_paragraphs_iteration.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/24_table_add_row_column.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/25_table_merge_cells.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/26_section_page_setup.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/27_section_margins.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/28_section_add_new.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/29_section_headers_linked.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/30_styles_iteration.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/31_styles_lookup_and_default.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/32_styles_add_paragraph_style.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/33_core_properties_set_and_get.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/34_inline_shapes_iterate_empty.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/35_full_report.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/36_replace_text_in_paragraph.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/37_iterate_runs_and_format_all_bold.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/38_font_all_properties.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/39_large_body_100_paragraphs.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/40_large_table_10x10.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/41_unicode_and_emoji.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/42_very_long_paragraph.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/43_paragraph_text_round_trip.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/44_paragraph_alignment_round_trip.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/45_cell_text_round_trip.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/46_run_text_setter_round_trip.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/47_font_size_round_trip.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/48_font_color_round_trip.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/49_resume_layout.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/50_multi_section_doc.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/52_iterate_everything.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/53_apply_style_to_paragraphs.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/54_empty_everything.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/55_single_character_runs.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/56_everything_in_one.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/57_runs_after_multiple_text_appends.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/58_modify_runs_in_place.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/59_indent_round_trip.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/60_space_round_trip.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/61_cell_paragraph_with_runs.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/62_many_cell_paragraphs.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/63_table_style_round_trip.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/64_many_sections.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/65_20x20_table_formatted.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/66_toc_like_structure.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/67_paragraph_insert_before_chain.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/68_invoice.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/69_newsletter.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/70_add_and_iterate_back.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/71_academic_paper.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/72_legal_contract.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/73_form_with_many_tables.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/74_paragraph_with_10_runs.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/75_paragraph_negative_first_line_indent.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/76_rgbcolor_from_string.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/77_length_unit_conversions.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/78_paragraph_copy_style.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/79_bulk_cell_formatting.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/80_apply_style_after_add_run.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/81_multi_page_with_breaks.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/82_add_text_on_existing_run.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/83_clear_then_repopulate_paragraph.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/84_table_reread_row_count.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/85_header_footer_access.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/86_font_read_unset_returns_none.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/87_500_paragraph_doc.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/88_mixed_content_iteration.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/89_alignment_clear_via_none.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/90_cell_add_paragraph_styled.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/91_many_small_tables.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/92_margins_every_section.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/93_font_bool_reads_after_set.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/94_page_break_before_paragraph.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/95_paragraph_hyperlinks_empty.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/96_paragraph_contains_page_break.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/97_document_styles_by_key.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/98_style_contains_check.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/99_run_add_picture_from_bytes.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/ex02_unicode_everywhere.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/ex03_1000_paragraphs.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/ex04_50x50_table.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/ex05_long_text_in_cell.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/ex06_hundred_tiny_runs.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/ex07_every_font_boolean.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/ex08_many_continuous_sections.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/ex10_complex_bom.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/ex11_banded_rows_formatting.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/ex12_section_reconfigure.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/ex13_cell_with_10_paragraphs.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/ex14_styled_report_table.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/ex15_paragraph_all_format_props.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/ex16_runs_interleaved_with_breaks.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/ex17_all_break_kinds.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/ex18_read_back_large_doc.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/ex19_mutate_all_runs.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/ex20_kitchen_sink_v2.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/mega01_book_chapter.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/mega02_research_proposal.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/mega03_financial_statement.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/mega04_recipe_card.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/mega05_user_manual.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/mega06_complex_newsletter.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/mega07_budget_spreadsheet.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/mega08_product_catalog.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/mega09_signed_contract.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/mega10_api_documentation.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/rw01_official_quickstart.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/rw02_paragraph_style_list.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/rw03_character_formatting.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/rw04_section_page_setup.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/rw05_toc_pattern.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/rw06_meeting_minutes.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/rw07_dense_formatting_demo.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/rw08_table_merged_header.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/rw09_bulk_run_iteration.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/rw10_colored_grid_table.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/rw11_header_text.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/rw12_first_page_footer.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/rw13_even_page_header.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/rw15_paragraph_style_instance.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/rw16_header_footer_tables.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/rw17_header_letterhead_filled.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/rw19_header_table_rows_columns.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/op_snapshots/rw20_header_table_merges.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/ours_spec.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/parity_crawl.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/parity_diff.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/real_world_cases.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/round_trip_tests.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/stock_spec.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fidelity/test_e2e_against_staging.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fixtures/field_reads.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fixtures/note_reference_reads.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fixtures/ruby_reads.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/fixtures/symbol_reads.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/live/__init__.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/live/reader.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/live/sdk_driver.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/live/stock_driver.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/parity/README.md +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/parity/__init__.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/parity/baseline_gaps.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/parity/compare.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/parity/intentional_deviations.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/parity/introspect.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/parity/reports/GAP_ANALYSIS.md +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/parity/reports/gap_report.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/parity/run_parity.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/parity/snapshots/athena_latest.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/parity/snapshots/upstream_python_docx_1.2.0.json +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/parity/test_parity_gap.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_add_section.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_add_section_extract_items.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_athena_extension_creates_session_open.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_athena_extensions_contract.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_athena_extensions_registry.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_batch_chunking.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_batching_perf.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_block_not_found_error.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_buffer.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_cell_add_paragraph_wire_shape.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_cell_add_table_not_supported.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_cell_borders_spec.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_cell_fastpath_runs.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_cell_inner_add_hyperlink_stash.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_cell_inner_add_run_via_cell_insert.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_cell_inner_format_stash.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_cell_inner_run_format_stash.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_cell_inner_run_guard.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_cell_merge.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_cell_nested_tables.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_cell_paragraphs_listed.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_cell_text_plain_fastpath.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_cell_text_replace_semantics.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_citations.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_collapsed_range_format.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_color_format_theme.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_command_dataclasses.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_commands.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_comment_paragraphs.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_comments.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_comments_first_read.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_content_control_value.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_core_properties.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_document_asset_id_property.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_document_clear.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_document_create.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_document_create_from_template.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_document_factory_validation.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_docx_exec_lab.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_docx_exec_lab_server.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_drawing_image.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_e2e_partial_failure_cascade.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_empty_hyperlinks.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_enum_parity.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_execution_scope.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_export_docx_clean.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_export_rescue_anchors.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_field_reads_python_docx_parity.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_field_refresh.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_find_replace_session_open.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_flushed_write_failures.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_hyperlink_coalescing.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_image_url_data_uri.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_inline_page_break.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_inline_shape_alt_text.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_inline_shape_size.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_inline_shape_type.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_inline_shapes_floating.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_insert_deferred.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_iter_inner_content.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_list_styles.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_merged_cell_secondary_slot.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_merged_cells.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_missing_modules.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_nested_table_refused.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_note_reference_reads_python_docx_parity.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_oxml_shim.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_page_break.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_paragraph_runs_hyperlinks.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_paragraph_text_len_cache.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_parity_round2.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_partial_failure_cascade.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_pdf_export_and_page_renders.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_phase_a_behavior.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_phase_b_headers_footers.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_phase_c_tables.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_positional_cell_id.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_postproc_cell_format_rewrite.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_postproc_cell_run_format_rewrite.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_postproc_ref_restore.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_pr19766_review_fixes.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_ptc.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_python_docx_api_parity.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_read_run_ranges.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_repeated_node_read.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_restart_numbering.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_revisions.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_round_trip_smoke_script.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_ruby_reads_python_docx_parity.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_run_add_picture_anchor.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_run_break_inner_content.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_run_edges.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_run_formatting_wire.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_run_identity.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_run_later_runs.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_run_mark_inheritance.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_run_table_style_objects.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_run_text_python_docx.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_run_text_refreshes_paragraph.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_run_unmodeled_toggles.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_sdk_reads_served.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_section_read_lengths.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_add_paragraph_style.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_add_picture.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_add_run.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_cell_add_paragraph.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_comments_add_comment.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_comments_get.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_document_audit.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_document_element.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_enum_section.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_font_audit.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_header_footer.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_hyperlink.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_inline_shape.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_insert_paragraph_before.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_misc.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_paragraph_strict.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_paragraph_style.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_paragraph_style_strict.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_run_add_break.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_run_bool_setters.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_run_style.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_run_style_strict.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_run_text.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_run_underline.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_section_audit.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_section_dimensions.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_settings.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_shared_audit.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_style.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_styles.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_table_audit.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_table_cell.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_silent_stub_table_dimensions.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_smoke_integration.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_style_acceptance.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_style_font.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_style_names.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_style_setters_contract.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_style_tab_stops_read.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_symbol_reads_python_docx_parity.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_table_anchors.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_table_direction.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_table_read_reuse.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_table_set_cell_perf.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_table_style_id_resolution.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_temporarily_unavailable.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_text_control_characters.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_tracked_revisions_offsets.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_uv_lock_version.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_validate_find_replace_asset_script.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_xml_attr_guard.py +0 -0
- {athena_python_docx-0.33.0 → athena_python_docx-0.35.0}/tests/test_zod_wire_contract.py +0 -0
|
@@ -85,16 +85,30 @@ pinned by focused tests and documented in
|
|
|
85
85
|
`quick_style`, `unhide_when_used`, `base_style`,
|
|
86
86
|
`next_paragraph_style`) write the style's definition
|
|
87
87
|
(`SetStyleMetadata`), `Styles.add_style` adds one (`CreateStyle`), and
|
|
88
|
-
a paragraph or
|
|
89
|
-
`style.paragraph_format
|
|
88
|
+
a paragraph, character or table style's formatting (`style.font.*`,
|
|
89
|
+
`style.paragraph_format.*`; a table style's on a docx-studio that reports
|
|
90
|
+
`tableStyleFormatting`, which a room imported before its cells resolved
|
|
91
|
+
table styles does not) is written too (`SetStyleFormatting`); each
|
|
90
92
|
reads back from the style table, whose `metadata` / `font` /
|
|
91
93
|
`paragraphFormat` entries are the capability signal
|
|
92
94
|
(`tests/test_style_metadata_writes.py`,
|
|
93
|
-
`tests/test_style_formatting_writes.py`)
|
|
94
|
-
|
|
95
|
-
a docx-studio
|
|
96
|
-
|
|
97
|
-
|
|
95
|
+
`tests/test_style_formatting_writes.py`), a paragraph style's
|
|
96
|
+
`tab_stops` (each mutation sends the style's whole `w:tabs` as python-docx's
|
|
97
|
+
`TabStops` leaves it, on a docx-studio that reports `styleTabStops`; each
|
|
98
|
+
tab stop object is its place in that list, which a write to another moves,
|
|
99
|
+
so of two equal stops each writes itself, and one removed writes nothing;
|
|
100
|
+
`tests/test_style_tab_stops.py`). `delete()` removes a paragraph
|
|
101
|
+
or character style's definition (`DeleteStyle`, on a docx-studio that
|
|
102
|
+
reports `deleteStyle`; `tests/test_style_delete.py`): its content keeps the
|
|
103
|
+
style's name and shows the default style, as in Word. A table style's
|
|
104
|
+
`delete()`, `base_style` and `style_id` are sent where docx-studio also
|
|
105
|
+
reports `tableStyleRestyles` (it draws the style's tables again), and its
|
|
106
|
+
font and paragraph format where it reports `tableStyleFormatting`; a room
|
|
107
|
+
imported before its cells resolved table styles reports neither. A
|
|
108
|
+
numbering style's `style_id` and deletion, and every style write on a
|
|
109
|
+
docx-studio without that signal emit
|
|
110
|
+
`PendingStyleMutationWarning` (or its delete / paragraph-format / registry
|
|
111
|
+
variant) and stash on `_overrides` (`tests/test_style_setters_contract.py`).
|
|
98
112
|
- **A picture is a run, and `Run.iter_inner_content()` yields its
|
|
99
113
|
`docx.drawing.Drawing`.** As python-docx reads a `w:r` holding a
|
|
100
114
|
`w:drawing`, `Paragraph.runs` and `iter_inner_content()` hold a run with
|
|
@@ -116,10 +130,15 @@ pinned by focused tests and documented in
|
|
|
116
130
|
- **`Styles.latent_styles`** (`docx.styles.latent.LatentStyles`) reads
|
|
117
131
|
the document's `<w:latentStyles>` (defaults and each `w:lsdException`)
|
|
118
132
|
from docx-studio's `Info` (`includeStyles` → `latentStyles`), as python-docx
|
|
119
|
-
reads them
|
|
120
|
-
and `_LatentStyle.delete`
|
|
121
|
-
|
|
122
|
-
|
|
133
|
+
reads them, and writes them as python-docx does: each setter,
|
|
134
|
+
`add_latent_style` and `_LatentStyle.delete` sends one `EditLatentStyles`
|
|
135
|
+
to a docx-studio that reports `latentStyleWrites`
|
|
136
|
+
(`tests/test_latent_style_writes.py`); an older one keeps the value, with
|
|
137
|
+
`PendingLatentStylesWriteWarning`. A `_LatentStyle` addresses its exception
|
|
138
|
+
by name and `occurrence` (which of that name's exceptions it is), moved
|
|
139
|
+
when an earlier one is deleted, so one `add_latent_style` returns beside an
|
|
140
|
+
exception of the same name writes to itself, as python-docx's element does. A docx-studio that predates the read (or
|
|
141
|
+
a document without a source copy) reads as empty, with
|
|
123
142
|
`PendingLatentStylesReadWarning`.
|
|
124
143
|
|
|
125
144
|
### Intentional deviations (additions / different semantics)
|
|
@@ -169,6 +188,22 @@ not file-backed. Each is documented in the relevant docstring.
|
|
|
169
188
|
cells stay. ``table.style = None`` removes an existing table's style as
|
|
170
189
|
python-docx does (``DOCX_STUDIO_LIMITATIONS.md`` § 25).
|
|
171
190
|
|
|
191
|
+
- **Table, row and cell properties set to None, and row height parts**, as
|
|
192
|
+
python-docx 1.2.0 writes them on a docx-studio that reports
|
|
193
|
+
``tableClears`` (``tests/test_table_clears.py``): ``Table.alignment =
|
|
194
|
+
None`` removes ``w:jc`` (a header or footer table's too),
|
|
195
|
+
``_Cell.vertical_alignment = None`` removes
|
|
196
|
+
``w:vAlign``, and ``_Row.height`` / ``_Row.height_rule`` each write their
|
|
197
|
+
own part of ``w:trHeight``, None removing it (``<w:trHeight
|
|
198
|
+
w:hRule="exact"/>``); a height set without a rule is the value alone.
|
|
199
|
+
``_Cell.width = None`` raises ``TypeError`` and ``Table.autofit = None``
|
|
200
|
+
changes nothing, as in python-docx. An older docx-studio keeps the
|
|
201
|
+
``PendingTableClearWarning`` and sends a rule (at least) with each height.
|
|
202
|
+
``_Column.width = None`` still warns: a ``w:gridCol`` without a width
|
|
203
|
+
needs the layout to size the column from its cells. An invalid height or
|
|
204
|
+
rule is refused before the capability read, whose ``Info`` would send the
|
|
205
|
+
edits still buffered.
|
|
206
|
+
|
|
172
207
|
- **`Document.create(name=, base_url=, api_key=, parent_folder_id=, workspace_id=, docx=, agora_base_url=)`**
|
|
173
208
|
classmethod. Stock python-docx returns a blank in-memory document
|
|
174
209
|
for `Document(None)`; we can't fabricate a Word document asset
|
|
@@ -921,10 +956,26 @@ architecture or a DOCX Studio constraint:
|
|
|
921
956
|
string DOCX Studio's commands carry for a member (`"center"`, `"wavy"`,
|
|
922
957
|
the `w:` XML value, …) where upstream rejects strings. The SDK sends
|
|
923
958
|
`member.to_docx_studio()` and reads with `from_docx_studio()`, never
|
|
924
|
-
`.value`.
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
`
|
|
959
|
+
`.value`. A paragraph's alignment and tab stops go as python-docx writes
|
|
960
|
+
them (distributed / kashida / Thai justification, `LIST`/`CLEAR`/`END`/
|
|
961
|
+
`NUM`/`START` tabs) to a DOCX Studio that reports `alignmentValues`
|
|
962
|
+
(`tests/test_alignment_values.py`); to an older one, as their closest
|
|
963
|
+
value (`"justify"`, `"left"`) with `PendingEnumCoercionWarning`.
|
|
964
|
+
`TabStops.add_tab_stop` keeps a stop already at its position and goes in
|
|
965
|
+
after it, as python-docx's `insert_tab_in_order` puts it
|
|
966
|
+
(`SetParagraphTabStop` with `insert`, sent to a DOCX Studio that reports
|
|
967
|
+
`tabStopInserts`; an older one replaces that stop). A stop's `alignment`
|
|
968
|
+
and `leader` change it in place, and its `position` moves it where
|
|
969
|
+
python-docx moves its `w:tab` (`tests/test_tab_stop_writes.py`). A
|
|
970
|
+
`TabStop` is its place in the paragraph's list, which a write through any
|
|
971
|
+
other moves (the live stops of each paragraph are held weakly per
|
|
972
|
+
session), as python-docx's proxy holds its `w:tab`: two stops at one
|
|
973
|
+
position are each their own, and two objects of one stop both write it.
|
|
974
|
+
One the paragraph no longer holds takes a value and writes nothing; its
|
|
975
|
+
`position` raises `AttributeError`, except for one `clear_all` took out,
|
|
976
|
+
as python-docx's do. An add reads nothing unless a stop of the paragraph
|
|
977
|
+
holds a place: the next read finds where it went.
|
|
978
|
+
`WD_ALIGN_VERTICAL.BOTH` goes as `"center"`. `INHERITED`
|
|
928
979
|
raises `ValueError` ("has no XML representation") as upstream's
|
|
929
980
|
`to_xml` does, and a bool is its int value (`True` is the member valued
|
|
930
981
|
1), as upstream reads it. `Table.alignment`
|
|
@@ -1009,7 +1060,10 @@ architecture or a DOCX Studio constraint:
|
|
|
1009
1060
|
docx-studio finds the table by those paragraphs, so a table an edit moved (a
|
|
1010
1061
|
row added above a table nested in a cell, a table added before it, a merge
|
|
1011
1062
|
moving a nested table into the merged cell) is still the one read and
|
|
1012
|
-
written, as python-docx's proxies follow the elements they hold.
|
|
1063
|
+
written, as python-docx's proxies follow the elements they hold. A write
|
|
1064
|
+
that replaces one of those paragraphs (`cell.text = …` on the first or last
|
|
1065
|
+
cell) leaves its paraId on the table as an alias (`anchorAliases`), so the
|
|
1066
|
+
proxy reaches the table in later batches on any docx-studio replica. When no
|
|
1013
1067
|
table holds them (the table was deleted, or the cell holding it had its
|
|
1014
1068
|
text replaced, which removes the tables it held), docx-studio refuses the
|
|
1015
1069
|
batch and the SDK raises `StaleTableError`: "the table this proxy named is
|
|
@@ -1069,11 +1123,16 @@ architecture or a DOCX Studio constraint:
|
|
|
1069
1123
|
exported paragraph as `annotation text`. Owner decision, 2026-10-12.
|
|
1070
1124
|
Recorded in `tests/parity/intentional_deviations.json` (`live_deviations`).
|
|
1071
1125
|
|
|
1072
|
-
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
`
|
|
1076
|
-
|
|
1126
|
+
- **A `ParagraphFormat` setter given `None` clears that property alone**, as
|
|
1127
|
+
upstream does, on a docx-studio that reports `paragraphFormatClears`:
|
|
1128
|
+
`space_before`, `space_after`, `line_spacing` (the line with its rule) and
|
|
1129
|
+
`line_spacing_rule` (the rule alone) send `ClearParagraphSpacing.only`;
|
|
1130
|
+
`left_indent`, `right_indent` and `first_line_indent` send
|
|
1131
|
+
`ClearParagraphIndentation.only`; `keep_with_next`, `keep_together` and
|
|
1132
|
+
`widow_control` send `SetParagraphKeepOptions.clear…`. On an older one a
|
|
1133
|
+
spacing or indent `None` clears all of the paragraph's spacing or indents,
|
|
1134
|
+
as before, and the keep options and `line_spacing_rule` warn
|
|
1135
|
+
(`PendingParfmtClearWarning`) and keep the value. The `Section` dimension setters
|
|
1077
1136
|
remove the attribute for `None`, as upstream does (`null` on the wire),
|
|
1078
1137
|
on a docx-studio whose section read reports `clearsDimensions`; on an
|
|
1079
1138
|
older one they warn (`PendingSectionDimensionClearWarning`) and keep the
|
|
@@ -1156,18 +1215,37 @@ architecture or a DOCX Studio constraint:
|
|
|
1156
1215
|
field's result changed (through another read's run, or by a
|
|
1157
1216
|
collaborator) raises `FieldRunWriteError` rather than write over that
|
|
1158
1217
|
change, where python-docx's run is live;
|
|
1159
|
-
- formatting a result run formats the field's whole result
|
|
1160
|
-
with a `field` target), from its source formatting,
|
|
1161
|
-
formats that run
|
|
1218
|
+
- formatting a field's one result run formats the field's whole result
|
|
1219
|
+
(`FormatApply` with a `field` target), from its source formatting, as
|
|
1220
|
+
python-docx formats that run, and in a body paragraph docx-studio writes
|
|
1221
|
+
the run's own `w:rPr` with it (a caption's number keeps its `w:noProof`
|
|
1222
|
+
and takes nothing of the Caption style); of a result of several runs, it formats that
|
|
1223
|
+
run alone, as python-docx does, against a docx-studio that reports
|
|
1224
|
+
`capabilities.fieldRunFormats` (an older one formats the whole result).
|
|
1225
|
+
The SDK names that run by its place among the result's runs and the text
|
|
1226
|
+
it was read with, and renumbers the result runs a read holds when a write
|
|
1227
|
+
through one of them empties it (docx-studio writes no emptied result
|
|
1228
|
+
run): a run that no longer has a place, or holds other text, is not
|
|
1229
|
+
formatted alone. The SDK warns (`PendingFieldRunFormatWarning`), or
|
|
1230
|
+
docx-studio refuses the format, so it never lands on another run;
|
|
1162
1231
|
- `.text` (and `clear()`) on a field character or field code run raises
|
|
1163
1232
|
`docx.errors.FieldRunWriteError` naming the field: python-docx replaces
|
|
1164
1233
|
the run's `w:fldChar` or `w:instrText` with the text, which breaks the
|
|
1165
1234
|
field;
|
|
1166
|
-
- formatting set on a field character or field code run
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1235
|
+
- formatting set on a field character or field code run, a table of
|
|
1236
|
+
contents' own runs among them, is written to that run's `w:rPr` as
|
|
1237
|
+
python-docx writes it, so `for run in p.runs: run.bold = True` formats
|
|
1238
|
+
every run, against a docx-studio that reports
|
|
1239
|
+
`capabilities.fieldRunFormats` (the SDK names the run: its `part`, with its
|
|
1240
|
+
field's index and which run of that part it is, or which of the
|
|
1241
|
+
paragraph's field runs no field node stands for it is). It is refused and
|
|
1242
|
+
warns (`DocxUnsupportedCommandWarning`) for a run of a field `add_field`
|
|
1243
|
+
added since the import, whose runs docx-studio writes from its node, and
|
|
1244
|
+
of a paragraph a field was added to or taken out of since; a tracked
|
|
1245
|
+
format raises naming `TrackedChangesUnsupported`. An older docx-studio has
|
|
1246
|
+
no command that writes those runs' `w:rPr`: there the setter changes
|
|
1247
|
+
nothing and emits `PendingFieldRunFormatWarning`
|
|
1248
|
+
(`tests/test_field_runs.py`, `DOCX_STUDIO_LIMITATIONS.md` § 27);
|
|
1171
1249
|
- `add_text`, `add_tab`, `add_break`, `add_picture`, `add_field`,
|
|
1172
1250
|
`add_footnote`, `add_endnote`, `add_math` and `add_cross_reference` on
|
|
1173
1251
|
any of a field's runs raise `FieldRunWriteError`; python-docx appends to
|
|
@@ -1177,6 +1255,34 @@ architecture or a DOCX Studio constraint:
|
|
|
1177
1255
|
exported file. Against a docx-studio that predates `fieldRun` reads, a
|
|
1178
1256
|
field reads as no runs and no text, as before (`tests/test_field_runs.py`).
|
|
1179
1257
|
|
|
1258
|
+
- **A run that holds a page number block refuses a tracked whole-run format
|
|
1259
|
+
and two text writes.** A page number block (`w:pgNum`) reads as a run with
|
|
1260
|
+
no text, and a run that holds text and blocks (or two blocks) reads as
|
|
1261
|
+
python-docx's one run. A whole-run format (`run.bold = True`, `run.font.*`,
|
|
1262
|
+
a format of a block's run) formats every piece of it, as python-docx formats
|
|
1263
|
+
its `w:rPr`, the on/off properties no editor mark holds included
|
|
1264
|
+
(`font.no_proof`, `snap_to_grid`, `web_hidden`, `spec_vanish`, `math`,
|
|
1265
|
+
`complex_script`, `cs_bold`, `cs_italic`). A tracked format
|
|
1266
|
+
(`track_revisions`) is refused while a block of the run has a node, and
|
|
1267
|
+
raises `DocxError` naming `TrackedChangesUnsupported`, because docx-studio
|
|
1268
|
+
records no tracked change on a block. A link's block has none, and takes it
|
|
1269
|
+
as the run's text does. In a document imported before docx-studio gave a
|
|
1270
|
+
block's node its run's properties (in October 2026, between the release that
|
|
1271
|
+
first read `w:pgNum` and the next), and in a comment, the on/off properties
|
|
1272
|
+
are refused too, in any format that reaches a block, and warn
|
|
1273
|
+
(`DocxUnsupportedCommandWarning`), because there a block keeps its source
|
|
1274
|
+
run's. python-docx writes both into the run's `w:rPr`. Made on the run's
|
|
1275
|
+
text alone, either would leave the run half formatted and split it in two
|
|
1276
|
+
(`DOCX_STUDIO_LIMITATIONS.md` § 27). `run.text = …` and `clear()` replace
|
|
1277
|
+
all of such a run, its blocks too, as upstream does: the SDK declares
|
|
1278
|
+
`wholeRunPieces`, and renumbers the field runs it holds of the paragraph,
|
|
1279
|
+
since each field after the blocks is numbered one lower for each
|
|
1280
|
+
(`tests/test_run_page_number_blocks.py`). Two text writes are refused and
|
|
1281
|
+
warn (`DocxUnsupportedCommandWarning`), where upstream replaces the blocks:
|
|
1282
|
+
text written to a block's run (a run of blocks alone, or a lone block),
|
|
1283
|
+
which would move the text offsets the SDK keeps, and the text of a link's
|
|
1284
|
+
run that holds a block, which has no node to take out.
|
|
1285
|
+
|
|
1180
1286
|
- **`Font.name = "…"` also clears the theme fonts of the two slots it
|
|
1181
1287
|
sets.** python-docx writes the name to `w:rFonts`' `w:ascii` and `w:hAnsi`
|
|
1182
1288
|
and leaves a `w:asciiTheme` / `w:hAnsiTheme` beside them; Word reads a
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: athena-python-docx
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.35.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>
|
|
@@ -43,6 +43,7 @@ from docx._execution import (
|
|
|
43
43
|
is_stale_execution,
|
|
44
44
|
)
|
|
45
45
|
from docx._timeouts import timeout_for_commands
|
|
46
|
+
from docx._xml_text import check_command_text
|
|
46
47
|
from docx.commands import (
|
|
47
48
|
Command,
|
|
48
49
|
GetNodeById,
|
|
@@ -596,6 +597,11 @@ class CommandBuffer:
|
|
|
596
597
|
proxy's ``_node_id`` in-place.
|
|
597
598
|
"""
|
|
598
599
|
self.ensure_usable()
|
|
600
|
+
# A write whose text holds a character XML does not allow raises
|
|
601
|
+
# python-docx's ValueError here, before anything is sent: every command
|
|
602
|
+
# comes through, a path-proxy op's and a direct ``send_command``'s.
|
|
603
|
+
if not is_query(cmd):
|
|
604
|
+
check_command_text(cmd.to_dict())
|
|
599
605
|
|
|
600
606
|
# A read of the node the last command read, with nothing sent or
|
|
601
607
|
# buffered since and within READ_REUSE_SECONDS of it, answers from
|
|
@@ -22,6 +22,16 @@ from docx._batching import run_sync
|
|
|
22
22
|
# An older docx-studio gives none, so the SDK needs no check.
|
|
23
23
|
TABLE_ANCHORS_CLIENT_CAPABILITY = "tableAnchors"
|
|
24
24
|
|
|
25
|
+
# What this SDK declares in ``client.capabilities``: it renumbers the field
|
|
26
|
+
# runs it holds once a whole run's text write (``run.text = …``, ``clear()``)
|
|
27
|
+
# took out the page number blocks (``w:pgNum``) of a run docx-studio cut at
|
|
28
|
+
# them, whose read lists their field indices (``pageNumberBlocks``). Such a
|
|
29
|
+
# write then replaces all of the run, its blocks too, as python-docx replaces
|
|
30
|
+
# its ``w:r``'s content, and each field after the blocks is numbered one lower
|
|
31
|
+
# for each. An older docx-studio lists no blocks and keeps them, so the SDK
|
|
32
|
+
# renumbers nothing.
|
|
33
|
+
WHOLE_RUN_PIECES_CLIENT_CAPABILITY = "wholeRunPieces"
|
|
34
|
+
|
|
25
35
|
# Session -> the capabilities its server reported, read once.
|
|
26
36
|
_capabilities: "weakref.WeakKeyDictionary[Any, dict[str, Any]]" = weakref.WeakKeyDictionary()
|
|
27
37
|
|
|
@@ -44,7 +44,7 @@ from urllib3.util.retry import Retry
|
|
|
44
44
|
from docx._batching import call_abandoned, note_progress
|
|
45
45
|
from docx._buffer import CommandBuffer, keep_reported_message
|
|
46
46
|
from docx._tracked import TRACKED_AUTHORING_CAPABILITY, TRACKED_MINIMAL_PARAGRAPH_TEXT_CAPABILITY
|
|
47
|
-
from docx._capabilities import TABLE_ANCHORS_CLIENT_CAPABILITY
|
|
47
|
+
from docx._capabilities import TABLE_ANCHORS_CLIENT_CAPABILITY, WHOLE_RUN_PIECES_CLIENT_CAPABILITY
|
|
48
48
|
from docx._timeouts import (
|
|
49
49
|
DEFAULT_OP_TIMEOUT_SECONDS,
|
|
50
50
|
LONG_RUNNING_COMMAND_TIMEOUT_SECONDS,
|
|
@@ -87,6 +87,8 @@ from docx.commands import (
|
|
|
87
87
|
CreateParagraph,
|
|
88
88
|
CreateSectionBreak,
|
|
89
89
|
CreateStyle,
|
|
90
|
+
EditLatentStyles,
|
|
91
|
+
DeleteStyle,
|
|
90
92
|
CreateTable,
|
|
91
93
|
CreateTOC,
|
|
92
94
|
CreateWatermark,
|
|
@@ -1209,11 +1211,13 @@ class HttpClient:
|
|
|
1209
1211
|
"version": _sdk_version(),
|
|
1210
1212
|
# Keeps its offsets as a tracked edit moves them, and reads a
|
|
1211
1213
|
# paragraph's length back after a tracked ``paragraph.text``
|
|
1212
|
-
# (``docx._tracked``); holds anchored table ids (``docx.table``)
|
|
1214
|
+
# (``docx._tracked``); holds anchored table ids (``docx.table``);
|
|
1215
|
+
# renumbers its field runs after a cut run's whole write (``docx._run_order``).
|
|
1213
1216
|
"capabilities": [
|
|
1214
1217
|
TRACKED_AUTHORING_CAPABILITY,
|
|
1215
1218
|
TRACKED_MINIMAL_PARAGRAPH_TEXT_CAPABILITY,
|
|
1216
1219
|
TABLE_ANCHORS_CLIENT_CAPABILITY,
|
|
1220
|
+
WHOLE_RUN_PIECES_CLIENT_CAPABILITY,
|
|
1217
1221
|
],
|
|
1218
1222
|
},
|
|
1219
1223
|
"commands": [
|
|
@@ -1374,6 +1378,8 @@ _OP_TO_COMMAND: dict[str, type[Command]] = {
|
|
|
1374
1378
|
"styles.set_formatting": SetStyleFormatting,
|
|
1375
1379
|
"styles.set_metadata": SetStyleMetadata,
|
|
1376
1380
|
"styles.create": CreateStyle,
|
|
1381
|
+
"styles.edit_latent": EditLatentStyles,
|
|
1382
|
+
"styles.delete": DeleteStyle,
|
|
1377
1383
|
"core_properties.set": SetCoreProperties,
|
|
1378
1384
|
# Sections
|
|
1379
1385
|
"sections.set_page_margins": SetSectionPageMargins,
|
|
@@ -2897,6 +2897,15 @@ def _replace_flag(
|
|
|
2897
2897
|
elem.set(f"{W_NS}val", "0")
|
|
2898
2898
|
|
|
2899
2899
|
|
|
2900
|
+
# The other ``w:jc`` justifications python-docx writes, by their lower case.
|
|
2901
|
+
_JUSTIFICATIONS_BY_LOWER = {
|
|
2902
|
+
"mediumkashida": "mediumKashida",
|
|
2903
|
+
"highkashida": "highKashida",
|
|
2904
|
+
"lowkashida": "lowKashida",
|
|
2905
|
+
"thaidistribute": "thaiDistribute",
|
|
2906
|
+
}
|
|
2907
|
+
|
|
2908
|
+
|
|
2900
2909
|
def normalize_alignment(value: Any) -> str | None:
|
|
2901
2910
|
"""Convert a python-docx ``WD_ALIGN_PARAGRAPH`` value (or string) to
|
|
2902
2911
|
the OOXML ``w:jc`` value (``left`` / ``center`` / ``right`` /
|
|
@@ -2919,7 +2928,7 @@ def normalize_alignment(value: Any) -> str | None:
|
|
|
2919
2928
|
return "both"
|
|
2920
2929
|
if s in {"distribute"}:
|
|
2921
2930
|
return "distribute"
|
|
2922
|
-
return
|
|
2931
|
+
return _JUSTIFICATIONS_BY_LOWER.get(s)
|
|
2923
2932
|
|
|
2924
2933
|
# WD_ALIGN_PARAGRAPH enum values (int-like).
|
|
2925
2934
|
name = getattr(value, "name", None)
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""python-docx's ``ElementProxy`` equality, for the SDK's proxies of the
|
|
2
|
+
objects python-docx wraps in one: styles, the styles part, settings, a
|
|
3
|
+
paragraph's or a style's paragraph format, a run's or a style's font."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import weakref
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ElementProxyEquality:
|
|
12
|
+
"""python-docx's ``docx.shared.ElementProxy`` equality: two proxies of the
|
|
13
|
+
same element are equal (``paragraph.style == doc.styles["Heading 1"]``),
|
|
14
|
+
a proxy of another element or anything else is not, and, as python-docx
|
|
15
|
+
defines ``__eq__`` there, a proxy is not hashable.
|
|
16
|
+
|
|
17
|
+
The element is :meth:`_proxy_element`: the docx-studio object it stands
|
|
18
|
+
for, named as the XML element python-docx's proxy wraps (a style's
|
|
19
|
+
``w:style``, so a style, its font and its paragraph format are equal, as
|
|
20
|
+
they are in python-docx).
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
__slots__ = ()
|
|
24
|
+
|
|
25
|
+
def _proxy_element(self) -> tuple[object, ...]:
|
|
26
|
+
raise NotImplementedError
|
|
27
|
+
|
|
28
|
+
def __eq__(self, other: object) -> bool:
|
|
29
|
+
if not isinstance(other, ElementProxyEquality):
|
|
30
|
+
return False
|
|
31
|
+
return self._proxy_element() == other._proxy_element()
|
|
32
|
+
|
|
33
|
+
def __ne__(self, other: object) -> bool:
|
|
34
|
+
return not self.__eq__(other)
|
|
35
|
+
|
|
36
|
+
__hash__ = None # type: ignore[assignment]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# Session -> style id -> the style definition that id names in the session's
|
|
40
|
+
# document now (:func:`style_definition`). Held weakly by session, as the
|
|
41
|
+
# run order is (``docx._run_order``); the document stores none of it.
|
|
42
|
+
_STYLE_DEFINITIONS: "weakref.WeakKeyDictionary[Any, dict[str, object]]" = weakref.WeakKeyDictionary()
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _definitions(session: object) -> "dict[str, object] | None":
|
|
46
|
+
if session is None:
|
|
47
|
+
return None
|
|
48
|
+
try:
|
|
49
|
+
return _STYLE_DEFINITIONS.setdefault(session, {})
|
|
50
|
+
except TypeError: # a session that takes no weak reference
|
|
51
|
+
return None
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def style_definition(session: object, style_id: str) -> object:
|
|
55
|
+
"""The style definition (its ``w:style`` element) that ``style_id`` names in
|
|
56
|
+
``session``'s document now, which a style proxy holds from its first read:
|
|
57
|
+
the same one after a rename (:func:`style_renamed`), another for a style
|
|
58
|
+
made after one of that id was deleted (:func:`style_deleted`)."""
|
|
59
|
+
definitions = _definitions(session)
|
|
60
|
+
if definitions is None:
|
|
61
|
+
return ("w:styleId", style_id)
|
|
62
|
+
return definitions.setdefault(style_id, object())
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def style_renamed(session: object, old: str, new: str) -> None:
|
|
66
|
+
"""``style_id`` renamed the definition ``old`` named to ``new``."""
|
|
67
|
+
definitions = _definitions(session)
|
|
68
|
+
if definitions is not None:
|
|
69
|
+
definitions[new] = definitions.pop(old, None) or object()
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def style_deleted(session: object, style_id: str) -> None:
|
|
73
|
+
"""``delete`` removed the definition ``style_id`` named."""
|
|
74
|
+
definitions = _definitions(session)
|
|
75
|
+
if definitions is not None:
|
|
76
|
+
definitions.pop(style_id, None)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def style_element(style: object) -> tuple[object, ...]:
|
|
80
|
+
"""The ``w:style`` element of ``style`` (a ``BaseStyle``): its document and
|
|
81
|
+
its definition (:func:`style_definition`), which a rename keeps."""
|
|
82
|
+
definition = getattr(style, "_definition", None)
|
|
83
|
+
if definition is None:
|
|
84
|
+
definition = ("w:styleId", getattr(style, "_style_id", None))
|
|
85
|
+
return ("w:style", getattr(style, "_session", None), definition)
|
|
@@ -29,6 +29,7 @@ document stores none of it.
|
|
|
29
29
|
|
|
30
30
|
from __future__ import annotations
|
|
31
31
|
|
|
32
|
+
import bisect
|
|
32
33
|
import itertools
|
|
33
34
|
import weakref
|
|
34
35
|
from dataclasses import dataclass, field
|
|
@@ -105,6 +106,36 @@ def _live_runs(run: "Run") -> list["Run"]:
|
|
|
105
106
|
return [proxy for block_id in ids for proxy in list(blocks.get(block_id, ()))]
|
|
106
107
|
|
|
107
108
|
|
|
109
|
+
def page_number_blocks_gone(run: "Run", gone: list[int], *, taken_out: bool) -> None:
|
|
110
|
+
"""The page number blocks ``gone`` (their field indices) are no run's of
|
|
111
|
+
``run``'s paragraph now: a whole run's text write took them out
|
|
112
|
+
(``taken_out``), or, with tracking on, deleted them, where they keep
|
|
113
|
+
their place and their numbers.
|
|
114
|
+
|
|
115
|
+
No live run proxy of the paragraph, read or created, lists them
|
|
116
|
+
(``pageNumberBlocks``). Taken out, each field after them is numbered one
|
|
117
|
+
lower for each, as docx-studio numbers them, so every proxy names its
|
|
118
|
+
field (``fieldIndex``) and the blocks it holds by the new numbers.
|
|
119
|
+
"""
|
|
120
|
+
removed = sorted(set(gone))
|
|
121
|
+
|
|
122
|
+
def renumbered(index: int) -> int:
|
|
123
|
+
return index - bisect.bisect_left(removed, index) if taken_out else index
|
|
124
|
+
|
|
125
|
+
for proxy in _live_runs(run):
|
|
126
|
+
snapshot: object = getattr(proxy, "_inline_snapshot", None)
|
|
127
|
+
if not isinstance(snapshot, dict):
|
|
128
|
+
continue
|
|
129
|
+
index: object = snapshot.get("fieldIndex")
|
|
130
|
+
if isinstance(index, int) and not isinstance(index, bool):
|
|
131
|
+
snapshot["fieldIndex"] = renumbered(index)
|
|
132
|
+
blocks: object = snapshot.get("pageNumberBlocks")
|
|
133
|
+
if isinstance(blocks, list):
|
|
134
|
+
snapshot["pageNumberBlocks"] = [
|
|
135
|
+
renumbered(block) for block in blocks if isinstance(block, int) and block not in removed
|
|
136
|
+
]
|
|
137
|
+
|
|
138
|
+
|
|
108
139
|
def _move_live_runs(
|
|
109
140
|
run: "Run",
|
|
110
141
|
old_span: tuple[int, int],
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""What lxml refuses in XML text and attribute values, where python-docx meets it.
|
|
2
|
+
|
|
3
|
+
python-docx writes every string it is given into an lxml element, and lxml
|
|
4
|
+
raises ``ValueError`` for a character XML does not allow: C0 controls other
|
|
5
|
+
than tab, LF and CR, the noncharacters U+FFFE / U+FFFF, and lone surrogates.
|
|
6
|
+
So ``run.text = "a\\x0bb"`` (a vertical tab, Word's line break in its object
|
|
7
|
+
model) raises there, before anything is written. docx-studio would take the
|
|
8
|
+
text, and a part holding it is one Word refuses to open.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import re
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
XML_INCOMPATIBLE_CHARACTER = re.compile(r"[\x00-\x08\x0b\x0c\x0e-\x1f\ud800-\udfff]")
|
|
17
|
+
XML_INCOMPATIBLE_MESSAGE = (
|
|
18
|
+
"All strings must be XML compatible: Unicode or ASCII, no NULL bytes or control characters"
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def check_xml_compatible(value: Any) -> None:
|
|
23
|
+
"""Raise python-docx's ``ValueError`` (lxml's) when a string in ``value``,
|
|
24
|
+
a command's params (strings, lists, dicts), holds a character XML does
|
|
25
|
+
not allow."""
|
|
26
|
+
if isinstance(value, str):
|
|
27
|
+
if XML_INCOMPATIBLE_CHARACTER.search(value):
|
|
28
|
+
raise ValueError(XML_INCOMPATIBLE_MESSAGE)
|
|
29
|
+
elif isinstance(value, dict):
|
|
30
|
+
for item in value.values():
|
|
31
|
+
check_xml_compatible(item)
|
|
32
|
+
elif isinstance(value, (list, tuple)):
|
|
33
|
+
for item in value:
|
|
34
|
+
check_xml_compatible(item)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
#: Fields of a write that name text to find, not text to write
|
|
38
|
+
#: (``FindReplace.pattern``): a pattern may match what a document already holds.
|
|
39
|
+
_SEARCH_FIELDS: frozenset[str] = frozenset({"pattern"})
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def check_command_text(command: dict[str, Any]) -> None:
|
|
43
|
+
""":func:`check_xml_compatible` over a write's wire fields (a command's
|
|
44
|
+
``to_dict()``), but for the text it searches for (``_SEARCH_FIELDS``)."""
|
|
45
|
+
check_xml_compatible({key: value for key, value in command.items() if key not in _SEARCH_FIELDS})
|
|
46
|
+
|
|
@@ -9,6 +9,8 @@ docx-studio; ``isinstance(cell, BlockItemContainer)`` holds as in python-docx.
|
|
|
9
9
|
|
|
10
10
|
from __future__ import annotations
|
|
11
11
|
|
|
12
|
+
from docx._xml_text import check_xml_compatible
|
|
13
|
+
|
|
12
14
|
from typing import TYPE_CHECKING, Iterator
|
|
13
15
|
|
|
14
16
|
if TYPE_CHECKING:
|
|
@@ -30,6 +32,7 @@ class BlockItemContainer:
|
|
|
30
32
|
self, text: str = "", style: "str | ParagraphStyle | None" = None
|
|
31
33
|
) -> "Paragraph":
|
|
32
34
|
"""Return paragraph newly added to the end of the content in this container."""
|
|
35
|
+
check_xml_compatible(text)
|
|
33
36
|
raise NotImplementedError(f"{type(self).__name__} holds no paragraphs")
|
|
34
37
|
|
|
35
38
|
def add_table(self, rows: int, cols: int, width: "Length") -> "Table":
|