remove-trailing-comma
A tool (and pre-commit hook) to automatically remove optional trailing commas
from calls and literals while preserving commas required for Python semantics.
It also keeps the original add-trailing-comma command for adding commas.
Installation
Python 3.12 or newer is required.
pip install remove-trailing-comma
As a pre-commit hook
See pre-commit for instructions
Sample .pre-commit-config.yaml:
- repo: https://github.com/basnijholt/remove-trailing-comma
rev: main
hooks:
- id: remove-trailing-comma
From the command line:
remove-trailing-comma path/to/file.py
The remove mode preserves commas that are required for Python semantics, such as one-element tuples:
x = (1,)
-y = [1, 2,]
+y = [1, 2]
Adding trailing commas
To add trailing commas instead, use the add-trailing-comma hook:
- repo: https://github.com/basnijholt/remove-trailing-comma
rev: main
hooks:
- id: add-trailing-comma
From the command line:
add-trailing-comma path/to/file.py
The legacy add-trailing-comma --remove-comma form is still supported.
multi-line method invocation style -- why?
# Sample of *ideal* syntax
function_call(
argument,
5 ** 5,
kwarg=foo,
)
- the initial paren is at the end of the line
- each argument is indented one level further than the function name
- the last parameter (unless the call contains an unpacking
(
*args/**kwargs)) has a trailing comma
This has the following benefits:
-
arbitrary indentation is avoided:
# I hear you like 15 space indents # oh your function name changed? guess you get to reindent :) very_long_call(arg, arg, arg)
-
adding / removing a parameter preserves
git blameand is a minimal diff:# with no trailing commas x( - arg + arg, + arg2 )
# with trailing commas x( arg, + arg2, )
Implemented features
trailing commas for function calls
x(
arg,
- arg
+ arg,
)
trailing commas for tuple / list / dict / set literals
x = [
- 1, 2, 3
+ 1, 2, 3,
]
trailing commas for function definitions
def func(
arg1,
- arg2
+ arg2,
):
async def func(
arg1,
- arg2
+ arg2,
):
trailing commas for from imports
from os import (
path,
- makedirs
+ makedirs,
)
trailing comma for class definitions
class C(
Base1,
- Base2
+ Base2,
):
pass
trailing comma for with statement
with (
open('f1', 'r') as f1,
- open('f2', 'w') as f2
+ open('f2', 'w') as f2,
):
pass
trailing comma for match statement
match x:
case A(
1,
- 2
+ 2,
):
pass
case (
1,
- 2
+ 2,
):
pass
case [
1,
- 2
+ 2,
]:
pass
case {
'x': 1,
- 'y': 2
+ 'y': 2,
}:
pass
trailing comma for PEP-695 type aliases
def f[
- T
+ T,
](x: T) -> T:
return x
class A[
- K
+ K,
]:
def __init__(self, x: T) -> None:
self.x = x
type ListOrSet[
- T
+ T,
] = list[T] | set[T]
unhug trailing paren
x(
arg1,
- arg2)
+ arg2,
+)
unhug leading paren
-function_name(arg1,
- arg2)
+function_name(
+ arg1,
+ arg2,
+)
match closing brace indentation
x = [
1,
2,
3,
- ]
+]
remove unnecessary commas
-[1, 2, 3,]
-[1, 2, 3, ]
+[1, 2, 3]
+[1, 2, 3]
Development
This project uses uv for dependency management and CI.
uv sync --dev
uv run coverage run -m pytest tests
uv run coverage report
uv run pre-commit run --all-files
Metadata
Release files for remove-trailing-comma 3.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| remove_trailing_comma-3.2.0.tar.gz | 12.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| remove_trailing_comma-3.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 28.9 kB
Release files / remove_trailing_comma-3.2.0.tar.gz
| Download URL | remove_trailing_comma-3.2.0.tar.gz |
|---|---|
| Size | 12.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c29915153d818723c79a5d861609b569e02e39a06f3058012bb8c901ff2aec90
|
|
BLAKE2b-256 checksum How to use checksums |
fc2f74acc72ed40a83814d2088bfc633c67d9ddd35b99fc748f82ab5c08179bc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 1, 2026.
Transparency logRelease files / remove_trailing_comma-3.2.0-py3-none-any.whl
| Download URL | remove_trailing_comma-3.2.0-py3-none-any.whl |
|---|---|
| Size | 16.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c83c98832173bfa45a140b4d18138a7d4351c588b1671d770f4fa8f4ffbcaabf
|
|
BLAKE2b-256 checksum How to use checksums |
ba1ada2ec5058e080357c653bcbd2e44fceb20505d7de31e7a8fb170beaf71e3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 1, 2026.
Transparency log