Compatible-release requires-python constraints infer unsupported targets
Maintainers usually reply within 1 day
@harisawan-bit is already working on this.
Since Jul 28, 2026.
Assessment
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Newbie friendliness
- 48/100
Research direction
Start with black.files.infer_target_version and the strip_specifier_set behavior described in the report. Run the provided Python reproduction and inspect the existing target-version tests before adding regression coverage for patch-release compatible constraints. Done means ~=3.11.0 infers only PY311 while the existing two-component behavior remains unchanged.
Written by the indexing model from the issue text.
Description
Describe the bug
Target-version inference widens a compatible-release constraint when it removes the patch component. requires-python = "~=3.11.0" permits Python 3.11 releases, but Black infers Python 3.11 through 3.15 on current main.
To Reproduce
Create pyproject.toml:
[project]
requires-python = "~=3.11.0"
Run:
black --verbose --config pyproject.toml --code 'x=1'
The verbose configuration includes:
target_version: ['py311', 'py312', 'py313', 'py314', 'py315']
This can also be reproduced without formatting a file:
from black.files import infer_target_version
print([v.name for v in infer_target_version(
{"project": {"requires-python": "~=3.11.0"}}
)])
# ['PY311', 'PY312', 'PY313', 'PY314', 'PY315']
Expected behavior
Only py311 should be inferred. The compatible-release specification preserves the prefix before the final release component: ~=3.11.0 is equivalent to >=3.11.0, ==3.11.*. In contrast, ~=3.11 permits later Python 3 minor versions.
Environment
- Black: source checkout of
main, commit994ef7eeb18172178552daa1f36f001d156ad583, installed editable in a clean virtual environment. - CPython 3.14.6, macOS arm64.
packaging26.3.
Additional context
strip_specifier_set turns ~=3.11.0 into ~=3.11, which loses the upper bound. ~=3.11.7 has the same problem. A focused fix can preserve the matching minor-version prefix while retaining the existing treatment of two-component constraints.
Related: #3581 discusses the strict-> lower-bound case; the broader rewrite in #3583 is closed. This report isolates the compatible-release upper-bound case. I have a small patch with regression coverage for patch releases, prereleases, additional release components, exclusions, and the distinct two-component form.
AI assistance: OpenAI Codex helped prepare the reproduction, patch, tests, and report. The outputs above were verified by execution locally.
- Dominant language
- Python
- Stars
- 42.2k
- Forks
- 3k
- Avg merge
- 2d 14h
- Merged PRs (30d)
- 98
Getting set up
- Ships a Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from psf/black
-
--line-ranges selects the wrong source line with --skip-source-first-linePossibly taken @SaifAli-S claimed this today. OpenT: bug
Difficulty 3/5 1-2 days Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
Difficulty 5/5 Over a week Newbie friendliness 25/100
Maintainers usually reply within 1 day
-
Odd behavior from `black` when handling long `lambda` functionsPossibly taken @harshitdeora claimed this 9 days ago. OpenF: linetoolong T: bug
Difficulty 3/5 1-2 days Newbie friendliness 57/100
Maintainers usually reply within 1 day
-
Project-relative cache-dir allows unrestricted pickle.load of attacker-controlled dataPossibly taken @rinopatrick claimed this 12 days ago. OpenS: needs discussion
Difficulty 4/5 3-5 days Newbie friendliness 22/100
Maintainers usually reply within 1 day
-
Nested .gitignore negations can never re-include what an ancestor excludedPossibly taken @RRXXZZYY claimed this 73 days ago. Open
Difficulty 4/5 3-5 days Newbie friendliness 65/100
Maintainers usually reply within 1 day
Similar issues
-
add entry to blockOpen
Difficulty 1/5 Under an hour Newbie friendliness 65/100
StevenBlack/hosts#3299 ·
-
`garak --report` overwrites the input report when its name has no ".report"Possibly taken @0z5a claimed this today. Openneeds-triage
Difficulty 2/5 Half a day Newbie friendliness 72/100
Maintainers usually reply within 2 days
-
plot_graph crashes when a mesh node has no m2m edgePossibly taken @tygvi claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
mllam/neural-lam#883 · 1 comment ·
Maintainers usually reply within 2 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
future-agi/future-agi#4092 · 1 comment ·
Maintainers usually reply within 1 day
-
transcript analytics: a text whose only protected spans the prose pass redacts is withheld wholeOpen
Difficulty 1/5 Under an hour Newbie friendliness 82/100
WingedGuardian/GENesis-AGI#4641 ·
Maintainers usually reply within 1 day