How to create a nix-shell environment with different python version as default?

I’d like to create a nix-shell environment for development that uses a different python version as default than nixpkgs does right now. Additionally all python modules are supposed to be built against that older python version.

My attempt so far:

{ pkgs ? import <nixpkgs> {} }:
with pkgs;

let
    myPythonPackages = ps: with ps; [
      pip
      Quart_lts
      matplotlib
      sqlalchemy
      pytest
      pytest-asyncio
      requests-toolbelt
      marshmallow
      cryptography
    ];
    pkgs.python = pkgs.python36;
    pytPackages = python36Packages;

in mkShell {
  buildInputs = [
    (python36.withPackages myPythonPackages)
    dosage
  ];
}

First of all: Is this the correct approach to take?

If yes, there’s still a problem: The pylint package is built locally and one of its test fails. Apparently running the tests under an older python version causes one of them to fail. What can be done about that?

Thanks

1 Like

The quick fix is to list pylint as the first module to give it versioning priority. Since it’s built locally though this will be a bit tricky.

pytPackages = python36Packages; is unused so it doesn’t do anything.
pkgs.python = pkgs.python36; Just overrides the top level attribute so it doesn’t affect the rest. In this case you probably don’t need to override it.

To ignore the tests of pytest you can do this:

let
  overlay = (self: super: rec {
    python36 = super.python36.override {
      packageOverrides = self: super: {
        pytest = super.pytest.overrideAttrs (old: {
          doCheck = true;
        });
      };
    };

    python36Packages = python36.pkgs;
  });

  myPythonPackages = ps: with ps; [
    pip
    matplotlib
    sqlalchemy
    pytest
    pytest-asyncio
    requests-toolbelt
    marshmallow
    cryptography
  ];
in
{ pkgs ? import <nixpkgs> { overlays = [ overlay ]; } }:
pkgs.mkShell {
  buildInputs = with pkgs; [
    (python36.withPackages myPythonPackages)
    dosage
  ];
}

Overriding recursive attribute sets like pythonPackages is tricky and has changed a lot so I hope this is the most up to date and correct way to do it.

I just spent a couple hours trying to figure out how to set up a script to basically prepare a virtual environment with a specific version of Python with Nix, and the

{ pkgs ? import <nixpkgs> {} }:
with pkgs;

incantation was most definitely the thing I was missing to figure out how to do it.

I think that the example brought up by OP (along with stuff like what kind of commands you usually want to run in the shell) would make a great ‘advanced getting started guide’ for nix (especially as an alternative to the heavy-handed Dockerfile solutions)