Lintrunner
Lintrunner is a command-line tool designed to orchestrate and run various linters across polyglot projects. It centralizes linter configuration, standardizes linter invocation via a common protocol, and aggregates results for user presentation. The current version is 0.13.0, and releases appear to be on an as-needed basis rather than a fixed cadence, reflecting its active development, particularly within the Meta/PyTorch ecosystem.
Warnings
- gotcha Lintrunner primarily functions as a command-line tool. While you can write custom linter adapters in Python that adhere to its JSON Lines output protocol, direct programmatic import of `lintrunner` as a library for general linting within Python code is not its primary use case. Its internal components are not designed for public API consumption.
- gotcha By default, `lintrunner` checks files changed in the HEAD commit or the user's working tree. Files not tracked by Git will not be linted.
- breaking Linters invoked by `lintrunner` are expected to exit with code 0, even if lint errors are reported. A non-zero exit code from a linter is treated by `lintrunner` as a 'general linter failure', indicating an issue with the linter's implementation of the protocol, rather than reported lint messages.
- gotcha Excluding patterns in `.lintrunner.toml` might not always work as expected, especially with newly added files or complex globbing. Issues have been reported where `exclude_patterns` are ignored.
- gotcha Due to its incremental linting approach, `lintrunner` might occasionally suggest unexpected or 'destructive' changes, especially when interacting with linters that are sensitive to partial file inputs.
Install
-
pip install lintrunner -
pip install lintrunner-adapters
Quickstart
# 1. Create a .lintrunner.toml configuration file
# Example .lintrunner.toml (save this to your project root)
# merge_base_with = 'main'
#
# [[linter]]
# name = 'EXAMPLE_LINTER'
# include_patterns = ['**/*.py']
# command = ['python3', '-c',
# 'import sys; import json;\n'
# 'for path in sys.stdin.read().splitlines():\n'
# ' with open(path) as f:\n'
# ' content = f.read()\n'
# ' if "TODO" in content:\n'
# ' print(json.dumps({"path": path, "line": 1, "char": 1, "code": "TODO_FOUND", "severity": "warning", "name": "TODO check", "message": "Found a TODO in the file."}))\n'
# ]
# 2. Create a dummy Python file to lint (e.g., my_file.py)
# print("This is a test file.")
# # TODO: implement this feature
# 3. Run lintrunner from your terminal in the project root:
# pip install lintrunner
# # For basic setup, you might need to run lintrunner init
# # lintrunner init # This can install various linter dependencies
# lintrunner
# Expected output for my_file.py with the EXAMPLE_LINTER:
# Path Line Char Code Severity Name Message
# -------------------- ------ ---- ---------- --------- ------------- ------------------------
# my_file.py 1 1 TODO_FOUND warning TODO check Found a TODO in the file.