Skip to main content

Rigorous linting and code quality setup for Python projects with pre-commit hooks

Project description

Hard-Lint for Python 🐍

Rigorous linting and code quality setup for Python projects with automatic pre-commit hooks.

Features

  • Automated Pre-commit Hooks: Validates code before every commit
    • pre-commit: Runs ruff, black, and isort
    • commit-msg: Validates messages follow Conventional Commits format
  • Strict Linting: Ruff checks for errors, complexity, and code quality
  • Synchronized Formatters: Ruff, Black, and isort configured with same profile (no conflicts)
  • Zero Configuration: Works out-of-the-box with sensible defaults
  • Multiplattform: Works on Windows, macOS, and Linux
  • Auto-setup: Single command to enable all checks

Installation

pip install hard-lint-py
# or with poetry
poetry add -D hard-lint-py

Quick Start

# 1. Install and setup hooks
hard-lint-py

# 2. Make your first commit
git add .
git commit -m "feat: initial setup"

That's it! Your project now has:

  • Ruff for fast Python linting
  • Black for code formatting
  • isort for import sorting
  • Commitlint for commit message validation

What Gets Installed

Git Hooks

Hooks are created in .hardlint/_/:

  • pre-commit: Runs before commits to validate code

    • Fixes issues with ruff check --fix
    • Formats with black
    • Sorts imports with isort
    • Validates no comments exist
  • commit-msg: Validates commit messages

    • Must follow Conventional Commits format
    • Examples: feat:, fix:, chore:, docs:, etc.

Linting Rules

Ruff Rules Enforced

Rule Category Description
E pycodestyle errors PEP 8 compliance
F Pyflakes Unused imports, undefined names
W pycodestyle warnings Code warnings
I isort Import sorting
N pep8-naming Naming conventions
C mccabe Code complexity
B flake8-bugbear Common bugs and design problems
RUF Ruff-specific Additional quality checks
UP pyupgrade Modernize Python syntax

Synchronized Formatter Configuration

All three formatters (Ruff, Black, isort) use the same profile to prevent conflicts:

Aspect Configuration Notes
Line Length 100 characters Consistent across all tools
Python Version 3.10+ Targets modern Python
Imports Profile isort: black Compatible with Black
Trailing Commas Enabled Multi-line consistency

Configuration

Auto-configured in pyproject.toml:

[tool.black]
line-length = 100
target-version = ["py310", "py311", "py312"]

[tool.isort]
profile = "black"           # Compatible with Black
line_length = 100
known_first_party = ["hard_lint_py"]

[tool.ruff]
line-length = 100
target-version = "py310"
select = ["E", "F", "W", "I", "N", "C", "B", "RUF", "UP"]

Usage

Normal workflow

# Make changes
cat > new_file.py << 'EOF'
def greet(name):
    # Greet a person by name
    return f"Hello, {name}!"
EOF

# Stage changes
git add new_file.py

# Commit (hooks will run automatically)
git commit -m "feat: add greeting function"

Pre-commit Hook Behavior

When you commit, the hook automatically:

  1. Ruff: Checks for linting issues, imports, and code quality
  2. Black: Formats code to 100-character lines
  3. isort: Sorts and organizes imports
  4. Blocks commit if any issues can't be auto-fixed

If pre-commit fails:

# Fix will be auto-applied, just re-add and commit
git add .
git commit -m "feat: your message"

If commit-msg fails

Invalid message example:

git commit -m "added this feature"  # ❌ Missing type prefix

Valid message example:

git commit -m "feat: added new feature"  # ✅ Has type prefix

Skip hooks (use with caution)

git commit -m "..." --no-verify

Configuration

All tools read from pyproject.toml. Customize as needed:

[tool.ruff]
line-length = 120
select = ["E", "F", "W"]

[tool.black]
line-length = 120

[tool.isort]
profile = "black"
line_length = 120

Troubleshooting

Hooks not running?

# Re-run installation
hard-lint-py

Commit-msg validation failing?

  • Check that your message starts with a type: feat:, fix:, chore:, etc.

Formatters conflicting with each other?

  • They shouldn't! Ruff, Black, and isort are configured with the same profile
  • If you see conflicts, run all three: ruff check --fix, black ., isort .

Line length conflicts?

  • All tools configured to 100 characters
  • Black and isort won't fight over formatting
  • Ruff respects Black's decisions (E501 ignored)

Supported Python Versions

  • Python 3.10+
  • Python 3.11
  • Python 3.12

Development

When developing with hard-lint-py:

Pre-commit Validation

Your code will be validated on every commit:

git commit -m "feat: your feature"
# Runs: ruff check --fix → black → isort → commitlint

Manual Validation

Run validation checks manually:

# All checks
make lint
make format
make test
make test-cov

# Individual tools
poetry run ruff check src/ tests/
poetry run black --check src/ tests/
poetry run isort --check-only src/ tests/

Quality Standards

  • ✅ 99% code coverage
  • ✅ No unused imports or variables
  • ✅ Consistent formatting (100 char lines)
  • ✅ Code complexity within limits
  • ✅ Modern Python syntax
  • ✅ No common bugs or design problems

License

MIT

Author

Naylson Ferreira

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hard_lint_py-0.0.0.tar.gz (5.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hard_lint_py-0.0.0-py3-none-any.whl (6.3 kB view details)

Uploaded Python 3

File details

Details for the file hard_lint_py-0.0.0.tar.gz.

File metadata

  • Download URL: hard_lint_py-0.0.0.tar.gz
  • Upload date:
  • Size: 5.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for hard_lint_py-0.0.0.tar.gz
Algorithm Hash digest
SHA256 ad0391f6a120b8ea11b81e9971906294542866800d15dab591bfd55788d77090
MD5 8ecc4a90a1aecf2a5b879b7347afcdb5
BLAKE2b-256 fe289c0cafaed4c39271e3d05b0a2f8193af3e02723e76f8eb253bdc7e163590

See more details on using hashes here.

Provenance

The following attestation bundles were made for hard_lint_py-0.0.0.tar.gz:

Publisher: publish.yml on naylsonferreira/hard-lint-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file hard_lint_py-0.0.0-py3-none-any.whl.

File metadata

  • Download URL: hard_lint_py-0.0.0-py3-none-any.whl
  • Upload date:
  • Size: 6.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for hard_lint_py-0.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9edd90bc5b274e58d730b92192b254ffc223e5a074429d153d931e25fe1a5c7b
MD5 f2061b2e5c0df727ecf38c074011a8c3
BLAKE2b-256 4c0cec179b2fc7cf21c8bdabeafd8d718604e90564c0aadc818da8a2094e8dba

See more details on using hashes here.

Provenance

The following attestation bundles were made for hard_lint_py-0.0.0-py3-none-any.whl:

Publisher: publish.yml on naylsonferreira/hard-lint-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page