Skip to content

Latest commit

 

History

History
276 lines (205 loc) · 8.24 KB

File metadata and controls

276 lines (205 loc) · 8.24 KB

Ruff Configuration Mapping Guide

This document explains how python-mode configuration options map to Ruff settings, and how to migrate from the old linting tools to Ruff.

Overview

Python-mode now uses Ruff for linting and formatting, replacing:

  • pyflakes - Syntax errors and undefined names
  • pycodestyle - PEP 8 style guide enforcement
  • mccabe - Cyclomatic complexity checking
  • pylint - Comprehensive static analysis
  • pydocstyle - Docstring style checking
  • pylama - Multi-tool linting wrapper
  • autopep8 - Automatic PEP 8 formatting

Configuration Options

Legacy Options (Still Supported)

These options are maintained for backward compatibility and are automatically converted to Ruff rules:

g:pymode_lint_checkers

Default: ['pyflakes', 'pycodestyle', 'mccabe']

Maps to Ruff rule categories:

  • 'pyflakes' → Ruff F rules (pyflakes)
  • 'pycodestyle' → Ruff E and W rules (pycodestyle)
  • 'mccabe' → Ruff C90 rule (mccabe complexity)
  • 'pylint' → Ruff PL rules (pylint)
  • 'pydocstyle' → Ruff D rules (pydocstyle)

Example:

let g:pymode_lint_checkers = ['pyflakes', 'pycodestyle']
" This enables Ruff rules: F (pyflakes), E (pycodestyle errors), W (pycodestyle warnings)

g:pymode_lint_ignore

Default: []

Maps to Ruff --ignore patterns. Supports both legacy error codes (E501, W503) and Ruff rule codes.

Example:

let g:pymode_lint_ignore = ['E501', 'W503', 'F401']
" Ruff will ignore: E501 (line too long), W503 (line break before binary operator), F401 (unused import)

g:pymode_lint_select

Default: []

Maps to Ruff --select patterns. Selects specific rules to enable.

Example:

let g:pymode_lint_select = ['E', 'F']
" Ruff will only check E (pycodestyle errors) and F (pyflakes) rules

New Ruff-Specific Options

These options provide direct control over Ruff behavior:

g:pymode_ruff_enabled

Default: 1

Enable or disable Ruff linting entirely.

Example:

let g:pymode_ruff_enabled = 1  " Enable Ruff (default)
let g:pymode_ruff_enabled = 0  " Disable Ruff

g:pymode_ruff_format_enabled

Default: 1

Enable or disable Ruff formatting (replaces autopep8).

Example:

let g:pymode_ruff_format_enabled = 1  " Enable Ruff formatting (default)
let g:pymode_ruff_format_enabled = 0  " Disable Ruff formatting

g:pymode_ruff_select

Default: []

Ruff-specific select rules. If set, overrides g:pymode_lint_select.

Example:

let g:pymode_ruff_select = ['E', 'F', 'W', 'C90']
" Enable pycodestyle errors, pyflakes, pycodestyle warnings, and mccabe complexity

g:pymode_ruff_ignore

Default: []

Ruff-specific ignore patterns. If set, overrides g:pymode_lint_ignore.

Example:

let g:pymode_ruff_ignore = ['E501', 'F401']
" Ignore line too long and unused import warnings

g:pymode_ruff_config_file

Default: ""

Path to Ruff configuration file (pyproject.toml, ruff.toml, etc.). If empty, Ruff will search for configuration files automatically.

Example:

let g:pymode_ruff_config_file = '/path/to/pyproject.toml'
" Use specific Ruff configuration file

g:pymode_ruff_config_mode

Default: "local_override"

Controls how Ruff configuration is resolved. This option determines whether local project configuration files (ruff.toml, pyproject.toml) or python-mode settings take precedence.

Modes:

  • "local": Use only the project's local Ruff config. Python-mode settings are ignored. Ruff will auto-discover configuration files in the project hierarchy.
  • "local_override": Local config takes priority. If a local Ruff config file exists, it will be used. If no local config exists, python-mode settings serve as fallback.
  • "global": Use only python-mode settings. Local config files are ignored (uses --isolated flag). This restores the previous behavior where python-mode settings always override local configs.

Example:

