Code coverage enforcement tool with flake8-style reporting
Project description
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: Executepytest --covbefore 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 | Noneinstead ofOptional) - 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:
- Tests pass:
uv run pytest --cov - Coverage stays above 90%:
uv run linecover --run-pytest --total-threshold 90 - Pre-commit hooks pass:
pre-commit run --all-files - Type hints are included for all new functions
- 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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file linecover_hook-0.1.0.tar.gz.
File metadata
- Download URL: linecover_hook-0.1.0.tar.gz
- Upload date:
- Size: 29.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e20d72dc4ad80d6f85daafcf313d0bd55a5ccd43b9cad0d1f20ef721bbec1478
|
|
| MD5 |
143a10806fa3d7295dbd19ff02e2c761
|
|
| BLAKE2b-256 |
8256aee827693c1337513b9f7cdc8b842c2e9340382eb1598936dcad123f1abf
|
File details
Details for the file linecover_hook-0.1.0-py3-none-any.whl.
File metadata
- Download URL: linecover_hook-0.1.0-py3-none-any.whl
- Upload date:
- Size: 13.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ab91601fde588212b224f601b9971cd9921e9f5deb1e193341fb935c3340daf7
|
|
| MD5 |
7ab0d74287da592e6635806a2137bd70
|
|
| BLAKE2b-256 |
c0a0865282ef315748a4462501bbeee90a978f74d006d1368e4781d0911bffa8
|