How book-to-skill Handles Missing Dependencies for Different Document Formats
book-to-skill manages missing dependencies through a centralized registry in book_to_skill/dependencies.py that assigns each document format to a dependency group, offering automatic installation, user-configurable modes, and graceful fallbacks to standard-library parsers when optional packages are absent.
The book-to-skill extraction pipeline treats third-party libraries as optional enhancements rather than hard requirements. By isolating dependency logic in a dedicated module, the tool ensures that missing packages never block core functionality for most formats, while clearly communicating installation options to the user.
Dependency Groups and Format-Specific Requirements
At startup, the extractor calls prepare_dependencies(ext, extraction_mode, install_mode) (defined in book_to_skill/dependencies.py) to look up a dependency group matching the file extension. Each group specifies optional Python modules, optional system binaries, and a fallback behavior if both are missing.
| Format | Python Modules (optional) | System Commands (optional) | Fallback Behaviour |
|---|---|---|---|
| PDF (text‑heavy) | pypdf, pdfminer (any one) |
pdftotext (poppler‑utils) |
Use any available parser; otherwise a plain‑text fallback chain |
| PDF (technical) | docling |
— | If missing, fall back to the text‑heavy chain |
| EPUB | ebooklib, bs4 (both required) |
— | If any missing, use the std‑lib zipfile parser |
| DOCX | docx |
— | If missing, use the std‑lib ZIP/XML parser |
| HTML | trafilatura, bs4 (any one) |
— | If missing, fall back to the std‑lib html.parser |
| RTF | striprtf |
— | If missing, perform a basic regex cleanup |
| MOBI / AZW / AZW3 | — | ebook-convert (Calibre) – required |
No fallback; Calibre must be present |
The groups are defined in [book_to_skill/dependencies.py](https://github.com/virgiliojr94/book-to-skill/blob/master/book_to_skill/dependencies.py#L13-L70), while PyPI package name mappings reside in book_to_skill/config.py under the PYTHON_DEPENDENCIES dictionary.
Runtime Detection and Resolution Workflow
When processing a file, prepare_dependencies selects the appropriate group and invokes offer_dependency_install. This helper executes a five-step resolution protocol:
- Detection: Uses
python_module_available(which callsimportlib.util.find_spec) to identify absent Python modules. - Notification: Prints a message describing the feature, missing packages, and the fallback strategy that will be used.
- Mode Resolution: Determines the install mode (
yes,no, orask) from the environment variableBOOK_SKILL_INSTALL_MISSINGor CLI flags--install-missing/--no-install-missing, normalized vianormalize_install_mode. - Installation: If mode is
yesor user confirmsask, runspip installviainstall_python_packages. - Fallback Execution: If installation is declined or the environment is non-interactive, proceeds with the alternative parser (or aborts for required formats like MOBI/AZW).
# Example: run the extractor with automatic installation of missing optional deps
# (equivalent to CLI flag `--install-missing yes`)
from book_to_skill.utils import resolve_input_files, extract_single_file
from book_to_skill.dependencies import normalize_install_mode, prepare_dependencies
files = resolve_input_files(["my_book.pdf"])
install_mode = normalize_install_mode(["--install-missing", "yes"])
for f in files:
ext = f.suffix
# Choose "technical" mode for PDFs that need tables/formulas
prepare_dependencies(ext, extraction_mode="technical", install_mode=install_mode)
result = extract_single_file(f, extraction_mode="technical", install_mode=install_mode)
print(result["full_text"][:200]) # preview
User-Controlled Installation Modes
You control dependency installation behavior through three mechanisms defined in dependencies.py:
- Environment Variable: Set
BOOK_SKILL_INSTALL_MISSINGtoyes,no, oraskto define default behavior across sessions. - CLI Flags: Pass
--install-missingor--no-install-missingtoextract.pyto override the environment variable for a single run. - Interactive Prompts: When mode is
ask(default), the tool interactively prompts for confirmation before runningpip install.
The normalize_install_mode function reconciles these inputs, ensuring that non-interactive environments safely default to no rather than hanging on input.
Auditing Dependencies with --check
Before processing a library of books, run the dependency audit to verify your environment:
# CLI: quick audit of all optional dependencies
python -m book_to_skill.extract --check
This invokes run_dependency_check (lines 44-71 in dependencies.py), which walks all dependency groups and reports:
- Presence:
✓for installed modules/binaries,✗for missing ones. - Isolation Hints: Flags when a binary exists (e.g.,
/usr/local/bin/pypdf) but the Python module is not importable. - Consolidated Install Command: Suggests a single
pip installcommand for all missing optional packages.
Example output:
PDF (text‑heavy)
✗ python: pypdf
↳ a `pypdf` command exists at /usr/local/bin/pypdf, so it is installed in an isolated environment …
✗ python: pdfminer.six
✗ system: pdftotext (poppler-utils)
→ fallback available (install for best quality) — any one of pdftotext / pypdf / pdfminer is enough
…
All optional dependencies are installed. You're ready for every format.
Format-Specific Fallback Deep Dive
Each parser module (pdf.py, epub.py, docx.py, html.py, rtf.py) assumes its optimized dependencies are present but gracefully degrades when they are missing:
- EPUB/DOCX: Falls back to
zipfileandxml.etree.ElementTreeparsing, preserving text content without metadata extraction. - HTML: Uses
html.parserfrom the standard library whentrafilaturaorbeautifulsoup4are absent, sacrificing structural awareness for reliability. - RTF: Applies basic regex cleanup to strip RTF control words when
striprtfis unavailable. - PDF Technical: Automatically downgrades to the text-heavy pipeline (pypdf/pdfminer/pdftotext) when
doclingis missing. - MOBI/AZW: Requires Calibre's
ebook-convertbinary with no fallback, as these proprietary formats lack pure-Python parsers.
Summary
- Centralized Registry: All dependency logic lives in
book_to_skill/dependencies.py, mapping extensions to optional Python modules and system binaries. - Graceful Degradation: Most formats offer standard-library fallbacks (ZIP parsing, HTML parser, regex cleanup) when third-party libraries are absent.
- User Control: Installation behavior is governed by
BOOK_SKILL_INSTALL_MISSING, CLI flags, and interactive prompts vianormalize_install_mode. - Pre-flight Auditing: The
--checkflag runsrun_dependency_checkto identify missing dependencies before extraction begins. - Hard Requirements: Only MOBI/AZW/AZW3 formats require a specific external binary (Calibre) with no fallback mechanism.
Frequently Asked Questions
What happens if Calibre is not installed when processing MOBI or AZW files?
Unlike other formats that offer fallback parsers, MOBI, AZW, and AZW3 processing requires the ebook-convert binary from Calibre. If the system command is missing, prepare_dependencies detects this as a hard requirement and aborts with an error message directing you to install Calibre. There is no standard-library fallback for these proprietary formats.
Can I force automatic installation of all missing Python packages without prompts?
Yes. Set the environment variable BOOK_SKILL_INSTALL_MISSING=yes or pass the --install-missing flag when running extract.py. The normalize_install_mode function will interpret this as yes, triggering install_python_packages for any missing optional dependencies without interactive confirmation.
How does book-to-skill determine if a Python module is available?
The utility function python_module_available in dependencies.py uses importlib.util.find_spec to check if a module can be imported without actually loading it. This lightweight check avoids import side effects while accurately detecting whether a package is installed in the current Python environment.
What's the difference between PDF text-heavy and technical modes regarding dependencies?
Text-heavy PDF mode accepts any available parser from pypdf, pdfminer.six, or the system pdftotext command, falling back through the chain until one succeeds. Technical PDF mode specifically requires the docling library to accurately extract tables, formulas, and complex layouts. If docling is missing, the extractor automatically falls back to the text-heavy chain, potentially losing structural formatting but preserving raw text content.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →