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)
[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)
[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 (usespoetry-core) -
Creates
.bakbackup 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)
-
Move metadata from
[tool.poetry]→[project](name, version, authors, etc.). -
Convert dependencies to PEP 508 strings under
[project].dependencies. -
Replace
{ path=..., develop=true }with a manual editable step:poetry run pip install -e /path/to/qlir -
Keep
build-systemconfigured for Poetry or switch backends as needed.
Troubleshooting
-
Edits to lib not showing up
- Using
[project]? You probably installed viafile://(snapshot). Runpoetry run pip install -e /path/to/lib. - Using
{ develop = true }? Ensure the lib has a validpyproject.tomland the package name matches its import path.
- Using
-
Duplicate log lines after calling
ensure_logging()- You likely created multiple handlers. Guard with
if not logger.hasHandlers()beforebasicConfig().
- You likely created multiple handlers. Guard with
-
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.
- Ensure VS Code is using Poetry’s interpreter (