Tool for automatically reordering Python imports using static analysis with advanced features for import modernization and deduplication
npx @tessl/cli install tessl/pypi-reorder-python-imports@3.15.0A command-line tool and Python library for automatically reordering Python imports using static analysis. Unlike similar tools like isort, it emphasizes static analysis over configuration, organizing imports into three distinct sections (standard library, third-party, first-party) while enforcing consistent ordering and splitting multi-import statements to reduce merge conflicts.
pip install reorder-python-importsfrom reorder_python_imports import fix_file_contents, mainFor advanced usage with replacement and removal rules:
from reorder_python_imports import (
fix_file_contents,
Replacements,
parse_imports,
apply_import_sorting,
partition_source
)# Reorder imports in specific files
reorder-python-imports file1.py file2.py
# Add an import to all processed files
reorder-python-imports --add-import 'from __future__ import annotations' *.py
# Remove obsolete imports for Python 3.9+
reorder-python-imports --py39-plus *.py
# Replace deprecated imports
reorder-python-imports --replace-import 'old.module::new.module' *.pyfrom reorder_python_imports import fix_file_contents
# Read a Python file
with open('example.py', 'r') as f:
original_contents = f.read()
# Reorder imports
reordered_contents = fix_file_contents(original_contents)
# Write back if changed
if reordered_contents != original_contents:
with open('example.py', 'w') as f:
f.write(reordered_contents)Core functionality for processing Python file contents and reordering imports.
def fix_file_contents(
contents: str,
*,
to_add: tuple[str, ...] = (),
to_remove: set[tuple[str, ...]],
to_replace: Replacements,
settings: Settings = Settings()
) -> str:
"""
Reorder imports in Python file contents.
Args:
contents: Python source code as string
to_add: Tuple of import strings to add
to_remove: Set of import tuples to remove (required)
to_replace: Replacements object for import substitutions (required)
settings: classify-imports Settings object for sorting behavior
Returns:
Modified source code with reordered imports
"""Functions for parsing and analyzing Python source code structure.
def partition_source(src: str) -> tuple[str, list[str], str, str]:
"""
Split Python source into pre-import, import, post-import sections.
Args:
src: Python source code string
Returns:
Tuple of (pre_import_code, import_lines, post_import_code, newline_char)
"""
def parse_imports(
imports: list[str],
*,
to_add: tuple[str, ...] = ()
) -> list[tuple[str, Import | ImportFrom]]:
"""
Parse import strings into Import/ImportFrom objects.
Args:
imports: List of import statement strings
to_add: Additional imports to include in parsing
Returns:
List of (import_string, import_object) tuples
"""Functions for manipulating and processing parsed imports.
def replace_imports(
imports: list[tuple[str, Import | ImportFrom]],
to_replace: Replacements
) -> list[tuple[str, Import | ImportFrom]]:
"""
Apply replacement rules to parsed imports.
Args:
imports: List of (import_string, import_object) tuples
to_replace: Replacements object containing substitution rules
Returns:
Modified import list with replacements applied
"""
def remove_duplicated_imports(
imports: list[tuple[str, Import | ImportFrom]],
*,
to_remove: set[tuple[str, ...]]
) -> list[tuple[str, Import | ImportFrom]]:
"""
Remove duplicate and specified imports.
Args:
imports: List of (import_string, import_object) tuples
to_remove: Set of import tuples to remove
Returns:
Deduplicated import list
"""
def apply_import_sorting(
imports: list[tuple[str, Import | ImportFrom]],
settings: Settings = Settings()
) -> list[str]:
"""
Sort imports according to classification settings.
Args:
imports: List of (import_string, import_object) tuples
settings: classify-imports Settings for sorting behavior
Returns:
List of sorted import strings
"""Entry point for command-line usage with argument processing.
def main(argv: Sequence[str] | None = None) -> int:
"""
Command-line entry point for the reorder tool.
Args:
argv: Command line arguments (uses sys.argv if None)
Returns:
Exit code: 0 for success, non-zero for changes made or errors
"""Configuration classes and constants for import modernization.
class Replacements:
"""Container for import replacement mappings."""
exact: dict[tuple[str, str], str] # Maps (module, attribute) to new_module
mods: dict[str, str] # Maps old_module to new_module
@classmethod
def make(cls, args: list[tuple[str, str, str]]) -> Replacements:
"""
Create Replacements from argument list.
Args:
args: List of (old_module, attribute, new_module) tuples
Returns:
Replacements object
"""
# Version-specific import modernization rules
REMOVALS: dict[tuple[int, ...], set[str]]
REPLACES: dict[tuple[int, ...], set[str]]Enums and constants for low-level source code analysis.
class CodeType(enum.Enum):
"""Code section type classifier."""
PRE_IMPORT_CODE = "PRE_IMPORT_CODE"
IMPORT = "IMPORT"
NON_CODE = "NON_CODE"
CODE = "CODE"
class Tok(enum.Enum):
"""Token types for import parsing."""
IMPORT = "IMPORT"
STRING = "STRING"
NEWLINE = "NEWLINE"
ERROR = "ERROR"
# Token patterns for parsing Python source
TOKENIZE: tuple[tuple[Tok, re.Pattern[str]], ...]from reorder_python_imports import fix_file_contents
# Add future imports to modernize code
contents = fix_file_contents(
source_code,
to_add=('from __future__ import annotations',)
)from reorder_python_imports import fix_file_contents, Replacements
# Replace deprecated imports
replacements = Replacements.make([
('collections', 'Mapping', 'collections.abc'),
('typing', 'Dict', 'builtins') # Use dict instead of typing.Dict
])
contents = fix_file_contents(
source_code,
to_replace=replacements
)from reorder_python_imports import (
partition_source,
parse_imports,
remove_duplicated_imports,
apply_import_sorting
)
# Manual processing pipeline
pre_import, imports, post_import, nl = partition_source(source_code)
parsed_imports = parse_imports(imports)
deduplicated = remove_duplicated_imports(parsed_imports, to_remove=set())
sorted_imports = apply_import_sorting(deduplicated)
# Reconstruct file
reordered = pre_import + ''.join(sorted_imports) + post_importThe tool enforces these specific formatting rules to minimize merge conflicts:
import statements before from statements within each sectionfrom module import a, b becomes separate linesThe tool handles common edge cases:
Import processing stops at the first non-import, non-comment, non-whitespace line or when encountering a # noreorder comment.