Skip to main content

LineCover

Code coverage enforcement tool with flake8-style reporting.

Overview

LineCover is a command-line tool that analyzes pytest coverage reports and enforces code quality standards. It reports violations in flake8-compatible format, making it easy to integrate into CI/CD pipelines and pre-commit hooks.

Features

  • Line Coverage Enforcement: Check that each file meets minimum line coverage thresholds
  • Function/Class Coverage: Ensure functions and classes are adequately tested
  • Total Project Coverage: Enforce overall project coverage requirements
  • Complexity Checks: Detect files with too many functions/classes or too many lines
  • Flake8-Style Output: Standard violation format for easy integration with existing tools
  • Flexible Execution: Run pytest automatically or analyze existing coverage data
  • Pre-commit Integration: Use as a pre-commit hook to enforce coverage on every commit

Installation

uv add linecover

Or install from source:

git clone https://github.com/yourusername/linecover.git
cd linecover
uv sync

Quick Start

Run linecover on your project:

# Run pytest and check that all files have 90% coverage
uv run linecover --run-pytest --line-threshold 90

# Check total project coverage is above 90%
uv run linecover --total-threshold 90

# Check for code complexity issues
uv run linecover --max-units 10 --max-lines 500

# Combine multiple checks
uv run linecover --run-pytest \
    --line-threshold 90 \
    --func-threshold 85 \
    --total-threshold 90 \
    --max-units 10 \
    --max-lines 600

Command-Line Options

Coverage Thresholds

  • --line-threshold PERCENT: Minimum line coverage percentage per file (default: none)
  • --func-threshold PERCENT: Minimum function/class coverage percentage per file (default: none)
  • --total-threshold PERCENT: Minimum total project coverage percentage (default: none)

Complexity Checks

  • --max-units N: Maximum number of functions/classes per file (default: none)
  • --max-lines N: Maximum lines per file (default: none)

Execution Options

  • --run-pytest: Execute pytest --cov before analyzing coverage (default: false)

Logging Options

  • --logfile PATH: Write logs to file (default: stderr only)
  • --loglevel LEVEL: Set log level - DEBUG, INFO, WARNING, ERROR (default: INFO)

Error Codes

LineCover reports violations using flake8-style error codes:

  • COV001: File line coverage below threshold
  • COV002: Function/class coverage below threshold
  • COV003: Too many units (functions/classes) in a file
  • COV004: File exceeds maximum line count

Output Format

Violations are reported in flake8-compatible format:

path/to/file.py:1:1: COV001 Line coverage 75.0% is below threshold 90.0%
path/to/file.py:1:1: COV002 Function coverage 60.0% is below threshold 85.0%
complex.py:1:1: COV003 File has 15 units (functions+classes), exceeds maximum 10
long_file.py:1:1: COV004 File has 650 lines, exceeds maximum 600

Pre-commit Integration

Add LineCover to your .pre-commit-config.yaml:

repos:
  - repo: https://github.com/yourusername/linecover
    rev: v0.1.0
    hooks:
      - id: linecover
        args:
          - '--run-pytest'
          - '--line-threshold'
          - '90'
          - '--total-threshold'
          - '90'

Or use as a local hook if linecover is installed in your project:

repos:
  - repo: local
    hooks:
      - id: linecover
        name: LineCover
        entry: uv run linecover
        language: system
        pass_filenames: false
        always_run: true
        args: ['--run-pytest', '--total-threshold', '90']

CI/CD Integration

GitHub Actions

name: Coverage Check
on: [push, pull_request]
jobs:
  coverage:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'
      - name: Install uv
        run: pip install uv
      - name: Install dependencies
        run: uv sync
      - name: Run linecover
        run: uv run linecover --run-pytest --line-threshold 90 --total-threshold 90

Exit Codes

  • 0: No violations found
  • 1: Violations found or error occurred

Examples

Enforcing 90% Line Coverage Per File

uv run linecover --run-pytest --line-threshold 90

Output if violations found:

src/parser.py:1:1: COV001 Line coverage 75.0% is below threshold 90.0%
src/utils.py:1:1: COV001 Line coverage 82.5% is below threshold 90.0%

Checking Project-Wide Coverage

uv run linecover --total-threshold 90

Output if project coverage is low:

<total>:1:1: COV001 Total project coverage 85.0% is below threshold 90.0%

Finding Complex Files

uv run linecover --max-units 10 --max-lines 500

Output for files that are too complex:

src/legacy.py:1:1: COV003 File has 25 units (functions+classes), exceeds maximum 10
src/monolith.py:1:1: COV004 File has 1250 lines, exceeds maximum 500

Development

Project Structure

