Skip to content

Examples Pep440Versions

Truong Giang Vu edited this page Feb 13, 2026 · 1 revision

PEP 440: Version Specifier Reference

Complete reference for version specifier syntax used in PEP 723 dependencies.


Quick Reference

Pattern Example Matches Doesn't Match
== pandas==1.5.3 1.5.3 only 1.5.2, 1.5.4, 2.0
!= numpy!=2.0.0 Any except 2.0.0 2.0.0
> matplotlib>3.0 3.0.1, 3.5, etc. 3.0.0, 2.9
< scipy<2.0 1.9, 1.0, etc. 2.0.0, 2.1
>= sklearn>=1.0 1.0, 1.5, 2.0, etc. 0.9, 0.8
<= torch<=1.13 1.13, 1.12, 1.0, etc. 1.13.1, 2.0
~= pydantic~=2.0 2.0, 2.1, 2.99 2.100+, 3.0

Basic Comparisons

Exact Version (==)

# /// script
# dependencies = [
#     "pandas==1.5.3",
# ]
# ///

Only this exact version is installed.

Use when: You've tested and know the exact version needed.


Not Equal (!=)

# /// script
# dependencies = [
#     "numpy!=2.0.0",  # Any version except 2.0.0
# ]
# ///

Installs any version except the specified one.

Use when: One specific version is broken but others work.


Greater Than (>)

# /// script
# dependencies = [
#     "matplotlib>3.1",  # Any version after 3.1
# ]
# ///

Matches: 3.1.1, 3.2, 3.5, 4.0, etc.
Doesn't match: 3.0, 3.1.0


Less Than (<)

# /// script
# dependencies = [
#     "scipy<2.0",  # Any version before 2.0
# ]
# ///

Matches: 1.0, 1.5, 1.9.9
Doesn't match: 2.0.0, 2.1


Greater or Equal (>=)

# /// script
# dependencies = [
#     "sklearn>=1.0",  # 1.0 or newer
# ]
# ///

Matches: 1.0, 1.1, 2.0, 10.0
Doesn't match: 0.9.9

Common use: "Requires at least this version"


Less or Equal (<=)

# /// script
# dependencies = [
#     "torch<=1.13",  # 1.13 or older
# ]
# ///

Matches: 1.13, 1.12, 1.0, 0.5
Doesn't match: 1.13.1, 2.0


Advanced: Combining Constraints

Multiple Constraints

# /// script
# dependencies = [
#     "pandas>=1.5,<2.0",  # Between 1.5 and 2.0 (exclusive)
# ]
# ///

Matches: 1.5.0, 1.5.3, 1.9.9
Doesn't match: 1.4.9, 2.0.0

Pattern: >=MIN,<MAX is very common for compatibility ranges.

Multiple Exclusions

# /// script
# dependencies = [
#     "scipy!=1.0.0,!=1.5.0",  # Any version except these
# ]
# ///

Matches: 1.4.0, 1.6.0, 2.0
Doesn't match: 1.0.0, 1.5.0


Compatible Release (~=)

The "compatible release" specifier is useful for minor version updates.

Pattern: ~=X.Y

# /// script
# dependencies = [
#     "pydantic~=2.0",  # 2.x but not 3.x
# ]
# ///

Meaning: X.y where y can be any number, but X cannot change.

Matches: 2.0, 2.1, 2.99
Doesn't match: 1.9, 3.0

Pattern: ~=X.Y.Z

# /// script
# dependencies = [
#     "numpy~=1.24.0",  # 1.24.x but not 1.25.x
# ]
# ///

Meaning: X.Y.z where z can be any number, but X.Y cannot change.

Matches: 1.24.0, 1.24.1, 1.24.999
Doesn't match: 1.23.9, 1.25.0

When to Use ~=

# ✅ GOOD: Allow bug fixes
# dependencies = ["pandas~=1.5.0"]  # Get fixes in 1.5.1, 1.5.2, etc.

# ❌ RISKY: Too permissive
# dependencies = ["pandas~=1.0"]  # Allows 1.0 to 1.999 (too broad!)

Pre-release & Development Versions

Alpha/Beta/RC Versions

# /// script
# dependencies = [
#     "scipy>=1.0.0a1",   # Alpha version
#     "numpy>=1.24.0rc1",  # Release candidate
# ]
# ///

