athena-python-docx 0.6.0__tar.gz → 0.6.1__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.6.0 → athena_python_docx-0.6.1}/PKG-INFO +1 -1
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/__init__.py +1 -1
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/comments.py +20 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/document.py +31 -6
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/enum/section.py +18 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/enum/text.py +27 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/section.py +87 -20
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/shape.py +26 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/table.py +118 -19
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/text/paragraph.py +163 -8
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/text/run.py +172 -8
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/pyproject.toml +1 -1
- athena_python_docx-0.6.0/tests/fidelity/op_snapshots/37_iterate_runs_and_format_all_bold.json → athena_python_docx-0.6.1/tests/fidelity/op_snapshots/03_runs_with_formatting.json +4 -4
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/04_font_name_and_size.json +0 -1
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/05_font_color_rgb.json +0 -1
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/06_font_character_properties.json +0 -1
- athena_python_docx-0.6.1/tests/fidelity/op_snapshots/07_font_subscript_superscript.json +7 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/08_font_highlight.json +0 -1
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/102_text_with_embedded_special_chars.json +0 -1
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/14_run_add_tab_and_break.json +0 -1
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/15_run_add_break_page.json +0 -1
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/16_paragraph_clear_and_insert_before.json +0 -1
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/35_full_report.json +0 -4
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/36_replace_text_in_paragraph.json +0 -1
- athena_python_docx-0.6.0/tests/fidelity/op_snapshots/07_font_subscript_superscript.json → athena_python_docx-0.6.1/tests/fidelity/op_snapshots/37_iterate_runs_and_format_all_bold.json +3 -3
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/38_font_all_properties.json +0 -1
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/46_run_text_setter_round_trip.json +0 -1
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/47_font_size_round_trip.json +0 -1
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/48_font_color_round_trip.json +0 -1
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/49_resume_layout.json +0 -7
- athena_python_docx-0.6.1/tests/fidelity/op_snapshots/54_empty_everything.json +4 -0
- athena_python_docx-0.6.0/tests/fidelity/op_snapshots/03_runs_with_formatting.json → athena_python_docx-0.6.1/tests/fidelity/op_snapshots/55_single_character_runs.json +2 -5
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/56_everything_in_one.json +0 -6
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/57_runs_after_multiple_text_appends.json +0 -3
- athena_python_docx-0.6.0/tests/fidelity/op_snapshots/55_single_character_runs.json → athena_python_docx-0.6.1/tests/fidelity/op_snapshots/58_modify_runs_in_place.json +3 -6
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/68_invoice.json +0 -1
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/69_newsletter.json +0 -9
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/71_academic_paper.json +0 -2
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/72_legal_contract.json +0 -6
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/74_paragraph_with_10_runs.json +0 -10
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/76_rgbcolor_from_string.json +0 -1
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/80_apply_style_after_add_run.json +0 -1
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/82_add_text_on_existing_run.json +0 -1
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/83_clear_then_repopulate_paragraph.json +0 -2
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/86_font_read_unset_returns_none.json +0 -1
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/93_font_bool_reads_after_set.json +0 -1
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/96_paragraph_contains_page_break.json +0 -1
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/99_run_add_picture_from_bytes.json +0 -1
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex02_unicode_everywhere.json +0 -3
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex06_hundred_tiny_runs.json +0 -100
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex07_every_font_boolean.json +0 -1
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex16_runs_interleaved_with_breaks.json +0 -4
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex17_all_break_kinds.json +0 -3
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex19_mutate_all_runs.json +0 -15
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex20_kitchen_sink_v2.json +0 -22
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/mega01_book_chapter.json +0 -8
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/mega02_research_proposal.json +0 -4
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/mega03_financial_statement.json +0 -1
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/mega04_recipe_card.json +0 -3
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/mega05_user_manual.json +0 -3
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/mega06_complex_newsletter.json +0 -17
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/mega08_product_catalog.json +0 -15
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/mega09_signed_contract.json +0 -11
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/mega10_api_documentation.json +0 -7
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw01_official_quickstart.json +0 -3
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw03_character_formatting.json +0 -2
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw06_meeting_minutes.json +0 -4
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw07_dense_formatting_demo.json +0 -6
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw09_bulk_run_iteration.json +0 -30
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/parity/introspect.py +14 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/parity/reports/GAP_ANALYSIS.md +1 -1
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/parity/reports/gap_report.json +297 -285
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/parity/snapshots/athena_latest.json +287 -976
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/parity/snapshots/upstream_python_docx_1.2.0.json +4046 -3115
- athena_python_docx-0.6.1/tests/test_collapsed_range_format.py +190 -0
- athena_python_docx-0.6.1/tests/test_paragraph_text_len_cache.py +161 -0
- athena_python_docx-0.6.1/tests/test_silent_stub_add_paragraph_style.py +67 -0
- athena_python_docx-0.6.1/tests/test_silent_stub_add_run.py +90 -0
- athena_python_docx-0.6.1/tests/test_silent_stub_cell_add_paragraph.py +47 -0
- athena_python_docx-0.6.1/tests/test_silent_stub_comments_add_comment.py +71 -0
- athena_python_docx-0.6.1/tests/test_silent_stub_enum_section.py +83 -0
- athena_python_docx-0.6.1/tests/test_silent_stub_inline_shape.py +105 -0
- athena_python_docx-0.6.1/tests/test_silent_stub_insert_paragraph_before.py +61 -0
- athena_python_docx-0.6.1/tests/test_silent_stub_paragraph_strict.py +170 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_paragraph_style.py +17 -9
- athena_python_docx-0.6.1/tests/test_silent_stub_paragraph_style_strict.py +93 -0
- athena_python_docx-0.6.1/tests/test_silent_stub_row_col_cell.py +181 -0
- athena_python_docx-0.6.1/tests/test_silent_stub_run_add_break.py +82 -0
- athena_python_docx-0.6.1/tests/test_silent_stub_run_style.py +57 -0
- athena_python_docx-0.6.1/tests/test_silent_stub_run_style_strict.py +71 -0
- athena_python_docx-0.6.1/tests/test_silent_stub_run_text.py +71 -0
- athena_python_docx-0.6.1/tests/test_silent_stub_run_underline.py +123 -0
- athena_python_docx-0.6.1/tests/test_silent_stub_section_dimensions.py +96 -0
- athena_python_docx-0.6.1/tests/test_silent_stub_section_onoff.py +83 -0
- athena_python_docx-0.6.1/tests/test_silent_stub_table_layout.py +153 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/uv.lock +1 -1
- athena_python_docx-0.6.0/tests/fidelity/op_snapshots/54_empty_everything.json +0 -6
- athena_python_docx-0.6.0/tests/fidelity/op_snapshots/58_modify_runs_in_place.json +0 -18
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/.gitignore +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/CLAUDE.md +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/README.md +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/_batching.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/_buffer.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/_http.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/_http_doc.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/_image_utils.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/_ptc.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/api.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/client.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/commands.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/enum/__init__.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/enum/style.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/enum/table.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/errors.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/exceptions.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/opc/__init__.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/opc/coreprops.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/revisions.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/settings.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/shared.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/styles/__init__.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/styles/style.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/styles/styles.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/text/__init__.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/text/font.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/text/hyperlink.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/text/pagebreak.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/text/parfmt.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/text/tabstops.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/docx/typing.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/scripts/publish.sh +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/scripts/release.sh +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/scripts/round_trip_smoke.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/__init__.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/conftest.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/METHODOLOGY.md +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/README.md +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/__init__.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/ab_probe_cases.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/ab_probe_runner.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/auto_gen_cases.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/binary_round_trip.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/cases.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/complex_cases.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/coverage_report.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/extract.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/extreme_cases.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/fake_session.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/local_runner.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/mega_cases.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshot.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/01_basic_paragraph.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/02_multiple_headings.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/09_paragraph_alignment.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/100_table_negative_indexing.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/101_table_cells_flat_iteration.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/103_cell_tables_enumeration.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/104_core_properties_datetime.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/105_default_one_section.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/106_heading_paragraph_format.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/107_varying_row_heights.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/10_paragraph_indents.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/11_paragraph_spacing.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/12_paragraph_keep_options.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/13_paragraph_tab_stops.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/17_table_basic.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/18_table_cell_text.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/19_table_row_column_sizing.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/20_table_cell_vertical_alignment.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/21_table_alignment_and_autofit.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/22_table_cell_paragraphs_iteration.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/23_nested_table.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/24_table_add_row_column.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/25_table_merge_cells.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/26_section_page_setup.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/27_section_margins.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/28_section_add_new.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/29_section_headers_linked.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/30_styles_iteration.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/31_styles_lookup_and_default.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/32_styles_add_paragraph_style.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/33_core_properties_set_and_get.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/34_inline_shapes_iterate_empty.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/39_large_body_100_paragraphs.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/40_large_table_10x10.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/41_unicode_and_emoji.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/42_very_long_paragraph.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/43_paragraph_text_round_trip.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/44_paragraph_alignment_round_trip.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/45_cell_text_round_trip.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/50_multi_section_doc.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/51_nested_tables_deep.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/52_iterate_everything.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/53_apply_style_to_paragraphs.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/59_indent_round_trip.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/60_space_round_trip.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/61_cell_paragraph_with_runs.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/62_many_cell_paragraphs.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/63_table_style_round_trip.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/64_many_sections.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/65_20x20_table_formatted.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/66_toc_like_structure.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/67_paragraph_insert_before_chain.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/70_add_and_iterate_back.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/73_form_with_many_tables.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/75_paragraph_negative_first_line_indent.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/77_length_unit_conversions.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/78_paragraph_copy_style.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/79_bulk_cell_formatting.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/81_multi_page_with_breaks.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/84_table_reread_row_count.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/85_header_footer_access.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/87_500_paragraph_doc.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/88_mixed_content_iteration.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/89_alignment_clear_via_none.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/90_cell_add_paragraph_styled.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/91_many_small_tables.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/92_margins_every_section.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/94_page_break_before_paragraph.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/95_paragraph_hyperlinks_empty.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/97_document_styles_by_key.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/98_style_contains_check.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex01_five_levels_deep_tables.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex03_1000_paragraphs.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex04_50x50_table.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex05_long_text_in_cell.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex08_many_continuous_sections.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex09_many_tab_stops.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex10_complex_bom.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex11_banded_rows_formatting.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex12_section_reconfigure.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex13_cell_with_10_paragraphs.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex14_styled_report_table.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex15_paragraph_all_format_props.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/ex18_read_back_large_doc.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/mega07_budget_spreadsheet.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw02_paragraph_style_list.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw04_section_page_setup.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw05_toc_pattern.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw08_table_merged_header.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw10_colored_grid_table.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw11_header_text.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw12_first_page_footer.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw13_even_page_header.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw14_nested_cell_table.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/op_snapshots/rw15_paragraph_style_instance.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/ours_spec.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/parity_crawl.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/parity_diff.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/real_world_cases.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/round_trip_tests.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/runner.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/fidelity/stock_spec.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/parity/README.md +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/parity/__init__.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/parity/baseline_gaps.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/parity/compare.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/parity/intentional_deviations.json +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/parity/run_parity.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/parity/test_parity_gap.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_batching_perf.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_buffer.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_command_dataclasses.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_commands.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_comments.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_document_create.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_http_transport.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_iter_inner_content.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_merged_cells.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_parity_misc.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_parity_round2.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_phase_a_behavior.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_phase_b_headers_footers.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_phase_c_tables.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_pr19766_review_fixes.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_ptc.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_python_docx_api_parity.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_revisions.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_add_picture.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_comments_get.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_document_audit.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_document_element.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_font_audit.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_header_footer.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_hyperlink.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_misc.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_parfmt.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_run_bool_setters.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_section_audit.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_settings.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_shared_audit.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_style.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_styles.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_table_audit.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_table_cell.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_silent_stub_table_dimensions.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_smoke_integration.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_style_acceptance.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_style_font.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_style_setters_contract.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_wire_contract.py +0 -0
- {athena_python_docx-0.6.0 → athena_python_docx-0.6.1}/tests/test_zod_wire_contract.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: athena-python-docx
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.1
|
|
4
4
|
Summary: Drop-in replacement for python-docx that connects to Athena's Superdoc/Keryx collaborative document stack
|
|
5
5
|
Project-URL: Homepage, https://athenaintelligence.ai
|
|
6
6
|
Author-email: Athena Intelligence <engineering@athenaintelligence.ai>
|
|
@@ -314,6 +314,26 @@ class Comments:
|
|
|
314
314
|
Use :meth:`Document.add_comment` to thread a run-anchored
|
|
315
315
|
target — this method creates an unanchored comment.
|
|
316
316
|
"""
|
|
317
|
+
# python-docx 1.x routes ``text`` / ``author`` / ``initials``
|
|
318
|
+
# through lxml's element setters which TypeError on non-str.
|
|
319
|
+
# Was: any value shipped to wire (text) or stashed as-is on
|
|
320
|
+
# the local info dict (author/initials) — caller's intent was
|
|
321
|
+
# lost when they passed a wrong type.
|
|
322
|
+
if not isinstance(text, str):
|
|
323
|
+
raise TypeError(
|
|
324
|
+
f"Comments.add_comment text requires str; got "
|
|
325
|
+
f"{type(text).__name__} {text!r}",
|
|
326
|
+
)
|
|
327
|
+
if not isinstance(author, str):
|
|
328
|
+
raise TypeError(
|
|
329
|
+
f"Comments.add_comment author requires str; got "
|
|
330
|
+
f"{type(author).__name__} {author!r}",
|
|
331
|
+
)
|
|
332
|
+
if initials is not None and not isinstance(initials, str):
|
|
333
|
+
raise TypeError(
|
|
334
|
+
f"Comments.add_comment initials requires str or None; "
|
|
335
|
+
f"got {type(initials).__name__} {initials!r}",
|
|
336
|
+
)
|
|
317
337
|
result: object = run_sync(
|
|
318
338
|
self._session.doc.comments.create({"text": text}),
|
|
319
339
|
)
|
|
@@ -596,9 +596,24 @@ class Document:
|
|
|
596
596
|
|
|
597
597
|
# Coerce ParagraphStyle instances to their style id so the rest
|
|
598
598
|
# of this method can treat `style` as an Optional[str].
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
599
|
+
# python-docx 1.x accepts ``str | ParagraphStyle | None`` and
|
|
600
|
+
# raises ``TypeError`` at the style-lookup layer for anything
|
|
601
|
+
# else. Mirror that — the previous code accepted ``style`` as
|
|
602
|
+
# the literal value when it wasn't a ParagraphStyle, so e.g.
|
|
603
|
+
# ``add_paragraph(style=42)`` shipped ``42`` as the style id.
|
|
604
|
+
style_str: str | None
|
|
605
|
+
if style is None:
|
|
606
|
+
style_str = None
|
|
607
|
+
elif isinstance(style, ParagraphStyle):
|
|
608
|
+
style_str = style.style_id
|
|
609
|
+
elif isinstance(style, str):
|
|
610
|
+
style_str = style
|
|
611
|
+
else:
|
|
612
|
+
raise TypeError(
|
|
613
|
+
f"Document.add_paragraph style requires str, "
|
|
614
|
+
f"ParagraphStyle, or None; got "
|
|
615
|
+
f"{type(style).__name__} {style!r}",
|
|
616
|
+
)
|
|
602
617
|
|
|
603
618
|
# Use Superdoc's canonical primitive `doc.create.paragraph`. It
|
|
604
619
|
# accepts an `at` anchor and a `text` body; an empty `text` creates
|
|
@@ -624,8 +639,9 @@ class Document:
|
|
|
624
639
|
# heavy lifting.
|
|
625
640
|
normalized: str = self._normalize_text(text)
|
|
626
641
|
has_control_chars = any(ch in "\t\n\r" for ch in normalized)
|
|
642
|
+
wire_text: str = "" if has_control_chars else normalized
|
|
627
643
|
params: dict = {
|
|
628
|
-
"text":
|
|
644
|
+
"text": wire_text,
|
|
629
645
|
"at": {"kind": "documentEnd"},
|
|
630
646
|
}
|
|
631
647
|
# When inside ``with doc.batch():`` we pre-assign a client UUID
|
|
@@ -650,8 +666,13 @@ class Document:
|
|
|
650
666
|
raise RuntimeError(
|
|
651
667
|
f"Superdoc did not return a nodeId for add_paragraph: {result!r}",
|
|
652
668
|
)
|
|
669
|
+
# Seed the text-length cache so the next ``p.add_run(...)``
|
|
670
|
+
# call can skip its ``get_node_by_id`` HTTP round-trip.
|
|
653
671
|
para = Paragraph(
|
|
654
|
-
session=self._session,
|
|
672
|
+
session=self._session,
|
|
673
|
+
node_id=node_id,
|
|
674
|
+
node_type="paragraph",
|
|
675
|
+
text_len=len(wire_text),
|
|
655
676
|
)
|
|
656
677
|
if client_node_id is not None:
|
|
657
678
|
self._register_proxy_for_batch(client_node_id, para)
|
|
@@ -722,6 +743,7 @@ class Document:
|
|
|
722
743
|
session=self._session,
|
|
723
744
|
node_id=node_id,
|
|
724
745
|
node_type="paragraph",
|
|
746
|
+
text_len=len(wire_text),
|
|
725
747
|
)
|
|
726
748
|
if client_node_id is not None:
|
|
727
749
|
self._register_proxy_for_batch(client_node_id, paragraph)
|
|
@@ -753,7 +775,10 @@ class Document:
|
|
|
753
775
|
f"Superdoc did not return a nodeId for add_heading: {result!r}",
|
|
754
776
|
)
|
|
755
777
|
heading = Paragraph(
|
|
756
|
-
session=self._session,
|
|
778
|
+
session=self._session,
|
|
779
|
+
node_id=node_id,
|
|
780
|
+
node_type="heading",
|
|
781
|
+
text_len=len(wire_text),
|
|
757
782
|
)
|
|
758
783
|
if client_node_id is not None:
|
|
759
784
|
self._register_proxy_for_batch(client_node_id, heading)
|
|
@@ -4,6 +4,17 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from enum import Enum
|
|
6
6
|
|
|
7
|
+
from docx.enum.text import _warn_enum_coercion
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"WD_HEADER_FOOTER",
|
|
11
|
+
"WD_HEADER_FOOTER_INDEX",
|
|
12
|
+
"WD_ORIENT",
|
|
13
|
+
"WD_ORIENTATION",
|
|
14
|
+
"WD_SECTION",
|
|
15
|
+
"WD_SECTION_START",
|
|
16
|
+
]
|
|
17
|
+
|
|
7
18
|
|
|
8
19
|
class WD_ORIENTATION(Enum):
|
|
9
20
|
PORTRAIT = "portrait"
|
|
@@ -31,6 +42,13 @@ class WD_SECTION_START(Enum):
|
|
|
31
42
|
return "evenPage"
|
|
32
43
|
if self == WD_SECTION_START.ODD_PAGE:
|
|
33
44
|
return "oddPage"
|
|
45
|
+
if self == WD_SECTION_START.NEW_PAGE:
|
|
46
|
+
return "nextPage"
|
|
47
|
+
# NEW_COLUMN — SuperDoc 1.8 doesn't have a column-break section
|
|
48
|
+
# type, so we collapse to "nextPage" but emit
|
|
49
|
+
# PendingEnumCoercionWarning so callers don't silently get a
|
|
50
|
+
# page break when they asked for a column break.
|
|
51
|
+
_warn_enum_coercion(self, "nextPage")
|
|
34
52
|
return "nextPage"
|
|
35
53
|
|
|
36
54
|
|
|
@@ -13,6 +13,19 @@ import warnings
|
|
|
13
13
|
from enum import Enum
|
|
14
14
|
|
|
15
15
|
|
|
16
|
+
_INT_TO_ALIGN: "dict[int, str]" = {
|
|
17
|
+
0: "LEFT",
|
|
18
|
+
1: "CENTER",
|
|
19
|
+
2: "RIGHT",
|
|
20
|
+
3: "JUSTIFY",
|
|
21
|
+
4: "DISTRIBUTE",
|
|
22
|
+
5: "JUSTIFY_MED",
|
|
23
|
+
7: "JUSTIFY_HI",
|
|
24
|
+
8: "JUSTIFY_LOW",
|
|
25
|
+
9: "THAI_JUSTIFY",
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
16
29
|
class PendingEnumCoercionWarning(UserWarning):
|
|
17
30
|
"""Emitted when an enum member's :meth:`to_superdoc` collapses the
|
|
18
31
|
value to a different SuperDoc-supported primitive.
|
|
@@ -58,6 +71,20 @@ class WD_ALIGN_PARAGRAPH(Enum):
|
|
|
58
71
|
JUSTIFY_LOW = "justifyLow"
|
|
59
72
|
THAI_JUSTIFY = "thaiJustify"
|
|
60
73
|
|
|
74
|
+
@classmethod
|
|
75
|
+
def from_int(cls, value: int) -> "WD_ALIGN_PARAGRAPH | None":
|
|
76
|
+
"""Coerce a python-docx-style int alignment to the enum.
|
|
77
|
+
|
|
78
|
+
python-docx 1.x's ``WD_ALIGN_PARAGRAPH`` is keyed on int (its
|
|
79
|
+
``BaseXmlEnum`` mapping: LEFT=0, CENTER=1, RIGHT=2, JUSTIFY=3,
|
|
80
|
+
DISTRIBUTE=4, JUSTIFY_MED=5, JUSTIFY_HI=7, JUSTIFY_LOW=8,
|
|
81
|
+
THAI_JUSTIFY=9). Callers passing ``paragraph.alignment = 1``
|
|
82
|
+
get CENTER. We mirror that without changing our enum's
|
|
83
|
+
string-valued definition.
|
|
84
|
+
"""
|
|
85
|
+
name = _INT_TO_ALIGN.get(value)
|
|
86
|
+
return getattr(cls, name) if name is not None else None
|
|
87
|
+
|
|
61
88
|
def to_superdoc(self) -> str:
|
|
62
89
|
# Superdoc only supports left/center/right/justify; coerce the
|
|
63
90
|
# distributed/thai variants to "justify" so set_alignment doesn't
|
|
@@ -83,6 +83,66 @@ def _emu_to_pt(emu: int) -> float:
|
|
|
83
83
|
return emu / 12700.0
|
|
84
84
|
|
|
85
85
|
|
|
86
|
+
def _reject_none_dimension(prop: str, value: object) -> None:
|
|
87
|
+
"""Raise ``TypeError`` if ``value`` is None for a dimension setter
|
|
88
|
+
that python-docx 1.2.0 doesn't accept None for.
|
|
89
|
+
|
|
90
|
+
Upstream ``Section.page_width = None`` (and every margin /
|
|
91
|
+
header_distance / footer_distance / gutter setter) routes through
|
|
92
|
+
``Emu(value).twips`` which raises ``TypeError`` on ``None``. Our
|
|
93
|
+
setters previously early-returned silently, swallowing the
|
|
94
|
+
intent. Raise to match upstream behavior — callers who actually
|
|
95
|
+
want a clear must pass ``Inches(0)`` (or similar) explicitly.
|
|
96
|
+
"""
|
|
97
|
+
if value is None:
|
|
98
|
+
raise TypeError(
|
|
99
|
+
f"Section.{prop} = None is not supported. python-docx "
|
|
100
|
+
f"1.2.0 raises TypeError here too — its Emu(None).twips "
|
|
101
|
+
f"fails with the same shape. Pass an explicit Length "
|
|
102
|
+
f"(e.g. Inches(0)) if you want to zero the dimension."
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class PendingSectionOnOffClearWarning(UserWarning):
|
|
107
|
+
"""Emitted when ``Section.different_first_page_header_footer = None``.
|
|
108
|
+
|
|
109
|
+
python-docx 1.x semantics: ``None`` clears the OOXML
|
|
110
|
+
``<w:titlePg/>`` element back to inherited. SuperDoc 1.8's
|
|
111
|
+
``sections.set_title_page`` only accepts ``enabled: bool`` — the
|
|
112
|
+
wire can't represent the clear-intent. The warning surfaces
|
|
113
|
+
silent-divergence. Tracked in
|
|
114
|
+
``docx-studio/SUPERDOC_UPSTREAM_REQUESTS.md``.
|
|
115
|
+
"""
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _warn_section_onoff_clear(prop: str) -> None:
|
|
119
|
+
warnings.warn(
|
|
120
|
+
f"Section.{prop} = None was IGNORED — SuperDoc 1.8 has no "
|
|
121
|
+
f"clear-op for this OnOff property. The section keeps its "
|
|
122
|
+
f"previous value. Tracked in "
|
|
123
|
+
f"docx-studio/SUPERDOC_UPSTREAM_REQUESTS.md.",
|
|
124
|
+
PendingSectionOnOffClearWarning,
|
|
125
|
+
stacklevel=3,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def _require_section_bool(prop: str, value: object) -> bool:
|
|
130
|
+
"""Reject non-bool input on Section OnOff setters.
|
|
131
|
+
|
|
132
|
+
python-docx 1.x's ``_OnOff`` typed-attribute setter raises
|
|
133
|
+
``ValueError`` for non-bool input. Our previous ``bool(value)``
|
|
134
|
+
coercion silently turned ``"yes"`` / ``1`` / ``[]`` into True/False
|
|
135
|
+
without surfacing the type mismatch.
|
|
136
|
+
"""
|
|
137
|
+
if not isinstance(value, bool):
|
|
138
|
+
raise TypeError(
|
|
139
|
+
f"Section.{prop} requires bool or None; got "
|
|
140
|
+
f"{type(value).__name__} {value!r}. python-docx 1.x's "
|
|
141
|
+
f"``_OnOff`` setter rejects truthy non-bool here too.",
|
|
142
|
+
)
|
|
143
|
+
return value
|
|
144
|
+
|
|
145
|
+
|
|
86
146
|
class Section:
|
|
87
147
|
"""A document section — page size, margins, headers/footers, break type."""
|
|
88
148
|
|
|
@@ -124,8 +184,7 @@ class Section:
|
|
|
124
184
|
|
|
125
185
|
@page_width.setter
|
|
126
186
|
def page_width(self, value: "Length | int | None") -> None:
|
|
127
|
-
|
|
128
|
-
return
|
|
187
|
+
_reject_none_dimension("page_width", value)
|
|
129
188
|
pt = _emu_to_pt(_emu_from(value))
|
|
130
189
|
self._set_page_setup(width=pt)
|
|
131
190
|
|
|
@@ -140,8 +199,7 @@ class Section:
|
|
|
140
199
|
|
|
141
200
|
@page_height.setter
|
|
142
201
|
def page_height(self, value: "Length | int | None") -> None:
|
|
143
|
-
|
|
144
|
-
return
|
|
202
|
+
_reject_none_dimension("page_height", value)
|
|
145
203
|
pt = _emu_to_pt(_emu_from(value))
|
|
146
204
|
self._set_page_setup(height=pt)
|
|
147
205
|
|
|
@@ -201,8 +259,7 @@ class Section:
|
|
|
201
259
|
|
|
202
260
|
@left_margin.setter
|
|
203
261
|
def left_margin(self, value: "Length | int | None") -> None:
|
|
204
|
-
|
|
205
|
-
return
|
|
262
|
+
_reject_none_dimension("left_margin", value)
|
|
206
263
|
self._set_margins(left=_emu_to_pt(_emu_from(value)))
|
|
207
264
|
|
|
208
265
|
@property
|
|
@@ -211,8 +268,7 @@ class Section:
|
|
|
211
268
|
|
|
212
269
|
@right_margin.setter
|
|
213
270
|
def right_margin(self, value: "Length | int | None") -> None:
|
|
214
|
-
|
|
215
|
-
return
|
|
271
|
+
_reject_none_dimension("right_margin", value)
|
|
216
272
|
self._set_margins(right=_emu_to_pt(_emu_from(value)))
|
|
217
273
|
|
|
218
274
|
@property
|
|
@@ -221,8 +277,7 @@ class Section:
|
|
|
221
277
|
|
|
222
278
|
@top_margin.setter
|
|
223
279
|
def top_margin(self, value: "Length | int | None") -> None:
|
|
224
|
-
|
|
225
|
-
return
|
|
280
|
+
_reject_none_dimension("top_margin", value)
|
|
226
281
|
self._set_margins(top=_emu_to_pt(_emu_from(value)))
|
|
227
282
|
|
|
228
283
|
@property
|
|
@@ -231,8 +286,7 @@ class Section:
|
|
|
231
286
|
|
|
232
287
|
@bottom_margin.setter
|
|
233
288
|
def bottom_margin(self, value: "Length | int | None") -> None:
|
|
234
|
-
|
|
235
|
-
return
|
|
289
|
+
_reject_none_dimension("bottom_margin", value)
|
|
236
290
|
self._set_margins(bottom=_emu_to_pt(_emu_from(value)))
|
|
237
291
|
|
|
238
292
|
@property
|
|
@@ -241,8 +295,7 @@ class Section:
|
|
|
241
295
|
|
|
242
296
|
@gutter.setter
|
|
243
297
|
def gutter(self, value: "Length | int | None") -> None:
|
|
244
|
-
|
|
245
|
-
return
|
|
298
|
+
_reject_none_dimension("gutter", value)
|
|
246
299
|
self._set_margins(gutter=_emu_to_pt(_emu_from(value)))
|
|
247
300
|
|
|
248
301
|
@property
|
|
@@ -256,8 +309,7 @@ class Section:
|
|
|
256
309
|
|
|
257
310
|
@header_distance.setter
|
|
258
311
|
def header_distance(self, value: "Length | int | None") -> None:
|
|
259
|
-
|
|
260
|
-
return
|
|
312
|
+
_reject_none_dimension("header_distance", value)
|
|
261
313
|
run_sync(
|
|
262
314
|
self._session.doc.sections.set_header_footer_margins(
|
|
263
315
|
{"target": self._address, "header": _emu_to_pt(_emu_from(value))},
|
|
@@ -275,8 +327,7 @@ class Section:
|
|
|
275
327
|
|
|
276
328
|
@footer_distance.setter
|
|
277
329
|
def footer_distance(self, value: "Length | int | None") -> None:
|
|
278
|
-
|
|
279
|
-
return
|
|
330
|
+
_reject_none_dimension("footer_distance", value)
|
|
280
331
|
run_sync(
|
|
281
332
|
self._session.doc.sections.set_header_footer_margins(
|
|
282
333
|
{"target": self._address, "footer": _emu_to_pt(_emu_from(value))},
|
|
@@ -335,14 +386,18 @@ class Section:
|
|
|
335
386
|
@different_first_page_header_footer.setter
|
|
336
387
|
def different_first_page_header_footer(self, value: bool | None) -> None:
|
|
337
388
|
if value is None:
|
|
389
|
+
_warn_section_onoff_clear("different_first_page_header_footer")
|
|
338
390
|
return
|
|
391
|
+
enabled = _require_section_bool(
|
|
392
|
+
"different_first_page_header_footer", value
|
|
393
|
+
)
|
|
339
394
|
run_sync(
|
|
340
395
|
self._session.doc.sections.set_title_page(
|
|
341
396
|
# SuperDoc's wire field is ``enabled`` (DocSectionsSet
|
|
342
397
|
# TitlePageParams). The earlier ``titlePage`` name was
|
|
343
398
|
# rejected silently because the apps/api applier punts
|
|
344
399
|
# SuperDoc's strict types via ``AnyDoc``.
|
|
345
|
-
{"target": self._address, "enabled":
|
|
400
|
+
{"target": self._address, "enabled": enabled},
|
|
346
401
|
),
|
|
347
402
|
)
|
|
348
403
|
|
|
@@ -622,8 +677,20 @@ class _HeaderFooter:
|
|
|
622
677
|
style_str = None
|
|
623
678
|
elif isinstance(style, ParagraphStyle):
|
|
624
679
|
style_str = style.style_id
|
|
680
|
+
elif isinstance(style, str):
|
|
681
|
+
style_str = style
|
|
625
682
|
else:
|
|
626
|
-
|
|
683
|
+
# python-docx 1.x's ``add_paragraph(style=...)`` accepts
|
|
684
|
+
# ``str | ParagraphStyle | None`` and raises ``TypeError``
|
|
685
|
+
# at the style-lookup layer for anything else. The
|
|
686
|
+
# previous ``str(style)`` silently shipped garbage like
|
|
687
|
+
# ``<MyStyle object at 0x...>`` as a style id, which
|
|
688
|
+
# SuperDoc would swallow or reject without a clear signal.
|
|
689
|
+
raise TypeError(
|
|
690
|
+
f"_HeaderFooter.add_paragraph style requires str, "
|
|
691
|
+
f"ParagraphStyle, or None; got "
|
|
692
|
+
f"{type(style).__name__} {style!r}",
|
|
693
|
+
)
|
|
627
694
|
|
|
628
695
|
result: object = run_sync(
|
|
629
696
|
self._section._session.doc.create.paragraph(
|
|
@@ -7,6 +7,7 @@ to image binary / metadata round-trips through `doc.images.get`.
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
9
|
import base64
|
|
10
|
+
import warnings
|
|
10
11
|
from typing import TYPE_CHECKING
|
|
11
12
|
|
|
12
13
|
from docx._batching import run_sync
|
|
@@ -16,6 +17,29 @@ if TYPE_CHECKING:
|
|
|
16
17
|
from docx.client import Session
|
|
17
18
|
|
|
18
19
|
|
|
20
|
+
class PendingInlineShapeClearWarning(UserWarning):
|
|
21
|
+
"""Emitted when ``InlineShape.width`` or ``.height`` is set to
|
|
22
|
+
``None`` (python-docx semantics: "revert to natural sizing").
|
|
23
|
+
|
|
24
|
+
SuperDoc 1.8 has no clear-op for image dimensions — its
|
|
25
|
+
``images.setSize`` requires explicit ``width`` and ``height``. The
|
|
26
|
+
SDK can't represent a "revert to natural" intent on the wire, so
|
|
27
|
+
``image.width = None`` is a no-op. The warning surfaces the
|
|
28
|
+
silent-divergence pattern so agent runs see the gap. Tracked in
|
|
29
|
+
``docx-studio/SUPERDOC_UPSTREAM_REQUESTS.md``.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _warn_inline_shape_clear(prop: str) -> None:
|
|
34
|
+
warnings.warn(
|
|
35
|
+
f"InlineShape.{prop} = None was IGNORED — SuperDoc 1.8 has no "
|
|
36
|
+
f"clear-op for image dimensions. The image keeps its previous "
|
|
37
|
+
f"size. Tracked in docx-studio/SUPERDOC_UPSTREAM_REQUESTS.md.",
|
|
38
|
+
PendingInlineShapeClearWarning,
|
|
39
|
+
stacklevel=3,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
19
43
|
def _strip_data_uri(src: str) -> tuple[bytes, str | None]:
|
|
20
44
|
"""If ``src`` is a ``data:`` URI, return (decoded_bytes, mime).
|
|
21
45
|
Otherwise return ``(b"", None)``."""
|
|
@@ -63,6 +87,7 @@ class InlineShape:
|
|
|
63
87
|
@width.setter
|
|
64
88
|
def width(self, value: "Length | int | None") -> None:
|
|
65
89
|
if value is None:
|
|
90
|
+
_warn_inline_shape_clear("width")
|
|
66
91
|
return
|
|
67
92
|
pt: float = value.pt if isinstance(value, Length) else float(value) / 12700.0
|
|
68
93
|
h = self.height
|
|
@@ -92,6 +117,7 @@ class InlineShape:
|
|
|
92
117
|
@height.setter
|
|
93
118
|
def height(self, value: "Length | int | None") -> None:
|
|
94
119
|
if value is None:
|
|
120
|
+
_warn_inline_shape_clear("height")
|
|
95
121
|
return
|
|
96
122
|
pt: float = value.pt if isinstance(value, Length) else float(value) / 12700.0
|
|
97
123
|
w = self.width
|
|
@@ -3,12 +3,41 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import sys
|
|
6
|
+
import warnings
|
|
6
7
|
from typing import TYPE_CHECKING
|
|
7
8
|
|
|
8
9
|
from docx._batching import run_sync
|
|
9
10
|
from docx.errors import ValidationError
|
|
10
11
|
from docx.shared import Length, Pt
|
|
11
12
|
|
|
13
|
+
|
|
14
|
+
class PendingTableClearWarning(UserWarning):
|
|
15
|
+
"""Emitted when a ``Table`` / ``_Row`` / ``_Column`` / ``_Cell``
|
|
16
|
+
setter is asked to clear a property (``None`` assignment) that
|
|
17
|
+
python-docx 1.x supports but SuperDoc 1.8 has no clear-op for.
|
|
18
|
+
|
|
19
|
+
Covers: ``Table.alignment / direction / autofit``,
|
|
20
|
+
``_Row.height / height_rule``, ``_Column.width``,
|
|
21
|
+
``_Cell.width / vertical_alignment``. SuperDoc's
|
|
22
|
+
``tables.set_layout`` / ``set_row_height`` / ``set_column_width``
|
|
23
|
+
/ ``set_cell_properties`` require explicit values — the wire
|
|
24
|
+
can't represent the python-docx "revert to inherited" intent.
|
|
25
|
+
The warning surfaces the silent-divergence so agent runs see
|
|
26
|
+
the gap. Tracked in
|
|
27
|
+
``docx-studio/SUPERDOC_UPSTREAM_REQUESTS.md``.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _warn_table_clear(prop: str, *, cls: str = "Table") -> None:
|
|
32
|
+
warnings.warn(
|
|
33
|
+
f"{cls}.{prop} = None was IGNORED — SuperDoc 1.8 has no "
|
|
34
|
+
f"clear-op for this property. The {cls.lower()} keeps its "
|
|
35
|
+
f"previous value. Tracked in "
|
|
36
|
+
f"docx-studio/SUPERDOC_UPSTREAM_REQUESTS.md.",
|
|
37
|
+
PendingTableClearWarning,
|
|
38
|
+
stacklevel=3,
|
|
39
|
+
)
|
|
40
|
+
|
|
12
41
|
if TYPE_CHECKING:
|
|
13
42
|
from docx.client import Session
|
|
14
43
|
from docx.enum.table import (
|
|
@@ -420,12 +449,28 @@ class Table:
|
|
|
420
449
|
from docx.enum.table import WD_TABLE_ALIGNMENT
|
|
421
450
|
|
|
422
451
|
if value is None:
|
|
452
|
+
_warn_table_clear("alignment")
|
|
423
453
|
return
|
|
424
|
-
|
|
425
|
-
value.to_superdoc()
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
454
|
+
if isinstance(value, WD_TABLE_ALIGNMENT):
|
|
455
|
+
v: str = value.to_superdoc()
|
|
456
|
+
elif isinstance(value, str):
|
|
457
|
+
# python-docx coerces strings through the enum and raises
|
|
458
|
+
# ``ValueError`` for non-member values. Mirror that here
|
|
459
|
+
# instead of shipping bogus ``str(value).lower()`` to
|
|
460
|
+
# SuperDoc, which would silently swallow unknowns.
|
|
461
|
+
try:
|
|
462
|
+
v = WD_TABLE_ALIGNMENT(value).to_superdoc()
|
|
463
|
+
except (ValueError, KeyError) as exc:
|
|
464
|
+
raise ValueError(
|
|
465
|
+
f"Table.alignment = {value!r}: not a valid "
|
|
466
|
+
f"WD_TABLE_ALIGNMENT. Expected one of "
|
|
467
|
+
f"{[m.value for m in WD_TABLE_ALIGNMENT]}."
|
|
468
|
+
) from exc
|
|
469
|
+
else:
|
|
470
|
+
raise TypeError(
|
|
471
|
+
f"Table.alignment requires WD_TABLE_ALIGNMENT, str, "
|
|
472
|
+
f"or None; got {type(value).__name__}",
|
|
473
|
+
)
|
|
429
474
|
# SuperDoc 1.8.1: alignment is a setLayout field, not a
|
|
430
475
|
# setTableOptions field. The earlier setTableOptions call
|
|
431
476
|
# silently dropped the value (Zod validated, AnyDoc punt let
|
|
@@ -456,12 +501,24 @@ class Table:
|
|
|
456
501
|
from docx.enum.table import WD_TABLE_DIRECTION
|
|
457
502
|
|
|
458
503
|
if value is None:
|
|
504
|
+
_warn_table_clear("direction")
|
|
459
505
|
return
|
|
460
|
-
|
|
461
|
-
value.to_superdoc()
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
506
|
+
if isinstance(value, WD_TABLE_DIRECTION):
|
|
507
|
+
v: str = value.to_superdoc()
|
|
508
|
+
elif isinstance(value, str):
|
|
509
|
+
try:
|
|
510
|
+
v = WD_TABLE_DIRECTION(value).to_superdoc()
|
|
511
|
+
except (ValueError, KeyError) as exc:
|
|
512
|
+
raise ValueError(
|
|
513
|
+
f"Table.direction = {value!r}: not a valid "
|
|
514
|
+
f"WD_TABLE_DIRECTION. Expected one of "
|
|
515
|
+
f"{[m.value for m in WD_TABLE_DIRECTION]}."
|
|
516
|
+
) from exc
|
|
517
|
+
else:
|
|
518
|
+
raise TypeError(
|
|
519
|
+
f"Table.direction requires WD_TABLE_DIRECTION, str, "
|
|
520
|
+
f"or None; got {type(value).__name__}",
|
|
521
|
+
)
|
|
465
522
|
# SuperDoc's setLayout takes ``tableDirection`` (not
|
|
466
523
|
# ``direction``). Same diagnostic as alignment above —
|
|
467
524
|
# setTableOptions silently swallowed the field.
|
|
@@ -488,7 +545,15 @@ class Table:
|
|
|
488
545
|
@autofit.setter
|
|
489
546
|
def autofit(self, value: bool | None) -> None:
|
|
490
547
|
if value is None:
|
|
548
|
+
_warn_table_clear("autofit")
|
|
491
549
|
return
|
|
550
|
+
if not isinstance(value, bool):
|
|
551
|
+
raise TypeError(
|
|
552
|
+
f"Table.autofit requires bool or None; got "
|
|
553
|
+
f"{type(value).__name__} {value!r}. python-docx 1.x "
|
|
554
|
+
f"is a ``_OnOff`` setter and rejects truthy non-bool "
|
|
555
|
+
f"here too.",
|
|
556
|
+
)
|
|
492
557
|
run_sync(
|
|
493
558
|
self._session.doc.tables.set_layout(
|
|
494
559
|
{
|
|
@@ -614,6 +679,7 @@ class _Row:
|
|
|
614
679
|
@height.setter
|
|
615
680
|
def height(self, value: "Length | int | None") -> None:
|
|
616
681
|
if value is None:
|
|
682
|
+
_warn_table_clear("height", cls="_Row")
|
|
617
683
|
return
|
|
618
684
|
# Mirror python-docx: row height is stored as unsigned twips
|
|
619
685
|
# (``ST_TwipsMeasure``), so negative inputs raise ``ValueError``
|
|
@@ -663,12 +729,27 @@ class _Row:
|
|
|
663
729
|
from docx.enum.table import WD_ROW_HEIGHT_RULE
|
|
664
730
|
|
|
665
731
|
if value is None:
|
|
732
|
+
_warn_table_clear("height_rule", cls="_Row")
|
|
666
733
|
return
|
|
667
|
-
|
|
668
|
-
value.to_superdoc()
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
734
|
+
if isinstance(value, WD_ROW_HEIGHT_RULE):
|
|
735
|
+
rule: str = value.to_superdoc()
|
|
736
|
+
elif isinstance(value, str):
|
|
737
|
+
# python-docx coerces strings through the enum and raises
|
|
738
|
+
# on misses. Was: ``str(value)`` shipped any value to the
|
|
739
|
+
# wire (SuperDoc swallowed unknowns silently).
|
|
740
|
+
try:
|
|
741
|
+
rule = WD_ROW_HEIGHT_RULE(value).to_superdoc()
|
|
742
|
+
except (ValueError, KeyError) as exc:
|
|
743
|
+
raise ValueError(
|
|
744
|
+
f"_Row.height_rule = {value!r}: not a valid "
|
|
745
|
+
f"WD_ROW_HEIGHT_RULE. Expected one of "
|
|
746
|
+
f"{[m.value for m in WD_ROW_HEIGHT_RULE]}."
|
|
747
|
+
) from exc
|
|
748
|
+
else:
|
|
749
|
+
raise TypeError(
|
|
750
|
+
f"_Row.height_rule requires WD_ROW_HEIGHT_RULE, str, "
|
|
751
|
+
f"or None; got {type(value).__name__}",
|
|
752
|
+
)
|
|
672
753
|
h = self.height
|
|
673
754
|
h_pt: float = float(h.pt) if isinstance(h, Length) else 12.0
|
|
674
755
|
run_sync(
|
|
@@ -719,6 +800,7 @@ class _Column:
|
|
|
719
800
|
@width.setter
|
|
720
801
|
def width(self, value: "Length | int | None") -> None:
|
|
721
802
|
if value is None:
|
|
803
|
+
_warn_table_clear("width", cls="_Column")
|
|
722
804
|
return
|
|
723
805
|
# Mirror python-docx: width must be non-negative. Upstream
|
|
724
806
|
# uses Emu which raises ``ValueError`` for negatives. Previously
|
|
@@ -1038,16 +1120,31 @@ class _Cell:
|
|
|
1038
1120
|
from docx.styles.style import ParagraphStyle
|
|
1039
1121
|
from docx.text.paragraph import Paragraph
|
|
1040
1122
|
|
|
1041
|
-
#
|
|
1042
|
-
#
|
|
1043
|
-
#
|
|
1123
|
+
# python-docx 1.x: ``text`` is ``str`` (lxml TypeErrors on
|
|
1124
|
+
# non-str). Was: any value flowed straight to the wire
|
|
1125
|
+
# ``text`` field — SuperDoc's permissive parser swallowed or
|
|
1126
|
+
# rejected silently.
|
|
1127
|
+
if not isinstance(text, str):
|
|
1128
|
+
raise TypeError(
|
|
1129
|
+
f"_Cell.add_paragraph text requires str; got "
|
|
1130
|
+
f"{type(text).__name__} {text!r}",
|
|
1131
|
+
)
|
|
1132
|
+
# ``style`` is ``str | ParagraphStyle | None``. Was: catch-all
|
|
1133
|
+
# ``str(style)`` shipped garbage like ``"<MyStyle object at
|
|
1134
|
+
# 0x...>"`` as a style id — Word silently fell back to Normal.
|
|
1044
1135
|
style_id: str | None
|
|
1045
1136
|
if style is None:
|
|
1046
1137
|
style_id = None
|
|
1047
1138
|
elif isinstance(style, ParagraphStyle):
|
|
1048
1139
|
style_id = style.style_id
|
|
1140
|
+
elif isinstance(style, str):
|
|
1141
|
+
style_id = style
|
|
1049
1142
|
else:
|
|
1050
|
-
|
|
1143
|
+
raise TypeError(
|
|
1144
|
+
f"_Cell.add_paragraph style requires str, "
|
|
1145
|
+
f"ParagraphStyle, or None; got "
|
|
1146
|
+
f"{type(style).__name__} {style!r}",
|
|
1147
|
+
)
|
|
1051
1148
|
|
|
1052
1149
|
ids = self._inner_paragraph_ids()
|
|
1053
1150
|
if ids:
|
|
@@ -1266,6 +1363,7 @@ class _Cell:
|
|
|
1266
1363
|
from docx.enum.table import WD_ALIGN_VERTICAL
|
|
1267
1364
|
|
|
1268
1365
|
if value is None:
|
|
1366
|
+
_warn_table_clear("vertical_alignment", cls="_Cell")
|
|
1269
1367
|
return
|
|
1270
1368
|
if isinstance(value, WD_ALIGN_VERTICAL):
|
|
1271
1369
|
v: str = value.to_superdoc()
|
|
@@ -1301,6 +1399,7 @@ class _Cell:
|
|
|
1301
1399
|
@width.setter
|
|
1302
1400
|
def width(self, value: "Length | int | None") -> None:
|
|
1303
1401
|
if value is None:
|
|
1402
|
+
_warn_table_clear("width", cls="_Cell")
|
|
1304
1403
|
return
|
|
1305
1404
|
# Mirror python-docx + ``_Column.width``: cell width is unsigned
|
|
1306
1405
|
# twips; negative widths previously round-tripped to the wire
|