Skip to content

fix: pin the Black target version to the minimum supported Python - #613

Merged
razor-x merged 1 commit into
betafrom
claude/black-python-3.15-warning-hft77w
Aug 13, 2026
Merged

fix: pin the Black target version to the minimum supported Python#613
razor-x merged 1 commit into
betafrom
claude/black-python-3.15-warning-hft77w

Conversation

@razor-x

@razor-x razor-x commented Aug 13, 2026

Copy link
Copy Markdown
Member

Problem

Every Lint job on beta emits a warning, on all four matrix legs (3.11–3.14):

Warning: Python 3.14 cannot parse code formatted for Python 3.15. To fix this: run Black
with Python 3.15, set --target-version to py314, or use --fast to skip the safety check.
Black's safety check verifies equivalence by parsing the AST, which fails when the running
Python is older than the target version.

Latest beta run: 31718873837. It also reproduces locally via just lint.

Cause

There was no [tool.black] section, so Black inferred its target versions from project.requires-python. Because that bound is open-ended (>=3.11), it expanded to every version Black knows about:

$ black --check --verbose seam/__init__.py
target_version: ['py311', 'py312', 'py313', 'py314', 'py315']

Black's safety check re-parses its own output with the stdlib ast module, using the highest target version. No interpreter from 3.11 through 3.14 can produce a 3.15 AST, so the check is skipped and the warning is printed.

Impact

Formatting was never wrong, and lint was never failing. Black only emits syntax common to all of its targets, so it was already formatting for the 3.11 floor. Verified two ways:

  • black --diff --target-version py315 . and --target-version py311 . produce byte-identical output across the repo.
  • Black still reformats correctly under the old config (checked against a deliberately unformatted file).

What was actually lost is the AST equivalence check — Black's guard against its own output changing program semantics. That guard was silently off for every lint run.

Change

[tool.black]
target-version = ["py311"]

Pinning the floor explicitly restores the safety check and silences the warning, with no formatting change.

Verification

$ black --check --verbose seam/__init__.py
target_version: ['py311']          # no warning

$ black --check .
All done! ✨ 🍰 ✨
110 files would be left unchanged.  # exit 0

Note for reviewers

This value needs bumping alongside any future increase to requires-python. The alternative — leaving the warning in place — keeps one less thing to maintain but leaves Black's safety check disabled, so pinning seemed the better trade.


Generated by Claude Code

Black infers its target versions from `requires-python`. Because that
bound is open-ended (`>=3.11`), it expanded to every version Black
knows about, including py315:

    target_version: ['py311', 'py312', 'py313', 'py314', 'py315']

Black's safety check re-parses its output with the stdlib `ast` module
using the highest target version, which no interpreter from 3.11 to 3.14
can do. That made every lint job emit:

    Warning: Python 3.14 cannot parse code formatted for Python 3.15.

Formatting was never affected, since Black only emits syntax common to
all targets and so was already formatting for the 3.11 floor; `--diff`
output is byte-identical between py311 and py315. What was lost is the
AST equivalence check that guards against Black corrupting code.

Pinning the floor explicitly restores that check and silences the
warning with no formatting change. This needs bumping alongside any
future increase to `requires-python`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X5qn7KvBztnwaRTFoL9KNo
@razor-x
razor-x requested a review from a team as a code owner August 13, 2026 16:31
@razor-x
razor-x merged commit aa15ecf into beta Aug 13, 2026
20 checks passed
@razor-x
razor-x deleted the claude/black-python-3.15-warning-hft77w branch August 13, 2026 16:39
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.

2 participants