linecover/
├── linecover/
│   ├── __init__.py
│   ├── cli.py          # Click-based CLI interface
│   ├── runner.py       # Pytest execution
│   ├── parser.py       # Coverage analysis with AST
│   ├── checker.py      # Threshold validation
│   └── reporter.py     # Flake8-style output
├── tests/
│   ├── test_cli.py
│   ├── test_runner.py
│   ├── test_parser.py
│   ├── test_checker.py
│   └── test_reporter.py
├── pyproject.toml
├── .pre-commit-config.yaml
├── .pre-commit-hooks.yaml
└── README.md

Running Tests

# Run all tests
uv run pytest

# Run tests with coverage
uv run pytest --cov=linecover --cov-report=term-missing

# Run linecover on itself
uv run linecover --run-pytest --total-threshold 90

Technology Stack

  • Python 3.12+ with modern type hints (str | None instead of Optional)
  • uv for fast dependency management
  • click for CLI interface with automatic help generation
  • loguru for structured logging
  • coverage.py for reading pytest coverage data
  • AST parsing to count functions, classes, and code lines
  • pytest for testing framework
  • pre-commit for code quality automation

Code Quality

This project maintains high code quality standards:

  • 97%+ test coverage
  • Type hints on all functions
  • Pre-commit hooks for formatting (ruff, mypy)
  • Self-testing with linecover

License

MIT

Contributing

Contributions welcome! Please ensure:

  1. Tests pass: uv run pytest --cov
  2. Coverage stays above 90%: uv run linecover --run-pytest --total-threshold 90
  3. Pre-commit hooks pass: pre-commit run --all-files
  4. Type hints are included for all new functions
  5. Docstrings follow Google style

Development Workflow

# Clone and setup
git clone https://github.com/yourusername/linecover.git
cd linecover
uv sync

# Install pre-commit hooks
pre-commit install

# Make changes and test
uv run pytest
uv run linecover --run-pytest --total-threshold 90

# Commit (pre-commit hooks will run automatically)
git commit -m "Your changes"

Comparison with Other Tools

Feature LineCover pytest-cov coverage.py
Flake8-style output ✅ ❌ ❌
Per-file thresholds ✅ ❌ ⚠️ (limited)
Complexity checks ✅ ❌ ❌
Pre-commit integration ✅ ⚠️ (manual) ⚠️ (manual)
Exit code on failure ✅ ✅ ✅
AST-based metrics ✅ ❌ ❌

FAQ

Q: Why does linecover exist when coverage.py already exists?

A: LineCover adds enforcement capabilities with flake8-compatible output, making it easy to integrate into existing workflows. It also adds complexity checks (max units, max lines) that coverage.py doesn't provide.

Q: Can I use linecover without pytest?

A: LineCover requires a .coverage file generated by coverage.py. While pytest is the recommended way to generate this, you can use coverage.py directly with any test framework.

Q: Does linecover modify my code?

A: No, linecover only analyzes coverage data and reports violations. It never modifies source files.

Q: Can I enforce different thresholds for different files?

A: Currently, linecover enforces the same thresholds across all files. File-specific thresholds may be added in a future release.

Q: What happens if pytest fails?

A: If --run-pytest is used and pytest fails, linecover will still analyze coverage for any tests that ran. This allows you to see which files need more coverage even when tests fail.

Changelog

v0.1.0 (2025-12-23)

  • Initial release
  • Core functionality: coverage parsing, threshold checking, reporting
  • Pre-commit hook support
  • CLI with logging options
  • 97%+ test coverage
  • AST-based complexity metrics

Metadata

Release files for linecover-hook 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for linecover-hook 0.1.0
File Size Uploaded Provenance Actions
linecover_hook-0.1.0.tar.gz 29.5 kB Without provenance Details for linecover_hook-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for linecover-hook 0.1.0
File Interpreter ABI Platform Actions
linecover_hook-0.1.0-py3-none-any.whl Python 3 none any Details for linecover_hook-0.1.0-py3-none-any.whl

Total release size: 43.4 kB

Release files / linecover_hook-0.1.0.tar.gz

Download URL linecover_hook-0.1.0.tar.gz
Size 29.5 kB
Tags Source
SHA-256 checksum
How to use checksums
e20d72dc4ad80d6f85daafcf313d0bd55a5ccd43b9cad0d1f20ef721bbec1478
BLAKE2b-256 checksum
How to use checksums
8256aee827693c1337513b9f7cdc8b842c2e9340382eb1598936dcad123f1abf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.5

Release files / linecover_hook-0.1.0-py3-none-any.whl

Download URL linecover_hook-0.1.0-py3-none-any.whl
Size 13.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ab91601fde588212b224f601b9971cd9921e9f5deb1e193341fb935c3340daf7
BLAKE2b-256 checksum
How to use checksums
c0a0865282ef315748a4462501bbeee90a978f74d006d1368e4781d0911bffa8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.5

Security for linecover-hook 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page