A Pylint-style scoring system for Ruff linter output
Project description
Ruff Score 🎯
A Pylint-style scoring system for Ruff linter output. Get a numerical quality score (0-10) for your Python code based on Ruff's analysis, using a rule-category mapping that covers every prefix in Ruff's rule set.
Features
- 🎯 Pylint-style scoring: Familiar 0-10 quality score system, using Pylint's own formula
- 🔧 Ruff integration: Built on top of the fast Ruff linter
- 🗂️ Full rule coverage: Every Ruff prefix (E, F, PLE/PLC/PLR/PLW, ASYNC, S, TRY, RUF, and 40+ more) is mapped to a Pylint-style category and severity weight — not just a handful of common ones
- ⚖️ Two-level weighting: Issues are bucketed into
error/warning/convention/refactor, and within a category, individual rules can carry different weights (e.g. a SQL-injection finding counts for more than a strayprint) - 📊 Detailed reports: Categorized issue breakdown with a printable summary
- 📁 File & directory support: Analyze single files or entire projects
- ⚙️ Configurable: Use your existing Ruff configuration file, and override weights/categories in Python
Installation
pip install ruff-score
Quick Start
from ruff_score import RuffScorer
scorer = RuffScorer()
# Score a single file
result = scorer.score_file("myfile.py")
print(f"Score: {result['score']:.2f}/10.00")
# Score a directory
result = scorer.score_directory("src/")
scorer.print_report(result)
# Score against a specific Ruff config
result = scorer.score_directory("src/", config_file="pyproject.toml")
How It Works
Ruff Score uses the same scoring formula as Pylint:
Score = 10.0 - ((5*errors + warnings + refactor + convention) / statements * 10)
statements is the number of AST statement nodes in the analyzed file(s), and errors / warnings / refactor / convention are the weighted issue totals for each category — not just raw counts. So a category's contribution to the score is the sum of each issue's individual rule weight, which means two "warning"-category issues aren't necessarily worth the same amount if one rule is riskier than another.
Rule Categories & Weights
Every Ruff prefix is mapped to one of four Pylint-style categories, based on Ruff's documented rule set:
| Category | Meaning | Example prefixes | Typical weight |
|---|---|---|---|
| Error | Real bugs / correctness issues | E (pycodestyle), F (Pyflakes), PLE (Pylint errors), AIR (Airflow) |
3–5 |
| Warning | Security risks and likely-bug patterns | S (bandit/security), B (bugbear), ASYNC, TRY, PERF, T20/T10, DTZ, PLW |
1–4 |
| Convention | Naming, docs, style, imports | N (naming), D (docstrings), ANN, I (isort), Q, COM, PLC |
1 |
| Refactor | Modernization / simplification | UP (pyupgrade), SIM (simplify), PLR, PTH, C4, RUF |
1 |
The full mapping (RULE_CATEGORIES and RULE_WEIGHTS) lives at the top of ruff_scorer.py and covers ~50 rule prefixes, including ones that embed a digit in the prefix itself (e.g. C4, C90, T10, T20) and multi-letter prefixes (e.g. PLE, ASYNC, TRY). Any prefix Ruff adds in the future that isn't in the table falls back to default_weight / default_category.
Score Interpretation
- 9.0-10.0: Excellent code quality
- 7.0-8.9: Good code quality
- 5.0-6.9: Needs improvement
- 0.0-4.9: Poor code quality
Example Output
==================================================
RUFF QUALITY SCORE REPORT
==================================================
Target: src/
Score: 8.45/10.00
Statements analyzed: 1,247
Files analyzed: 23
Total issues: 12
Issues by category:
Error: 0
Warning: 3
Convention: 8
Refactor: 1
Good code quality
Advanced Usage
Custom Weights and Categories
from ruff_scorer import RuffScorer
# Change the fallback used for any rule prefix not in RULE_WEIGHTS/RULE_CATEGORIES
scorer = RuffScorer(default_weight=2, default_category="warning")
# Override the weight or category for a specific prefix
scorer.RULE_WEIGHTS["D"] = 1 # docstring issues
scorer.RULE_CATEGORIES["D"] = "convention"
# Inspect how a given rule code resolves
scorer.get_rule_weight("S608") # -> 4
scorer.get_rule_category("S608") # -> "warning"
Integration with CI/CD
# check_quality.py
import sys
from ruff_scorer import RuffScorer
scorer = RuffScorer()
result = scorer.score_directory("src/")
scorer.print_report(result)
THRESHOLD = 7.0
sys.exit(0 if result["score"] >= THRESHOLD else 1)
python check_quality.py && echo "Quality check passed!" || echo "Quality check failed!"
Configuration
Ruff Score respects your existing Ruff configuration by passing it straight through to ruff check --config. Place your settings in:
pyproject.tomlruff.toml.ruff.toml
Example configuration:
[tool.ruff]
line-length = 88
target-version = "py38"
[tool.ruff.lint]
select = ["E", "F", "W", "C", "N", "D", "S", "B"]
ignore = ["E501", "D100"]
Requirements
- Python 3.8+
- Ruff installed and available on your
PATH
License
MIT License - see LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Related Projects
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
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 ruff_score-0.2.0.tar.gz.
File metadata
- Download URL: ruff_score-0.2.0.tar.gz
- Upload date:
- Size: 43.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.27 {"installer":{"name":"uv","version":"0.11.27","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"CachyOS Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b41ff1f181cbcb4200befbd16bb86250a49f05cd73632612251223990362aed0
|
|
| MD5 |
b9066a1fd7feef063c809ef735d079f4
|
|
| BLAKE2b-256 |
da35c289f36b152ca34075dc45f1bbb189f4042917eea81f472108ea31de9dbb
|
File details
Details for the file ruff_score-0.2.0-py3-none-any.whl.
File metadata
- Download URL: ruff_score-0.2.0-py3-none-any.whl
- Upload date:
- Size: 10.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.27 {"installer":{"name":"uv","version":"0.11.27","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"CachyOS Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
68862020b1fad8f2a5001a5d55f0ddc761ff75abebb11c94792ca96971cf14cb
|
|
| MD5 |
4c0010074568ec0db401f18c77dd2673
|
|
| BLAKE2b-256 |
5eba48c1804f5f4ac816b5a89ed9b262bd52ffae7c1821d5613e8c8ad74e4236
|