Poetry2Nix - Bug in the tuto and should I use it?

Hello,

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()
# file: default.nix
let
  sources = import ./nix/sources.nix;
  pkgs = import sources.nixpkgs { };
  poetry2nix = import sources.poetry2nix { inherit pkgs; };
  myPythonApp = poetry2nix.mkPoetryApplication { projectDir = ./.; };
in
myPythonApp

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 !

1 Like

I have a Django application that is packaged using poetry2nix and it works well, I’ll try to post it in the next days

1 Like

This is what we use, slightly adjusted.

# 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:

{ pkgs }:
(pkgs.poetry2nix.mkPoetryApplication {
  projectDir = ./.;
  inherit python;
  checkGroups = [ "test" ];  # I think it uses "dev" by default?
  checkPhase = ''
    runHook preCheck
    pytest -v
    runHook postCheck
  '';
})

Hope this helps. Otherwise, it would be helpful if you could push your project to a git repo somewhere so I can check it out.

Thank you !

I will try again using your example as inspiration

1 Like