Skip to content

Commit 9523a7a

Browse files
authored
Merge pull request #37 from DavHau/dev
# 2.1.0 (04 Jul 2020) Bug fixes + new feature **buildPythonPackage** / **buildPythonApplication** ### Fixes: - fix `value is null while a set was expected` error when python package is used which is set to null in nixpkgs. ### Features: - **buildPythonPackage** / **buildPythonApplication**: Interface to build python packages from their source code + requirements.txt
2 parents 65e50b3 + fc45307 commit 9523a7a

10 files changed

Lines changed: 377 additions & 100 deletions

File tree

Changelog.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
# 2.1.0 (04 Jul 2020)
2+
Bug fixes + new feature **buildPythonPackage** / **buildPythonApplication**
3+
### Fixes:
4+
- fix `value is null while a set was expected` error when python package is used which is set to null in nixpkgs.
5+
6+
### Features:
7+
- **buildPythonPackage** / **buildPythonApplication**: Interface to build python packages from their source code + requirements.txt
8+
19
# 2.0.1 (29 Jun 2020)
210
Improves build-time closure, build success rate and fixes disable_checks option.
311
### Fixes:

Readme.md

Lines changed: 125 additions & 60 deletions
Large diffs are not rendered by default.

default.nix

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,51 @@ rec {
3636
machNixFile = args: import ./mach_nix/nix/mach.nix args;
3737

3838
# Returns `overrides` and `select_pkgs` which satisfy your requirements
39-
machNix = args: import "${machNixFile args}/share/mach_nix_file.nix";
39+
machNix = args:
40+
let result = import "${machNixFile args}/share/mach_nix_file.nix";
41+
in {
42+
overrides = result.overrides pkgs.pythonManylinuxPackages.manylinux1 autoPatchelfHook;
43+
select_pkgs = result.select_pkgs;
44+
};
4045

4146
# call this to use the python environment with nix-shell
4247
mkPythonShell = args: (mkPython args).env;
4348

49+
# equivalent to buildPythonPackage of nixpkgs
50+
buildPythonPackage = _buildPython "buildPythonPackage";
51+
52+
# equivalent to buildPythonApplication of nixpkgs
53+
buildPythonApplication = _buildPython "buildPythonApplication";
54+
55+
_buildPython = func: args@{
56+
requirements, # content from a requirements.txt file
57+
disable_checks ? true, # Disable tests wherever possible to decrease build time.
58+
overrides_pre ? [], # list of pythonOverrides to apply before the machnix overrides
59+
overrides_post ? [], # list of pythonOverrides to apply after the machnix overrides
60+
pkgs ? nixpkgs, # pass custom nixpkgs. Only used for manylinux wheel dependencies
61+
providers ? {}, # define provider preferences
62+
pypi_deps_db_commit ? builtins.readFile ./mach_nix/nix/PYPI_DEPS_DB_COMMIT, # python dependency DB version
63+
pypi_deps_db_sha256 ? builtins.readFile ./mach_nix/nix/PYPI_DEPS_DB_SHA256,
64+
python ? pkgs.python3, # select custom python to base overrides on. Should be from nixpkgs >= 20.03
65+
_provider_defaults ? with builtins; fromTOML (readFile ./mach_nix/provider_defaults.toml),
66+
...
67+
}:
68+
let
69+
py = python.override { packageOverrides = mergeOverrides overrides_pre; };
70+
result = machNix {
71+
inherit requirements disable_checks providers pypi_deps_db_commit pypi_deps_db_sha256 _provider_defaults;
72+
python = py;
73+
};
74+
py_final = python.override { packageOverrides = mergeOverrides (
75+
overrides_pre ++ [ result.overrides ] ++ overrides_post
76+
);};
77+
pass_args = removeAttrs args (builtins.attrNames ({inherit requirements disable_checks providers pypi_deps_db_commit pypi_deps_db_sha256 _provider_defaults;}));
78+
in
79+
py_final.pkgs."${func}" ( pass_args // {
80+
propagatedBuildInputs = result.select_pkgs py_final.pkgs;
81+
});
82+
83+
4484
# (High level API) generates a python environment with minimal user effort
4585
mkPython =
4686
{
@@ -61,11 +101,8 @@ rec {
61101
inherit requirements disable_checks providers pypi_deps_db_commit pypi_deps_db_sha256 _provider_defaults;
62102
python = py;
63103
};
64-
overrides_machnix = result.overrides pkgs.pythonManylinuxPackages.manylinux1 autoPatchelfHook;
65104
py_final = python.override { packageOverrides = mergeOverrides (
66-
overrides_pre ++ [
67-
overrides_machnix
68-
] ++ overrides_post
105+
overrides_pre ++ [ result.overrides ] ++ overrides_post
69106
);};
70107
in
71108
py_final.withPackages (ps: result.select_pkgs ps)

example/requirements.txt

Lines changed: 0 additions & 4 deletions
This file was deleted.

example/simple-usage-expression.nix

Lines changed: 0 additions & 8 deletions
This file was deleted.

example/simple-usage-shell.nix

Lines changed: 0 additions & 8 deletions
This file was deleted.

example/simple-usage.nix

Lines changed: 0 additions & 8 deletions
This file was deleted.

examples.md

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
2+
<!--ts-->
3+
* [Basic Usage in Nix Expressions:](#basic-usage-in-nix-expressions)
4+
* [mkPython / mkPythonShell](#mkpython--mkpythonshell)
5+
* [buildPythonPackage / buildPythonApplication](#buildpythonpackage--buildpythonapplication)
6+
* [buildPythonPackage from GitHub](#buildpythonpackage-from-github)
7+
* [Examples for Tensorflow / PyTorch](#examples-for-tensorflow--pytorch)
8+
* [Tensorflow with SSE/AVX/FMA support](#tensorflow-with-sseavxfma-support)
9+
* [Tensorflow via wheel (newer versions, quicker builds)](#tensorflow-via-wheel-newer-versions-quicker-builds)
10+
* [Recent PyTorch with nixpkgs dependencies, overlays, and custom python](#recent-pytorch-with-nixpkgs-dependencies-overlays-and-custom-python)
11+
* [Using overrides](#using-overrides)
12+
* [Fixing packages via overrides](#fixing-packages-via-overrides)
13+
* [Include poetry2nix overrides](#include-poetry2nix-overrides)
14+
15+
<!-- Added by: grmpf, at: Sat 04 Jul 2020 12:18:42 PM UTC -->
16+
17+
<!--te-->
18+
19+
20+
## Basic Usage in Nix Expressions:
21+
### mkPython / mkPythonShell
22+
build a python environment from a list of requirements
23+
```nix
24+
let
25+
mach-nix = import (builtins.fetchGit {
26+
url = "https://github.com/DavHau/mach-nix/";
27+
ref = "2.1.0";
28+
});
29+
in mach-nix.mkPython {
30+
requirements = builtins.readFile ./requirements.txt;
31+
}
32+
```
33+
34+
### buildPythonPackage / buildPythonApplication
35+
Build a python package from its source code and a list of requirements
36+
```nix
37+
let
38+
mach-nix = import (builtins.fetchGit {
39+
url = "https://github.com/DavHau/mach-nix/";
40+
ref = "2.1.0";
41+
});
42+
in mach-nix.buildPythonPackage {
43+
pname = "my-package";
44+
version = "1.0.0";
45+
src = /project-path;
46+
requirements = builtins.readFile /project-path/requirements.txt;
47+
}
48+
```
49+
50+
### buildPythonPackage from GitHub
51+
Build a python package from its source code and a list of requirements
52+
```nix
53+
let
54+
mach-nix = import (builtins.fetchGit {
55+
url = "https://github.com/DavHau/mach-nix/";
56+
ref = "2.1.0";
57+
});
58+
in mach-nix.buildPythonPackage rec {
59+
pname = "projectname";
60+
version = "1.0.0";
61+
src = builtins.fetchGit{
62+
url = "https://github.com/user/projectname";
63+
ref = "master";
64+
# rev = "put_commit_hash_here";
65+
};
66+
doCheck = false;
67+
doInstallCheck = false;
68+
requirements = builtins.readFile "${src}/requirements.txt";
69+
}
70+
```
71+
72+
## Examples for Tensorflow / PyTorch
73+
74+
### Tensorflow with SSE/AVX/FMA support
75+
I have a complex set of requirements including tensorflow. I'd like to have tensorflow with the usual nix features enabled like SSE/AVX/FMA which I cannot get from pypi. Therefore I must take tensorflow from nixpkgs. For everything else I keep the default, which means wheels are preferred. This allows for quicker installation of dependencies.
76+
```nix
77+
let
78+
mach-nix = import (builtins.fetchGit {
79+
url = "https://github.com/DavHau/mach-nix/";
80+
ref = "2.1.0";
81+
});
82+
in mach-nix.mkPython {
83+
84+
requirements = ''
85+
# bunch of other requirements
86+
tensorflow
87+
'';
88+
89+
providers = {
90+
# force tensorflow to be taken from nixpkgs
91+
tensorflow = "nixpkgs";
92+
};
93+
}
94+
```
95+
This only works if the restrictions in `requirements.txt` allow for the tensorflow version from nixpkgs.
96+
97+
### Tensorflow via wheel (newer versions, quicker builds)
98+
I'd like to install a more recent version of tensorflow which is not available from nixpkgs. Also I don't like long build times and therefore I want to install tensorflow via wheel. Usually most wheels work pretty well out of the box, but the tensorflow wheel has an issue which I need to fix with an override.
99+
```nix
100+
let
101+
mach-nix = import (builtins.fetchGit {
102+
url = "https://github.com/DavHau/mach-nix/";
103+
ref = "2.1.0";
104+
});
105+
in mach-nix.mkPython {
106+
107+
requirements = ''
108+
# bunch of other requirements
109+
tensorflow == 2.2.0rc4
110+
'';
111+
112+
# no need to specify provider settings since wheel is the default anyways
113+
114+
# Fix the tensorflow wheel
115+
overrides_post = [( pythonSelf: pythonSuper: {
116+
tensorflow = pythonSuper.tensorflow.overridePythonAttrs ( oldAttrs: {
117+
postInstall = ''
118+
rm $out/bin/tensorboard
119+
'';
120+
});
121+
})];
122+
}
123+
124+
```
125+
126+
### Recent PyTorch with nixpkgs dependencies, overlays, and custom python
127+
I'd like to use a recent version of Pytorch from wheel, but I'd like to build the rest of the requirements from sdist or nixpkgs, since I've already written overlays for those packages which I'd like to continue using. Also I require python 3.6
128+
```nix
129+
let
130+
mach-nix = import (builtins.fetchGit {
131+
url = "https://github.com/DavHau/mach-nix/";
132+
ref = "2.1.0";
133+
});
134+
overlays = []; # some very useful overlays
135+
in mach-nix.mkPython rec {
136+
137+
requirements = ''
138+
# bunch of other requirements
139+
torch == 1.5.0
140+
'';
141+
142+
providers = {
143+
# disallow wheels by default
144+
_default = "nixpkgs,sdist";
145+
# allow wheels only for torch
146+
torch = "wheel";
147+
};
148+
149+
# Include my own overlay.
150+
pkgs = import <nixpkgs> { config = { allowUnfree = true; }; inherit overlays; };
151+
152+
# Select custom python version (Must be taken from pkgs with the overlay applied)
153+
python = pkgs.python36;
154+
}
155+
```
156+
157+
## Using overrides
158+
### Fixing packages via overrides
159+
See previous example for tensorflow wheel
160+
161+
### Include poetry2nix overrides
162+
I have a complex requirements.txt which includes `imagecodecs`. It is available via wheel, but I prefer to build everything from source. This package has complex build dependencies and is not available from nixpkgs. Luckily poetry2nix` overrides make it work. The peotry2nix overrides depend on nixpkgs-unstable.
163+
```nix
164+
let
165+
mach-nix = import (builtins.fetchGit {
166+
url = "https://github.com/DavHau/mach-nix/";
167+
ref = "2.1.0";
168+
});
169+
in mach-nix.mkPython rec {
170+
171+
requirements = ''
172+
# bunch of other requirements
173+
imagecodecs
174+
'';
175+
176+
providers = {
177+
_default = "sdist";
178+
};
179+
180+
# Use unstable channel
181+
pkgs = import <unstable> {};
182+
183+
# Import overrides from poetry2nix
184+
# Caution! Use poetry2nix overrides only in `overrides_post`, not `overrides_pre`.
185+
overrides_post = [
186+
(
187+
import (builtins.fetchurl {
188+
url = "https://raw.githubusercontent.com/nix-community/poetry2nix/1cfaa4084d651d73af137866622e3d0699851008/overrides.nix";
189+
}) { inherit pkgs; }
190+
)
191+
];
192+
}
193+
```

mach_nix/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.0.1
1+
2.1.0

mach_nix/nix/nixpkgs-json.nix

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,18 @@ let
1313
in
1414
{"${pname}" = (toString res.value);};
1515

16-
is_broken = pkg:
16+
not_usable = pkg:
1717
(tryEval (
18-
if hasAttrByPath ["meta" "broken"] pkg
18+
if pkg == null
19+
then true
20+
else if hasAttrByPath ["meta" "broken"] pkg
1921
then pkg.meta.broken
2022
else false
2123
)).value;
2224

2325

24-
without_broken = python_pkgs: filterAttrs (name: val: ! (is_broken val)) python_pkgs;
25-
all_versions = python: map (pname: get_version python pname) (attrNames (without_broken python.pkgs));
26-
merged = python: mapAttrs (name: val: builtins.elemAt val 0) (zipAttrs (all_versions python));
26+
usable_pkgs = python_pkgs: filterAttrs (name: val: ! (not_usable val)) python_pkgs;
27+
all_versions = python: map (pname: get_version python pname) (attrNames (usable_pkgs python.pkgs));
28+
merged = python: mapAttrs (name: val: elemAt val 0) (zipAttrs (all_versions python));
2729
in
28-
writeText "nixpkgs-py-pkgs-json" (builtins.toJSON (merged python))
30+
writeText "nixpkgs-py-pkgs-json" (toJSON (merged python))

0 commit comments

Comments
 (0)