10aday › Version Constraint Checker › Poetry ^ and ~ to PEP 440

Poetry ^ and ~ version constraints, and how to write them in PEP 440

Short answer: in Poetry, ^1.2.3 means ≥1.2.3 <2.0.0: anything up to the next change of the left-most non-zero number. So ^0.2.3 means ≥0.2.3 <0.3.0. ~1.2.3 means ≥1.2.3 <1.3.0 (patch updates), but ~1 means <2. A bare 1.2.3 is an exact pin. Neither ^ nor ~ exist in PEP 440, so the [project] table used by Poetry 2, uv, pip and Hatch rejects them. Write the bounds out: ^1.2.3 → >=1.2.3,<2.0.0. Careful: ~=1.2.3 is not the same as ^1.2.3.

Migrating a whole file to Poetry 2 or uv? Paste your pyproject.toml into the Poetry to PEP 621 converter: it rewrites every dependency, the python constraint and the groups.

Have a constraint and a list of versions? Paste them into the Version Constraint Checker: it shows, side by side, what npm, Cargo, Composer, pip and RubyGems accept.

Poetry constraints and their PEP 440 form

Middle column: the exact text to put in [project] dependencies, requirements.txt or uv add. It is what our converter outputs, and each range is checked with pip's rules.

Poetry ([tool.poetry])PEP 440 ([project], pip, uv)Allows
^1.2.3>=1.2.3,<2.0.0≥1.2.3 <2.0.0
^1.2>=1.2,<2.0≥1.2.0 <2.0.0
^1>=1,<2≥1.0.0 <2.0.0
^0.2.3
below 1.0, the minor is the breaking number
>=0.2.3,<0.3.0≥0.2.3 <0.3.0
^0.0.3
only 0.0.3
>=0.0.3,<0.0.4≥0.0.3 <0.0.4
^0>=0,<1≥0.0.0 <1.0.0
~1.2.3>=1.2.3,<1.3.0≥1.2.3 <1.3.0
~1.2>=1.2,<1.3≥1.2.0 <1.3.0
~1
one number: same as ^1
>=1,<2≥1.0.0 <2.0.0
~0.2.3>=0.2.3,<0.3.0≥0.2.3 <0.3.0
~=1.2
already PEP 440
~=1.2≥1.2.0 <2.0.0
~=1
Poetry accepts it, pip does not
>=1,<2≥1.0.0 <2.0.0
1.2.*==1.2.*≥1.2.0 <1.3.0
*"" (no specifier)any version
1.2.3
bare version: exact pin (Cargo would read ^)
==1.2.3exactly 1.2.3
>=1.2 <2.0
space or comma = and
>=1.2,<2.0≥1.2.0 <2.0.0
^1.2 || ^2.0>=1.2,<2.0 or >=2.0,<3.0
no single PEP 440 form
≥1.2.0 <2.0.0 or ≥2.0.0 <3.0.0

Ranges shown for final releases. Poetry and pip both skip pre-releases (2.0.0rc1) unless you ask for them, but their edge rules differ; the converter lists the cases it cannot translate exactly.

The usual mistake: translating ^ into ~=

Both look like “compatible release”, so ^ is often rewritten as ~= with the same numbers. That is right for ^1.2 and ^0.2.3, wrong for ^1.2.3 and ^0.2:

PoetryWrong translationIt allowsShould allow
^1.2.3~=1.2.3≥1.2.3 <1.3.0≥1.2.3 <2.0.0
^0.2~=0.2≥0.2.0 <1.0.0≥0.2.0 <0.3.0
^1.2~=1.2 (fine)≥1.2.0 <2.0.0≥1.2.0 <2.0.0
^0.2.3~=0.2.3 (fine)≥0.2.3 <0.3.0≥0.2.3 <0.3.0

~=1.2.3 blocks the 1.3 minor release that ^1.2.3 allowed: you silently stop getting features and fixes. ~=0.2 lets 0.3 and later 0.x releases in, which ^0.2 excluded on purpose, since before 1.0 a minor bump may break the API.

Where each syntax is accepted

Common questions

What does ^ mean in Poetry?

It is a caret requirement: updates that do not change the left-most non-zero number are allowed. ^1.2.3 = ≥1.2.3 <2.0.0, ^0.2.3 = ≥0.2.3 <0.3.0, ^0.0.3 = ≥0.0.3 <0.0.4. In PEP 440 you write >=1.2.3,<2.0.0.

What does ~ mean in Poetry?

A tilde requirement. With two or three numbers only the last one may increase, starting from the second: ~1.2.3 = ≥1.2.3 <1.3.0 and ~1.2 = ≥1.2 <1.3. With one number, ~1 = ≥1 <2.

Is ^1.2.3 the same as ~=1.2.3?

No. ~=1.2.3 stops before 1.3.0; ^1.2.3 goes up to 2.0.0. The PEP 440 form of ^1.2.3 is >=1.2.3,<2.0.0. For ^1.2, ~=1.2 is equivalent.

Can I use ^ in [project] dependencies with Poetry 2?

No. Poetry 2 reads PEP 621 [project] metadata, where only PEP 440 specifiers are valid; ^ and ~ are only accepted in [tool.poetry.dependencies]. uv and pip reject them too.

How do I write ^1.2 || ^2.0 in PEP 440?

You cannot in one specifier: PEP 440 has no “or”. Here the two ranges touch, so >=1.2,<3.0 is equivalent. When they do not touch, pick one range or split the dependency with environment markers.

Related

Sources