CoolFace
Apppublic

apodex/frontier-agent-demo

sourceHugging Faceapache-2.0updated 1mo agoView on Hugging Face
14likes
_reader_docx.py70 linesDownload Raw Back to tools
1 2import shutil3import subprocess4 5 6def _doc_to_docx(path: str):7    """Legacy .doc (OLE binary, readable by neither pandoc nor python-docx) → a LibreOffice-converted .docx temp copy.8    Returns the new path; None when soffice is unavailable or the conversion fails."""9    import os10    import tempfile11    if not shutil.which("soffice"):12        return None13    outdir = tempfile.mkdtemp(prefix="doc2docx_")14    env = dict(os.environ)15    env["SAL_USE_VCLPLUGIN"] = "svp"16    try:17        subprocess.run(["soffice", "--headless", "--convert-to", "docx", "--outdir", outdir, path],18                       capture_output=True, timeout=120, env=env)19    except Exception:20        return None21    new = os.path.join(outdir, os.path.splitext(os.path.basename(path))[0] + ".docx")22    return new if os.path.exists(new) else None23 24 25def _docx_to_md(path: str) -> str:26    """docx → markdown. The base path is pandoc → markdown27    (keeps run-level formatting signals: bold / italic / strikethrough / lists / tables, which is more than python-docx's plain text).28    When pandoc is unavailable it falls back to python-docx (text + heading levels only, run-level formatting lost).29    A legacy .doc is converted to .docx by LibreOffice first and then takes the same path.30    """31    if path.lower().endswith(".doc"):32        conv = _doc_to_docx(path)33        if not conv:34            return ("[read_file] .doc (legacy Word) detected but LibreOffice (soffice) is "35                    "unavailable for .doc→.docx conversion; cannot read.")36        path = conv37    if shutil.which("pandoc"):38        try:39            r = subprocess.run(40                ["pandoc", "-f", "docx", "-t", "markdown", "--wrap=none", path],41                capture_output=True, text=True, timeout=120,42            )43            if r.returncode == 0 and r.stdout.strip():44                return r.stdout45        except Exception:46            pass  # fall through to the python-docx fallback47 48    # Fallback: python-docx when pandoc is absent (plain text + headings)49    _ensure("docx", "python-docx")50    import docx51    d = docx.Document(path)52    out = []53    for p in d.paragraphs:54        if not p.text.strip():55            continue56        style = (p.style.name or "").lower()57        if style.startswith("heading"):58            lvl = "".join(c for c in style if c.isdigit()) or "1"59            out.append("#" * min(int(lvl), 6) + " " + p.text)60        else:61            out.append(p.text)62    for ti, t in enumerate(d.tables):63        out.append(f"\n**Table {ti + 1}:**")64        for ri, row in enumerate(t.rows):65            cells = [c.text for c in row.cells]66            out.append("| " + " | ".join(cells) + " |")67            if ri == 0:68                out.append("| " + " | ".join("---" for _ in cells) + " |")69    return "\n".join(out)70