migrate pyproject.toml from [tool.poetry] to PEP 621 [project] for uv #28

Closed
opened 2026-05-26 21:33:27 +00:00 by padreug · 1 comment
Owner

Problem

pyproject.toml declares deps under the legacy [tool.poetry] /
[tool.poetry.dependencies] tables. The working dev toolchain is
uv (not poetry — confirmed in
reference_satmachineadmin_test_runner.md), and uv reads the PEP 621
[project] table. Running uv lock against the current
pyproject.toml produces a header-only uv.lock (3 lines, no deps)
because uv can't see anything under the poetry tables.

Symptom: uv.lock was untracked for a long time and looked committable
but pinned nothing. We added it to .gitignore in
[commit-pending] as a stopgap; this issue tracks the real fix.

What needs to change

Migrate the relevant sections of pyproject.toml:

Before (current):

[tool.poetry]
name = "satmachineadmin"
version = "0.0.4"
description = "..."
authors = ["benarc", "dni <dni@lnbits.com>"]

[tool.poetry.dependencies]
python = "^3.10 | ^3.9"
lnbits = {version = "*", allow-prereleases = true}
mypy = "^1.13.0"

[tool.poetry.group.dev.dependencies]
black = "^24.3.0"
pytest-asyncio = "^0.21.0"
pytest = "^7.3.2"
mypy = "^1.5.1"
pre-commit = "^3.2.2"
ruff = "^0.3.2"
pytest-md = "^0.2.0"

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

After (PEP 621 + uv):

[project]
name = "satmachineadmin"
version = "0.0.4"
description = "Satoshi Machine admin extension for LNbits"
authors = [{name = "Padreug", email = "padreug@aiolabs.dev"}]
requires-python = ">=3.10"
dependencies = [
  "lnbits",         # version pin via lnbits's own deps; we follow upstream
  "mypy>=1.13.0",
]

