Skip to main content

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 stray print)
  • 📊 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.toml
  • ruff.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

  • Ruff - The fast Python linter
  • Pylint - The original Python code quality tool

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

ruff_score-0.3.0.tar.gz (43.3 kB view details)

Uploaded Source

Built Distribution

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

ruff_score-0.3.0-py3-none-any.whl (10.3 kB view details)

Uploaded Python 3

File details

Details for the file ruff_score-0.3.0.tar.gz.

File metadata

  • Download URL: ruff_score-0.3.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

Hashes for ruff_score-0.3.0.tar.gz
Algorithm Hash digest
SHA256 ab63fca53dea88074219f1285d1501c2343d04cf661605fb67c1c4b1ce1b12cd
MD5 4b6c6a1ccdb6ca352764f4fb2c596a26
BLAKE2b-256 44eb6fcafd66801a37306264eb74d2889694f625c3f617e6f1c3b7b65ad6b506

See more details on using hashes here.

File details

Details for the file ruff_score-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: ruff_score-0.3.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

Hashes for ruff_score-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3a4c20fbaac08a7af1a3d4c87d91edde9330509a32eddb151261b32e75b6bb0a
MD5 dbf12db3ed03085b4a69aae0e0cda636
BLAKE2b-256 7942e02239406b0b41d108cb594b7189ccb9eae12bd726401b0608e33c3d9357

See more details on using hashes here.

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