Describe the bug
A magic trailing comma correctly explodes a PEP 695 type-parameter list of plain type vars (one per line), but is silently ignored once the list contains a *TypeVarTuple or **ParamSpec — the params collapse back onto a single line.
To Reproduce
class C[
T,
*Ts,
**P,
]:
pass
Running black --target-version py312 (stable style) produces:
class C[
T, *Ts, **P,
]:
pass
The same construct with only plain type vars is exploded as expected:
class C[
T,
U,
V,
]:
pass
It reproduces on def/async def/type aliases too, and regardless of --target-version (autodetected). In a def, the argument list still explodes correctly while the type-param list collapses, e.g. def f[T, *Ts, **P,](x): -> the [...] collapses but (x,) explodes.
Expected behavior
The magic trailing comma should force the type-parameter list to explode one-per-line, identical to the plain-type-var case, whether or not the list contains a *TypeVarTuple/**ParamSpec.
Environment
- Black's version: 26.5.2.dev29+gb74b23013 (commit b74b230), also reproduces on current
main
- OS and Python version: Linux, CPython 3.14
Additional context
The collapsed output is stable and AST-equivalent, so it does not trip idempotency/AST-safety checks — it's purely a splitting-decision bug specific to starred type params.
Describe the bug
A magic trailing comma correctly explodes a PEP 695 type-parameter list of plain type vars (one per line), but is silently ignored once the list contains a
*TypeVarTupleor**ParamSpec— the params collapse back onto a single line.To Reproduce
Running
black --target-version py312(stable style) produces:The same construct with only plain type vars is exploded as expected:
It reproduces on
def/async def/typealiases too, and regardless of--target-version(autodetected). In adef, the argument list still explodes correctly while the type-param list collapses, e.g.def f[T, *Ts, **P,](x):-> the[...]collapses but(x,)explodes.Expected behavior
The magic trailing comma should force the type-parameter list to explode one-per-line, identical to the plain-type-var case, whether or not the list contains a
*TypeVarTuple/**ParamSpec.Environment
mainAdditional context
The collapsed output is stable and AST-equivalent, so it does not trip idempotency/AST-safety checks — it's purely a splitting-decision bug specific to starred type params.