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:

  1. Detection: Uses python_module_available (which calls importlib.util.find_spec) to identify absent Python modules.
  2. Notification: Prints a message describing the feature, missing packages, and the fallback strategy that will be used.
  3. Mode Resolution: Determines the install mode (yes, no, or ask) from the environment variable BOOK_SKILL_INSTALL_MISSING or CLI flags --install-missing / --no-install-missing, normalized via normalize_install_mode.
  4. Installation: If mode is yes or user confirms ask, runs pip install via install_python_packages.
  5. 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_MISSING to yes, no, or ask to define default behavior across sessions.
  • CLI Flags: Pass --install-missing or --no-install-missing to extract.py to override the environment variable for a single run.
  • Interactive Prompts: When mode is ask (default), the tool interactively prompts for confirmation before running pip 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 install command 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 zipfile and xml.etree.ElementTree parsing, preserving text content without metadata extraction.
  • HTML: Uses html.parser from the standard library when trafilatura or beautifulsoup4 are absent, sacrificing structural awareness for reliability.
  • RTF: Applies basic regex cleanup to strip RTF control words when striprtf is unavailable.
  • PDF Technical: Automatically downgrades to the text-heavy pipeline (pypdf/pdfminer/pdftotext) when docling is missing.
  • MOBI/AZW: Requires Calibre's ebook-convert binary 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 via normalize_install_mode.
  • Pre-flight Auditing: The --check flag runs run_dependency_check to 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →