3 minutes
Written: 2020-08-26 05:42 +0000
Updated: 2024-08-06 00:52 +0000
Niv and Mach-Nix for Nix Python
Short post on using
mach-nix
withniv
.
Background
In previous posts, there was a discussion on a ground up approach to adding packages which aren’t on the core nixpkgs
channels using GitHub or PyPi sources. However, this lacked a way to do so programmatically, and also a way to convert existing python projects.
Python Dependency Management
This time, instead of the more pedagogical approach of building packages from PyPi or GitHub, we will use overlays and the excellent mach-nix to speed up the process. We will continue to use niv.
1niv init
2niv update nixpkgs -b nixpkgs-unstable
To leverage mach-nix
we will simply need the following setup to work with niv
.
1let
2 sources = import ./nix/sources.nix;
3 pkgs = import sources.nixpkgs { };
4 inherit (pkgs.lib) optional optionals;
5 mach-nix = import (builtins.fetchGit {
6 url = "https://github.com/DavHau/mach-nix/";
7 ref = "refs/tags/3.1.1";
8 }) {
9 pkgs = pkgs;
10
11 # optionally specify the python version
12 # python = "python38";
13
14 # optionally update pypi data revision from https://github.com/DavHau/pypi-deps-db
15 # pypiDataRev = "some_revision";
16 # pypiDataSha256 = "some_sha256";
17 };
18 customPython = mach-nix.mkPython {
19 requirements = ''
20 copier
21 pytest
22 '';
23 providers = {
24 _default = "nixpkgs,wheel,sdist";
25 pytest = "nixpkgs";
26 };
27 pkgs = pkgs;
28 };
29in pkgs.mkShell { buildInputs = with pkgs; [ customPython ]; }
Note that we have essentially written out a requirements.txt
and can actually pass a path there instead as well. The key point to make it work with niv
is the pkgs
parameter. To use the older method of overriding parts of the setup, we can use the overrides_pre
hook as shown below:
1let
2 sources = import ./prjSource/nix/sources.nix;
3 pkgs = import sources.nixpkgs { };
4 inherit (pkgs.lib) optional optionals;
5 mach-nix = import (builtins.fetchGit {
6 url = "https://github.com/DavHau/mach-nix/";
7 ref = "refs/tags/3.1.1";
8 }) {
9 pkgs = pkgs;
10
11 # optionally specify the python version
12 # python = "python38";
13
14 # optionally update pypi data revision from https://github.com/DavHau/pypi-deps-db
15 # pypiDataRev = "some_revision";
16 # pypiDataSha256 = "some_sha256";
17 };
18 customPython = mach-nix.mkPython {
19 requirements = ''
20 copier
21 pytest
22 f90wrap
23 '';
24 providers = {
25 _default = "nixpkgs,wheel,sdist";
26 pytest = "nixpkgs";
27 };
28 overrides_pre = [
29 (pythonSelf: pythonSuper: {
30 pytest = pythonSuper.pytest.overrideAttrs (oldAttrs: {
31 doCheck = false;
32 doInstallCheck = false;
33 });
34 f90wrap = pythonSelf.buildPythonPackage rec {
35 pname = "f90wrap";
36 version = "0.2.3";
37 src = pkgs.fetchFromGitHub {
38 owner = "jameskermode";
39 repo = "f90wrap";
40 rev = "master";
41 sha256 = "0d06nal4xzg8vv6sjdbmg2n88a8h8df5ajam72445mhzk08yin23";
42 };
43 buildInputs = with pkgs; [ gfortran stdenv ];
44 propagatedBuildInputs = with pythonSelf; [
45 setuptools
46 setuptools-git
47 wheel
48 numpy
49 ];
50 preConfigure = ''
51 export F90=${pkgs.gfortran}/bin/gfortran
52 '';
53 doCheck = false;
54 doIstallCheck = false;
55 };
56 })
57 ];
58 pkgs = pkgs;
59 };
60in pkgs.mkShell { buildInputs = with pkgs; [ customPython ]; }
We can also pull in overrides from poetry2nix
with overrides_post
as described here.
Conclusion
With the completion of this final remaining hurdle, nix
is now fully realized as a python
management system. At this point the “only” thing remaining is to find an optimal way of leveraging nix
for setting up re-usable data science and scientific computing projects.