[dependency-groups]
dev = [
  "black>=24.3.0",
  "pytest-asyncio>=0.21.0",
  "pytest>=7.3.2",
  "mypy>=1.5.1",
  "pre-commit>=3.2.2",
  "ruff>=0.3.2",
  "pytest-md>=0.2.0",
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

(Hatchling is uv's preferred default backend; could also stay on
poetry.core.masonry.api if we want backward compat with anyone still
on poetry — but since the working tool is uv, hatchling is the
simplest path.)

The [tool.mypy], [tool.pytest.ini_options], [tool.black],
[tool.ruff] sections stay as-is — uv doesn't touch those.

Why bother

  • Real lockfile. uv lock produces a sha-pinned lockfile listing
    every transitive dep. Reproducible installs, security audits, and
    the "is this dep version compromised?" check all become tractable.
  • Dev environment hygiene. Right now uv sync does nothing
    useful because the project declaration is invisible to uv.
    Contributors pip install-ing into the LNbits venv work by
    accident, not by spec.
  • Consistent across aiolabs. The user-global instructions say
    "use uv, not poetry"; the workspace CLAUDE.md calls poetry the
    primary toolchain only as legacy mention. Migrating brings the
    satmachineadmin repo in line with the workflow we actually use.

Steps

  1. Rewrite pyproject.toml per the sketch above. Watch for
    subtleties:
    • lnbits version constraint: currently {version = "*", allow-prereleases = true}. Confirm whether uv needs an explicit
      prerelease policy (tool.uv.prerelease).
    • Python constraint: current "^3.10 | ^3.9" is poetry-flavored
      OR-syntax; PEP 621 takes requires-python = ">=3.10". Drop the
      3.9 branch (LNbits itself requires 3.10+).
  2. Run uv lock — confirm it produces a real lockfile with every
    transitive dep pinned.
  3. Run uv sync --frozen in a fresh venv to verify install matches
    the LNbits dev container's existing /app/.venv.
  4. Run the test suite (/app/.venv/bin/python -m pytest -q inside
    the dev container) — should remain at 75 passed.
  5. Remove uv.lock from .gitignore and commit the lockfile.
  6. Update the repo's CLAUDE.md "Development Commands" section to
    document uv run … patterns (not poetry run …).

Cross-cutting

Same migration is probably warranted across other aiolabs LNbits
extensions (aiolabs/lnurlp, aiolabs/withdraw, aiolabs/events,
aiolabs/libra) and the lnbits fork itself. Don't bundle them
into this issue
— each is a separate small migration. Track
sibling issues as they're filed.

Priority

Low. The current setup works — dev container has the right deps
installed, tests pass, production builds via NixOS flake input
(which doesn't consult pyproject.toml for runtime deps). The
migration is hygiene, not a blocker. Ship after v2 launch.

## Problem `pyproject.toml` declares deps under the legacy `[tool.poetry]` / `[tool.poetry.dependencies]` tables. The working dev toolchain is **uv** (not poetry — confirmed in `reference_satmachineadmin_test_runner.md`), and uv reads the PEP 621 `[project]` table. Running `uv lock` against the current `pyproject.toml` produces a header-only `uv.lock` (3 lines, no deps) because uv can't see anything under the poetry tables. Symptom: `uv.lock` was untracked for a long time and looked committable but pinned nothing. We added it to `.gitignore` in [commit-pending] as a stopgap; this issue tracks the real fix. ## What needs to change Migrate the relevant sections of `pyproject.toml`: **Before (current):** ```toml [tool.poetry] name = "satmachineadmin" version = "0.0.4" description = "..." authors = ["benarc", "dni <dni@lnbits.com>"] [tool.poetry.dependencies] python = "^3.10 | ^3.9" lnbits = {version = "*", allow-prereleases = true} mypy = "^1.13.0" [tool.poetry.group.dev.dependencies] black = "^24.3.0" pytest-asyncio = "^0.21.0" pytest = "^7.3.2" mypy = "^1.5.1" pre-commit = "^3.2.2" ruff = "^0.3.2" pytest-md = "^0.2.0" [build-system] requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" ``` **After (PEP 621 + uv):** ```toml [project] name = "satmachineadmin" version = "0.0.4" description = "Satoshi Machine admin extension for LNbits" authors = [{name = "Padreug", email = "padreug@aiolabs.dev"}] requires-python = ">=3.10" dependencies = [ "lnbits", # version pin via lnbits's own deps; we follow upstream "mypy>=1.13.0", ] [dependency-groups] dev = [ "black>=24.3.0", "pytest-asyncio>=0.21.0", "pytest>=7.3.2", "mypy>=1.5.1", "pre-commit>=3.2.2", "ruff>=0.3.2", "pytest-md>=0.2.0", ] [build-system] requires = ["hatchling"] build-backend = "hatchling.build" ``` (Hatchling is uv's preferred default backend; could also stay on `poetry.core.masonry.api` if we want backward compat with anyone still on poetry — but since the working tool is uv, hatchling is the simplest path.) The `[tool.mypy]`, `[tool.pytest.ini_options]`, `[tool.black]`, `[tool.ruff]` sections stay as-is — uv doesn't touch those. ## Why bother - **Real lockfile.** `uv lock` produces a sha-pinned lockfile listing every transitive dep. Reproducible installs, security audits, and the "is this dep version compromised?" check all become tractable. - **Dev environment hygiene.** Right now `uv sync` does nothing useful because the project declaration is invisible to uv. Contributors `pip install`-ing into the LNbits venv work by accident, not by spec. - **Consistent across aiolabs.** The user-global instructions say "use uv, not poetry"; the workspace `CLAUDE.md` calls poetry the primary toolchain only as legacy mention. Migrating brings the satmachineadmin repo in line with the workflow we actually use. ## Steps 1. Rewrite `pyproject.toml` per the sketch above. Watch for subtleties: - `lnbits` version constraint: currently `{version = "*", allow-prereleases = true}`. Confirm whether uv needs an explicit prerelease policy (`tool.uv.prerelease`). - Python constraint: current `"^3.10 | ^3.9"` is poetry-flavored OR-syntax; PEP 621 takes `requires-python = ">=3.10"`. Drop the 3.9 branch (LNbits itself requires 3.10+). 2. Run `uv lock` — confirm it produces a real lockfile with every transitive dep pinned. 3. Run `uv sync --frozen` in a fresh venv to verify install matches the LNbits dev container's existing `/app/.venv`. 4. Run the test suite (`/app/.venv/bin/python -m pytest -q` inside the dev container) — should remain at 75 passed. 5. Remove `uv.lock` from `.gitignore` and commit the lockfile. 6. Update the repo's `CLAUDE.md` "Development Commands" section to document `uv run …` patterns (not `poetry run …`). ## Cross-cutting Same migration is probably warranted across other aiolabs LNbits extensions (`aiolabs/lnurlp`, `aiolabs/withdraw`, `aiolabs/events`, `aiolabs/libra`) and the lnbits fork itself. **Don't bundle them into this issue** — each is a separate small migration. Track sibling issues as they're filed. ## Priority Low. The current setup *works* — dev container has the right deps installed, tests pass, production builds via NixOS flake input (which doesn't consult `pyproject.toml` for runtime deps). The migration is hygiene, not a blocker. Ship after v2 launch.
Author
Owner

➡️ Migrated to aiolabs/spirekeeper#16 (aiolabs/spirekeeper#16).

The v2-bitspire line of this extension now lives in its own repo, aiolabs/spirekeeper. Tracking for this issue continues there; closing here. (Issue numbers were reassigned in the new repo.)

➡️ **Migrated to https://git.atitlan.io/aiolabs/spirekeeper/issues/16 (aiolabs/spirekeeper#16).** The v2-bitspire line of this extension now lives in its own repo, `aiolabs/spirekeeper`. Tracking for this issue continues there; closing here. (Issue numbers were reassigned in the new repo.)
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
aiolabs/satmachineadmin#28
No description provided.