Files
stack/tests/rex/comments/test_extract_docx.py
kert b2ad400764 feat(comments): DOCX/text extract + combined.md writer (refs #253)
- extract_attachment now dispatches PDF/DOCX/TXT/HTML; DOCX via
  python-docx, text-like via plain read with cheap HTML strip.
- combine.py writes one combined.md per comment dir with YAML
  frontmatter (per-attachment status + chars) and per-section body.
- extract_comment is idempotent (existing combined.md is a no-op
  unless force=True).
- parse_combined() splits frontmatter ↔ body for downstream consumers.

Walker + DuckDB view land in the next batch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 15:42:32 -04:00

45 lines
1.2 KiB
Python

"""DOCX extraction via python-docx."""
from __future__ import annotations
from pathlib import Path
import docx
from rex.comments import extract_attachment
def _make_docx(path: Path, paragraphs: list[str]) -> Path:
d = docx.Document()
for p in paragraphs:
d.add_paragraph(p)
d.save(str(path))
return path
def test_extract_docx_with_text(tmp_path: Path):
p = _make_docx(
tmp_path / "a.docx",
["First paragraph of comment letter.", "Second paragraph with details."],
)
result = extract_attachment(p)
assert result.status == "ok"
assert "First paragraph" in result.text
assert "Second paragraph" in result.text
def test_extract_docx_empty_marked_ocr_needed(tmp_path: Path):
p = _make_docx(tmp_path / "empty.docx", [])
result = extract_attachment(p)
# No paragraphs ⇒ 0 chars ⇒ ocr_needed (we treat empty docx the same as
# an image-only pdf — body lives somewhere we can't read it).
assert result.status == "ocr_needed"
assert result.chars <= 50
def test_extract_docx_corrupted_marked_failed(tmp_path: Path):
bad = tmp_path / "bad.docx"
bad.write_bytes(b"this is not a docx zip")
result = extract_attachment(bad)
assert result.status == "failed"