"""OCR 文档结果包的合成 fixtures(#34)。 全部**合成**: 保留 2026-10-21 实测的结构骨架(para_blocks 块类型、table/image 的嵌套 `blocks`、span 字段),一切识别文本替换为 `SYNTH-*` 占位——第三方论文内容许可不明、 医疗数据不入库(零业务假设 + P5),真实 ZIP 不提交。 """ import io import json import zipfile _BBOX = (10.0, 20.0, 110.0, 40.0) def _span(content="SYNTH-TEXT", type_="text"): return {"type": type_, "content": content, "bbox": list(_BBOX), "score": 1.0} def _text_block(content="SYNTH-TEXT", *, type_="text", bbox=_BBOX): return { "type": type_, "bbox": list(bbox), "index": 0, "lines": [{"bbox": list(bbox), "spans": [_span(content)]}], } def _body(type_, spans, bbox=_BBOX): return {"type": type_, "bbox": list(bbox), "lines": [{"bbox": list(bbox), "spans": spans}]} def _table_block(html="
SYNTH-CELL
", extra_subs=()): body = _body("table_body", [{"type": "table", "html": html, "image_path": "synth.jpg"}]) return {"type": "table", "bbox": list(_BBOX), "index": 1, "blocks": [*extra_subs, body]} def _image_block(): body = _body("image_body", [{"type": "image", "image_path": "synth.jpg"}]) return {"type": "image", "bbox": list(_BBOX), "index": 2, "blocks": [body]} def _page(blocks=None, *, page_idx=0, page_size=(612.0, 792.0), **extra): page = {"page_idx": page_idx, "page_size": list(page_size), "discarded_blocks": []} if blocks is not None: page["para_blocks"] = blocks page.update(extra) return page def _package( pages=None, *, md="# synth\n", middle=None, middle_name="doc_middle.json", md_name=None, extra=(), ): """组装结果包。`middle` 给原始 bytes 时原样写入;`md_name` 默认由 middle 名配对。""" if middle is None: middle = json.dumps({"pdf_info": pages if pages is not None else [_page([])]}).encode() if md_name is None: md_name = middle_name[: -len("_middle.json")] + ".md" buf = io.BytesIO() with zipfile.ZipFile(buf, "w") as zf: zf.writestr(middle_name, middle) if md is not None: zf.writestr(md_name, md if isinstance(md, bytes) else md.encode()) for name, data in extra: zf.writestr(name, data) return buf.getvalue()