# How book-to-skill Handles Missing Dependencies for Different Document Formats

> Discover how book-to-skill efficiently manages missing dependencies for various document formats with its centralized registry and automatic installation options.

- Repository: [Virgilio Junior/book-to-skill](https://github.com/virgiliojr94/book-to-skill)
- Tags: internals
- Published: 2026-08-24

---

**book-to-skill manages missing dependencies through a centralized registry in [`book_to_skill/dependencies.py`](https://github.com/virgiliojr94/book-to-skill/blob/main/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`](https://github.com/virgiliojr94/book-to-skill/blob/main/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/main/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`](https://github.com/virgiliojr94/book-to-skill/blob/main/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).

```python

# 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`](https://github.com/virgiliojr94/book-to-skill/blob/main/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`](https://github.com/virgiliojr94/book-to-skill/blob/main/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:

```bash

# 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`](https://github.com/virgiliojr94/book-to-skill/blob/main/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`](https://github.com/virgiliojr94/book-to-skill/blob/main/pdf.py), [`epub.py`](https://github.com/virgiliojr94/book-to-skill/blob/main/epub.py), [`docx.py`](https://github.com/virgiliojr94/book-to-skill/blob/main/docx.py), [`html.py`](https://github.com/virgiliojr94/book-to-skill/blob/main/html.py), [`rtf.py`](https://github.com/virgiliojr94/book-to-skill/blob/main/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`](https://github.com/virgiliojr94/book-to-skill/blob/main/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`](https://github.com/virgiliojr94/book-to-skill/blob/main/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`](https://github.com/virgiliojr94/book-to-skill/blob/main/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.