" Respect project's local Ruff config (recommended for team projects)
let g:pymode_ruff_config_mode = "local"

" Use local config if available, otherwise use pymode defaults (default)
let g:pymode_ruff_config_mode = "local_override"

" Always use pymode settings, ignore project configs
let g:pymode_ruff_config_mode = "global"

Note: The default "local_override" mode provides the best user experience by respecting project-specific configurations while providing sensible defaults when no local config exists.

Migration Examples

Example 1: Basic Configuration

Before (using legacy tools):

let g:pymode_lint_checkers = ['pyflakes', 'pycodestyle']
let g:pymode_lint_ignore = ['E501', 'W503']

After (using Ruff - backward compatible):

" Same configuration works automatically!
let g:pymode_lint_checkers = ['pyflakes', 'pycodestyle']
let g:pymode_lint_ignore = ['E501', 'W503']

After (using Ruff-specific options):

let g:pymode_ruff_select = ['F', 'E', 'W']  " pyflakes, pycodestyle errors/warnings
let g:pymode_ruff_ignore = ['E501', 'W503']

Example 2: Advanced Configuration

Before:

let g:pymode_lint_checkers = ['pyflakes', 'pycodestyle', 'mccabe', 'pylint']
let g:pymode_lint_options_mccabe = {'complexity': 10}
let g:pymode_lint_options_pycodestyle = {'max_line_length': 88}

After:

" Option 1: Use legacy options (still works)
let g:pymode_lint_checkers = ['pyflakes', 'pycodestyle', 'mccabe', 'pylint']
let g:pymode_lint_options_mccabe = {'complexity': 10}
let g:pymode_lint_options_pycodestyle = {'max_line_length': 88}

" Option 2: Use Ruff-specific options + config file
let g:pymode_ruff_select = ['F', 'E', 'W', 'C90', 'PL']
let g:pymode_ruff_config_file = 'pyproject.toml'
" In pyproject.toml:
" [tool.ruff]
" line-length = 88
" [tool.ruff.mccabe]
" max-complexity = 10

Example 3: Disabling Formatting

Before:

" No direct way to disable autopep8

After:

let g:pymode_ruff_format_enabled = 0  " Disable Ruff formatting

Rule Code Reference

Pycodestyle Rules (E, W)

  • E - Errors (syntax, indentation, etc.)
  • W - Warnings (whitespace, line breaks, etc.)
  • Common codes: E501 (line too long), E302 (expected blank lines), W503 (line break before binary operator)

Pyflakes Rules (F)

  • F - Pyflakes errors
  • Common codes: F401 (unused import), F811 (redefined while unused), F841 (unused variable)

McCabe Rules (C90)

  • C90 - Cyclomatic complexity
  • Configured via g:pymode_lint_options_mccabe or Ruff config file

Pylint Rules (PL)

  • PL - Pylint rules
  • Common codes: PLR0913 (too many arguments), PLR2004 (magic value)

Pydocstyle Rules (D)

  • D - Docstring style rules
  • Common codes: D100 (missing docstring), D400 (first line should end with period)

Configuration File Support

Ruff supports configuration via pyproject.toml or ruff.toml files. Python-mode will automatically use these if found, or you can specify a path with g:pymode_ruff_config_file.

Example pyproject.toml:

[tool.ruff]
line-length = 88
select = ["E", "F", "W", "C90"]
ignore = ["E501"]

[tool.ruff.mccabe]
max-complexity = 10

Backward Compatibility

All legacy configuration options continue to work. The migration is transparent - your existing configuration will automatically use Ruff under the hood.

Troubleshooting

Ruff not found

If you see "Ruff is not available", install it:

pip install ruff

Verify installation:

./scripts/verify_ruff_installation.sh

Configuration not working

  1. Check that g:pymode_ruff_enabled = 1 (default)
  2. Verify Ruff is installed: ruff --version
  3. Check configuration file path if using g:pymode_ruff_config_file
  4. Review Ruff output: :PymodeLint and check for errors

Performance issues

Ruff is significantly faster than the old tools. If you experience slowdowns:

  1. Check if Ruff config file is being read correctly
  2. Verify Ruff version: ruff --version (should be recent)
  3. Check for large ignore/select lists that might slow down rule processing

Additional Resources