Migrating from Poetry to UV
Problem
Many Python developers using Poetry face challenges when migrating to the newer uv package manager. Common hurdles include:
- Lack of official migration guides
- Uncertainty about required modifications in
pyproject.toml
- Confusion around proper build system configuration
- Concerns about preserving dependency groups and private repository access
- Potential dependency version conflicts during migration
Below is a typical Poetry pyproject.toml
that requires conversion:
[tool.poetry]
name = "name"
version = "1.6.0"
description = ""
# ... poetry configuration
[tool.poetry.dependencies]
python = "^3.12"
fastapi = "^0.115.2"
# ... dependencies
[tool.poetry.group.dev.dependencies]
pytest = "^8.3.3"
# ... dev dependencies
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
Recommended Solution: Using migrate-to-uv
Step-by-Step Migration
- Install migration tools:
pipx install uv
uv pip install uv-migrate
- Run the migration command:
cd your-project-directory
uvx migrate-to-uv
- Generate the lock file:
uv lock
- Install dependencies:
uv sync
Key Changes Performed by migrate-to-uv
Original Poetry Section | Converted UV Section |
---|---|
[tool.poetry.dependencies] | [project.dependencies] |
[tool.poetry.group.dev] | [dependency-groups.dev] |
Poetry-compatible version spec | PEP 621-compatible requirements |
poetry.lock file | Removed & replaced with uv.lock |
Handling Private Repositories
For projects using private package repositories:
# For source named "company-repo" in tool.poetry.source
export UV_INDEX_COMPANY_REPO_USERNAME=<username>
export UV_INDEX_COMPANY_REPO_PASSWORD=<password>
uvx migrate-to-uv
Alternatively include directly in pyproject.toml
:
[[tool.uv.index]]
name = "custom-repo"
url = "https://your-private-repo.example.com/simple/"
Post-Migration Verification
- Verify authors format conversion:
# Before
authors = ["John Doe <john.doe@company.com>"]
# After
authors = [
{name = "John Doe", email = "john.doe@company.com"}
]
- Confirm build-system update:
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
- Run test suite to verify dependencies:
uv run pytest
Alternative Approach: Manual Conversion
- Convert with PDM:
uvx pdm import pyproject.toml
- Modify dependency groups:
# Replace
[tool.pdm.dev-dependencies]
# With
[dependency-groups]
- Remove all Poetry-specific sections:
# Remove these blocks:
[tool.poetry]
[tool.poetry.dependencies]
[tool.poetry.group.dev]
Preserving Exact Dependency Versions (Optional Advanced Step)
Use this script to enforce Poetry's locked versions during migration:
from pathlib import Path
import toml
lock_data = toml.load(Path("poetry.lock"))
pyproject_data = toml.load(Path("pyproject.toml"))
locked_versions = {pkg["name"]: pkg["version"] for pkg in lock_data["package"]}
def update_deps(section):
for dep in list(section):
if dep in locked_versions:
section[dep] = locked_versions[dep]
update_deps(pyproject_data["tool"]["poetry"]["dependencies"])
update_deps(pyproject_data["tool"]["poetry"]["group"]["dev"]["dependencies"])
with open("pyproject.toml", "w") as f:
toml.dump(pyproject_data, f)
WARNING
Use this script with caution! It may generate invalid constraints for dependencies with special sources or extras. After migration, revert the frozen versions.
Troubleshooting
Dependency resolution conflicts:
bashuv lock --refresh uv pip list --outdated
Missing build backend:
diff+ [build-system] + requires = ["hatchling"] + build-backend = "hatchling.build"
Authentication failures: Verify
UV_INDEX_*
environment variables match your private repository names exactly
TIP
If migrating complex projects, run uv pip freeze > requirements.txt
pre-migration to compare dependency versions post-migration
Post-Migration Commands Cheat Sheet
Task | Poetry Command | UV Equivalent |
---|---|---|
Add dependency | poetry add package | uv add package |
Install dependencies | poetry install | uv sync |
Remove dependency | poetry remove pkg | uv remove pkg |
Update dependencies | poetry update | uv update |
Generate lockfile | poetry lock | uv lock |
Virtual environment | poetry shell | source .venv/Scripts/activate (Windows/Linux) |
By following these steps, you'll maintain dependency consistency while benefiting from UV's improved performance and modern tooling features.