Cross-platform lightweight PDF toolkit. CLI-first (argparse), GUI (Tkinter). qpdf must be installed separately (scoop / brew / apt).
- A — Major: architecture rewrite, first stable release
- B — Feature: new commands, changed UX
- C — Patch: performance, polish, bug fixes (user-facing unchanged)
Current: 0.3.2
UI (cli.py / gui.py) → Core (pure functions) → Adapters (external tools)
↓ ↓
services/ adapters/
worker.py (threading) qpdf_adapter.py (subprocess + cancel_event)
task_manager.py fitz_adapter.py (PyMuPDF)
CLI ──→ core/ ──→ adapters/ (direct calls)
GUI ──→ services/worker ──→ core/ ──→ adapters/ (threaded, queue.Queue)
- GUI launched via: pdf-lite gui
- GUI = 7 tabs (Split / Merge / Extract / Compress / PDF→Img / Img→PDF / Info)
- Shared bottom bar: progress, cancel, timeout, log
- Core = stateless functions, no UI dependencies, return/raise
- Adapters = wrap
subprocess/ C libraries - Worker =
threading.Thread+queue.Queue, GUI polls viaafter()
- Killable subprocess:
qpdf_adapter.run_qpdf()acceptscancel_event— polls every 100ms, kills on signal - No bundled qpdf: user must install via system package manager; adapter detects at runtime
- Output follows input: default output path = input file's directory (not CWD)
- Progress: qpdf = heartbeat dots (10s); PyMuPDF = tqdm per-page
- Errors: always print
[OK]/[FAIL]prefix - Language: CLI help in English, documentation bilingual (EN + zh-CN)
Core (bundled via PyInstaller): PyMuPDF, img2pdf, tqdm, Pillow, lxml
Not bundled (must be on PATH): qpdf
Planned / experimental: weasyprint, dxpdf, python-docx, markdown (not yet in dist)
conda activate pdf_lite
pip install pytest
python -m pytest tests/ -vAlways run tests before committing.
conda activate pdf_lite
pyinstaller pdf-lite.spec
# output: dist/pdf-lite/