Skip to content

Fix stubgen emitting invalid syntax for keyword-only dunder parameters - #21864

Open
arose26 wants to merge 1 commit into
python:masterfrom
arose26:stubgen-historical-posonly-kwonly
Open

Fix stubgen emitting invalid syntax for keyword-only dunder parameters#21864
arose26 wants to merge 1 commit into
python:masterfrom
arose26:stubgen-historical-posonly-kwonly

Conversation

@arose26

@arose26 arose26 commented Aug 17, 2026

Copy link
Copy Markdown

Fixes #19315

stubgen produces output that will not parse:

# input
def f1(*, __kw): pass
def f2(x, /, *, __kw): pass
# generated
def f1(*, /, __kw) -> None: ...     # SyntaxError: / must be ahead of *
def f2(x, *, /, __kw) -> None: ...  # SyntaxError

Cause

A parameter whose name starts with two underscores is positional-only by the historical convention, and mypy marks it pos_only on that basis alone. stubgen counts every such argument to decide where the / belongs:

if actually_pos_only_args and arg_.pos_only:
    pos_only_marker_position += 1

The convention does not apply after the keyword-only separator — __kw in def f1(*, __kw) is simply keyword-only — but the argument is still counted, so the marker is inserted past the * that was already emitted.

Change

A keyword-only argument no longer advances the marker position. Genuine positional-only parameters are unaffected, including the double-underscore spelling: def f3(__pos, *, kw) still generates def f3(__pos, /, *, kw).

Tests

testHistoricalPosOnlyParamsWithKeywordOnly covers a keyword-only dunder on its own, mixed with a PEP 570 positional-only parameter, alongside a historical positional-only parameter, and with two of them. It fails before this change with def f1(*, /, __kw) and passes after.

mypy/test/teststubgen.py is otherwise unchanged: 367 passed, with testAttrsClass_semanal failing identically before and after this change on my machine. Self-check on mypy/stubgen.py, ruff and black are clean.

A parameter whose name starts with two underscores is positional-only by
convention, but not when it appears after the keyword-only separator, where
counting it put the / marker after the * and produced unparsable output.
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.

stubgen generates bad signatures when mixing historical positional-only names and keyword-only parameters

1 participant