A tool for refurbishing and modernizing Python codebases
—
Powerful configuration system supporting CLI arguments, TOML configuration files, and path-specific amendment rules for flexible analysis customization.
The central configuration object that contains all analysis options and preferences.
class Settings:
"""
Main configuration class containing all refurb analysis options.
Combines CLI arguments, configuration file settings, and defaults into a single
object that controls all aspects of the analysis process.
Attributes:
- files: list[str] - Files and directories to analyze
- explain: ErrorCode | None - Specific error code to explain (for --explain command)
- ignore: set[ErrorClassifier] - Error codes/categories to ignore
- load: list[str] - Additional module paths to search for checks
- enable: set[ErrorClassifier] - Error codes/categories to explicitly enable
- disable: set[ErrorClassifier] - Error codes/categories to explicitly disable
- debug: bool - Print AST representation of analyzed files
- generate: bool - Generate boilerplate for new check (gen subcommand)
- help: bool - Display help information
- version: bool - Display version information
- quiet: bool - Suppress default explanation suggestions
- enable_all: bool - Enable all available checks by default
- disable_all: bool - Disable all checks by default
- verbose: bool - Increase output verbosity
- color: bool - Use colored output in terminal
- config_file: str | None - Path to configuration file used
- python_version: tuple[int, int] | None - Target Python version (e.g., (3, 11))
- mypy_args: list[str] - Additional arguments to pass to mypy
- format: Literal["text", "github"] | None - Output format preference
- sort_by: Literal["filename", "error"] | None - Error sorting preference
- timing_stats: Path | None - File to export timing statistics to
"""
files: list[str]
explain: ErrorCode | None
ignore: set[ErrorClassifier]
load: list[str]
enable: set[ErrorClassifier]
disable: set[ErrorClassifier]
debug: bool
generate: bool
help: bool
version: bool
quiet: bool
enable_all: bool
disable_all: bool
verbose: bool
color: bool
config_file: str | None
python_version: tuple[int, int] | None
mypy_args: list[str]
format: Literal["text", "github"] | None
sort_by: Literal["filename", "error"] | None
timing_stats: Path | None
def get_python_version(self) -> tuple[int, int]:
"""
Get target Python version for analysis.
Returns:
Python version tuple, using system version if not specified
"""
@staticmethod
def merge(old: Settings, new: Settings) -> Settings:
"""
Merge two Settings objects with precedence rules.
Combines configuration from multiple sources, with new settings
taking precedence over old ones. Handles special logic for
enable_all/disable_all flags and list merging.
Parameters:
- old: Base settings (lower precedence)
- new: Override settings (higher precedence)
Returns:
Merged Settings object with combined configuration
"""Functions that parse configuration from various sources and merge them into Settings objects.
def load_settings(args: list[str]) -> Settings:
"""
Parse command line arguments and configuration files into Settings object.
Combines configuration from multiple sources in order of precedence:
1. Command line arguments (highest precedence)
2. Configuration file settings
3. Default values (lowest precedence)
Parameters:
- args: Command line arguments to parse
Returns:
Settings object with all configuration options resolved
Raises:
- ValueError: For invalid argument values or configuration conflicts
"""
def parse_command_line_args(args: list[str]) -> Settings:
"""
Parse command line arguments into Settings object.
Handles all CLI options including flags, repeated options, and positional arguments.
Parameters:
- args: Raw command line arguments
Returns:
Settings object with CLI configuration
Raises:
- ValueError: For invalid or conflicting command line options
"""
def parse_config_file(contents: str) -> Settings:
"""
Parse TOML configuration file contents into Settings object.
Supports all CLI options plus additional configuration features:
- Amendment rules for path-specific error filtering
- Complex ignore/enable patterns
- Structured configuration organization
Parameters:
- contents: TOML file contents as string
Returns:
Settings object with configuration file options
Raises:
- ValueError: For invalid TOML syntax or configuration values
"""Specialized functions for parsing and validating specific configuration values.
def parse_error_classifier(value: str) -> ErrorClassifier:
"""
Parse string representation of error code or category.
Supports formats like:
- "FURB105" (specific error code)
- "pathlib" (error category)
- "readability" (error category)
Parameters:
- value: String representation to parse
Returns:
ErrorCode or ErrorCategory object
Raises:
- ValueError: For invalid format or unknown error codes/categories
"""
def parse_error_id(value: str) -> ErrorCode:
"""
Parse string representation of specific error code.
Parameters:
- value: Error code string (e.g., "FURB105")
Returns:
ErrorCode object
Raises:
- ValueError: For invalid error code format
"""
def parse_python_version(value: str) -> tuple[int, int]:
"""
Parse Python version string into tuple.
Parameters:
- value: Version string (e.g., "3.11", "3.10")
Returns:
Version tuple (e.g., (3, 11))
Raises:
- ValueError: For invalid version format or unsupported versions
"""Refurb supports TOML configuration files, typically in pyproject.toml:
[tool.refurb]
# Files to analyze (optional, usually specified as CLI args)
files = ["src/", "tests/"]
# Error filtering
ignore = ["FURB105", "readability"]
enable = ["FURB999"]
disable = ["pathlib"]
enable_all = false
disable_all = false
# Additional check modules
load = ["./custom_checks", "my_plugin"]
# Output formatting
format = "text" # or "github"
sort_by = "filename" # or "error"
quiet = false
verbose = false
# Analysis options
debug = false
python_version = "3.11"
# Amendment rules (path-specific ignores)
[[tool.refurb.amend]]
path = "legacy/"
ignore = ["FURB105", "FURB123"]
[[tool.refurb.amend]]
path = "tests/"
ignore = ["readability"]Path-specific configuration that allows different rules for different parts of the codebase:
# Settings with amendment rules
settings = Settings(
files=["src/"],
ignore={ErrorCode(105, "FURB", "legacy/old_module.py")}
)
# Amendment matching logic
def is_ignored_via_amend(error: Error, settings: Settings) -> bool:
"""Check if error is ignored by path-specific amendment rules."""from refurb.settings import load_settings, parse_config_file
# Load from CLI args
settings = load_settings([
"src/",
"--ignore", "FURB105,readability",
"--format", "github",
"--python-version", "3.11"
])
# Load from config file
toml_content = """
[tool.refurb]
ignore = ["FURB105", "readability"]
format = "github"
python_version = "3.11"
"""
file_settings = parse_config_file(toml_content)
# Combine with CLI args (CLI takes precedence)
combined_settings = load_settings(["src/", "--quiet"])
# Access configuration
print(f"Analyzing: {settings.files}")
print(f"Ignoring: {settings.ignore}")
print(f"Python version: {settings.get_python_version()}")The Settings object is used throughout the analysis pipeline:
# Error filtering uses settings
should_ignore = should_ignore_error(error, settings)
# Check loading respects enable/disable settings
checks = load_checks(settings)
# Output formatting uses display preferences
formatted = format_errors(errors, settings)
# Mypy integration uses Python version
opt.python_version = settings.get_python_version()Plugin checks can define their own configuration options:
# Custom check that respects settings
def check_custom_pattern(node: Node, errors: list[Error], settings: Settings) -> None:
if settings.verbose:
# More detailed checking in verbose mode
pass
# Access custom settings from config file
# [tool.refurb.plugins.my_plugin]
# custom_option = trueInstall with Tessl CLI
npx tessl i tessl/pypi-refurb