refactor: solidify startup UX and engine-aware preprocessing
- Slim core deps: move ML stack to optional extras (paddle/tables/figures/scientific/full) - Lazy settings proxy with config search paths (env var, cwd, user dir) - New commands: init, demo, setup [basic|full], first-run guard on run/watch - Engine-aware preprocessing: Paddle gets original image (fixes dark mode 0.83->0.95) - Results table shows Skipped count; lazy run-dir creation - kg_ocr marked experimental with extra, Docker defaults with OCR_PIPELINE_CONFIG - 25/25 tests, ruff clean
This commit is contained in:
64
src/ocr_pipeline/onboarding.py
Normal file
64
src/ocr_pipeline/onboarding.py
Normal file
@@ -0,0 +1,64 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import platform
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
|
||||
from ocr_pipeline.config import DEFAULT_CONFIG_FILENAME, user_config_dir
|
||||
from ocr_pipeline.utils.logging import get_logger
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
CONFIG_HEADER = "# ocr-pipeline configuration (generated by `ocr-pipeline init`)\n"
|
||||
|
||||
|
||||
def default_screenshots_dir() -> Path:
|
||||
"""The directory where this OS puts screenshots by default."""
|
||||
system = platform.system().lower()
|
||||
if system == "darwin":
|
||||
return Path.home() / "Desktop"
|
||||
if system == "windows":
|
||||
return Path.home() / "Pictures" / "Screenshots"
|
||||
return Path.home() / "Pictures"
|
||||
|
||||
|
||||
def tesseract_path() -> str | None:
|
||||
"""Path to the tesseract executable, or None when it is not on PATH."""
|
||||
return shutil.which("tesseract")
|
||||
|
||||
|
||||
def tesseract_install_hint() -> str:
|
||||
"""One-line install instruction for the current platform."""
|
||||
system = platform.system().lower()
|
||||
if system == "darwin":
|
||||
return "brew install tesseract"
|
||||
if system == "windows":
|
||||
return "choco install tesseract # or https://github.com/UB-Mannheim/tesseract/wiki"
|
||||
return "sudo apt-get install tesseract-ocr # or your distro's package manager"
|
||||
|
||||
|
||||
def default_config(target_dir: Path, screenshots_dir: Path | None = None) -> dict:
|
||||
"""Minimal config content: safe Tesseract defaults, everything optional off."""
|
||||
shots = screenshots_dir or default_screenshots_dir()
|
||||
return {
|
||||
"input": {"paths": [str(shots)]},
|
||||
"ocr": {"engine": "tesseract"},
|
||||
"output": {"write_consolidated": True},
|
||||
}
|
||||
|
||||
|
||||
def write_default_config(target_dir: Path, screenshots_dir: Path | None = None) -> Path:
|
||||
"""Write a minimal config.yaml into target_dir and return its path."""
|
||||
target_dir.mkdir(parents=True, exist_ok=True)
|
||||
config_path = target_dir / DEFAULT_CONFIG_FILENAME
|
||||
body = yaml.safe_dump(default_config(target_dir, screenshots_dir), sort_keys=False)
|
||||
config_path.write_text(CONFIG_HEADER + body, encoding="utf-8")
|
||||
logger.info("config_written", path=str(config_path))
|
||||
return config_path
|
||||
|
||||
|
||||
def default_config_location(local: bool) -> Path:
|
||||
"""Where `init` writes config: cwd with --local, else the per-user config dir."""
|
||||
return Path.cwd() if local else user_config_dir()
|
||||
Reference in New Issue
Block a user