athena-python-docx 0.34.0__tar.gz → 0.36.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.34.0 → athena_python_docx-0.36.0}/AGENTS.md +36 -19
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/PKG-INFO +1 -1
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/__init__.py +1 -1
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_buffer.py +6 -0
- athena_python_docx-0.36.0/docx/_proxy.py +109 -0
- athena_python_docx-0.36.0/docx/_xml_text.py +46 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/blkcntnr.py +3 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/commands.py +4 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/document.py +4 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/oxml/__init__.py +1 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/section.py +3 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/settings.py +15 -1
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/styles/latent.py +21 -4
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/styles/style.py +94 -28
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/styles/styles.py +5 -1
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/table.py +96 -17
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/text/paragraph.py +42 -6
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/text/parfmt.py +16 -4
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/text/run.py +168 -48
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/text/tabstops.py +26 -3
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/pyproject.toml +1 -1
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/METHODOLOGY.md +9 -1
- athena_python_docx-0.36.0/tests/fidelity/ab_probe/__init__.py +15 -0
- athena_python_docx-0.36.0/tests/fidelity/ab_probe/agent_documents.py +133 -0
- athena_python_docx-0.36.0/tests/fidelity/ab_probe/default_style_run_formatting.py +25 -0
- athena_python_docx-0.36.0/tests/fidelity/ab_probe/header_footer_pictures.py +28 -0
- athena_python_docx-0.36.0/tests/fidelity/ab_probe/less_used_writes.py +219 -0
- athena_python_docx-0.36.0/tests/fidelity/ab_probe/merged_cell_identity.py +31 -0
- athena_python_docx-0.36.0/tests/fidelity/ab_probe/paragraph_text_setter.py +57 -0
- athena_python_docx-0.36.0/tests/fidelity/ab_probe/picture_runs.py +101 -0
- athena_python_docx-0.36.0/tests/fidelity/ab_probe/proxy_equality.py +41 -0
- athena_python_docx-0.36.0/tests/fidelity/ab_probe/return_types.py +44 -0
- athena_python_docx-0.36.0/tests/fidelity/ab_probe/xml_incompatible_text.py +24 -0
- athena_python_docx-0.36.0/tests/fidelity/ab_probe/zero_and_negative_indents.py +26 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/ab_probe_cases.py +196 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/101_table_cells_flat_iteration.json +0 -1
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/99_run_add_picture_from_bytes.json +1 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/live/baseline.json +8 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/live/fixture_scripts.py +17 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/live/runner.py +25 -16
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/live/test_live_runner.py +24 -0
- athena_python_docx-0.36.0/tests/test_battery_cases.py +54 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_inner_run_guard.py +5 -7
- athena_python_docx-0.36.0/tests/test_document_settings_session_open.py +63 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_drawing_image.py +179 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_enum_parity.py +3 -1
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_latent_style_writes.py +21 -0
- athena_python_docx-0.36.0/tests/test_merged_cell_identity.py +104 -0
- athena_python_docx-0.36.0/tests/test_paragraph_indent_reads.py +60 -0
- athena_python_docx-0.36.0/tests/test_paragraph_text_empty_run.py +44 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_parfmt_clears.py +24 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_parity_misc.py +15 -2
- athena_python_docx-0.36.0/tests/test_proxy_equality.py +179 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_run_identity.py +13 -11
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_style_tab_stops.py +77 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_tab_stop_writes.py +21 -0
- athena_python_docx-0.36.0/tests/test_unmapped_alignment_reads.py +95 -0
- athena_python_docx-0.36.0/tests/test_xml_incompatible_text.py +103 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/uv.lock +1 -1
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/.gitignore +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/CLAUDE.md +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/DOCX_EXEC_LAB.md +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/README.md +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_athena_extension.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_batching.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_capabilities.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_citations.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_execution.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_http.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_http_doc.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_image_utils.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_postproc.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_ptc.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_references.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_run_order.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_table_styles.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_timeouts.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/_tracked.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/api.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/bookmarks.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/charts.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/client.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/comments.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/drawing/__init__.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/enum/__init__.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/enum/base.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/enum/dml.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/enum/section.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/enum/shape.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/enum/style.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/enum/table.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/enum/text.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/errors.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/exceptions.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/fields.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/footnotes.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/image/__init__.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/image/exceptions.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/image/image.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/math.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/opc/__init__.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/opc/coreprops.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/revisions.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/sdt.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/session.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/shape.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/shared.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/styles/__init__.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/styles/_table.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/text/__init__.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/text/font.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/text/hyperlink.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/text/pagebreak.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/toc.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/docx/typing.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/scripts/docx_exec_lab.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/scripts/docx_exec_lab_examples/fast_table_fill.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/scripts/docx_exec_lab_examples/find_replace_literal.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/scripts/docx_exec_lab_server.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/scripts/dump_wire_fixtures.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/scripts/release.sh +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/scripts/round_trip_smoke.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/scripts/smoke_test_block_not_found.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/scripts/validate_find_replace_asset.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/__init__.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/conftest.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/README.md +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/__init__.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/ab_probe_runner.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/auto_gen_cases.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/binary_round_trip.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/cases.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/complex_cases.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/coverage_report.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/extract.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/extreme_cases.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/fake_session.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/firm_templates/README.md +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/firm_templates/__init__.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/firm_templates/_runner.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/firm_templates/extractor.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/firm_templates/test_pw_corpus.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/firm_templates/test_pw_research_digest.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/local_runner.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/mega_cases.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshot.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/01_basic_paragraph.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/02_multiple_headings.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/03_runs_with_formatting.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/04_font_name_and_size.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/05_font_color_rgb.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/06_font_character_properties.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/07_font_subscript_superscript.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/08_font_highlight.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/09_paragraph_alignment.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/100_table_negative_indexing.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/102_text_with_embedded_special_chars.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/104_core_properties_datetime.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/105_default_one_section.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/106_heading_paragraph_format.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/107_varying_row_heights.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/10_paragraph_indents.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/11_paragraph_spacing.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/12_paragraph_keep_options.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/13_paragraph_tab_stops.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/14_run_add_tab_and_break.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/15_run_add_break_page.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/16_paragraph_clear_and_insert_before.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/17_table_basic.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/18_table_cell_text.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/19_table_row_column_sizing.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/20_table_cell_vertical_alignment.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/21_table_alignment_and_autofit.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/22_table_cell_paragraphs_iteration.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/24_table_add_row_column.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/25_table_merge_cells.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/26_section_page_setup.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/27_section_margins.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/28_section_add_new.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/29_section_headers_linked.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/30_styles_iteration.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/31_styles_lookup_and_default.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/32_styles_add_paragraph_style.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/33_core_properties_set_and_get.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/34_inline_shapes_iterate_empty.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/35_full_report.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/36_replace_text_in_paragraph.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/37_iterate_runs_and_format_all_bold.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/38_font_all_properties.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/39_large_body_100_paragraphs.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/40_large_table_10x10.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/41_unicode_and_emoji.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/42_very_long_paragraph.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/43_paragraph_text_round_trip.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/44_paragraph_alignment_round_trip.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/45_cell_text_round_trip.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/46_run_text_setter_round_trip.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/47_font_size_round_trip.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/48_font_color_round_trip.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/49_resume_layout.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/50_multi_section_doc.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/52_iterate_everything.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/53_apply_style_to_paragraphs.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/54_empty_everything.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/55_single_character_runs.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/56_everything_in_one.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/57_runs_after_multiple_text_appends.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/58_modify_runs_in_place.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/59_indent_round_trip.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/60_space_round_trip.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/61_cell_paragraph_with_runs.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/62_many_cell_paragraphs.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/63_table_style_round_trip.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/64_many_sections.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/65_20x20_table_formatted.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/66_toc_like_structure.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/67_paragraph_insert_before_chain.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/68_invoice.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/69_newsletter.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/70_add_and_iterate_back.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/71_academic_paper.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/72_legal_contract.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/73_form_with_many_tables.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/74_paragraph_with_10_runs.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/75_paragraph_negative_first_line_indent.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/76_rgbcolor_from_string.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/77_length_unit_conversions.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/78_paragraph_copy_style.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/79_bulk_cell_formatting.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/80_apply_style_after_add_run.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/81_multi_page_with_breaks.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/82_add_text_on_existing_run.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/83_clear_then_repopulate_paragraph.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/84_table_reread_row_count.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/85_header_footer_access.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/86_font_read_unset_returns_none.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/87_500_paragraph_doc.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/88_mixed_content_iteration.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/89_alignment_clear_via_none.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/90_cell_add_paragraph_styled.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/91_many_small_tables.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/92_margins_every_section.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/93_font_bool_reads_after_set.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/94_page_break_before_paragraph.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/95_paragraph_hyperlinks_empty.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/96_paragraph_contains_page_break.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/97_document_styles_by_key.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/98_style_contains_check.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex02_unicode_everywhere.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex03_1000_paragraphs.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex04_50x50_table.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex05_long_text_in_cell.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex06_hundred_tiny_runs.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex07_every_font_boolean.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex08_many_continuous_sections.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex09_many_tab_stops.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex10_complex_bom.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex11_banded_rows_formatting.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex12_section_reconfigure.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex13_cell_with_10_paragraphs.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex14_styled_report_table.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex15_paragraph_all_format_props.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex16_runs_interleaved_with_breaks.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex17_all_break_kinds.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex18_read_back_large_doc.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex19_mutate_all_runs.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/ex20_kitchen_sink_v2.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/mega01_book_chapter.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/mega02_research_proposal.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/mega03_financial_statement.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/mega04_recipe_card.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/mega05_user_manual.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/mega06_complex_newsletter.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/mega07_budget_spreadsheet.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/mega08_product_catalog.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/mega09_signed_contract.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/mega10_api_documentation.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw01_official_quickstart.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw02_paragraph_style_list.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw03_character_formatting.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw04_section_page_setup.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw05_toc_pattern.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw06_meeting_minutes.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw07_dense_formatting_demo.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw08_table_merged_header.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw09_bulk_run_iteration.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw10_colored_grid_table.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw11_header_text.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw12_first_page_footer.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw13_even_page_header.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw15_paragraph_style_instance.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw16_header_footer_tables.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw17_header_letterhead_filled.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw18_header_table_properties.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw19_header_table_rows_columns.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/op_snapshots/rw20_header_table_merges.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/ours_spec.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/parity_crawl.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/parity_diff.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/real_world_cases.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/round_trip_tests.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/stock_spec.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fidelity/test_e2e_against_staging.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fixtures/field_reads.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fixtures/note_reference_reads.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fixtures/ruby_reads.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/fixtures/symbol_reads.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/live/__init__.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/live/reader.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/live/sdk_driver.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/live/stock_driver.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/parity/README.md +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/parity/__init__.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/parity/baseline_gaps.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/parity/compare.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/parity/intentional_deviations.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/parity/introspect.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/parity/reports/GAP_ANALYSIS.md +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/parity/reports/gap_report.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/parity/run_parity.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/parity/snapshots/athena_latest.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/parity/snapshots/upstream_python_docx_1.2.0.json +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/parity/test_parity_gap.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_add_section.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_add_section_extract_items.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_alignment_values.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_athena_extension_creates_session_open.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_athena_extensions_contract.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_athena_extensions_registry.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_batch_chunking.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_batching_perf.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_block_not_found_error.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_buffer.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_add_paragraph_wire_shape.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_add_table_not_supported.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_borders_spec.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_fastpath_runs.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_inner_add_hyperlink_stash.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_inner_add_run_via_cell_insert.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_inner_format_stash.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_inner_run_format_stash.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_merge.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_nested_tables.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_paragraphs_listed.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_text_plain_fastpath.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_cell_text_replace_semantics.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_citations.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_collapsed_range_format.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_color_format_theme.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_command_dataclasses.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_commands.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_comment_paragraphs.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_comments.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_comments_first_read.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_content_control_value.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_core_properties.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_document_asset_id_property.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_document_clear.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_document_create.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_document_create_from_template.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_document_factory_validation.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_docx_exec_lab.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_docx_exec_lab_server.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_e2e_partial_failure_cascade.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_empty_hyperlinks.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_execution_scope.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_export_docx_clean.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_export_rescue_anchors.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_field_reads_python_docx_parity.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_field_refresh.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_field_runs.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_find_replace_session_open.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_flushed_write_failures.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_http_transport.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_hyperlink_coalescing.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_image_url_data_uri.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_inline_page_break.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_inline_shape_alt_text.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_inline_shape_size.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_inline_shape_type.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_inline_shapes_floating.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_insert_deferred.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_iter_inner_content.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_line_clear_break.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_list_styles.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_merged_cell_secondary_slot.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_merged_cells.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_missing_modules.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_nested_table_refused.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_note_reference_reads_python_docx_parity.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_oxml_shim.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_page_break.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_paragraph_delete.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_paragraph_runs_hyperlinks.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_paragraph_text_len_cache.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_parity_round2.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_partial_failure_cascade.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_pdf_export_and_page_renders.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_phase_a_behavior.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_phase_b_headers_footers.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_phase_c_tables.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_positional_cell_id.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_postproc_cell_format_rewrite.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_postproc_cell_run_format_rewrite.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_postproc_ref_restore.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_pr19766_review_fixes.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_ptc.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_python_docx_api_parity.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_read_run_ranges.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_rendered_page_breaks.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_repeated_node_read.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_restart_numbering.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_revisions.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_round_trip_smoke_script.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_ruby_reads_python_docx_parity.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_run_add_picture_anchor.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_run_break_inner_content.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_run_edges.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_run_formatting_wire.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_run_later_runs.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_run_mark_inheritance.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_run_page_number_blocks.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_run_table_style_objects.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_run_text_python_docx.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_run_text_refreshes_paragraph.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_run_unmodeled_toggles.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_sdk_reads_served.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_section_read_lengths.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_add_paragraph_style.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_add_picture.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_add_run.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_cell_add_paragraph.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_comments_add_comment.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_comments_get.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_document_audit.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_document_element.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_enum_section.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_font_audit.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_header_footer.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_hyperlink.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_inline_shape.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_insert_paragraph_before.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_misc.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_paragraph_strict.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_paragraph_style.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_paragraph_style_strict.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_parfmt.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_row_col_cell.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_run_add_break.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_run_bool_setters.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_run_style.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_run_style_strict.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_run_text.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_run_underline.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_section_audit.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_section_dimensions.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_section_onoff.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_settings.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_shared_audit.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_style.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_styles.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_table_audit.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_table_cell.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_table_dimensions.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_silent_stub_table_layout.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_smoke_integration.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_style_acceptance.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_style_delete.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_style_font.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_style_formatting_writes.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_style_metadata_writes.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_style_names.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_style_setters_contract.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_style_tab_stops_read.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_symbol_reads_python_docx_parity.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_table_anchors.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_table_clears.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_table_direction.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_table_read_reuse.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_table_set_cell_perf.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_table_style_id_resolution.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_temporarily_unavailable.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_text_control_characters.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_tracked_revisions_offsets.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_uv_lock_version.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_validate_find_replace_asset_script.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_wire_contract.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_xml_attr_guard.py +0 -0
- {athena_python_docx-0.34.0 → athena_python_docx-0.36.0}/tests/test_zod_wire_contract.py +0 -0
|
@@ -121,6 +121,21 @@ pinned by focused tests and documented in
|
|
|
121
121
|
`horz_dpi`, `width`, `scaled_dimensions`, …). A picture in a table cell or
|
|
122
122
|
a header has no id to read its image by, so `.image` raises `ValueError`;
|
|
123
123
|
an older docx-studio does not report pictures, so they are not runs there.
|
|
124
|
+
`Run.add_picture` puts the picture in that run, as python-docx appends the
|
|
125
|
+
`w:drawing` to its `w:r`: after what the run holds, and text `add_text`
|
|
126
|
+
adds goes after it. Against a docx-studio that reports
|
|
127
|
+
`capabilities.pictureRuns`, `CreateImage` carries `runEdge: "append"` (the
|
|
128
|
+
run's identity as `add_text` names it), the run's record holds the picture
|
|
129
|
+
(`pictureRun`), and the run reads as one run whose pictures stand at their
|
|
130
|
+
places in its text (`pictures`), so `iter_inner_content()` yields its text
|
|
131
|
+
and each `Drawing` in order (with Word's rendered page breaks where the read
|
|
132
|
+
places them among the pictures, `afterPictures`), a whole-run format takes
|
|
133
|
+
its pictures too, and `run.text = ...` takes every one of them out
|
|
134
|
+
(`wholeRun`). A picture's run (no text) formats its picture at once, named
|
|
135
|
+
by its identity (`laterRuns`), so `r = p.add_run(); r.bold = True;
|
|
136
|
+
r.add_picture(img)` writes the bold `w:rPr` beside the `w:drawing`. An older
|
|
137
|
+
docx-studio puts the picture in a run of its own (`tests/test_drawing_image.py`,
|
|
138
|
+
battery `ab_probe/picture_runs.py`).
|
|
124
139
|
- **A run holding only a page or column break yields `""` from
|
|
125
140
|
`Run.iter_inner_content()`,** as python-docx reads a `w:br` of type `page`
|
|
126
141
|
or `column` as empty text; an empty run (a comment reference's) yields
|
|
@@ -1255,31 +1270,33 @@ architecture or a DOCX Studio constraint:
|
|
|
1255
1270
|
exported file. Against a docx-studio that predates `fieldRun` reads, a
|
|
1256
1271
|
field reads as no runs and no text, as before (`tests/test_field_runs.py`).
|
|
1257
1272
|
|
|
1258
|
-
- **A run that holds a page number block refuses
|
|
1259
|
-
page number block (`w:pgNum`) reads as a run with
|
|
1260
|
-
holds text and blocks (or two blocks) reads as
|
|
1261
|
-
whole-run format (`run.bold = True`, `run.font.*`,
|
|
1262
|
-
run) formats every piece of it, as python-docx formats
|
|
1263
|
-
|
|
1264
|
-
has none, and takes both as the run's text does. The first is a tracked
|
|
1265
|
-
format (`track_revisions`), which raises `DocxError` naming
|
|
1266
|
-
`TrackedChangesUnsupported`, because docx-studio records no tracked change
|
|
1267
|
-
on a block. The second is the on/off properties no editor mark holds
|
|
1273
|
+
- **A run that holds a page number block refuses a tracked whole-run format
|
|
1274
|
+
and two text writes.** A page number block (`w:pgNum`) reads as a run with
|
|
1275
|
+
no text, and a run that holds text and blocks (or two blocks) reads as
|
|
1276
|
+
python-docx's one run. A whole-run format (`run.bold = True`, `run.font.*`,
|
|
1277
|
+
a format of a block's run) formats every piece of it, as python-docx formats
|
|
1278
|
+
its `w:rPr`, the on/off properties no editor mark holds included
|
|
1268
1279
|
(`font.no_proof`, `snap_to_grid`, `web_hidden`, `spec_vanish`, `math`,
|
|
1269
|
-
`complex_script`, `cs_bold`, `cs_italic`)
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1280
|
+
`complex_script`, `cs_bold`, `cs_italic`). A tracked format
|
|
1281
|
+
(`track_revisions`) is refused while a block of the run has a node, and
|
|
1282
|
+
raises `DocxError` naming `TrackedChangesUnsupported`, because docx-studio
|
|
1283
|
+
records no tracked change on a block. A link's block has none, and takes it
|
|
1284
|
+
as the run's text does. In a document imported before docx-studio gave a
|
|
1285
|
+
block's node its run's properties (in October 2026, between the release that
|
|
1286
|
+
first read `w:pgNum` and the next), and in a comment, the on/off properties
|
|
1287
|
+
are refused too, in any format that reaches a block, and warn
|
|
1288
|
+
(`DocxUnsupportedCommandWarning`), because there a block keeps its source
|
|
1289
|
+
run's. python-docx writes both into the run's `w:rPr`. Made on the run's
|
|
1290
|
+
text alone, either would leave the run half formatted and split it in two
|
|
1274
1291
|
(`DOCX_STUDIO_LIMITATIONS.md` § 27). `run.text = …` and `clear()` replace
|
|
1275
1292
|
all of such a run, its blocks too, as upstream does: the SDK declares
|
|
1276
1293
|
`wholeRunPieces`, and renumbers the field runs it holds of the paragraph,
|
|
1277
1294
|
since each field after the blocks is numbered one lower for each
|
|
1278
1295
|
(`tests/test_run_page_number_blocks.py`). Two text writes are refused and
|
|
1279
|
-
warn (`DocxUnsupportedCommandWarning`), where upstream replaces the
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1296
|
+
warn (`DocxUnsupportedCommandWarning`), where upstream replaces the blocks:
|
|
1297
|
+
text written to a block's run (a run of blocks alone, or a lone block),
|
|
1298
|
+
which would move the text offsets the SDK keeps, and the text of a link's
|
|
1299
|
+
run that holds a block, which has no node to take out.
|
|
1283
1300
|
|
|
1284
1301
|
- **`Font.name = "…"` also clears the theme fonts of the two slots it
|
|
1285
1302
|
sets.** python-docx writes the name to `w:rFonts`' `w:ascii` and `w:hAnsi`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: athena-python-docx
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.36.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
|
|
@@ -0,0 +1,109 @@
|
|
|
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, tab
|
|
4
|
+
stops and the latent styles."""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import weakref
|
|
9
|
+
from collections.abc import Iterator
|
|
10
|
+
from typing import Any, Generic, TypeVar
|
|
11
|
+
|
|
12
|
+
_T = TypeVar("_T")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class IdentityWeakSet(Generic[_T]):
|
|
16
|
+
"""A set of objects held weakly, by identity: a ``weakref.WeakSet`` hashes
|
|
17
|
+
its members, and a proxy that compares by its element
|
|
18
|
+
(:class:`ElementProxyEquality`) is not hashable, as in python-docx."""
|
|
19
|
+
|
|
20
|
+
__slots__ = ("_members",)
|
|
21
|
+
|
|
22
|
+
def __init__(self) -> None:
|
|
23
|
+
self._members: "weakref.WeakValueDictionary[int, _T]" = weakref.WeakValueDictionary()
|
|
24
|
+
|
|
25
|
+
def add(self, item: _T) -> None:
|
|
26
|
+
self._members[id(item)] = item
|
|
27
|
+
|
|
28
|
+
def __iter__(self) -> Iterator[_T]:
|
|
29
|
+
return iter(list(self._members.values()))
|
|
30
|
+
|
|
31
|
+
def __len__(self) -> int:
|
|
32
|
+
return len(self._members)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class ElementProxyEquality:
|
|
36
|
+
"""python-docx's ``docx.shared.ElementProxy`` equality: two proxies of the
|
|
37
|
+
same element are equal (``paragraph.style == doc.styles["Heading 1"]``),
|
|
38
|
+
a proxy of another element or anything else is not, and, as python-docx
|
|
39
|
+
defines ``__eq__`` there, a proxy is not hashable.
|
|
40
|
+
|
|
41
|
+
The element is :meth:`_proxy_element`: the docx-studio object it stands
|
|
42
|
+
for, named as the XML element python-docx's proxy wraps (a style's
|
|
43
|
+
``w:style``, so a style, its font and its paragraph format are equal, as
|
|
44
|
+
they are in python-docx).
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
__slots__ = ()
|
|
48
|
+
|
|
49
|
+
def _proxy_element(self) -> tuple[object, ...]:
|
|
50
|
+
raise NotImplementedError
|
|
51
|
+
|
|
52
|
+
def __eq__(self, other: object) -> bool:
|
|
53
|
+
if not isinstance(other, ElementProxyEquality):
|
|
54
|
+
return False
|
|
55
|
+
return self._proxy_element() == other._proxy_element()
|
|
56
|
+
|
|
57
|
+
def __ne__(self, other: object) -> bool:
|
|
58
|
+
return not self.__eq__(other)
|
|
59
|
+
|
|
60
|
+
__hash__ = None # type: ignore[assignment]
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# Session -> style id -> the style definition that id names in the session's
|
|
64
|
+
# document now (:func:`style_definition`). Held weakly by session, as the
|
|
65
|
+
# run order is (``docx._run_order``); the document stores none of it.
|
|
66
|
+
_STYLE_DEFINITIONS: "weakref.WeakKeyDictionary[Any, dict[str, object]]" = weakref.WeakKeyDictionary()
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _definitions(session: object) -> "dict[str, object] | None":
|
|
70
|
+
if session is None:
|
|
71
|
+
return None
|
|
72
|
+
try:
|
|
73
|
+
return _STYLE_DEFINITIONS.setdefault(session, {})
|
|
74
|
+
except TypeError: # a session that takes no weak reference
|
|
75
|
+
return None
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def style_definition(session: object, style_id: str) -> object:
|
|
79
|
+
"""The style definition (its ``w:style`` element) that ``style_id`` names in
|
|
80
|
+
``session``'s document now, which a style proxy holds from its first read:
|
|
81
|
+
the same one after a rename (:func:`style_renamed`), another for a style
|
|
82
|
+
made after one of that id was deleted (:func:`style_deleted`)."""
|
|
83
|
+
definitions = _definitions(session)
|
|
84
|
+
if definitions is None:
|
|
85
|
+
return ("w:styleId", style_id)
|
|
86
|
+
return definitions.setdefault(style_id, object())
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def style_renamed(session: object, old: str, new: str) -> None:
|
|
90
|
+
"""``style_id`` renamed the definition ``old`` named to ``new``."""
|
|
91
|
+
definitions = _definitions(session)
|
|
92
|
+
if definitions is not None:
|
|
93
|
+
definitions[new] = definitions.pop(old, None) or object()
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def style_deleted(session: object, style_id: str) -> None:
|
|
97
|
+
"""``delete`` removed the definition ``style_id`` named."""
|
|
98
|
+
definitions = _definitions(session)
|
|
99
|
+
if definitions is not None:
|
|
100
|
+
definitions.pop(style_id, None)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def style_element(style: object) -> tuple[object, ...]:
|
|
104
|
+
"""The ``w:style`` element of ``style`` (a ``BaseStyle``): its document and
|
|
105
|
+
its definition (:func:`style_definition`), which a rename keeps."""
|
|
106
|
+
definition = getattr(style, "_definition", None)
|
|
107
|
+
if definition is None:
|
|
108
|
+
definition = ("w:styleId", getattr(style, "_style_id", None))
|
|
109
|
+
return ("w:style", getattr(style, "_session", None), definition)
|
|
@@ -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":
|
|
@@ -140,6 +140,10 @@ class CreateImage(Command):
|
|
|
140
140
|
at: dict[str, Any]
|
|
141
141
|
client_node_id: str | None = None
|
|
142
142
|
run: dict[str, Any] | None = None
|
|
143
|
+
# ``"append"`` (``Run.add_picture`` against a docx-studio that reports
|
|
144
|
+
# ``capabilities.pictureRuns``): the picture ends the run that ends at the
|
|
145
|
+
# anchor's offset, in that run's ``w:r``, as python-docx appends it.
|
|
146
|
+
run_edge: str | None = None
|
|
143
147
|
|
|
144
148
|
|
|
145
149
|
@dataclass
|
|
@@ -14,6 +14,8 @@ Phase 1 supported methods:
|
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
|
+
from docx._xml_text import check_xml_compatible
|
|
18
|
+
|
|
17
19
|
import base64
|
|
18
20
|
import os
|
|
19
21
|
import re
|
|
@@ -1789,6 +1791,7 @@ class Document:
|
|
|
1789
1791
|
Returns:
|
|
1790
1792
|
The newly-created Paragraph.
|
|
1791
1793
|
"""
|
|
1794
|
+
check_xml_compatible(text)
|
|
1792
1795
|
from docx.styles._table import paragraph_style_name
|
|
1793
1796
|
from docx.styles.style import ParagraphStyle
|
|
1794
1797
|
from docx.text.paragraph import Paragraph
|
|
@@ -2033,6 +2036,7 @@ class Document:
|
|
|
2033
2036
|
level: int = 1,
|
|
2034
2037
|
) -> "Paragraph":
|
|
2035
2038
|
"""Append a heading via DOCX Studio's canonical `doc.create.heading`."""
|
|
2039
|
+
check_xml_compatible(text)
|
|
2036
2040
|
from docx.text.paragraph import Paragraph
|
|
2037
2041
|
|
|
2038
2042
|
self._ensure_open()
|
|
@@ -92,6 +92,7 @@ _XML_ELEMENT_ATTRS: frozenset[str] = frozenset(
|
|
|
92
92
|
"_tc", # _Cell._tc
|
|
93
93
|
"_tbl", # Table._tbl
|
|
94
94
|
"_tr", # _Row._tr
|
|
95
|
+
"_t", # _Text._t (the ``w:t`` Run.add_text added)
|
|
95
96
|
"element", # Run.element / Paragraph.element / Document.element
|
|
96
97
|
"_element", # private alias used by some python-docx forks
|
|
97
98
|
},
|
|
@@ -11,6 +11,8 @@ or twip values depending on the op).
|
|
|
11
11
|
|
|
12
12
|
from __future__ import annotations
|
|
13
13
|
|
|
14
|
+
from docx._xml_text import check_xml_compatible
|
|
15
|
+
|
|
14
16
|
import warnings
|
|
15
17
|
from collections.abc import Sequence
|
|
16
18
|
from typing import TYPE_CHECKING
|
|
@@ -986,6 +988,7 @@ class _HeaderFooter(BlockItemContainer):
|
|
|
986
988
|
server turns tabs and line breaks in ``text`` into ``<w:tab/>`` /
|
|
987
989
|
``<w:br/>``, as python-docx's ``Run.text`` does.
|
|
988
990
|
"""
|
|
991
|
+
check_xml_compatible(text)
|
|
989
992
|
from docx.styles.style import ParagraphStyle
|
|
990
993
|
|
|
991
994
|
style_str: str | None
|
|
@@ -21,6 +21,7 @@ from __future__ import annotations
|
|
|
21
21
|
from typing import TYPE_CHECKING
|
|
22
22
|
|
|
23
23
|
from docx._batching import run_sync
|
|
24
|
+
from docx._proxy import ElementProxyEquality
|
|
24
25
|
|
|
25
26
|
if TYPE_CHECKING:
|
|
26
27
|
from docx.client import Session
|
|
@@ -38,7 +39,7 @@ class PendingSettingsMutationWarning(UserWarning):
|
|
|
38
39
|
"""
|
|
39
40
|
|
|
40
41
|
|
|
41
|
-
class Settings:
|
|
42
|
+
class Settings(ElementProxyEquality):
|
|
42
43
|
def __init__(
|
|
43
44
|
self,
|
|
44
45
|
*,
|
|
@@ -49,12 +50,16 @@ class Settings:
|
|
|
49
50
|
self._document: "Document | None" = document
|
|
50
51
|
self._odd_and_even_pages_header_footer: bool = False
|
|
51
52
|
|
|
53
|
+
def _proxy_element(self) -> tuple[object, ...]:
|
|
54
|
+
return ("w:settings", self._session)
|
|
55
|
+
|
|
52
56
|
@property
|
|
53
57
|
def odd_and_even_pages_header_footer(self) -> bool:
|
|
54
58
|
"""The document's ``w:evenAndOddHeaders`` in ``word/settings.xml``, as
|
|
55
59
|
python-docx reads it (False when absent or off). A docx-studio that
|
|
56
60
|
does not report it (``Info`` without ``settings``) gives the value this
|
|
57
61
|
proxy last set."""
|
|
62
|
+
self._open()
|
|
58
63
|
info: object = run_sync(self._session.doc.info({"includeSettings": True}))
|
|
59
64
|
settings: object = info.get("settings") if isinstance(info, dict) else None
|
|
60
65
|
reported: object = settings.get("evenAndOddHeaders") if isinstance(settings, dict) else None
|
|
@@ -65,6 +70,7 @@ class Settings:
|
|
|
65
70
|
@odd_and_even_pages_header_footer.setter
|
|
66
71
|
def odd_and_even_pages_header_footer(self, value: bool) -> None:
|
|
67
72
|
enabled = bool(value)
|
|
73
|
+
self._open()
|
|
68
74
|
run_sync(
|
|
69
75
|
self._session.doc.sections.set_odd_even_headers_footers(
|
|
70
76
|
{"enabled": enabled},
|
|
@@ -72,6 +78,14 @@ class Settings:
|
|
|
72
78
|
)
|
|
73
79
|
self._odd_and_even_pages_header_footer = enabled
|
|
74
80
|
|
|
81
|
+
def _open(self) -> None:
|
|
82
|
+
"""Open the document's session before a read or write of it, as every
|
|
83
|
+
member of ``Document`` that touches it does (``Document.create()``
|
|
84
|
+
returns before it opens). ``track_revisions`` needs no session: it
|
|
85
|
+
stays a local flag until one opens."""
|
|
86
|
+
if self._document is not None:
|
|
87
|
+
self._document._ensure_open()
|
|
88
|
+
|
|
75
89
|
# --- Track changes alias (Athena: forwards to Document.track_revisions) ---
|
|
76
90
|
|
|
77
91
|
@property
|
|
@@ -23,6 +23,7 @@ import warnings
|
|
|
23
23
|
import weakref
|
|
24
24
|
from typing import TYPE_CHECKING, Any, Iterator
|
|
25
25
|
|
|
26
|
+
from docx._proxy import ElementProxyEquality, IdentityWeakSet
|
|
26
27
|
from docx.styles import BabelFish
|
|
27
28
|
|
|
28
29
|
if TYPE_CHECKING:
|
|
@@ -52,12 +53,12 @@ _XML_INCOMPATIBLE_MESSAGE = (
|
|
|
52
53
|
# Session -> every live ``_LatentStyle``, read or added: deleting one moves the
|
|
53
54
|
# others of its name after it up one place (:func:`_removed`), as python-docx's
|
|
54
55
|
# are elements a deletion elsewhere does not move. The sets hold them weakly.
|
|
55
|
-
_LIVE: "weakref.WeakKeyDictionary[Any,
|
|
56
|
+
_LIVE: "weakref.WeakKeyDictionary[Any, IdentityWeakSet[_LatentStyle]]" = weakref.WeakKeyDictionary()
|
|
56
57
|
|
|
57
58
|
|
|
58
59
|
def _track(latent_style: "_LatentStyle") -> None:
|
|
59
60
|
try:
|
|
60
|
-
_LIVE.setdefault(latent_style._session,
|
|
61
|
+
_LIVE.setdefault(latent_style._session, IdentityWeakSet()).add(latent_style)
|
|
61
62
|
except TypeError: # no session, or one that takes no weak reference
|
|
62
63
|
return
|
|
63
64
|
|
|
@@ -67,6 +68,7 @@ def _removed(deleted: "_LatentStyle", name: Any) -> None:
|
|
|
67
68
|
that name after it move up one place, and another object of the same
|
|
68
69
|
exception is out of the document, writing nothing to it, as python-docx's
|
|
69
70
|
removed element is."""
|
|
71
|
+
deleted._element = removed = object()
|
|
70
72
|
try:
|
|
71
73
|
live = _LIVE.get(deleted._session)
|
|
72
74
|
except TypeError:
|
|
@@ -78,6 +80,7 @@ def _removed(deleted: "_LatentStyle", name: Any) -> None:
|
|
|
78
80
|
continue
|
|
79
81
|
if other._occurrence == deleted._occurrence:
|
|
80
82
|
other._detached = True
|
|
83
|
+
other._element = removed
|
|
81
84
|
elif other._occurrence > deleted._occurrence:
|
|
82
85
|
other._occurrence -= 1
|
|
83
86
|
|
|
@@ -140,13 +143,17 @@ def _int(text: object) -> int | None:
|
|
|
140
143
|
return None
|
|
141
144
|
|
|
142
145
|
|
|
143
|
-
class LatentStyles:
|
|
146
|
+
class LatentStyles(ElementProxyEquality):
|
|
144
147
|
"""The default behaviors for latent styles in this document, and the
|
|
145
148
|
|_LatentStyle| objects that override them for a named latent style."""
|
|
146
149
|
|
|
147
150
|
def __init__(self, *, session: "Session | None" = None) -> None:
|
|
148
151
|
self._session: "Session | None" = session
|
|
149
152
|
|
|
153
|
+
def _proxy_element(self) -> tuple[object, ...]:
|
|
154
|
+
# python-docx's LatentStyles wraps the styles part's w:latentStyles.
|
|
155
|
+
return ("w:latentStyles", self._session)
|
|
156
|
+
|
|
150
157
|
def _read(self, prop: str | None) -> dict[str, Any]:
|
|
151
158
|
"""The latent styles docx-studio reports; a read of ``prop`` from one
|
|
152
159
|
that reports none warns (iterating, an empty collection, does not)."""
|
|
@@ -246,7 +253,7 @@ class LatentStyles:
|
|
|
246
253
|
self._set_default("load_count", "count", None if value is None else int(value))
|
|
247
254
|
|
|
248
255
|
|
|
249
|
-
class _LatentStyle:
|
|
256
|
+
class _LatentStyle(ElementProxyEquality):
|
|
250
257
|
"""A ``w:lsdException``: display behaviors for a built-in style the
|
|
251
258
|
document does not define yet, overriding the |LatentStyles| defaults."""
|
|
252
259
|
|
|
@@ -260,8 +267,18 @@ class _LatentStyle:
|
|
|
260
267
|
#: Removed through another object of the same exception: like
|
|
261
268
|
#: python-docx's element out of the part, it writes nothing to the document.
|
|
262
269
|
self._detached = False
|
|
270
|
+
#: The exception it held once removed, which its other objects hold too.
|
|
271
|
+
self._element: object | None = None
|
|
263
272
|
_track(self)
|
|
264
273
|
|
|
274
|
+
def _proxy_element(self) -> tuple[object, ...]:
|
|
275
|
+
# python-docx's _LatentStyle wraps its w:lsdException: the exception
|
|
276
|
+
# of its name at its place among them, or, removed, that exception, as
|
|
277
|
+
# its other objects are.
|
|
278
|
+
if self._detached or self._exception is None:
|
|
279
|
+
return ("w:lsdException", self._element if self._element is not None else id(self))
|
|
280
|
+
return ("w:lsdException", self._session, self._exception.get("name"), self._occurrence)
|
|
281
|
+
|
|
265
282
|
def _target(self) -> dict[str, Any]:
|
|
266
283
|
"""The exception's address in ``EditLatentStyles``."""
|
|
267
284
|
name = self._exception.get("name")
|