Skip to content

Replace pylint + autopep8 with ruff for Python linting and formatting #1281

@sbryngelson

Description

@sbryngelson

Motivation

We currently use two separate tools for Python code quality:

  • autopep8 for formatting (in format_python.sh)
  • pylint for linting (in lint.sh, with ~20 disabled rules passed as CLI flags)

Both are slow compared to modern alternatives, and the pylint configuration is scattered across inline CLI flags in bash scripts with no centralized config file. There are also 229 inline # pylint: disable=... comments spread across the toolchain source.

Ruff is a single tool that replaces both, written in Rust, and is 10-100x faster than pylint/autopep8. We already use uv (also from Astral) for dependency installation.

Proposed changes

1. Replace autopep8 with ruff format

  • Configure max line length (200) in pyproject.toml under [tool.ruff]
  • Update format_python.sh to call ruff format instead of autopep8

2. Replace pylint with ruff check

  • Translate the currently-disabled pylint rules to ruff equivalents in pyproject.toml
  • Update lint.sh to call ruff check instead of three separate pylint invocations
  • Use per-path rule overrides in pyproject.toml for the different configs (toolchain vs examples/benchmarks)

3. Enable ruff check --fix for auto-fixable lint violations

  • Ruff can auto-fix many issues (unused imports, import sorting, simple style fixes)
  • Integrate this into ./mfc.sh format so fixable lint issues are corrected alongside formatting
  • The ./mfc.sh lint step then only reports issues that require manual intervention

4. Remove all 229 inline # pylint: disable= comments

Current breakdown of inline disables:

Count pylint rule Ruff disposition
79 import-outside-toplevel Globally disable — intentional lazy-import pattern
44 too-many-locals Globally disable — project style
23 too-many-branches Globally disable — project style
18 too-many-statements Globally disable — project style
17 too-many-arguments Globally disable — project style
14 too-many-positional-arguments Globally disable — project style
14 protected-access Globally disable — intentional in this codebase
8 too-many-instance-attributes Globally disable — project style
7 too-many-nested-blocks Globally disable — project style
7 too-many-boolean-expressions Globally disable — project style
5 too-many-lines Globally disable — project style
3 too-many-return-statements Globally disable — project style
1 too-many-public-methods Globally disable — project style
1 too-few-public-methods Globally disable — project style
9 unsubscriptable-object Globally disable — false positives
5 unused-import Keep enabled, auto-fix with ruff check --fix
2 unused-argument Keep enabled, auto-fix (prefix with _)
6 wrong-import-position Keep enabled, auto-fix with isort rules
2 consider-using-with Keep enabled, fix manually where appropriate
1 consider-using-enumerate Keep enabled, auto-fix
1 use-dict-literal Keep enabled, auto-fix
4 broad-except Keep enabled — catch-all exceptions should be flagged
10 global-statement Keep enabled — discourage new globals
3 global-variable-not-assigned Keep enabled
1 redefined-builtin Keep enabled
1 not-an-iterable Keep enabled

Once the ruff config in pyproject.toml globally disables the ~200 project-style suppressions, all 229 inline comments can be removed.

5. Centralize config in toolchain/pyproject.toml

  • All rule selection, ignores, and per-path overrides in one place under [tool.ruff]
  • Remove inline CLI flag sprawl from lint.sh

6. Update dependencies in pyproject.toml

  • Remove autopep8 and pylint
  • Add ruff

Benefits

  • Single tool instead of two
  • 10-100x faster linting and formatting
  • Auto-fix for common issues (unused imports, import order, etc.)
  • Remove 229 inline # pylint: disable comments
  • Centralized configuration in pyproject.toml
  • Already in the Astral ecosystem alongside uv

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions