athena-python-docx 0.28.0__tar.gz → 0.29.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.28.0 → athena_python_docx-0.29.0}/AGENTS.md +113 -36
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/PKG-INFO +1 -1
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/__init__.py +1 -1
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/_buffer.py +49 -12
- athena_python_docx-0.29.0/docx/_capabilities.py +38 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/_http_doc.py +239 -26
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/_run_order.py +149 -3
- athena_python_docx-0.29.0/docx/_tracked.py +29 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/bookmarks.py +13 -9
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/commands.py +72 -16
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/comments.py +131 -44
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/document.py +107 -39
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/enum/shape.py +6 -2
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/errors.py +19 -3
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/fields.py +17 -3
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/sdt.py +19 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/section.py +90 -79
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/shape.py +52 -4
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/table.py +239 -56
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/text/paragraph.py +118 -12
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/text/run.py +168 -31
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/pyproject.toml +1 -1
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/ab_probe_cases.py +21 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/15_run_add_break_page.json +1 -0
- athena_python_docx-0.29.0/tests/fidelity/op_snapshots/54_empty_everything.json +6 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/56_everything_in_one.json +2 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/96_paragraph_contains_page_break.json +1 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/99_run_add_picture_from_bytes.json +1 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/ex16_runs_interleaved_with_breaks.json +1 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/ex17_all_break_kinds.json +1 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/ex20_kitchen_sink_v2.json +7 -0
- athena_python_docx-0.29.0/tests/fidelity/op_snapshots/rw16_header_footer_tables.json +15 -0
- athena_python_docx-0.29.0/tests/fidelity/op_snapshots/rw17_header_letterhead_filled.json +21 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/real_world_cases.py +34 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fixtures/note_reference_reads.json +71 -1
- athena_python_docx-0.29.0/tests/fixtures/ruby_reads.json +204 -0
- athena_python_docx-0.29.0/tests/fixtures/symbol_reads.json +163 -0
- athena_python_docx-0.29.0/tests/live/baseline.json +262 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/live/reader.py +12 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/live/runner.py +51 -9
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/live/test_live_runner.py +28 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/parity/intentional_deviations.json +49 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_batch_chunking.py +166 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_cell_fastpath_runs.py +5 -1
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_cell_paragraphs_listed.py +1 -0
- athena_python_docx-0.29.0/tests/test_comment_paragraphs.py +184 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_comments.py +17 -9
- athena_python_docx-0.29.0/tests/test_content_control_value.py +75 -0
- athena_python_docx-0.29.0/tests/test_empty_hyperlinks.py +91 -0
- athena_python_docx-0.29.0/tests/test_export_docx_clean.py +138 -0
- athena_python_docx-0.29.0/tests/test_field_refresh.py +32 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_field_runs.py +5 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_http_transport.py +5 -1
- athena_python_docx-0.29.0/tests/test_inline_page_break.py +70 -0
- athena_python_docx-0.29.0/tests/test_inline_shape_type.py +95 -0
- athena_python_docx-0.29.0/tests/test_inline_shapes_floating.py +60 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_note_reference_reads_python_docx_parity.py +9 -5
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_parity_misc.py +2 -2
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_phase_b_headers_footers.py +110 -2
- athena_python_docx-0.29.0/tests/test_read_run_ranges.py +153 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_revisions.py +55 -1
- athena_python_docx-0.29.0/tests/test_ruby_reads_python_docx_parity.py +192 -0
- athena_python_docx-0.29.0/tests/test_run_edges.py +138 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_run_identity.py +1 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_run_mark_inheritance.py +88 -42
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_document_audit.py +44 -54
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_header_footer.py +32 -17
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_misc.py +7 -13
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_table_audit.py +93 -0
- athena_python_docx-0.29.0/tests/test_symbol_reads_python_docx_parity.py +122 -0
- athena_python_docx-0.29.0/tests/test_table_read_reuse.py +266 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_text_control_characters.py +11 -5
- athena_python_docx-0.29.0/tests/test_tracked_revisions_offsets.py +170 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_wire_contract.py +6 -1
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/uv.lock +1 -1
- athena_python_docx-0.28.0/tests/fidelity/op_snapshots/54_empty_everything.json +0 -4
- athena_python_docx-0.28.0/tests/live/baseline.json +0 -1925
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/.gitignore +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/CLAUDE.md +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/DOCX_EXEC_LAB.md +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/README.md +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/_athena_extension.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/_batching.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/_citations.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/_execution.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/_http.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/_image_utils.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/_postproc.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/_ptc.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/_references.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/_table_styles.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/_timeouts.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/api.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/blkcntnr.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/charts.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/client.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/drawing/__init__.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/enum/__init__.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/enum/base.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/enum/dml.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/enum/section.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/enum/style.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/enum/table.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/enum/text.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/exceptions.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/footnotes.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/image/__init__.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/image/exceptions.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/image/image.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/math.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/opc/__init__.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/opc/coreprops.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/oxml/__init__.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/revisions.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/session.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/settings.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/shared.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/styles/__init__.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/styles/_table.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/styles/latent.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/styles/style.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/styles/styles.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/text/__init__.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/text/font.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/text/hyperlink.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/text/pagebreak.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/text/parfmt.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/text/tabstops.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/toc.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/docx/typing.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/scripts/docx_exec_lab.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/scripts/docx_exec_lab_examples/fast_table_fill.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/scripts/docx_exec_lab_examples/find_replace_literal.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/scripts/docx_exec_lab_server.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/scripts/dump_wire_fixtures.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/scripts/release.sh +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/scripts/round_trip_smoke.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/scripts/smoke_test_block_not_found.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/scripts/validate_find_replace_asset.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/__init__.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/conftest.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/METHODOLOGY.md +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/README.md +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/__init__.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/ab_probe_runner.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/auto_gen_cases.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/binary_round_trip.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/cases.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/complex_cases.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/coverage_report.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/extract.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/extreme_cases.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/fake_session.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/firm_templates/README.md +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/firm_templates/__init__.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/firm_templates/_runner.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/firm_templates/extractor.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/firm_templates/test_pw_corpus.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/firm_templates/test_pw_research_digest.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/local_runner.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/mega_cases.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshot.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/01_basic_paragraph.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/02_multiple_headings.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/03_runs_with_formatting.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/04_font_name_and_size.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/05_font_color_rgb.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/06_font_character_properties.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/07_font_subscript_superscript.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/08_font_highlight.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/09_paragraph_alignment.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/100_table_negative_indexing.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/101_table_cells_flat_iteration.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/102_text_with_embedded_special_chars.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/104_core_properties_datetime.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/105_default_one_section.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/106_heading_paragraph_format.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/107_varying_row_heights.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/10_paragraph_indents.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/11_paragraph_spacing.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/12_paragraph_keep_options.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/13_paragraph_tab_stops.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/14_run_add_tab_and_break.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/16_paragraph_clear_and_insert_before.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/17_table_basic.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/18_table_cell_text.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/19_table_row_column_sizing.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/20_table_cell_vertical_alignment.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/21_table_alignment_and_autofit.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/22_table_cell_paragraphs_iteration.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/24_table_add_row_column.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/25_table_merge_cells.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/26_section_page_setup.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/27_section_margins.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/28_section_add_new.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/29_section_headers_linked.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/30_styles_iteration.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/31_styles_lookup_and_default.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/32_styles_add_paragraph_style.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/33_core_properties_set_and_get.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/34_inline_shapes_iterate_empty.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/35_full_report.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/36_replace_text_in_paragraph.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/37_iterate_runs_and_format_all_bold.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/38_font_all_properties.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/39_large_body_100_paragraphs.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/40_large_table_10x10.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/41_unicode_and_emoji.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/42_very_long_paragraph.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/43_paragraph_text_round_trip.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/44_paragraph_alignment_round_trip.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/45_cell_text_round_trip.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/46_run_text_setter_round_trip.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/47_font_size_round_trip.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/48_font_color_round_trip.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/49_resume_layout.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/50_multi_section_doc.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/52_iterate_everything.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/53_apply_style_to_paragraphs.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/55_single_character_runs.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/57_runs_after_multiple_text_appends.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/58_modify_runs_in_place.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/59_indent_round_trip.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/60_space_round_trip.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/61_cell_paragraph_with_runs.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/62_many_cell_paragraphs.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/63_table_style_round_trip.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/64_many_sections.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/65_20x20_table_formatted.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/66_toc_like_structure.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/67_paragraph_insert_before_chain.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/68_invoice.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/69_newsletter.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/70_add_and_iterate_back.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/71_academic_paper.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/72_legal_contract.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/73_form_with_many_tables.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/74_paragraph_with_10_runs.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/75_paragraph_negative_first_line_indent.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/76_rgbcolor_from_string.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/77_length_unit_conversions.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/78_paragraph_copy_style.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/79_bulk_cell_formatting.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/80_apply_style_after_add_run.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/81_multi_page_with_breaks.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/82_add_text_on_existing_run.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/83_clear_then_repopulate_paragraph.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/84_table_reread_row_count.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/85_header_footer_access.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/86_font_read_unset_returns_none.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/87_500_paragraph_doc.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/88_mixed_content_iteration.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/89_alignment_clear_via_none.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/90_cell_add_paragraph_styled.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/91_many_small_tables.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/92_margins_every_section.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/93_font_bool_reads_after_set.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/94_page_break_before_paragraph.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/95_paragraph_hyperlinks_empty.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/97_document_styles_by_key.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/98_style_contains_check.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/ex02_unicode_everywhere.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/ex03_1000_paragraphs.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/ex04_50x50_table.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/ex05_long_text_in_cell.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/ex06_hundred_tiny_runs.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/ex07_every_font_boolean.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/ex08_many_continuous_sections.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/ex09_many_tab_stops.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/ex10_complex_bom.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/ex11_banded_rows_formatting.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/ex12_section_reconfigure.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/ex13_cell_with_10_paragraphs.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/ex14_styled_report_table.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/ex15_paragraph_all_format_props.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/ex18_read_back_large_doc.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/ex19_mutate_all_runs.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/mega01_book_chapter.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/mega02_research_proposal.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/mega03_financial_statement.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/mega04_recipe_card.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/mega05_user_manual.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/mega06_complex_newsletter.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/mega07_budget_spreadsheet.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/mega08_product_catalog.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/mega09_signed_contract.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/mega10_api_documentation.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/rw01_official_quickstart.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/rw02_paragraph_style_list.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/rw03_character_formatting.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/rw04_section_page_setup.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/rw05_toc_pattern.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/rw06_meeting_minutes.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/rw07_dense_formatting_demo.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/rw08_table_merged_header.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/rw09_bulk_run_iteration.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/rw10_colored_grid_table.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/rw11_header_text.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/rw12_first_page_footer.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/rw13_even_page_header.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/op_snapshots/rw15_paragraph_style_instance.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/ours_spec.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/parity_crawl.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/parity_diff.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/round_trip_tests.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/stock_spec.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fidelity/test_e2e_against_staging.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/fixtures/field_reads.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/live/__init__.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/live/sdk_driver.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/live/stock_driver.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/parity/README.md +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/parity/__init__.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/parity/baseline_gaps.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/parity/compare.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/parity/introspect.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/parity/reports/GAP_ANALYSIS.md +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/parity/reports/gap_report.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/parity/run_parity.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/parity/snapshots/athena_latest.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/parity/snapshots/upstream_python_docx_1.2.0.json +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/parity/test_parity_gap.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_add_section.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_add_section_extract_items.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_athena_extension_creates_session_open.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_athena_extensions_contract.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_athena_extensions_registry.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_batching_perf.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_block_not_found_error.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_buffer.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_cell_add_paragraph_wire_shape.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_cell_add_table_not_supported.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_cell_borders_spec.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_cell_inner_add_hyperlink_stash.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_cell_inner_add_run_via_cell_insert.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_cell_inner_format_stash.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_cell_inner_run_format_stash.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_cell_inner_run_guard.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_cell_merge.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_cell_text_plain_fastpath.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_cell_text_replace_semantics.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_citations.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_collapsed_range_format.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_color_format_theme.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_command_dataclasses.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_commands.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_core_properties.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_document_asset_id_property.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_document_clear.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_document_create.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_document_create_from_template.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_document_factory_validation.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_docx_exec_lab.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_docx_exec_lab_server.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_drawing_image.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_e2e_partial_failure_cascade.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_enum_parity.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_execution_scope.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_field_reads_python_docx_parity.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_find_replace_session_open.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_hyperlink_coalescing.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_image_url_data_uri.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_inline_shape_alt_text.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_inline_shape_size.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_insert_deferred.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_iter_inner_content.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_list_styles.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_merged_cell_secondary_slot.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_merged_cells.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_missing_modules.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_oxml_shim.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_page_break.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_paragraph_runs_hyperlinks.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_paragraph_text_len_cache.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_parity_round2.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_partial_failure_cascade.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_pdf_export_and_page_renders.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_phase_a_behavior.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_phase_c_tables.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_positional_cell_id.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_postproc_cell_format_rewrite.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_postproc_cell_run_format_rewrite.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_postproc_ref_restore.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_pr19766_review_fixes.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_ptc.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_python_docx_api_parity.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_repeated_node_read.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_restart_numbering.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_round_trip_smoke_script.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_run_add_picture_anchor.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_run_formatting_wire.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_run_table_style_objects.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_run_text_python_docx.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_run_text_refreshes_paragraph.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_sdk_reads_served.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_section_read_lengths.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_add_paragraph_style.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_add_picture.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_add_run.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_cell_add_paragraph.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_comments_add_comment.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_comments_get.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_document_element.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_enum_section.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_font_audit.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_hyperlink.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_inline_shape.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_insert_paragraph_before.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_paragraph_strict.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_paragraph_style.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_paragraph_style_strict.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_parfmt.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_row_col_cell.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_run_add_break.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_run_bool_setters.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_run_style.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_run_style_strict.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_run_text.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_run_underline.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_section_audit.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_section_dimensions.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_section_onoff.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_settings.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_shared_audit.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_style.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_styles.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_table_cell.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_table_dimensions.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_silent_stub_table_layout.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_smoke_integration.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_style_acceptance.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_style_font.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_style_formatting_writes.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_style_metadata_writes.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_style_names.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_style_setters_contract.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_table_set_cell_perf.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_table_style_id_resolution.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_temporarily_unavailable.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_uv_lock_version.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_validate_find_replace_asset_script.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_xml_attr_guard.py +0 -0
- {athena_python_docx-0.28.0 → athena_python_docx-0.29.0}/tests/test_zod_wire_contract.py +0 -0
|
@@ -40,12 +40,14 @@ These standard python-docx members don't apply to a DOCX Studio-backed SDK:
|
|
|
40
40
|
- `Document.part`, `Paragraph.part`, `Run.part` — package part access
|
|
41
41
|
- `Document.settings` — Word app settings (not surfaced by DOCX Studio)
|
|
42
42
|
- `InlineShape.chart` — charts are not currently surfaced by the SDK.
|
|
43
|
-
- `Comment.
|
|
44
|
-
`Comment
|
|
45
|
-
`
|
|
46
|
-
`
|
|
47
|
-
|
|
48
|
-
`
|
|
43
|
+
- `Comment.add_table` / `Comment.tables` — a DOCX Studio comment holds
|
|
44
|
+
paragraphs only. `Comment` is a `docx.blkcntnr.BlockItemContainer`, as
|
|
45
|
+
`_Cell` and the header/footer proxies are: `paragraphs`,
|
|
46
|
+
`add_paragraph`, `iter_inner_content` and `text` work as in python-docx
|
|
47
|
+
1.2.0 (the paragraphs list the comment's story, `blocks.list` with
|
|
48
|
+
`in: {storyType: "comment"}`, and `add_paragraph` sends
|
|
49
|
+
`CommentsParagraphAppend`), while `tables` is empty and `add_table`
|
|
50
|
+
raises `CommentsNotImplementedError`.
|
|
49
51
|
- **`_Cell.add_table(rows, cols)`** — surface preserved for parity
|
|
50
52
|
(signature matches python-docx, no `width` kwarg) but raises
|
|
51
53
|
:class:`docx.errors.NestedTableNotSupportedError` (subclass of
|
|
@@ -188,22 +190,33 @@ not file-backed. Each is documented in the relevant docstring.
|
|
|
188
190
|
on the other studios: `Workbook.workbook_id` (xlsx) and
|
|
189
191
|
`Presentation.deck_id` (pptx).
|
|
190
192
|
|
|
191
|
-
- **`Document.save(path_or_stream=None)`** — argument is optional
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
193
|
+
- **`Document.save(path_or_stream=None)`** — the argument is optional.
|
|
194
|
+
Stock python-docx requires it and `TypeError`s on no-arg, but writes
|
|
195
|
+
are always in place against the Y.Doc, and forcing the upstream
|
|
196
|
+
signature broke every agent invocation that reflexively called
|
|
197
|
+
`doc.save()`, so the no-arg form flushes and writes no file. With a
|
|
198
|
+
path (`str` or `os.PathLike`) or a binary stream, `save` also writes
|
|
199
|
+
the document's `.docx` there, as python-docx does, through
|
|
200
|
+
`export_docx` (0.29.0+; earlier versions raised
|
|
201
|
+
`LocalSaveTargetNotSupportedError`, which stays importable).
|
|
202
|
+
|
|
203
|
+
- **`Document.track_revisions: bool`** — when `True`, subsequent batches
|
|
204
|
+
are sent with `changeMode: "tracked"`, and docx-studio records their text
|
|
205
|
+
edits as Word revisions (`w:ins` / `w:del`): run and paragraph text,
|
|
206
|
+
`find_replace` in the body, new paragraphs and headings (an inserted
|
|
207
|
+
paragraph mark), tabs and line breaks, run formatting (`w:rPrChange`) and
|
|
208
|
+
`paragraph_format` properties (`w:pPrChange`). The replaced text stays, deleted,
|
|
209
|
+
and the new text follows it, so the SDK keeps its paragraph lengths and
|
|
210
|
+
run ranges that way (`docx/_tracked.py`): a tracked `run.text = value`
|
|
211
|
+
leaves the run over `value`, after its deleted text, and the paragraph
|
|
212
|
+
grows by `len(value)`. Every batch says so to docx-studio
|
|
213
|
+
(`client.capabilities: ["trackedAuthoring"]`); a docx-studio refuses a
|
|
214
|
+
tracked edit from an SDK that does not. A batch holding an edit it cannot
|
|
215
|
+
record yet (paragraph styles, tables, pictures, lists, sections, notes,
|
|
216
|
+
page breaks, header/footer/comment text) is refused (HTTP 422,
|
|
217
|
+
`TrackedChangesUnsupported`) and applies nothing; reads, exports,
|
|
218
|
+
comments and `TrackChangesDecide` run either way
|
|
219
|
+
(`DOCX_STUDIO_LIMITATIONS.md` § 32).
|
|
207
220
|
python-docx upstream has no top-level toggle (the closest is
|
|
208
221
|
hand-edited `<w:trackChanges/>` on `Document.settings.element`).
|
|
209
222
|
We expose this as a Document-level property because every DOCX Studio
|
|
@@ -219,10 +232,12 @@ not file-backed. Each is documented in the relevant docstring.
|
|
|
219
232
|
because the upstream package has no track-changes API at all.
|
|
220
233
|
|
|
221
234
|
- **`Document.user_name: str | None` / `Document.user_email: str |
|
|
222
|
-
None`** —
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
235
|
+
None`** — the name sent with each batch, which DOCX Studio uses as the
|
|
236
|
+
author of a comment that names none. It is not a tracked change's author:
|
|
237
|
+
DOCX Studio stamps those with the signed-in user agora's access check
|
|
238
|
+
names, so a script cannot choose who a redline's changes are by.
|
|
239
|
+
Separate from `Document.core_properties.last_modified_by`, the
|
|
240
|
+
`docProps/core.xml` metadata the SDK reads and writes as python-docx
|
|
226
241
|
does.
|
|
227
242
|
|
|
228
243
|
- **`Document.revisions: Revisions`** — collection of tracked changes
|
|
@@ -278,9 +293,10 @@ Issue numbers reference `python-openxml/python-docx`.
|
|
|
278
293
|
`"FILENAME"`, `"NUMWORDS"`, `"REF"`, `"SEQ"`, `"TOC"`, and the
|
|
279
294
|
generic `"FIELD"` escape hatch. python-docx has no field API
|
|
280
295
|
whatsoever; issue #498 (page numbers) and #31 (23 comments) demand
|
|
281
|
-
this. `Fields` is sequence-like; `Fields.refresh_all(scope?)`
|
|
282
|
-
|
|
283
|
-
|
|
296
|
+
this. `Fields` is sequence-like; `Fields.refresh_all(scope?)` updates
|
|
297
|
+
every unlocked REF and SEQ result as Word's F9 does (PAGE, PAGEREF
|
|
298
|
+
and TOC results depend on pages and stay). Routes through
|
|
299
|
+
`CreateField` / `FieldsRefresh` / `FieldsList`.
|
|
284
300
|
|
|
285
301
|
- **`Document.bookmarks: Bookmarks`** + **`Paragraph.add_bookmark
|
|
286
302
|
(name)`** + **`Document.add_bookmark(name, *, paragraph=None,
|
|
@@ -611,12 +627,10 @@ Issue numbers reference `python-openxml/python-docx`.
|
|
|
611
627
|
|
|
612
628
|
- **`Document.export_docx(path=None, *, include_revisions=False)
|
|
613
629
|
-> bytes`** (0.11.4+) — export the document's current state as
|
|
614
|
-
``.docx`` bytes, optionally writing to ``path
|
|
615
|
-
|
|
616
|
-
``
|
|
617
|
-
|
|
618
|
-
diff against ``python-docx`` output that doesn't require a
|
|
619
|
-
human-driven Olympus UI action. Routes through ``ExportDocx`` →
|
|
630
|
+
``.docx`` bytes, optionally writing to ``path``; ``Document.save(path_or_stream)``
|
|
631
|
+
writes its file through it. Parity test harnesses and CI workflows
|
|
632
|
+
use it to diff against ``python-docx`` output without a human-driven
|
|
633
|
+
Olympus UI action. Routes through ``ExportDocx`` →
|
|
620
634
|
apps/api's backend export path. apps/api
|
|
621
635
|
writes the session state to a temp ``.docx``, reads bytes back,
|
|
622
636
|
base64-encodes for the wire, and unlinks the temp in a
|
|
@@ -625,6 +639,26 @@ Issue numbers reference `python-openxml/python-docx`.
|
|
|
625
639
|
the current backend export path has no ``includeRevisions`` support,
|
|
626
640
|
so honoring the flag isn't possible yet.
|
|
627
641
|
|
|
642
|
+
``export_docx(path=None, *, include_revisions=False, clean=False,
|
|
643
|
+
clear_title=False)`` (0.29.0+): called with ``clean=True`` it returns a
|
|
644
|
+
clean copy for sending outside the firm instead, from
|
|
645
|
+
``GET /docs/:id/export.docx?clean=1`` (VIEW gate): docx-studio imports
|
|
646
|
+
the export into an in-memory room, accepts every tracked change and
|
|
647
|
+
deletes every comment through the command runner, exports that room and
|
|
648
|
+
leaves out the author, last-modified-by, revision, company, manager,
|
|
649
|
+
template, editing-time and hyperlink-base properties, rsids, document
|
|
650
|
+
variables, custom properties, Custom XML (a content control bound to it
|
|
651
|
+
keeps its content, not its binding), the attached template and the
|
|
652
|
+
thumbnail; ``clear_title=True`` drops the title too. The live document is
|
|
653
|
+
not changed. The SDK refuses (``DocxUnsupportedCommandError``) an answer
|
|
654
|
+
without ``X-Docx-Clean-Copy: 1``, the plain export an older docx-studio
|
|
655
|
+
sends, and raises ``DocxError`` with docx-studio's reason when a header,
|
|
656
|
+
footer or note still holds a tracked change (the engine accepts the
|
|
657
|
+
body's only; ``DOCX_STUDIO_LIMITATIONS.md`` § 31). The in-process
|
|
658
|
+
post-export rewrites are applied to a clean copy as to a plain export,
|
|
659
|
+
and the copy is refused (``DocxError``) if they put revision, comment or
|
|
660
|
+
rsid markup back into ``word/document.xml``.
|
|
661
|
+
|
|
628
662
|
Template seeding: ``Document.create()`` (no ``docx=``) already
|
|
629
663
|
produces an exportable asset because ``POST /docs/empty`` seeds
|
|
630
664
|
from the default Athena template, so ``export_docx`` works
|
|
@@ -915,6 +949,18 @@ architecture or a DOCX Studio constraint:
|
|
|
915
949
|
but DOCX Studio's ProseMirror table node can't represent one; the SDK
|
|
916
950
|
raises eagerly rather than failing opaquely on the wire.
|
|
917
951
|
|
|
952
|
+
- **`Document.add_table` writes Athena's brand table.** Owner decision
|
|
953
|
+
(2026-10-12): keep the brand defaults. The table's layout is fixed, so
|
|
954
|
+
`Table.autofit` reads `False` (python-docx leaves autofit on); its columns
|
|
955
|
+
share 9,360 twips, where python-docx shares the section's text width; and
|
|
956
|
+
in the fixed layout a column width the script sets sizes the column's
|
|
957
|
+
cells too, where python-docx sets the `w:gridCol` alone. It also draws
|
|
958
|
+
borders and a zebra fill, which no python-docx read sees. Recorded as
|
|
959
|
+
`live_deviations` for the script cases' `tables.autofit`, `tables.widths`
|
|
960
|
+
and `tables.cell_format` in `tests/parity/intentional_deviations.json`;
|
|
961
|
+
an imported table's gaps stay gaps, and so do the two cases whose
|
|
962
|
+
`cell_format` also differs for another cause (`except`).
|
|
963
|
+
|
|
918
964
|
- **`_Cell.merge` raises `InvalidSpanError` for every span that would cut
|
|
919
965
|
through a merged cell.** It merges what python-docx merges and refuses
|
|
920
966
|
what python-docx refuses (an L- or T-shaped pair of corners), but where
|
|
@@ -953,6 +999,18 @@ architecture or a DOCX Studio constraint:
|
|
|
953
999
|
Keryx attributes the edit to the signed-in user (and agent), and
|
|
954
1000
|
nothing reads a comment's author as identity.
|
|
955
1001
|
|
|
1002
|
+
- **A comment's paragraphs are in Word's comment style, which the export
|
|
1003
|
+
defines.** python-docx 1.2.0's `add_comment` and `Comment.add_paragraph`
|
|
1004
|
+
write `w:pStyle CommentText` (Word's built-in "annotation text", Comment
|
|
1005
|
+
Text in Word's UI) without defining the style in `styles.xml`, so
|
|
1006
|
+
python-docx reads those paragraphs as Normal. docx-studio writes the same
|
|
1007
|
+
`w:pStyle` and defines the style as Word does: `Comment.paragraphs[i].style`
|
|
1008
|
+
reads `Comment Text` (a built-in the document lacks reads back as that
|
|
1009
|
+
built-in, as above), and the export adds Word's definition of the style and
|
|
1010
|
+
of its linked `Comment Text Char` to `styles.xml`, so python-docx reads the
|
|
1011
|
+
exported paragraph as `annotation text`. Owner decision, 2026-10-12.
|
|
1012
|
+
Recorded in `tests/parity/intentional_deviations.json` (`live_deviations`).
|
|
1013
|
+
|
|
956
1014
|
- **`ParagraphFormat.line_spacing_rule = None` warns-and-preserves on a
|
|
957
1015
|
clear** rather than raising (upstream accepts `None` to clear, but DOCX
|
|
958
1016
|
Studio's merging mutation ops have no single-attribute clear). It emits a
|
|
@@ -970,7 +1028,17 @@ architecture or a DOCX Studio constraint:
|
|
|
970
1028
|
given. `Run.add_tab()` and `Run.add_break()` take the run's formatting, as
|
|
971
1029
|
upstream appends them to the run's `w:r`; `Run.add_break(WD_BREAK.COLUMN)`
|
|
972
1030
|
sends a column break (`breakType: "column"`), which docx-studio writes after
|
|
973
|
-
the paragraph's content. `DOCX_STUDIO_LIMITATIONS.md` §26.
|
|
1031
|
+
the paragraph's content. `DOCX_STUDIO_LIMITATIONS.md` §26. `Run.text` and
|
|
1032
|
+
`Paragraph.text` leave a ruby's base text out (`w:ruby`, a phonetic guide
|
|
1033
|
+
over its base text), as upstream reads only a run's own text elements, while
|
|
1034
|
+
the base text keeps its room in the text-address space (`ruby` spans on the
|
|
1035
|
+
read's run; `tests/test_ruby_reads_python_docx_parity.py`). That holds while
|
|
1036
|
+
the paragraph's runs are as its records hold them, in the body, a table cell,
|
|
1037
|
+
a header, a footer or a comment; a paragraph with a link or a tracked change
|
|
1038
|
+
reads its runs from their marks, the base text included. A write to the run
|
|
1039
|
+
(its text, an append, its formatting) makes the base text ordinary text,
|
|
1040
|
+
which then reads as text: docx-studio keeps no guide through an edit, where
|
|
1041
|
+
upstream keeps the `w:ruby` through all but a text write.
|
|
974
1042
|
|
|
975
1043
|
- **`CoreProperties.modified` is the time of the last save.** The asset is a
|
|
976
1044
|
live Word document, and docx-studio stamps `dcterms:modified` when it saves
|
|
@@ -1104,6 +1172,15 @@ This is a **thin HTTP client** that mimics the sync python-docx API.
|
|
|
1104
1172
|
the context-manager exit drain explicitly; `docx.flush_all()` is
|
|
1105
1173
|
the executor-postamble hook that flushes every live buffer in the
|
|
1106
1174
|
process.
|
|
1175
|
+
- A flush of more than 500 commands (`MAX_BATCH_COMMANDS`,
|
|
1176
|
+
docx-studio's request cap) goes out as consecutive requests, and
|
|
1177
|
+
docx-studio applies each all or nothing: when one fails, the requests
|
|
1178
|
+
before it are saved and it and every later one are not. The
|
|
1179
|
+
`DocxError` (0.29.0+) says how many of the flush's commands were
|
|
1180
|
+
applied and names the failed one by its flush index; it carries
|
|
1181
|
+
`unapplied_commands` and `failed_command`, and `partial_applied`
|
|
1182
|
+
holds the saved requests' results. A retry re-applies the unapplied
|
|
1183
|
+
edits, never the whole flush.
|
|
1107
1184
|
- Execution scope: executor sandboxes may keep Python globals
|
|
1108
1185
|
between tool calls so imports, constants, and helper functions can be
|
|
1109
1186
|
reused. Live SDK objects are different. The executor calls
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: athena-python-docx
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.29.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,7 +43,13 @@ from docx._execution import (
|
|
|
43
43
|
is_stale_execution,
|
|
44
44
|
)
|
|
45
45
|
from docx._timeouts import timeout_for_commands
|
|
46
|
-
from docx.commands import
|
|
46
|
+
from docx.commands import (
|
|
47
|
+
Command,
|
|
48
|
+
GetNodeById,
|
|
49
|
+
is_query,
|
|
50
|
+
is_response_bearing,
|
|
51
|
+
must_flush_immediately,
|
|
52
|
+
)
|
|
47
53
|
from docx.errors import DocxError, DocxUnsupportedCommandError, FlushAllError
|
|
48
54
|
|
|
49
55
|
|
|
@@ -402,6 +408,11 @@ class CommandBuffer:
|
|
|
402
408
|
# The last command's ``GetNodeById`` key, result and time, while
|
|
403
409
|
# nothing has been sent or buffered after it (see :meth:`call`).
|
|
404
410
|
self._last_read: tuple[str, Any, float] | None = None
|
|
411
|
+
# Counts each command that may change the document (anything but a
|
|
412
|
+
# query) this buffer has taken, buffered or sent, and each
|
|
413
|
+
# forget_reads(): a read kept from an earlier count (a ``Table``'s
|
|
414
|
+
# ``tables.get``) may no longer show the document. See ``writes``.
|
|
415
|
+
self._writes: int = 0
|
|
405
416
|
_register(self)
|
|
406
417
|
|
|
407
418
|
def register_proxy_id_ref(self, client_id: str, proxy: object, attr: str = "_node_id") -> None:
|
|
@@ -460,10 +471,15 @@ class CommandBuffer:
|
|
|
460
471
|
if current == mode:
|
|
461
472
|
return
|
|
462
473
|
# Drain any queued commands with the *previous* mode before
|
|
463
|
-
# adopting the new one.
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
474
|
+
# adopting the new one. The new mode is adopted even when that
|
|
475
|
+
# flush raises (docx-studio refuses a tracked batch that edits):
|
|
476
|
+
# ``Document`` has already recorded the new flag, so keeping the
|
|
477
|
+
# old mode here would refuse every later direct edit.
|
|
478
|
+
try:
|
|
479
|
+
self.flush()
|
|
480
|
+
finally:
|
|
481
|
+
with self._lock:
|
|
482
|
+
self._change_mode = mode
|
|
467
483
|
|
|
468
484
|
def set_user(self, name: str | None, email: str | None = None) -> None:
|
|
469
485
|
"""Set the batch-level user identity.
|
|
@@ -485,11 +501,34 @@ class CommandBuffer:
|
|
|
485
501
|
if email:
|
|
486
502
|
self._user["email"] = email
|
|
487
503
|
|
|
504
|
+
@property
|
|
505
|
+
def writes(self) -> int:
|
|
506
|
+
"""How many commands that may change the document this buffer has
|
|
507
|
+
taken, buffered or sent, plus each :meth:`forget_reads` (which a batch
|
|
508
|
+
another handle of the document sends calls). A read kept at one count
|
|
509
|
+
shows the document while the count stays, but for a collaborator's
|
|
510
|
+
edit."""
|
|
511
|
+
with self._lock:
|
|
512
|
+
return self._writes
|
|
513
|
+
|
|
488
514
|
def forget_reads(self) -> None:
|
|
489
515
|
"""The next node read goes to the server, not to the read before it
|
|
490
|
-
(:meth:`call`)
|
|
516
|
+
(:meth:`call`), and so does a table's next read (``writes``): for a
|
|
517
|
+
read that checks the document before a write."""
|
|
491
518
|
with self._lock:
|
|
492
519
|
self._last_read = None
|
|
520
|
+
self._writes += 1
|
|
521
|
+
|
|
522
|
+
def ensure_usable(self) -> None:
|
|
523
|
+
"""Raise as :meth:`call` does before it sends or reuses anything: for a
|
|
524
|
+
buffer of an earlier execution, a batch the idle timer failed to send,
|
|
525
|
+
and a closed buffer. A read kept outside the buffer checks it too."""
|
|
526
|
+
self._assert_current_execution()
|
|
527
|
+
self._raise_deferred_flush_error()
|
|
528
|
+
if self._closed:
|
|
529
|
+
raise RuntimeError(
|
|
530
|
+
f"CommandBuffer for {self._asset_id} is closed",
|
|
531
|
+
)
|
|
493
532
|
|
|
494
533
|
def call(self, cmd: Command) -> Any:
|
|
495
534
|
"""Execute or buffer ``cmd``.
|
|
@@ -508,12 +547,7 @@ class CommandBuffer:
|
|
|
508
547
|
``clientIdMap`` on flush and the buffer rewrites each registered
|
|
509
548
|
proxy's ``_node_id`` in-place.
|
|
510
549
|
"""
|
|
511
|
-
self.
|
|
512
|
-
self._raise_deferred_flush_error()
|
|
513
|
-
if self._closed:
|
|
514
|
-
raise RuntimeError(
|
|
515
|
-
f"CommandBuffer for {self._asset_id} is closed",
|
|
516
|
-
)
|
|
550
|
+
self.ensure_usable()
|
|
517
551
|
|
|
518
552
|
# A read of the node the last command read, with nothing sent or
|
|
519
553
|
# buffered since and within READ_REUSE_SECONDS of it, answers from
|
|
@@ -532,6 +566,9 @@ class CommandBuffer:
|
|
|
532
566
|
and _now() - last_read[2] <= READ_REUSE_SECONDS
|
|
533
567
|
):
|
|
534
568
|
return copy.deepcopy(last_read[1])
|
|
569
|
+
if not is_query(cmd):
|
|
570
|
+
with self._lock:
|
|
571
|
+
self._writes += 1
|
|
535
572
|
|
|
536
573
|
# PTC begin: emit only for commands in the allow-list. Other
|
|
537
574
|
# commands still flow through the buffer (and through the batched
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""What the docx-studio a session talks to takes, from its ``Info`` reply.
|
|
2
|
+
|
|
3
|
+
A command shape an older docx-studio would refuse (``InsertLineBreak`` with
|
|
4
|
+
``breakType: "page"``) is sent only to a server that names it in
|
|
5
|
+
``Info.capabilities``; a server that names none gets the older shape. The
|
|
6
|
+
promotion rings put tenants on different docx-studio trains, so an SDK release
|
|
7
|
+
meets servers from before and after the capability.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import weakref
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
from docx._batching import run_sync
|
|
16
|
+
|
|
17
|
+
# Session -> the capabilities its server reported, read once.
|
|
18
|
+
_capabilities: "weakref.WeakKeyDictionary[Any, dict[str, Any]]" = weakref.WeakKeyDictionary()
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def server_takes(session: Any, capability: str) -> bool:
|
|
22
|
+
"""True when the session's docx-studio reports ``capability``
|
|
23
|
+
(``Info.capabilities``), read on first use and kept for the session.
|
|
24
|
+
|
|
25
|
+
``Info`` flushes the edits queued before it, as every read does.
|
|
26
|
+
"""
|
|
27
|
+
if session is None:
|
|
28
|
+
return False
|
|
29
|
+
try:
|
|
30
|
+
known = _capabilities.get(session)
|
|
31
|
+
except TypeError:
|
|
32
|
+
return False
|
|
33
|
+
if known is None:
|
|
34
|
+
info: object = run_sync(session.doc.info({}))
|
|
35
|
+
reported = info.get("capabilities") if isinstance(info, dict) else None
|
|
36
|
+
known = reported if isinstance(reported, dict) else {}
|
|
37
|
+
_capabilities[session] = known
|
|
38
|
+
return known.get(capability) is True
|