Installation non-nix python package in NixOS (findiff)

596 Views Asked by At

I'm trying to install findiff Python package in NixOS follow this guide.

My pkgs/development/python-modules/findiff/default.nix file is:

{ lib
, buildPythonPackage
, fetchPypi
, pytestCheckHook
, pytest-runner
, numpy
, scipy
, sympy
}:

buildPythonPackage rec {
  pname = "findiff";
  version = "0.9.2";

  src = fetchPypi {
    inherit pname version;
    sha256 = "sha256-IWqQhGv+8d3mYdnwJh1byj0su2c0K5fpMTylsvR4c2U=";
  };

  checkInputs = [
    pytestCheckHook
    pytest-runner
  ];

  propagatedBuildInputs = [
    numpy
    scipy
    sympy
  ];

  meta = with lib; {
    description = "A Python package for finite difference derivatives in any number of dimensions";
    homepage    = "https://github.com/maroba/findiff";
    license     = licenses.mit;
    maintainers = with maintainers; [ "f0ma" ];
  };
}

Package was built successfully as /nix/store/cx78cip77nyb0fiwbqk2v2ddl2jvqc8v-python3.9-findiff-0.9.2 with nix-build -A python39Packages.findiff.

Command nix-env -f . -iA python39Packages.findiff shows: installing 'python3.9-findiff-0.9.2'

But I have no idea how to make this package available for python (per-profile, per-user or system-wide) properly (nix-env?, nix-shell?):

>>> import findiff
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'findiff'

Only this dirty way works:

>>> import sys
>>> sys.path.append("/nix/store/cx78cip77nyb0fiwbqk2v2ddl2jvqc8v-python3.9-findiff-0.9.2/lib/python3.9/site-packages")
>>> import findiff
2

There are 2 best solutions below

0
Stanislav Ivanov On

I found that I can import package description from file findiff.nix (copy of pkgs/development/python-modules/findiff/default.nix) with nixpkgs.overlays in my configuration.nix:

  nixpkgs.overlays = [ (self: super: {
                         findiff = super.callPackage ./findiff.nix {
                             buildPythonPackage = super.python39Packages.buildPythonPackage;
                             fetchPypi = super.python39Packages.fetchPypi;
                             numpy = super.python39Packages.numpy;
                             scipy = super.python39Packages.scipy;
                             sympy = super.python39Packages.sympy;
                             pytestCheckHook = super.python39Packages.pytestCheckHook;
                             pytest-runner = super.python39Packages.pytest-runner;
                         }; } ) ];

After that I can add package in installation list:

(python39.withPackages (p: with p; [
      requests
      numpy
      scipy
      matplotlib
      cartopy
      sympy
      pytest-runner
      findiff # New package
]))

I am not sure that it is a right solution but in works for me.

0
OmnipotentEntity On

You may find it simpler to embed the package directly into your package list.

(python39.withPackages (p: with p; [
      requests
      numpy
      scipy
      matplotlib
      cartopy
      sympy
      pytest-runner
      (python39.pkgs.buildPythonPackage rec {
        pname = "findiff";
        version = "0.9.2";

        src = fetchPypi {
          inherit pname version;
          sha256 = "sha256-IWqQhGv+8d3mYdnwJh1byj0su2c0K5fpMTylsvR4c2U=";
        };

        doCheck = false;

        buildInputs = [
          numpy
          scipy
          sympy
        ];
      })
]))

Alternatively, you can assign it to a variable in a let block, and then reference that variable. Or make it another .nix file local to configuration.nix and then call that nix file from your configuration.nix (without using it as an overlay).

Example, using it in a let variable:

let
  pkgs = import <nixpkgs> {};
  stdenv = pkgs.stdenv;
  findiff = (python39.pkgs.buildPythonPackage rec {
    pname = "findiff";
    version = "0.9.2";

    src = fetchPypi {
      inherit pname version;
      sha256 = "sha256-IWqQhGv+8d3mYdnwJh1byj0su2c0K5fpMTylsvR4c2U=";
    };

    doCheck = false;

    buildInputs = [
      numpy
      scipy
      sympy
    ];
  });

in stdenv.mkDerivation (with pkgs; {
  name = "env";
  nativeBuildInputs = [ ];

  buildInputs = [
    (python3.withPackages(ps: with ps; [
      requests
      numpy
      scipy
      matplotlib
      cartopy
      sympy
      pytest-runner
      findiff # new package
    ]))
  ];
});

Example, calling your findiff.nix file (move it local to shell.nix):

let
  pkgs = import <nixpkgs> {};
  stdenv = pkgs.stdenv;
  findiff = with pkgs; with python3.pkgs; callPackage ./findiff.nix {};

in stdenv.mkDerivation (with pkgs; {
  name = "env";
  nativeBuildInputs = [ ];

  buildInputs = [
    (python3.withPackages(ps: with ps; [
      requests
      numpy
      scipy
      matplotlib
      cartopy
      sympy
      pytest-runner
      findiff # new package
    ]))
  ];
})