or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/pypi-add-trailing-comma

Automatically add trailing commas to calls and literals in Python code

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/add-trailing-comma@3.2.x

To install, run

npx @tessl/cli install tessl/pypi-add-trailing-comma@3.2.0

index.mddocs/

add-trailing-comma

A Python tool and pre-commit hook that automatically adds trailing commas to function calls, literals (lists, tuples, dicts, sets), function definitions, import statements, class definitions, with statements, match statements, and PEP-695 type aliases. This improves code maintainability by ensuring consistent trailing comma usage, reducing git diff noise, preserving git blame information, and avoiding arbitrary indentation issues.

Package Information

  • Package Name: add-trailing-comma (for pip), add_trailing_comma (Python module)
  • Language: Python
  • Installation: pip install add-trailing-comma
  • Python Requirements: >=3.9
  • Dependencies: tokenize-rt>=3.0.1

Core Imports

This package is primarily designed for command-line usage and does not export a public programmatic API. The __init__.py is empty, making direct imports unsuitable for typical programmatic use.

Command-line usage (recommended):

add-trailing-comma

Python module invocation:

python -m add_trailing_comma

Internal API access (for advanced use cases, accessing private modules):

from add_trailing_comma._main import main, fix_file

Basic Usage

Command Line Usage

# Process single file
add-trailing-comma script.py

# Process multiple files
add-trailing-comma file1.py file2.py src/

# Read from stdin
cat script.py | add-trailing-comma -

# Exit with 0 even if files were changed (useful for CI)
add-trailing-comma --exit-zero-even-if-changed file.py

Pre-commit Hook Usage

Add to your .pre-commit-config.yaml:

-   repo: https://github.com/asottile/add-trailing-comma
    rev: v3.2.0
    hooks:
    -   id: add-trailing-comma

Programmatic Usage

Note: The following shows internal API usage accessing private modules. This is not recommended for production use as private APIs may change without notice.

import argparse
from add_trailing_comma._main import fix_file, main

# Process a single file using internal API
args = argparse.Namespace(exit_zero_even_if_changed=False)
result = fix_file("script.py", args)

# Use main function with arguments
result = main(["script.py", "--exit-zero-even-if-changed"])

Capabilities

Command Line Interface

The main entry point for command-line usage with argument parsing and file processing.

def main(argv: Sequence[str] | None = None) -> int:
    """
    Main entry point for command line interface.
    
    Parameters:
    - argv: Command line arguments (defaults to sys.argv if None)
    
    Returns:
    int: Exit code (0 for success or no changes, 1 for errors or changes made)
    
    Available command line options:
    - filenames: List of files to process
    - --exit-zero-even-if-changed: Exit with 0 even if files were modified
    - --py35-plus, --py36-plus: Legacy flags (deprecated, no effect)
    """

File Processing

Process individual files to add trailing commas with configurable options.

def fix_file(filename: str, args: argparse.Namespace) -> int:
    """
    Process a single file to add trailing commas.
    
    Parameters:
    - filename: Path to file to process, or '-' for stdin
    - args: Namespace with configuration options (requires exit_zero_even_if_changed attribute)
    
    Returns:
    int: 1 if file was changed or error occurred, 0 if no changes or exit_zero_even_if_changed=True
    
    Handles:
    - Unicode decode errors (prints error message, returns 1)
    - Syntax errors (returns content unchanged)
    - File I/O operations for both files and stdin
    """

Source Code Transformation

Core internal functionality for transforming Python source code to add trailing commas. This is a private function used internally by the tool.

def _fix_src(contents_text: str) -> str:
    """
    Internal function that applies AST transformations to add trailing commas.
    
    Note: This is a private function (prefix '_') and should not be used in 
    production code as it may change without notice.
    
    Parameters:
    - contents_text: Python source code as string
    
    Returns:
    str: Transformed source code with trailing commas added
    
    Raises:
    SyntaxError: Returns original content if syntax errors are encountered
    """

Transformations Supported

Function Calls

Adds trailing commas to multi-line function calls:

