Packaging a Python website

Hello,

I’m trying to package a Django website to get the following:

  1. A Python environment with the dependencies (and the Django website modules) installed
  2. A custom binary manage-myproject, which would set some custom environment variables, and then run the django-admin binary, provided by the Django Python package
  3. An additional Python package, gunicorn, installed in the same Python environment (so that it can run the site with all its dependencies)

My project uses Poetry, and I was able to use poetry2nix to create a Python environment with all the dependencies installed:

(poetry2nix.mkPoetryApplication {
    projectDir = ./.;
    configurePhase = ''
      ln -s ${nodeDependencies} ./blog/staticfiles
    '';
  }).dependencyEnv

Now to get point 2 to work, I tried the following:

let
  app = poetry2nix.mkPoetryApplication {
    projectDir = ./.;
    configurePhase = ''
      ln -s ${nodeDependencies} ./blog/staticfiles
    '';
  };

  manageScript = ''
    #!${pkgs.bash}/bin/bash
    export DJANGO_SETTINGS_MODULE=myproject.config.settings.base
    ${app.python}/bin/django-admin $@
  '';

  managePy = pkgs.runCommand "manage-myproject" {
  } ''
    mkdir -p $out/bin
    echo -e '${manageScript}' > $out/bin/managepy-myproject
    chmod +x $out/bin/managepy-myproject
  '';

  pythonWithApp = pkgs.symlinkJoin {
    name = "myproject";
    paths = [ managePy app.dependencyEnv ];
  };
in pythonWithApp

Which correctly adds a bin/managepy-myproject file, but it seems it’s not pointing to the correct Python environment, because the resulting ${app.python}/bin/django-admin file doesn’t exist (and indeed, the path of the Python interpreter referenced in the file is a Python environment without any dependency installed).

Anyway, trying to get point 3 to work, I tried using the following to get the gunicorn Python application added to the environment:

  pythonWithApp = pkgs.symlinkJoin {
    name = "myproject";
    paths = [
      managePy
      (app.python.withPackages (ps: [ ps.gunicorn app.dependencyEnv ]))
    ];
  };

But this resulted in the other Python applications (such as django-admin) not being included anymore in the Python environment.

So my questions are:

  1. How can I properly reference the Python interpreter from the Python environment that has all the other packages installed?
  2. How can I add a Python application to an existing Python environment, while keeping all other applications?
  3. How can I get rid of unwanted binaries in bin? I tried adding my package to environment.systemPackages and all of these packages were then in the PATH (I would just like to have managepy-myproject):
❯ ls result/bin/
2to3        django-admin     idle3    pydoc3    python-config   python3.8         unidecode
2to3-3.8    django-admin.py  idle3.8  pydoc3.8  python3         python3.8-config  wagtail
chardetect  idle             pydoc    python    python3-config  sqlformat 

Any hint would be much appreciated. Thanks!