scanlayer
Docs / Help

Contributing

The full guide lives at CONTRIBUTING.md in the repository root; this page mirrors the essentials.

Tests and linting run in CI on every push and pull request Run pytest after installing the test extra; CI also uploads coverage to Codecov. A few of the newer or trickier modules still have no coverage, see Adding tests below.

Development setup

bash
git clone https://github.com/Hyacinthe-primus/scanlayer.git
cd scanlayer
python -m venv .venv
source .venv/bin/activate   # .venv\Scripts\activate on Windows
pip install -r requirements.txt   # from the repo root, next to scanlayer/
pip install -e .

You will also need Tesseract OCR (and poppler, for PDF-input work), see Installation.

Project layout

text
scanlayer/
├── __init__.py               # public API: convert, convert_batch, convert_merge, configure
├── main.py                    # the top-level convert()/convert_batch()/convert_merge()
├── config.py                   # all tunables, Tesseract/poppler discovery
├── cli/                        # argparse CLI: parser.py, run.py, dry_run.py
├── preprocessing/enhance.py      # EXIF/OSD/deskew, illumination, denoise, CLAHE, sharpen
├── ocr/engine.py                 # PSM candidate racing, Tesseract invocation
├── ocr/export.py                 # txt/json/tsv/hocr exporters
├── layout/columns.py              # multi-column reading-order reconstruction
├── pdf/builder.py                  # searchable PDF construction (single + multi-page)
├── pdf/fonts.py                     # automatic font selection
└── utils/                            # validators, exceptions, logging, debug-image overlay

Making a change

  1. Open an issue first for anything non-trivial (new flags, a changed default, anything touching the exception hierarchy). Small, obviously-correct fixes can go straight to a PR.
  2. Keep the CLI and library in sync: every capability should be reachable both ways, with matching parameter names (--langlang=).
  3. Respect the two-tier exception hierarchy: a failed precondition is a ValidationError subclass; an operational failure mid-stage is a PipelineError subclass. Map any new exception to a CLI exit code. See Library API → Exceptions.
  4. Never let OCR-only processing touch the visual background: background and ocr_image stay separate throughout preprocessing/enhance.py.
  5. Update the docs in the same PR: new CLI flag → CLI Reference; new library parameter → Library API; new default → Configuration; new capability → Feature Catalog.

Adding tests

A tests/ directory already exists, covering config.py, ocr/export.py, layout/columns.py, pdf/fonts.py, pdf/builder.py, and an end-to-end convert() test (skipped automatically without a real Tesseract install). Run it with pytest after installing requirements.txt (which includes pytest). Coverage gaps worth closing next, in priority order:

  1. utils/validators.py: pure functions, no Tesseract required, and not yet exercised directly (only indirectly, through the integration test).
  2. preprocessing/enhance.py: EXIF/OSD/deskew, illumination, denoise; needs fixture images with known rotation/lighting defects.
  3. ocr/engine.py: the PSM-candidate racing logic, with a real or mocked Tesseract invocation.
  4. More end-to-end cases: a genuine multi-column sample, a rotated sample, a blank-page sample, asserting on word-count/confidence ranges rather than exact OCR text.

Submitting

  • One logical change per PR.
  • Describe what you tested it against (image type, OS, Tesseract version); CI runs the suite on push, but a manual check of your actual scenario is still welcome.
  • Reference the issue you opened, if applicable.

By contributing, you agree your contribution is licensed under this project's MIT License.