chore(nix): migrate flake from poetry2nix to uv2nix

The project switched from poetry to uv in 44385ca, but the flake still
built everything through poetry2nix (an undeclared input resolved via
the flake registry) and no longer evaluated against the uv-based
pyproject.toml.

- build packages.blitz-api as a uv2nix virtualenv from uv.lock
  (wheels preferred), keeping the bin/api entry point the NixOS
  module expects
- replace the poetry dev shell with a uv-based tooling shell that
  mirrors devenv.nix
- move click to the main dependencies: the api console script
  imports it at runtime, so a production install without the dev
  group would crash on startup
- update the nixpkgs pin so the dev shell ships a uv that
  understands the current lockfile revision

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
fusion44 2026-07-03 15:30:17 +02:00
parent 49d5fcb9bf
commit c9f27c3f47
No known key found for this signature in database
6 changed files with 133 additions and 132 deletions

View file

@ -14,7 +14,7 @@ import click # isort:skip
help="Set the ASGI 'root_path' for applications submounted below a given URL path.",
)
def main(port, host, root_path):
"""Launched with `poetry run api` at root level"""
"""Launched with `uv run api` at root level"""
p = ""
if root_path is not None and root_path != "":

146
flake.lock generated
View file

@ -18,52 +18,13 @@
"type": "github"
}
},
"flake-utils_2": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1726560853,
"narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nix-github-actions": {
"inputs": {
"nixpkgs": [
"poetry2nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1729742964,
"narHash": "sha256-B4mzTcQ0FZHdpeWcpDYPERtyjJd/NIuaQ9+BV1h+MpA=",
"owner": "nix-community",
"repo": "nix-github-actions",
"rev": "e04df33f62cdcf93d73e9a04142464753a16db67",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nix-github-actions",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1739446958,
"narHash": "sha256-+/bYK3DbPxMIvSL4zArkMX0LQvS7rzBKXnDXLfKyRVc=",
"lastModified": 1782723713,
"narHash": "sha256-oPXCU/SSUokcGaJREHibG1CBX3+s/W7orDWQOZDsEeQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "2ff53fe64443980e139eaa286017f53f88336dd0",
"rev": "b5aa0fbd538984f6e3d201be0005b4463d8b09f8",
"type": "github"
},
"original": {
@ -73,28 +34,49 @@
"type": "github"
}
},
"poetry2nix": {
"pyproject-build-systems": {
"inputs": {
"flake-utils": "flake-utils_2",
"nix-github-actions": "nix-github-actions",
"nixpkgs": [
"nixpkgs"
],
"systems": "systems_3",
"treefmt-nix": "treefmt-nix"
"pyproject-nix": [
"pyproject-nix"
],
"uv2nix": [
"uv2nix"
]
},
"locked": {
"lastModified": 1746721691,
"narHash": "sha256-M01XrCCnM6/iTm5L4NYc0/GFJAnuxFsEsn9gdkB7pgY=",
"owner": "fusion44",
"repo": "poetry2nix",
"rev": "cc3336142abb08a2dd3eda202e572a26a39c68bc",
"lastModified": 1782093830,
"narHash": "sha256-6gmEVe69+KlRkZD4PEEV5xAlB9CB0Y9TiuEgQjDrKTQ=",
"owner": "pyproject-nix",
"repo": "build-system-pkgs",
"rev": "430680a19bc85a3bda55f12e4cc1a1aadcf2e478",
"type": "github"
},
"original": {
"owner": "fusion44",
"ref": "nb",
"repo": "poetry2nix",
"owner": "pyproject-nix",
"repo": "build-system-pkgs",
"type": "github"
}
},
"pyproject-nix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1782905613,
"narHash": "sha256-SvXJcAemihifkTn4BGvyE5K1FJX9bl4U8DQ5pqKvD0s=",
"owner": "pyproject-nix",
"repo": "pyproject.nix",
"rev": "7af23cfe91064865ecf2e835da28b45b3c6f49fd",
"type": "github"
},
"original": {
"owner": "pyproject-nix",
"repo": "pyproject.nix",
"type": "github"
}
},
@ -102,7 +84,9 @@
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"poetry2nix": "poetry2nix"
"pyproject-build-systems": "pyproject-build-systems",
"pyproject-nix": "pyproject-nix",
"uv2nix": "uv2nix"
}
},
"systems": {
@ -120,54 +104,26 @@
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_3": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"treefmt-nix": {
"uv2nix": {
"inputs": {
"nixpkgs": [
"poetry2nix",
"nixpkgs"
],
"pyproject-nix": [
"pyproject-nix"
]
},
"locked": {
"lastModified": 1730120726,
"narHash": "sha256-LqHYIxMrl/1p3/kvm2ir925tZ8DkI0KA10djk8wecSk=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "9ef337e492a5555d8e17a51c911ff1f02635be15",
"lastModified": 1782810559,
"narHash": "sha256-loy132LKn8QfiPbFJhdTjm+yZG3zklyOQhVabLyx2l4=",
"owner": "pyproject-nix",
"repo": "uv2nix",
"rev": "2f698e4b5a3c6004edaf051543542f18a36afe77",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"owner": "pyproject-nix",
"repo": "uv2nix",
"type": "github"
}
}

109
flake.nix
View file

@ -4,68 +4,111 @@
inputs = {
flake-utils.url = "github:numtide/flake-utils";
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
pyproject-nix = {
url = "github:pyproject-nix/pyproject.nix";
inputs.nixpkgs.follows = "nixpkgs";
};
uv2nix = {
url = "github:pyproject-nix/uv2nix";
inputs = {
pyproject-nix.follows = "pyproject-nix";
nixpkgs.follows = "nixpkgs";
};
};
pyproject-build-systems = {
url = "github:pyproject-nix/build-system-pkgs";
inputs = {
pyproject-nix.follows = "pyproject-nix";
uv2nix.follows = "uv2nix";
nixpkgs.follows = "nixpkgs";
};
};
};
outputs = {
self,
nixpkgs,
flake-utils,
poetry2nix,
pyproject-nix,
uv2nix,
pyproject-build-systems,
}: let
name = "blitz-api";
inherit (nixpkgs) lib;
workspace = uv2nix.lib.workspace.loadWorkspace {workspaceRoot = ./.;};
# Prefer prebuilt binary wheels: building grpcio & friends from
# source is slow and needs extra native build inputs.
overlay = workspace.mkPyprojectOverlay {
sourcePreference = "wheel";
};
systems = flake-utils.lib.eachDefaultSystem (system: let
pkgs = nixpkgs.legacyPackages.${system};
inherit (poetry2nix.lib.mkPoetry2Nix {inherit pkgs;}) mkPoetryApplication overrides mkPoetryEnv;
poetryDev = mkPoetryEnv {
projectDir = ./.;
preferWheels = true;
overrides = overrides.withDefaults (final: prev: {
ruff = prev.ruff.override {
preferWheel = true;
};
});
};
# 3.12 to match devenv.nix; RaspiBlitz 1.12 ships 3.11
python = pkgs.python312;
pythonSet =
(pkgs.callPackage pyproject-nix.build.packages {
inherit python;
}).overrideScope (
lib.composeManyExtensions [
pyproject-build-systems.overlays.default
overlay
]
);
venv = pythonSet.mkVirtualEnv "${name}-env" workspace.deps.default;
in {
packages = {
default = self.packages.${system}.${name};
${name} = mkPoetryApplication {
projectDir = ./.;
meta.mainProgram = name;
};
poetryDev = mkPoetryEnv {
projectDir = ./.;
preferWheels = true;
};
# A virtualenv with blitz_api and all of its dependencies.
# Provides the `api` console script used by the NixOS module.
${name} = venv.overrideAttrs (old: {
meta = (old.meta or {}) // {mainProgram = "api";};
});
};
# Python dependencies are managed impurely via `uv sync` into
# ./.venv, mirroring devenv.nix; this shell provides the tooling.
devShells.default = pkgs.mkShell {
# TODO: dirty dirty to be able to run the app. May break other packages.
# https://discourse.nixos.org/t/using-nix-shells-without-polluting-repositories/37362
shellHook = ''
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${
with pkgs;
lib.makeLibraryPath [pkgs.stdenv.cc.cc.lib]
}"
'';
nativeBuildInputs = with pkgs; [
packages = with pkgs; [
python
uv
stdenv.cc.cc
poetry
poetryDev
pyright
isort
alejandra
statix
ruff
ruff-lsp
redis
pueue
nushell
typos
typos-lsp
sshpass
bitcoind
lnd
clightning
pueue
];
env = {
# use the nix-provided interpreter and never download one
UV_PYTHON = python.interpreter;
UV_PYTHON_DOWNLOADS = "never";
};
shellHook = ''
unset PYTHONPATH
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${
lib.makeLibraryPath [pkgs.stdenv.cc.cc.lib]
}"
'';
};
});

View file

@ -24,6 +24,8 @@ dependencies = [
"deepdiff==8.6.1",
"loguru==0.7.3",
"celery[redis]==5.6.2",
# used by the `api` console script entry point (app/server.py)
"click==8.3.1",
]
[project.scripts]
@ -36,7 +38,6 @@ dev = [
"coverage==7.13.2",
"ruff==0.14.14",
"debugpy==1.8.20",
"click==8.3.1",
"watchfiles==1.1.1",
]

View file

@ -37,6 +37,7 @@ charset-normalizer==3.4.2
# via requests
click==8.3.1
# via
# blitz-api (pyproject.toml)
# celery
# click-didyoumean
# click-plugins

4
uv.lock generated
View file

@ -155,6 +155,7 @@ dependencies = [
{ name = "anyio" },
{ name = "async-timeout" },
{ name = "celery", extra = ["redis"] },
{ name = "click" },
{ name = "deepdiff" },
{ name = "fastapi", extra = ["standard-no-fastapi-cloud-cli"] },
{ name = "grpcio" },
@ -173,7 +174,6 @@ dependencies = [
[package.dev-dependencies]
dev = [
{ name = "click" },
{ name = "coverage" },
{ name = "debugpy" },
{ name = "pytest" },
@ -188,6 +188,7 @@ requires-dist = [
{ name = "anyio", specifier = "==4.9.0" },
{ name = "async-timeout", specifier = "==5.0.1" },
{ name = "celery", extras = ["redis"], specifier = "==5.6.2" },
{ name = "click", specifier = "==8.3.1" },
{ name = "deepdiff", specifier = "==8.6.1" },
{ name = "fastapi", extras = ["standard-no-fastapi-cloud-cli"], specifier = "==0.128.0" },
{ name = "grpcio", specifier = "==1.76.0" },
@ -206,7 +207,6 @@ requires-dist = [
[package.metadata.requires-dev]
dev = [
{ name = "click", specifier = "==8.3.1" },
{ name = "coverage", specifier = "==7.13.2" },
{ name = "debugpy", specifier = "==1.8.20" },
{ name = "pytest", specifier = "==9.0.2" },