A tool and pre-commit hook to automatically upgrade Python syntax for newer versions of the language.
npx @tessl/cli install tessl/pypi-pyupgrade@3.20.0A tool and pre-commit hook to automatically upgrade Python syntax for newer versions of the language. pyupgrade modernizes Python code by transforming legacy syntax patterns into their modern equivalents, supporting upgrades across Python versions from 3.6 through 3.14+.
pip install pyupgradeFor command-line usage:
pyupgrade [OPTIONS] [FILES]For programmatic usage:
from pyupgrade._main import main
from pyupgrade._data import Settings# Upgrade a single file
pyupgrade example.py
# Upgrade multiple files
pyupgrade src/*.py
# Upgrade for specific Python version
pyupgrade --py311-plus src/*.py
# Use as pre-commit hook
pyupgrade --py310-plus --keep-percent-format src/*.pyfrom pyupgrade._main import main, _fix_plugins, _fix_tokens
from pyupgrade._data import Settings
# Use main function
exit_code = main(['--py310-plus', 'example.py'])
# Transform code programmatically
settings = Settings(min_version=(3, 10), keep_percent_format=True)
upgraded_code = _fix_plugins(source_code, settings)
upgraded_code = _fix_tokens(upgraded_code)pyupgrade uses a two-phase transformation approach:
The plugin system uses a registration mechanism where plugins register callbacks for specific AST node types. Each plugin can examine the AST and generate token-level transformations that are applied during the second phase.
Command-line tool for upgrading Python files with extensive configuration options for different Python versions and preservation settings.
def main(argv: Sequence[str] | None = None) -> int:
"""
Main entry point for command-line interface.
Args:
argv: Command line arguments (None uses sys.argv)
Returns:
Exit code (0 for success, 1 for failure/changes made)
"""Core functionality for applying syntax transformations through plugin and token systems.
def _fix_plugins(contents_text: str, settings: Settings) -> str:
"""Apply plugin-based AST transformations."""
def _fix_tokens(contents_text: str) -> str:
"""Apply token-level transformations."""
class Settings(NamedTuple):
min_version: Version = (3,)
keep_percent_format: bool = False
keep_mock: bool = False
keep_runtime_typing: bool = FalseExtensible plugin architecture for registering AST-based syntax transformations.
def register(tp: type[AST_T]) -> Callable[[ASTFunc[AST_T]], ASTFunc[AST_T]]:
"""Register transformation function for AST node type."""
def visit(funcs: ASTCallbackMapping, tree: ast.Module, settings: Settings) -> dict[Offset, list[TokenFunc]]:
"""Visit AST and collect transformation callbacks."""
class State(NamedTuple):
settings: Settings
from_imports: dict[str, set[str]]
in_annotation: bool = FalseHelper functions for working with Python AST nodes during transformations.
def ast_parse(contents_text: str) -> ast.Module:
"""Parse Python source into AST."""
def ast_to_offset(node: ast.expr | ast.stmt) -> Offset:
"""Convert AST node position to token offset."""
def is_name_attr(node: ast.AST, imports: dict[str, set[str]], mods: tuple[str, ...], names: Container[str]) -> bool:
"""Check if node matches imported name or attribute."""Comprehensive token-level manipulation utilities for precise code transformations.
def parse_call_args(tokens: list[Token], i: int) -> tuple[list[tuple[int, int]], int]:
"""Parse function call arguments from tokens."""
def replace_call(tokens: list[Token], start: int, end: int, args: list[tuple[int, int]], tmpl: str, *, parens: Sequence[int] = ()) -> None:
"""Replace function call with template."""
class Block(NamedTuple):
"""Code block boundaries in tokens."""
start: int
colon: int
block: int
end: int
line: boolSpecialized utilities for processing and transforming string literals and format strings.
def parse_format(s: str) -> list[DotFormatPart]:
"""Parse format string into component parts."""
def unparse_parsed_string(parsed: list[DotFormatPart]) -> str:
"""Convert parsed format parts back to string."""
def is_codec(encoding: str, name: str) -> bool:
"""Check if encoding matches codec name."""# Version and callback types
Version = tuple[int, ...]
TokenFunc = Callable[[int, list[Token]], None]
ASTFunc = Callable[[State, AST_T, ast.AST], Iterable[tuple[Offset, TokenFunc]]]
# String format processing
DotFormatPart = tuple[str, Optional[str], Optional[str], Optional[str]]
# Token manipulation structures
class Victims(NamedTuple):
starts: list[int]
ends: list[int]
first_comma_index: int | None
arg_index: int