I write a flake.nix in an adjacent directory, so it’s like:
.
├── theproj
│ ├── .envrc
│ ├── poetry.lock
│ └── pyproject.toml
└── theproj-flake
├── flake.lock
└── flake.nix
.envrc contains:
use flake ../theproj-flake
The flake usually looks something like this:
{
inputs = {
flake-utils.url = "github:numtide/flake-utils";
nixpkgs.url = "github:nixos/nixpkgs?ref=23.11";
poetry2nix = {
url = "github:nix-community/poetry2nix";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { self, nixpkgs, flake-utils, poetry2nix }:
flake-utils.lib.eachDefaultSystem (system:
let
inherit (poetry2nix.lib.mkPoetry2Nix { inherit pkgs; }) # maybe
mkPoetryApplication; # maybe
pkgs = import nixpkgs { inherit system; };
in rec {
theproj-poetry = mkPoetryApplication{ projectDir = ./.; }; # maybe
devShells.default = pkgs.mkShell {
inputsFrom = [ theproj-poetry ]; # maybe
packages = [
pkgs.poetry
pkgs.python311
pkgs.python311Packages.pylsp-mypy
pkgs.postgresql_16 # or whatever else
];
};
});
}
If I’m lucky, then the project has dependencies which just work via poetry2nix, in which case I include the lines marked # maybe
. Otherwise, I exclude them and just use poetry2nix
as an overkill way to install poetry and use poetry install
from the devshell that direnv sets up.
The aspiration here is that maybe one day I’ll port those dependencies, or maybe I can use poetry2nix on just a certain group of them, at any rate it’s nice to have a place to pin non-python dependencies, even if I’m still handling the python dependencies imperatively.
There are occasionally weird interactions between the devshell’s tweaks to PYTHONPATH which cause trouble inside of the venv, but I manage to dodge these most of the time. I think they can be avoiding by altering the package-generated wrapper scripts to be a bit less assertive (so that the venv is authoritative) but I have not yet mastered this art.