# Before
function_call(
    argument,
    5 ** 5,
    kwarg=foo
)

# After  
function_call(
    argument,
    5 ** 5,
    kwarg=foo,
)

Literals

Adds trailing commas to lists, tuples, dictionaries, and sets:

# Lists
x = [
    1, 2, 3,  # trailing comma added
]

# Tuples
y = (
    'a', 'b', 'c',  # trailing comma added
)

# Dictionaries
config = {
    'key1': 'value1',
    'key2': 'value2',  # trailing comma added
}

# Sets
items = {
    'item1',
    'item2',  # trailing comma added
}

Function Definitions

Adds trailing commas to function and method parameters:

def func(
        arg1,
        arg2,  # trailing comma added
):
    pass

async def async_func(
        arg1,
        arg2,  # trailing comma added
):
    pass

Import Statements

Adds trailing commas to from-import statements:

from os import (
    path,
    makedirs,  # trailing comma added
)

Class Definitions

Adds trailing commas to class inheritance lists:

class MyClass(
    Base1,
    Base2,  # trailing comma added
):
    pass

With Statements

Adds trailing commas to with statement context managers:

with (
        open('f1', 'r') as f1,
        open('f2', 'w') as f2,  # trailing comma added
):
    pass

Match Statements (Python 3.10+)

Adds trailing commas to match patterns:

match x:
    case A(
       1,
       2,  # trailing comma added
    ):
        pass
    case (
       1,
       2,  # trailing comma added
    ):
        pass
    case [
       1,
       2,  # trailing comma added
    ]:
        pass
    case {
       'x': 1,
       'y': 2,  # trailing comma added
    }:
        pass

PEP-695 Type Aliases (Python 3.12+)

Adds trailing commas to type parameter lists:

def f[
    T,  # trailing comma added
](x: T) -> T:
    return x

class A[
    K,  # trailing comma added
]:
    def __init__(self, x: K) -> None:
        self.x = x

type ListOrSet[
     T,  # trailing comma added
] = list[T] | set[T]

Additional Features

Parentheses Formatting

The tool also performs "unhugging" - formatting parentheses positioning:

# Unhug trailing paren
x(
    arg1,
    arg2,  # trailing comma and proper closing
)

# Unhug leading paren
function_name(
    arg1,
    arg2,
)

# Match closing brace indentation
x = [
    1,
    2,
    3,
]  # proper indentation

Comma Removal

Removes unnecessary commas from single-line structures:

# Before
[1, 2, 3,]
[1, 2, 3, ]

# After
[1, 2, 3]
[1, 2, 3]

Command Line Arguments

The tool supports the following command line arguments:

  • filenames: List of files to process (accepts multiple files and directories)
  • --exit-zero-even-if-changed: Exit with code 0 even if files were modified
  • --py35-plus: Legacy flag (deprecated, does nothing)
  • --py36-plus: Legacy flag (deprecated, does nothing)

Error Handling

The tool handles various error conditions gracefully:

  • Syntax Errors: Files with syntax errors are returned unchanged
  • Unicode Errors: Non-UTF-8 files are skipped with error message
  • File Access: Handles stdin input with '-' filename

Integration

Pre-commit Hook

The tool is designed to work seamlessly with pre-commit hooks for automated code formatting in development workflows.

CI/CD Integration

Use --exit-zero-even-if-changed flag in CI environments where you want the tool to run but not fail the build when changes are made.

Dependencies and Types

The tool relies on the following dependencies and type definitions:

External Dependencies

# Required external dependency
from tokenize_rt import src_to_tokens, tokens_to_src, Token, Offset

# Standard library dependencies
from typing import Sequence, Iterable
from collections.abc import Sequence
from argparse import Namespace, ArgumentParser
import ast
import sys

Core Type Signatures

# Main API functions
def main(argv: Sequence[str] | None = None) -> int
def fix_file(filename: str, args: Namespace) -> int

# Internal transformation function
def _fix_src(contents_text: str) -> str

# Helper types from tokenize-rt
Token: # Represents a token with .src, .name, .offset attributes
Offset: # Represents position in source (line, column)