CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-autoflake

Removes unused imports and unused variables from Python code

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

import-detection.mddocs/

Import Detection and Analysis

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.

Capabilities

Standard Library Detection

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
    """

Import Statement Analysis

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
    """

Import Processing and Filtering

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
    """

Constants and Predefined Sets

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.

Usage Examples

Standard Library Detection

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 Statement Analysis

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}'")

Multiline Import Detection

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 Filtering and Processing

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)

Side Effect Detection

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}")

Custom Import Analysis

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}")

Integration with Code Processing

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

docs

code-analysis.md

configuration.md

file-processing.md

import-detection.md

index.md

tile.json