fix: Poetry tilde on a short version converts to the wrong upper bound - #3858
Merged
frostming merged 2 commits intoAug 27, 2026
Merged
Conversation
A tilde requirement allows patch-level changes when a minor version is given and minor-level changes otherwise, so `~1.2` means `<1.3.0` and `~1` means `<2.0.0`. Mapping it onto PEP 440's `~=` only agrees when all three components are present: `~=1.2` means `<2.0`, and `~=1` is not a valid specifier at all, so a one-component tilde aborted the import. Give the tilde an explicit upper bound the way the caret already has one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RUJeBSssdWdgDj3AVsPqkA
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RUJeBSssdWdgDj3AVsPqkA
frostming
approved these changes
Aug 27, 2026
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3858 +/- ##
=======================================
Coverage 88.51% 88.52%
=======================================
Files 121 121
Lines 13281 13288 +7
Branches 2257 2257
=======================================
+ Hits 11756 11763 +7
Misses 960 960
Partials 565 565
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What's broken
pdm import -f poetryconverts every tilde constraint to PEP 440's~=. That only means the same thing when all three components are present. With a short version it either widens the constraint or produces a specifier that isn't valid at all:~=equivalent~1.2.3>=1.2.3 <1.3.0>=1.2.3, ==1.2.*~1.2>=1.2.0 <1.3.0>=1.2, ==1.*<2.0, too wide~1>=1.0.0 <2.0.0~=requires at least two release segments, so the one-component case doesn't just import wrongly, it raises.Repro
foo = "~1.2"andbar = "~1"in a Poetry project:The same path handles
requires-python, sopython = "~3"aborts the whole import today:The fix
A tilde allows patch-level changes when a minor version is given and minor-level changes otherwise, so the bumped position is the minor when there is one and the major when there isn't.
_tilde_upper_boundcomputes it and the tilde gets an explicit upper bound, the way_caret_upper_boundalready does for^(#3848).Verification
test_convert_poetry_tilde_constraintis parametrised over Poetry's own tilde table,~1.2.3through~0, checked against the table in their dependency-specification docs, plustest_convert_poetry_tilde_python_constraintfor therequires-pythonpath. Reverting onlysrc/pdm/formats/poetry.pyturns 8 of the 9 new cases red; the one that stays green is~1.2.3, which~=already handled correctly.One assertion in
test_convert_poetryhad the old bound baked in. The fixture is Poetry's ownpyproject.tomlwithpython = "~2.7 || ^3.4", sorequires-pythonwas asserting the bug —~2.7stops below 2.8, and the expectation now carries the resulting!=2.8.*.tests/test_formats.pypasses, 68 tests. Full suite is 1378 passed / 7 failed on this box, and those 7 are identical on a clean checkout — they need symlink privileges, POSIXecho/caton PATH, or a workingpython3.14.ruff checkandruff format --checkclean. Windows 11, CPython 3.11.