Skip to main content

Dependency Tradeoffs — Poetry vs PEP 621 (and editable installs)

A practical guide for Poetry users importing a local lib that they are actively developing and want "hot reloading".

Canonical Examples

A) Poetry-native (best for monorepo/dev)

pyproject.toml
[tool.poetry]
name = "breakouts"
version = "0.1.0"
description = "Breakout tagging experiments"
authors = ["Thomas Rones <you@example.com>"]

[tool.poetry.dependencies]
python = "^3.11"
pandas = "^2.2"
numpy = "^1.26"
# 👇 Live editable link to your local lib
qlir = { path = "/home/tjr/gh/qlir", develop = true }

Usage:

poetry install
# Edits in /home/tjr/gh/qlir are reflected immediately

B) PEP 621 [project] (standardized)

pyproject.toml
[project]
name = "breakouts"
version = "0.1.0"
dependencies = [
"pandas>=2.2,<3.0",
"numpy>=1.26,<2.0",
# Static reference (snapshot); NOT editable
"qlir @ file:///home/tjr/gh/qlir",
]

Add live linkage manually (one-time per venv):

poetry run pip install -e /home/tjr/gh/qlir
# Re-run if you blow away the venv, or want to switch back from a snapshot

Migration Script — Convert [tool.poetry] to [project]

To simplify switching formats, use the helper script below. It automatically converts Poetry-style pyproject.toml files to PEP 621-compliant versions.

📜 migrate_to_pep621.py

# Dry run (prints converted TOML to stdout)
python migrate_to_pep621.py /path/to/pyproject.toml --dry-run

# Write in-place (creates pyproject.toml.bak)
python migrate_to_pep621.py /path/to/pyproject.toml

# Write to a different file
python migrate_to_pep621.py /path/to/pyproject.toml --out /tmp/new-pyproject.toml

✨ Features

  • Converts [tool.poetry][project] (PEP 621)

  • Translates version specs:

    • ^1.2.3>=1.2.3,<2.0.0
    • ~1.4>=1.4,<1.5
  • Converts path/git deps to PEP 508 strings

    • { path = "…", develop = true }pkg @ file:///abs/path
    • { git = "…", rev = "main" }pkg @ git+…@main
  • Maps [tool.poetry.group.dev.dependencies][project.optional-dependencies].dev

  • Preserves [tool.poetry.scripts] as [project.scripts]

  • Adds [build-system] if missing (uses poetry-core)

  • Creates .bak backup before overwriting

📦 Download: migrate_to_pep621


Makefile / Scripts (quality of life)

With [project] style (standardized)

.PHONY: dev
# Ensure editable link to qlir inside Poetry venv
dev:
poetry run pip install -e /home/tjr/gh/qlir
poetry install
@echo "✅ Dev environment ready (qlir in editable mode)"

With Poetry tables (develop=true)

.PHONY: dev
# One command setup
dev:
poetry install
@echo "✅ Dev environment ready (Poetry develop=true for qlir)"

Optional Poetry script:

[tool.poetry.scripts]
make-dev = "breakouts.scripts:make_dev"

Migration Notes (Poetry → PEP 621)

  1. Move metadata from [tool.poetry][project] (name, version, authors, etc.).

  2. Convert dependencies to PEP 508 strings under [project].dependencies.

  3. Replace { path=..., develop=true } with a manual editable step:

    poetry run pip install -e /path/to/qlir
  4. Keep build-system configured for Poetry or switch backends as needed.


Troubleshooting

  • Edits to lib not showing up

    • Using [project]? You probably installed via file:// (snapshot). Run poetry run pip install -e /path/to/lib.
    • Using { develop = true }? Ensure the lib has a valid pyproject.toml and the package name matches its import path.
  • Duplicate log lines after calling ensure_logging()

    • You likely created multiple handlers. Guard with if not logger.hasHandlers() before basicConfig().
  • Pylance/IntelliSense can’t find the local package

    • Ensure VS Code is using Poetry’s interpreter (.venv/bin/python).
    • For workspaces, set "python.defaultInterpreterPath" to the venv’s python for the folder.