Skip to content

Respect the magic trailing comma in starred type parameter lists#5244

Open
dchaudhari7177 wants to merge 2 commits into
psf:mainfrom
dchaudhari7177:fix/magic-trailing-comma-starred-type-params
Open

Respect the magic trailing comma in starred type parameter lists#5244
dchaudhari7177 wants to merge 2 commits into
psf:mainfrom
dchaudhari7177:fix/magic-trailing-comma-starred-type-params

Conversation

@dchaudhari7177

Copy link
Copy Markdown

Summary

Fixes #5243. A magic trailing comma explodes a PEP 695 type-parameter list of plain type vars, but was silently ignored once the list contained a *TypeVarTuple or **ParamSpec:

class C[
    T,
    *Ts,
    **P,
]:
    pass

collapsed back to

class C[
    T, *Ts, **P,
]:
    pass

Root cause

is_split_before_delimiter / is_split_after_delimiter deliberately skip a star that is_vararg() recognises, with the comment:

# * and ** might also be MATH_OPERATORS but in this case they are not.
# Don't treat them as a delimiter.

is_vararg() decides that by checking the star's parent against VARARGS_PARENTS, which listed the argument/lambda nodes but not the PEP 695 typevartuple and paramspec nodes:

leaf='*'  parent_sym=typevartuple   is_vararg=False
leaf='**' parent_sym=paramspec      is_vararg=False

So the stars in a type-parameter list were scored as * and ** math operators, and that delimiter outranked the comma when the line was split — which is why the trailing comma stopped mattering.

Adding both nodes to VARARGS_PARENTS restores the intended "not a delimiter" treatment.

Scope

Fixes def, async def, class and type aliases alike, matching the issue. The non-magic case is unchanged — def all_in[T: int, U: (bytes, str), *Ts, **P]() still stays on one line (pinned by the existing fixture case).

Tests

Added magic_starred (def), MagicStarred (class) and MagicStarredAlias (type alias) to tests/data/cases/type_params.py, right beside the existing plain-type-var magic[Trailing, Comma,] case.

Reverting only src/ fails the fixture with exactly the reported collapse, on all three constructs:

-    *Ts,
+    T, *Ts, **P,
-    *Ts,
+    T, *Ts, **P,
-    *Ts,
+    T, *Ts, **P,

Verification

  • pytest tests/ -k "not symlink"464 passed, 3 skipped, 8 subtests passed — no formatting regressions across the fixture corpus
  • The 6 deselected symlink tests fail on a clean tree on my machine (OSError: WinError 1314 A required privilege is not held by the client — Windows needs elevation to create symlinks), verified by stashing; unrelated to this change

I'll add the CHANGES.md entry under Stable style in a follow-up commit on this branch, since the file asks for the PR number rather than the issue number and I only get that once this is opened.

A magic trailing comma exploded a PEP 695 type parameter list of plain
type vars, but was silently ignored once the list contained a
*TypeVarTuple or **ParamSpec, collapsing the params back onto one line.

is_split_before_delimiter/is_split_after_delimiter skip a star that
is_vararg() recognises, so it is not mistaken for a MATH_OPERATORS
delimiter. is_vararg() checks the star's parent against
VARARGS_PARENTS, which listed the argument and lambda nodes but not the
PEP 695 typevartuple and paramspec ones. The stars in a type parameter
list were therefore scored as multiplication and power operators, and
that delimiter beat the comma when the line was split.

Add both nodes to VARARGS_PARENTS. This affects def, async def, class
and type aliases alike.

Closes psf#5243
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Magic trailing comma does not explode a type-parameter list containing *TypeVarTuple / **ParamSpec

2 participants