Python versions follow PEP 440:

  • a = alpha
  • b = beta
  • rc = release candidate

Post Releases

# /// script
# dependencies = [
#     "package>=1.0.0.post1",  # Post-release version
# ]
# ///

Real-World Examples

Example 1: Web Scraping

# /// script
# dependencies = [
#     "requests==2.31.0",         # Exact version
#     "beautifulsoup4>=4.11,<5.0",  # Compatible range
# ]
# ///

Example 2: Data Science Stack

# /// script
# dependencies = [
#     "pandas~=1.5.0",             # Allow 1.5.x patches
#     "numpy>=1.24,<2.0",          # Not numpy 2
#     "scikit-learn==1.3.0",       # Exact version
#     "matplotlib>=3.7,<4.0",      # Next major pending
# ]
# ///

Example 3: Machine Learning

# /// script
# dependencies = [
#     "torch>=2.0,<3.0",           # Major version 2
#     "torchvision>=0.15,<0.16",   # Minor version lock
#     "transformers~=4.30.0",      # Allow 4.30.x patches
# ]
# ///

Example 4: Minimal Dependencies

# /// script
# dependencies = [
#     "requests",                  # Latest (risky!)
# ]
# ///

# Better:
# dependencies = [
#     "requests>=2.28",            # Minimum version
# ]
# ///

Version Format Details

Python versions follow semantic versioning: MAJOR.MINOR.PATCH

Standard Format

1.5.3         # Major.Minor.Patch
↑ ↑ ↑
| | └─ Patch version (bug fixes: 3 → 4)
| └─── Minor version (features: 5 → 6)
└───── Major version (breaking changes: 1 → 2)

Extended Format

1.5.3.post2dev1
      └─ Dev version (developer preview)
      └─ Post-release (patch after release)

Decision Tree: Which Specifier to Use?

Do you have tested version?
├─ YES → Use exact: "package==1.5.3"
└─ NO → Continue...

Does package have breaking changes often?
├─ YES (unstable) → Use major.minor: "package~=1.5"
└─ NO (stable) → Continue...

Industry standard version available?
├─ YES → "package>=1.5,<2.0"  (safe range)
└─ NO → "package>=1.5"        (minimum only)

Common Mistakes

❌ Mistake 1: Single equals not double

# WRONG
# dependencies = ["pandas=1.5.3"]

# CORRECT
# dependencies = ["pandas==1.5.3"]

❌ Mistake 2: Mixed spaces/punctuation

# WRONG
# dependencies = ["pandas == 1.5.3"]  # Spaces!
# dependencies = ["pandas >=1.5 , <2.0"]  # Bad comma

# CORRECT
# dependencies = ["pandas==1.5.3"]
# dependencies = ["pandas>=1.5,<2.0"]

❌ Mistake 3: Too restrictive

# WRONG (blocks updates)
# dependencies = ["pandas==1.5.3", "numpy==1.24.0", "scipy==1.9.0"]

# BETTER (allow compatible updates)
# dependencies = ["pandas~=1.5.0", "numpy~=1.24.0", "scipy~=1.9.0"]

❌ Mistake 4: Too permissive

# WRONG (May install incompatible version)
# dependencies = ["pandas>=1.0"]

# BETTER (Known boundary)
# dependencies = ["pandas>=1.5,<2.0"]

How UV(Resolver Uses These

Your PEP 723:
dependencies = ["pandas~=1.5.0", "numpy>=1.24,<2.0"]
            ↓
UV reads specifiers
            ↓
Queries PyPI for matching versions
            ↓
Resolves conflicts (uses SAT solver)
            ↓
Selects: pandas 1.5.3, numpy 1.24.0
            ↓
Installs

Checking Your Versions

Check package on PyPI

# Visit: https://pypi.org/project/pandas
# See all available versions

Test version locally (if you have PyPI mirror access)

# Try installing
uv pip install "pandas==1.5.3"  # Exact
uv pip install "pandas~=1.5.0"  # Range

See installed version

import pandas
print(pandas.__version__)  # e.g., "1.5.3"

Reference Card

When unsure, use:

"package>=X.Y.0,<X+1.0"  # Allow bug fixes, not major change

For reproducibility:

"package==X.Y.Z"  # Exact version

For less critical dependencies:

"package>=X.Y"  # At least this version

More Information

Clone this wiki locally