scanlayer
Docs / Help

Roadmap & Limitations

An honest list of what is missing or deliberately out of scope, written from reading the source directly rather than from a promise. Some of these are gaps worth fixing; some are boundaries the project draws on purpose. Both kinds are listed here so neither gets mistaken for the other, or for a bug.

Packaging

  • requirements.txt pins no exact versions (only lower bounds), so two installs a few months apart are not guaranteed to resolve to identical dependency versions. There is no lockfile.
  • PyYAML is an optional dependency (scanlayer[yaml]) needed only for .yaml/.yml config files; a base install without it is fully functional for everything else, including .json config files.

CLI gaps

  • There is no --version / -V flag. Get the version from the library instead: python -c "import scanlayer; print(scanlayer.__version__)".
  • There is no way to pass Tesseract configuration beyond PSM, OEM, language, and the whitelist/blacklist (e.g. custom Tesseract config variables) short of forking the process launch in ocr/engine.py.

Tests exist, and CI runs them on every PR

Tests, linting, and publishing are all automated A tests/ directory covers config.py (including platform-specific Tesseract discovery), utils/validators.py, layout/columns.py, ocr/export.py, pdf/fonts.py, pdf/builder.py, the --dry-run flag, and an end-to-end integration test in main.py (the last one needs a real Tesseract install and skips automatically when one isn't found). Run it with pytest after pip install -r requirements.txt (which includes pytest). In CI, the test suite (with Tesseract, including English and French traineddata, plus poppler installed) and ruff run automatically on every push and every pull request, and each release is built and published to PyPI automatically when its version tag is pushed. Before relying on new Tesseract versions or platforms, check Contributing for where coverage is thinnest.

Deliberate scope boundaries

These are not bugs. They are places the pipeline stops on purpose, documented here so a surprising result is not mistaken for a defect.

AreaWhat it does not doWhy
Multi-column layoutDetect or reorder table/grid layouts.A table's narrow, per-row gutters are a structurally different problem from a two-column article; the heuristics that make prose reordering reliable (wide, consistent full-height gutters) would misfire constantly on tabular data.
OCRAttempt handwriting recognition.Tesseract's LSTM engine targets printed text; handwriting needs a different model family entirely.
Output formatsOffer a multi-page schema for txt/json/tsv/hocr.There is no single obvious way to represent "page 3 of 7" in a flat text or TSV file; PDF alone supports --merge.
Export functionsApply multi-column reordering inside to_text/to_json/to_tsv/to_hocr themselves.That reordering happens once, upstream, in the shared pipeline (convert()/convert_merge()); calling the exporters directly on raw extract_words() output bypasses it, see Library API.
Language supportGuarantee a font for every script without the caller providing one.The automatic font selection covers a CJK CID font, bundled DejaVu Sans, and a Helvetica fallback; scripts outside that coverage (Arabic, Hebrew, Thai, Devanagari, and others) need --font/font_path= pointed at a TTF that covers them, or the invisible text layer may not render correctly for those glyphs even though OCR itself may still recognize the text.

Other things to know before relying on this

  • No async API: convert()/convert_batch()/convert_merge() are synchronous and blocking. Parallelism only exists internally, across PSM candidates within a single file's OCR pass.
  • No built-in retry/backoff for a failed Tesseract invocation within a batch; a per-file failure is recorded and the batch moves on, but that one file is not automatically retried.
  • No streaming API for very large batches; convert_batch() returns one BatchResult once every file has been processed, rather than yielding results as they complete.
Found something else missing? File an issue, or see Contributing to send a fix directly.