A tool for refurbishing and modernizing Python codebases
—
Comprehensive error handling system including error definitions, classification, filtering, and formatting for various output targets.
The foundational classes that represent analysis findings and organize them into a hierarchical classification system.
class Error:
"""
Base class for all refurb analysis findings.
Each Error represents a specific code improvement opportunity found during analysis.
Contains location information, descriptive message, and classification metadata.
Attributes:
- line: int - Line number where issue was found (1-based)
- column: int - Column position where issue starts (0-based)
- msg: str - Human-readable description of the issue and suggested improvement
- filename: str | None - Source file path (None for synthetic errors)
- line_end: int | None - End line number for multi-line issues
- column_end: int | None - End column position for multi-line issues
Class attributes:
- enabled: bool - Whether check is enabled by default
- name: str - Human-readable name for the check
- prefix: str - Error code prefix (e.g., "FURB")
- categories: set[str] - Categories this error belongs to
- code: int - Unique numeric identifier for this error type
"""
line: int
column: int
msg: str
filename: str | None
line_end: int | None
column_end: int | None
@classmethod
def from_node(cls, node: Node, msg: str | None = None) -> Error:
"""
Create Error instance from AST node.
Convenience method that extracts position information from AST node
and creates Error with appropriate line/column information.
Parameters:
- node: AST node to extract position from
- msg: Optional custom message (uses class default if None)
Returns:
Error instance with node position information
"""
class ErrorCode:
"""
Identifier for specific error types, used in configuration and filtering.
Attributes:
- id: int - Numeric error identifier
- prefix: str - Error prefix (e.g., "FURB")
- path: str | None - Module path for plugin errors
"""
id: int
prefix: str
path: str | None
class ErrorCategory:
"""
Category grouping for related error types, enabling bulk configuration.
Attributes:
- value: str - Category name (e.g., "readability", "pathlib")
- path: str | None - Module path for plugin categories
"""
value: str
path: str | NoneType definitions and utilities for organizing and filtering errors.
ErrorClassifier = ErrorCategory | ErrorCode
"""Union type representing either a specific error code or error category."""
@classmethod
def from_error(cls, error: type[Error]) -> ErrorCode:
"""
Create ErrorCode from Error class.
Parameters:
- error: Error class to extract code from
Returns:
ErrorCode instance with id, prefix, and path from error class
"""Functions that provide detailed explanations and documentation for error codes.
def explain(settings: Settings) -> str:
"""
Generate detailed explanation for specified error code.
Provides comprehensive documentation including:
- Description of what the error detects
- Examples of problematic code patterns
- Suggested improvements and modern alternatives
- Related error codes and categories
Parameters:
- settings: Settings object with explain field specifying error code
Returns:
Formatted explanation text ready for display
"""Refurb organizes its 94 built-in checks into focused categories:
Core Python Improvements:
builtin (21 checks): Core Python builtin function usagereadability (22 checks): Code clarity and Pythonic patternsflow (4 checks): Control flow optimizationlogical (3 checks): Logical expression simplificationStandard Library Modernization:
pathlib (15 checks): Modern path manipulation with pathlibstring (7 checks): String operation optimizationiterable (3 checks): Iterable processing improvementsdatetime (2 checks): Date and time handlingitertools (2 checks): Iterator tool usagemath (2 checks): Mathematical operation optimizationregex (2 checks): Regular expression improvementshashlib (2 checks): Hashing function usageSpecialized Improvements:
collections (1 check): Collection type improvementscontextlib (1 check): Context manager usagedecimal (1 check): Decimal arithmeticfunction (1 check): Function definition improvementsfunctools (1 check): Functional programming patternspattern_matching (1 check): Pattern matching optimizationsecrets (1 check): Secure random number generationshlex (1 check): Shell lexing improvementsThird-party Integration:
third_party/fastapi (1 check): FastAPI-specific patternsCommon error codes and their meanings:
FURB105: Replace open and read with pathlib.Path.read_text()FURB123: Replace type(x) is type(y) with isinstance(x, type(y))FURB131: Replace del dict[key] with dict.pop(key, None)FURB140: Replace import os; os.path.exists() with pathlib.Path.exists()FURB161: Replace int(x, 0) with int(x)from refurb.error import Error, ErrorCode, ErrorCategory
# Define custom error class
class MyCustomError(Error):
enabled = True
name = "Use modern API"
prefix = "FURB"
categories = {"readability"}
code = 999
# Create error instance
error = MyCustomError(
line=10,
column=5,
msg="Replace `old_function()` with `new_function()`",
filename="example.py"
)
# Work with error codes
error_code = ErrorCode(id=105, prefix="FURB", path=None)
category = ErrorCategory(value="pathlib", path=None)
# Check error classification
assert ErrorCode.from_error(MyCustomError).id == 999Errors integrate with the configuration system for flexible filtering:
# Settings-based error filtering
settings = Settings(
ignore={ErrorCode(105, "FURB", None)}, # Ignore FURB105
enable={ErrorCategory("pathlib", None)}, # Enable all pathlib checks
disable={ErrorCategory("readability", None)} # Disable readability checks
)The error system supports plugin-defined errors with custom prefixes and categories:
# Plugin error with custom prefix
class PluginError(Error):
enabled = True
name = "Plugin check"
prefix = "PLUG" # Custom prefix
categories = {"plugin-category"}
code = 1
# Results in error code PLUG001Install with Tessl CLI
npx tessl i tessl/pypi-refurb