I’ve been trying to use poetry2nix to package the backend of a webapp. It seems to be the more widely recommended option but I have two concerns :
why is it out-of-tree ? it seems ironic that the main way to build a package from a poetry project isn’t itself a official package. Is it about to be discontinued ? Should I try and find another tool ?
I can’t get it to work anyway. I created a dummy project based on this tutorial.
# __init__.py
from flask import send_file
from flask import Flask
from io import BytesIO
from PIL import Image
import requests
app = Flask(__name__)
@app.route('/')
def hello():
return "Hello World!"
def main():
app.run()
if __name__ == '__main__':
main()
and when running nix-build default.nix I get this error
… while evaluating the attribute 'drvPath'
at /nix/store/pp307nbzkgsd6393zl2i9j4j86z5nz9b-nixpkgs-src/lib/customisation.nix:228:7:
227| in commonAttrs // {
228| drvPath = assert condition; drv.drvPath;
| ^
229| outPath = assert condition; drv.outPath;
… while calling the 'derivationStrict' builtin
at /builtin/derivation.nix:9:12: (source not available)
(stack trace truncated; use '--show-trace' to show the full trace)
error: function 'anonymous lambda' called with unexpected argument 'flit-core'
at /nix/store/pp307nbzkgsd6393zl2i9j4j86z5nz9b-nixpkgs-src/pkgs/development/python-modules/wheel/default.nix:1:1:
1| { lib
| ^
2| , buildPythonPackage
Thanks for your help either with the bug or to find the most suitable tool !
# Take python explicitly because we want to select the python version in another file,
# you could as well use pkgs.python
{ pkgs, python }:
let
inherit (builtins) elem any;
inherit (pkgs.lib)
id
hasPrefix
cleanSourceWith
fileset
;
in
(pkgs.poetry2nix.mkPoetryApplication {
# This file is in a subdirectory (nix/my-backend.nix) while our python project is in the repo root
projectDir = ./..;
src = fileset.toSource {
root = ./..;
fileset = fileset.unions [
# We also have a frontend in the repo, so we filter the files to avoid unnecessary rebuilds
../src
../manage.py
../poetry.lock
../pyproject.toml
];
};
inherit python;
checkGroups = [ "test" ];
# We have to use this pyright instead of the one installed through poetry because it wants to
# download nodejs stuff, which doesnt work in the sandbox.
nativeCheckInputs = with pkgs; [
pyright
postgresql
retry
];
checkPhase = ''
runHook preCheck
TMP=$(mktemp -d)
# Note that `pkgs.playwright-browsers` is `pkgs.playwright-driver.browsers` but the specific version playwright
# version we need. We also set up postgres because we use procrastinate, a python library which requires it.
export PLAYWRIGHT_BROWSERS_PATH=${pkgs.playwright-browsers};
export PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS=true
export PYRIGHT_PYTHON_CACHE_DIR="$TMP/pyright"
mkdir "$PYRIGHT_PYTHON_CACHE_DIR"
pyright
# We also set up postgres because we use procrastinate, a python library which requires it.
export PGHOST="$TMP/pghost"
export PGDATA="$TMP/pgdata"
export PGDATABASE=myproject
mkdir $PGHOST
initdb "$PGDATA" --auth=trust
postgres -c listen_addresses= -c unix-socket-directories=$PGHOST &
retry -t 5 -d 1 pg_isready
createdb
# Skip integration tests here because they talk to external systems
pytest -v -m 'not integration'
runHook postCheck
'';
})
As noted, this is doing specific stuff all over the place, so you might be fine with something along these lines: