Removes unused imports and unused variables from Python code
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Functions for detecting and handling Python standard library imports, package names, and import patterns. These utilities ensure safe removal of unused imports while preserving necessary functionality and side effects.
Functions for identifying Python standard library modules to enable safe automatic removal.
def standard_package_names() -> Iterable[str]:
"""
Yields standard Python module names from the standard library.
Discovers standard library modules by examining the Python installation
paths and filtering out internal/private modules and platform-specific extensions.
Returns:
Iterator of standard library module names safe for automatic removal
"""def standard_paths() -> Iterable[str]:
"""
Yields filesystem paths to standard Python modules.
Returns paths from the Python installation including stdlib and platstdlib
directories, used internally by standard_package_names().
Returns:
Iterator of filesystem paths containing standard library modules
"""Functions for parsing and analyzing import statements to understand their structure and content.
def extract_package_name(line: str) -> str | None:
"""
Extracts the package name from an import statement line.
Parses various import statement formats to identify the root package name,
handling both 'import' and 'from...import' statements.
Args:
line: Python source line containing an import statement
Returns:
Root package name, or None if line is not a valid import statement
"""def multiline_import(line: str, previous_line: str = "") -> bool:
"""
Returns True if the import statement spans multiple lines.
Detects multiline import patterns including parenthesized imports and
backslash continuations to handle complex import processing.
Args:
line: Current line to analyze
previous_line: Previous line for context (default empty string)
Returns:
True if this line is part of a multiline import statement
"""def multiline_statement(line: str, previous_line: str = "") -> bool:
"""
Returns True if this line is part of any multiline statement.
More general than multiline_import, detects any Python statement that
continues across multiple lines using parentheses or backslashes.
Args:
line: Current line to analyze
previous_line: Previous line for context (default empty string)
Returns:
True if this line is part of a multiline statement
"""Functions for processing and transforming import statements during cleanup.
def filter_from_import(line: str, unused_module: Iterable[str]) -> str:
"""
Removes unused imports from 'from module import ...' statements.
Parses "from module import a, b, c" statements and removes only the
unused imports while preserving the rest, maintaining proper syntax.
Args:
line: Source line containing a 'from...import' statement
unused_module: Names of unused imported items to remove
Returns:
Modified import line with unused imports removed, or empty string if all removed
"""def break_up_import(line: str) -> str:
"""
Returns import statement with each import on a separate line.
Converts "import a, b, c" into separate "import a", "import b", "import c"
statements to make individual import removal easier.
Args:
line: Import statement line with multiple imports
Returns:
Multi-line string with each import on its own line
"""Important constants that control import detection and removal behavior:
SAFE_IMPORTS: frozenset[str]Computed set of imports that are safe to remove automatically (combines standard library detection).
IMPORTS_WITH_SIDE_EFFECTS: set[str]Set of modules known to have side effects when imported: {"antigravity", "rlcompleter", "this"}.
BINARY_IMPORTS: set[str]Set of modules that may be built into CPython and don't have separate files.
import autoflake
# Get all standard library module names
stdlib_modules = list(autoflake.standard_package_names())
print(f"Found {len(stdlib_modules)} standard library modules")
# Check if a specific module is in the standard library
if "os" in stdlib_modules:
print("'os' is a standard library module")
# Safe imports (standard library modules safe for automatic removal)
safe_modules = autoflake.SAFE_IMPORTS
print(f"Safe to remove: {len(safe_modules)} modules")import autoflake
# Extract package names from various import formats
examples = [
"import os.path",
"from django.conf import settings",
"import requests.adapters",
"from . import utils"
]
for line in examples:
package = autoflake.extract_package_name(line)
print(f"'{line}' -> package: '{package}'")import autoflake
# Detect multiline imports
lines = [
"from django.contrib.auth import (",
" User,",
" Group,",
" Permission",
")"
]
for i, line in enumerate(lines):
prev_line = lines[i-1] if i > 0 else ""
is_multiline = autoflake.multiline_import(line, prev_line)
print(f"Line {i}: '{line.strip()}' - multiline: {is_multiline}")import autoflake
# Filter unused imports from 'from...import' statements
line = "from django.contrib.auth import User, Group, Permission"
unused = ["Group", "Permission"] # These are unused
filtered = autoflake.filter_from_import(line, unused)
print(f"Original: {line}")
print(f"Filtered: {filtered}")
# Result: "from django.contrib.auth import User"
# Break up multiple imports
multi_import = "import os, sys, json, unused_module"
broken_up = autoflake.break_up_import(multi_import)
print("Broken up imports:")
print(broken_up)import autoflake
# Check for imports with known side effects
def is_side_effect_import(module_name):
"""Check if a module has known side effects."""
return module_name in autoflake.IMPORTS_WITH_SIDE_EFFECTS
# These imports should not be automatically removed
test_modules = ["antigravity", "os", "rlcompleter", "sys"]
for module in test_modules:
has_side_effects = is_side_effect_import(module)
print(f"'{module}' has side effects: {has_side_effects}")import autoflake
import ast
def analyze_import_safety(source_code):
"""Analyze which imports in source code are safe to remove."""
# Get unused imports from pyflakes
messages = list(autoflake.check(source_code))
unused_imports = {}
for line_num, module_name in autoflake.unused_import_module_name(messages):
unused_imports[line_num] = module_name
# Analyze safety
results = {}
for line_num, module_name in unused_imports.items():
is_stdlib = module_name in autoflake.SAFE_IMPORTS
has_side_effects = module_name in autoflake.IMPORTS_WITH_SIDE_EFFECTS
results[line_num] = {
"module": module_name,
"is_stdlib": is_stdlib,
"has_side_effects": has_side_effects,
"safe_to_remove": is_stdlib and not has_side_effects
}
return results
# Example usage
source = '''
import os
import sys
import antigravity
import requests # Third-party
import unused_local_module
'''
analysis = analyze_import_safety(source)
for line_num, info in analysis.items():
print(f"Line {line_num}: {info}")import autoflake
def smart_import_removal(source_code, config):
"""Remove imports intelligently based on configuration and safety."""
# Start with conservative settings
processing_config = {
"remove_all_unused_imports": False, # Only standard library by default
"additional_imports": config.get("additional_safe_modules", [])
}
# If user explicitly enables aggressive removal, add checks
if config.get("remove_all_unused_imports", False):
# Get list of unused modules
messages = list(autoflake.check(source_code))
unused_modules = [module for _, module in autoflake.unused_import_module_name(messages)]
# Filter out side-effect modules
safe_unused = [
module for module in unused_modules
if module not in autoflake.IMPORTS_WITH_SIDE_EFFECTS
]
print(f"Would remove {len(safe_unused)} unused imports")
print(f"Preserving {len(unused_modules) - len(safe_unused)} imports with side effects")
processing_config["remove_all_unused_imports"] = True
return autoflake.fix_code(source_code, **processing_config)Install with Tessl CLI
npx tessl i tessl/pypi-autoflake