Files
meetus/doocus/output_manager.py
Mariano Gabriel ca8b3a784d doocus first ver
2026-07-05 10:08:42 -03:00

81 lines
2.9 KiB
Python

"""
Manage per-document output folders and their sidecar files.
Parallels meetus/output_manager.py but for the document contract:
docs-output/<YYYYMMDD-NNN-stem>/
content.md textified document — the product
meta.json structured metadata
thumb.jpg optional single preview image
assets/ optional embedded images / per-page text (later)
manifest.json run config + outputs inventory + source pointer
"""
from pathlib import Path
from datetime import datetime
import json
import logging
from typing import Dict, Any, Optional
from .naming import resolve_run_dir
logger = logging.getLogger(__name__)
class DocOutputManager:
"""Create and populate a run folder for one source document."""
def __init__(self, source_path: Path, base_output_dir: str = "docs-output", use_cache: bool = True):
self.source_path = Path(source_path)
self.base_output_dir = Path(base_output_dir)
self.use_cache = use_cache
self.output_dir = resolve_run_dir(self.base_output_dir, self.source_path.stem, use_cache)
logger.info("Output directory: %s", self.output_dir)
def get_path(self, filename: str) -> Path:
return self.output_dir / filename
def write_content(self, markdown: str) -> Path:
path = self.output_dir / "content.md"
path.write_text(markdown, encoding="utf-8")
return path
def write_meta(self, meta: Dict[str, Any]) -> Path:
path = self.output_dir / "meta.json"
with open(path, "w", encoding="utf-8") as f:
json.dump(meta, f, indent=2, ensure_ascii=False)
return path
def write_thumb(self, jpeg_bytes: bytes) -> Path:
path = self.output_dir / "thumb.jpg"
path.write_bytes(jpeg_bytes)
return path
def assets_dir(self) -> Path:
d = self.output_dir / "assets"
d.mkdir(exist_ok=True)
return d
def save_manifest(self, config: Dict[str, Any], outputs: Dict[str, Any], source_sha256: str) -> Path:
manifest_path = self.output_dir / "manifest.json"
manifest = {
"source": {
"name": self.source_path.name,
"path": str(self.source_path.absolute()),
"sha256": source_sha256,
},
"processed_at": datetime.now().isoformat(),
"configuration": config,
"outputs": outputs,
}
with open(manifest_path, "w", encoding="utf-8") as f:
json.dump(manifest, f, indent=2, ensure_ascii=False)
logger.info("Saved manifest: %s", manifest_path)
return manifest_path
def load_manifest(self) -> Optional[Dict[str, Any]]:
manifest_path = self.output_dir / "manifest.json"
if manifest_path.exists():
with open(manifest_path, "r", encoding="utf-8") as f:
return json.load(f)
return None