Skip to content

Commit d37c1eb

Browse files
authored
Version 2.0.0 (#20)
See Changelog.md for changes. * adapt data interface for new sdist dependency graph format * change wording in readme * wheel support + concept providers * overlay support WIP * overlay support * extras support for nixpkgs * machnix as overrides * granular provider settings + custom autoPatchelfHook * improve overlay generator, remove prefer_new * unify nixpkgs src * update interface, bump version and examples * fixes and updated docs
1 parent 9cdd2b7 commit d37c1eb

38 files changed

Lines changed: 969 additions & 438 deletions

Changelog.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# 2.0.0
2+
## Features:
3+
- **Python Wheels**: Wheels are supported for linux including manylinux1, manylinux2010, manylinux2014
4+
- **Nixpkgs python packages**: Nixpkgs is now treated as a separate provider. That means packages can be taken directly from there, independent on their availability from pypi.
5+
- **Configurable Providers**: The user can now freely decide where packages should be taken from either via a default or on a per package basis. Currently available provider are `nixpkgs`, `sdist`, `wheel`.
6+
- **Core architecture - Python Overrides**: The core of mach nix now produces python overrides instead of nixpkgs overlays which makes it much more composible and allows for a less strange API.
7+
- **Overlay support**: `mkPython` and lower level interfaces now accept new parameter `pkgs` and `python` which indirectly enables you to use any nixpkgs overlays (But don't use this for modifying python packages. Better do this with **Python Overrides**)
8+
- **Python Overrides support**: `mkPython` now accepts new parameter `overrides_pre` and `overrides_post` each allowing to inject a list of python overrides to apply before and after the mach-nix internal overrides. This allows you to fixup packages or add your own modifications to them.
9+
- **Extras support**: All providers now fully support python [extras](https://www.python.org/dev/peps/pep-0508/#extras). That means requirements like for example '`requests[security]`' will be correctly resolved.
10+
11+
## Nix Interface changes:
12+
- Removed:
13+
- **mkPythonExpr**: removed in favor of `machNixFile` and `machNix`
14+
- Added:
15+
- **machNixFile** which generates a nex expresison
16+
- **machNix** which evaluates the generated nix expression to get `overrides` and `select_pkgs`
17+
- Changed:
18+
- **mkPython**:
19+
- Removed arguments:
20+
- `python_attr` in favor if `python`
21+
- `prefer_nixpkgs` in favor of `providers`
22+
- `nixpkgs_commit` in favor of `pkgs`
23+
- `nixpkgs_tarball_sha256` in favor of `pkgs`
24+
- Added arguments:
25+
- `overrides_pre`: list of python overrides to apply before the machnix overrides
26+
- `overrides_post`: list of python overrides to apply after the machnix overrides
27+
- `pkgs`: pass custom nixpkgs. Only used for manylinux wheel dependencies.
28+
- `providers`: define provider preferences
29+
- `_provider_defaults`: builtin provider defaults. Disable them by passing {}
30+
31+
# 1.0.0
32+
Initial Release

Readme.md

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ Mach-nix makes it easy to create and share reproducible python environments. Whi
99
You can either install mach-nix via pip or by using nix in case you already have the nix package manager installed.
1010
### Installing via pip
1111
```shell
12-
pip install git+git://github.com/DavHau/mach-nix@1.0.0
12+
pip install git+git://github.com/DavHau/mach-nix@2.0.0
1313
```
1414
### Installing via nix
1515
```shell
16-
nix-env -if https://github.com/DavHau/mach-nix/tarball/1.0.0 -A mach-nix
16+
nix-env -if https://github.com/DavHau/mach-nix/tarball/2.0.0 -A mach-nix
1717
```
1818

1919
## Basic usage
@@ -44,8 +44,7 @@ If you are comfortable with writing nix expressions, you don't need to install t
4444
let
4545
mach-nix = import (builtins.fetchGit {
4646
url = "https://github.com/DavHau/mach-nix/";
47-
ref = "master";
48-
rev = "fa2bb2d33fb9b9dc3113046e4fcc16088f56981a";
47+
ref = "2.0.0";
4948
});
5049
in
5150
mach-nix.mkPython {
@@ -70,7 +69,7 @@ mach-nix.mkPython {
7069
The general mechanism can be broken down into the following:
7170

7271
### Dependency resolution
73-
Mach-nix contains a dependency graph of nearly all python packages available on pypi.org. With this, mach-nix is able to do dependency resolution offline within seconds.
72+
Mach-nix contains a dependency graph of nearly all python packages available on pypi.org. This allows mach-nix to resolve dependencies offline within seconds.
7473

7574
The dependency graph data can be found here: https://github.com/DavHau/pypi-deps-db
7675
The dependency graph is updated on a daily basis by this set of tools: https://github.com/DavHau/pypi-crawlers
@@ -100,31 +99,34 @@ The overlay is generated by applying the following strategy to each required pyt
10099
- If no version of the required package is found in nixpkgs, the package is built from scratch by using `buildPythonPackage`.
101100

102101
## Advanced Usage (Nix Only)
103-
Mach-nix can be fine tuned with additional arguments by importing it via `builtins.fetchGit`. Examples can be found in [./example](./example/). There are 3 different methods which can be invoked:
104-
1. **mkPythonExpr** - returns a derivation containing a nix expression in $out/share/expr.nix which describes the python environment defined by your inputs
105-
1. **mkPython** - returns the python environment derivation. It basically just evaluates the expression coming from **mkPythonExpr**.
102+
Mach-nix can be fine tuned with additional arguments by importing it via `builtins.fetchGit`. Examples can be found in [./example](./example/). There are 4 different methods which can be invoked:
103+
1. **machNixFile** - returns a single file derivation containing a nix expression in $out/share/mach_nix_file.nix which contains python overrides and a package selector.
104+
1. **MachNix** - evaluates **machNixFile** and returns `overrides` and `select_pkgs` which you can use to satisfy your requirements.
105+
1. **mkPython** - builds a python environment for a given `requirements.txt`.
106106
1. **mkPythonShell** - returns the python environment suitable for nix-shell.
107107

108-
All 3 methods take the following set of inputs which are processed in [./mach_nix/nix/expression.nix](./mach_nix/nix/expression.nix):
108+
Both **mkPython** and **mkPythonShell** take the following arguments:
109109

110110
### Required Arguments:
111111
- **requirements** (string): Text content of a typical `requirements.txt`.
112112

113113
### Optional Arguments:
114-
- **python_attr** (string): Select one of (python27, python35, python36, python37, python38). (default: python37)
115-
- **prefer_nixpkgs** (bool): Prefer python package versions from nixpkgs instead of newer ones. Decreases build time. (default: true)
116-
- **disable_checks** (bool): Disable tests wherever possible to decrease build time.
117-
- **nixpkgs_commit** (string): commit hash of nixpkgs version to use python packages from
118-
- **nixpkgs_tarball_sha256** (string): sha256 hash of the unpacked tarball for the selected nixpkgs version. (obtained via `nix-prefetch-url --unpack https://github.com/nixos/nixpkgs/tarball/<nixpkgs_commit>`)
114+
- **disable_checks** (bool): Disable tests wherever possible to decrease build time and failures due to nix incompatible tests
115+
- **overrides_pre** (list): list of pythonOverrides to apply before the machnix overrides
116+
- **overrides_post** (list): list of pythonOverrides to apply after the machnix overrides
117+
- **pkgs** (set): pass custom nixpkgs version (20.03 or higher is required for wheel support)
118+
- **providers** (set): define provider preferences
119119
- **pypi_deps_db_commit** (string): commit hash of a specific version of the dependency graph ([pypi-deps-db](https://github.com/DavHau/pypi-deps-db)).
120120
- **pypi_deps_db_sha256** (string): sha256 hash obtained via `nix-prefetch-url --unpack https://github.com/DavHau/pypi-deps-db/tarball/<pypi_deps_db_commit>`
121+
- **python** (set): select custom python to base overrides on. Should be from nixpkgs >= 20.03
122+
- **_provider_defaults** (set): builtin provider defaults. Disable them by passing {}
123+
121124

122125
## Contributing
123126
Contributions to this project are welcome in the form of GitHub PRs. If you are planning to make any considerable changes, you should first present your plans in a GitHub issue so it can be discussed.
124127

125128
## Limitations
126-
- Currently mach-nix does not provide any functionality which supports you in publishing python projects, like [Poetry](https://python-poetry.org/) does for example.
127-
- Mach-nix does not yet support python packages in form of bdist_wheels, therefore some packages from pypi are not available.
129+
- Currently mach-nix does not provide any functionality which supports you in publishing python projects, like [Poetry](https://python-poetry.org/) does for example.
128130

129131
## Alternative / Similar Software:
130132
- [Poetry](https://python-poetry.org/)

debug/build_overrides.nix

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
let
2+
nixpkgs_commit = builtins.readFile ../mach_nix/nix/NIXPKGS_COMMIT; # nixpkgs version to use python packages from
3+
nixpkgs_tarball_sha256 = builtins.readFile ../mach_nix/nix/NIXPKGS_SHA256;
4+
pkgs = import (builtins.fetchTarball {
5+
name = "nixpkgs";
6+
url = "https://github.com/nixos/nixpkgs/tarball/${builtins.readFile ../mach_nix/nix/NIXPKGS_COMMIT}";
7+
sha256 = "${builtins.readFile ../mach_nix/nix/NIXPKGS_SHA256}";
8+
}) { config = {}; overlays = []; };
9+
python = pkgs.python37;
10+
manylinux1 = [ pkgs.pythonManylinuxPackages.manylinux1 ];
11+
result = import ./overrides.nix;
12+
overrides = result.overrides manylinux1 pkgs.autoPatchelfHook;
13+
py = pkgs.python37.override { packageOverrides = overrides; };
14+
in
15+
py.withPackages (ps: result.select_pkgs ps)

debug/debug.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,46 @@
1+
import json
12
import os
23
import subprocess as sp
34
import tempfile
45
from os.path import realpath, dirname
56

7+
import toml
8+
69
from mach_nix.generate import main
710

811
pwd = dirname(realpath(__file__))
912

1013
os.environ['py_ver_str'] = '3.7.5'
11-
os.environ['out_file'] = f'{pwd}/expr.nix'
14+
os.environ['out_file'] = f'{pwd}/overrides.nix'
1215
os.environ['disable_checks'] = 'true'
13-
os.environ['prefer_nixpkgs'] = 'true'
16+
17+
with open(pwd + "/../mach_nix/provider_defaults.toml") as f:
18+
provider_settings = toml.load(f)
19+
provider_settings.update(dict(
20+
_default="wheel,nixpkgs,sdist",
21+
))
22+
os.environ['providers'] = json.dumps(provider_settings)
1423

1524
nixpkgs_json = tempfile.mktemp()
1625
cmd = f'nix-build {pwd}/nixpkgs-json.nix -o {nixpkgs_json}'
17-
print(cmd)
1826
sp.check_call(cmd, shell=True)
1927
os.environ['nixpkgs_json'] = nixpkgs_json
2028

2129
pypi_deps_db = tempfile.mktemp()
22-
2330
cmd = f'nix-build {pwd}/pypi-deps-db.nix -o {pypi_deps_db}'
2431
sp.check_call(cmd, shell=True)
25-
os.environ['pypi_deps_db_data_dir'] = pypi_deps_db + "/data"
32+
os.environ['pypi_deps_db_src'] = pypi_deps_db
2633

27-
for key in ('NIXPKGS_COMMIT', 'NIXPKGS_TARBALL_SHA256'):
34+
for key in ('NIXPKGS_COMMIT', 'NIXPKGS_SHA256'):
2835
with open(f"{pwd}/../mach_nix/nix/{key}") as f:
2936
os.environ[key.lower()] = f.read()
3037

31-
for key in ('PYPI_FETCHER_COMMIT', 'PYPI_FETCHER_TARBALL_SHA256'):
38+
for key in ('PYPI_FETCHER_COMMIT', 'PYPI_FETCHER_SHA256'):
3239
with open(f"{pypi_deps_db}/{key}") as f:
3340
os.environ[key.lower()] = f.read()
3441

35-
os.environ['requirements'] = 'requests'
36-
42+
with open(pwd + "/reqs.txt") as f:
43+
os.environ['requirements'] = f.read()
3744

3845
# generates and writes nix expression into ./debug/expr.nix
3946
main()

debug/nixpkgs-json.nix

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
let
2-
nixpkgs_src = (import ../mach_nix/nix/nixpkgs-src.nix).stable;
3-
python = (import nixpkgs_src { config = {}; }).python37;
2+
nixpkgs_commit = builtins.readFile ../mach_nix/nix/NIXPKGS_COMMIT; # nixpkgs version to use python packages from
3+
nixpkgs_tarball_sha256 = builtins.readFile ../mach_nix/nix/NIXPKGS_SHA256;
4+
target_nixpkgs_src = builtins.fetchTarball {
5+
name = "nixpkgs";
6+
url = "https://github.com/nixos/nixpkgs/tarball/${nixpkgs_commit}";
7+
sha256 = "${nixpkgs_tarball_sha256}";
8+
};
9+
#nixpkgs_src = (import ../mach_nix/nix/nixpkgs-src.nix).stable;
10+
python = (import target_nixpkgs_src { config = {}; }).python37;
411
in
5-
with import nixpkgs_src { config = {}; };
12+
with import target_nixpkgs_src { config = {}; overlays = []; };
613
import ../mach_nix/nix/nixpkgs-json.nix { inherit pkgs python; }

debug/pypi-deps-db.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
let
22
pkgs = import (import ../mach_nix/nix/nixpkgs-src.nix).stable {};
33
commit = builtins.readFile ../mach_nix/nix/PYPI_DEPS_DB_COMMIT;
4-
sha256 = builtins.readFile ../mach_nix/nix/PYPI_DEPS_DB_TARBALL_SHA256;
4+
sha256 = builtins.readFile ../mach_nix/nix/PYPI_DEPS_DB_SHA256;
55
src = builtins.fetchTarball {
66
name = "pypi-deps-db-src";
77
url = "https://github.com/DavHau/pypi-deps-db/tarball/${commit}";

default.nix

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,23 @@
11
let
2-
pkgs = import (import ./mach_nix/nix/nixpkgs-src.nix).stable { config = {}; };
2+
pkgs = import (import ./mach_nix/nix/nixpkgs-src.nix) { config = {}; overlays = []; };
33
python = import ./mach_nix/nix/python.nix { inherit pkgs; };
4-
python_deps = (pkgs.lib.attrValues (import ./mach_nix/nix/python-deps.nix { inherit python; fetchurl = pkgs.fetchurl; }));
4+
python_deps = (builtins.attrValues (import ./mach_nix/nix/python-deps.nix { inherit python; fetchurl = pkgs.fetchurl; }));
5+
mergeOverrides = with pkgs.lib; overrides:
6+
if length overrides == 0
7+
then a: b: {} # return dummy overrides
8+
else
9+
if length overrides == 1
10+
then elemAt overrides 0
11+
else
12+
let
13+
last = head ( reverseList overrides );
14+
rest = reverseList (tail ( reverseList overrides ));
15+
in
16+
composeExtensions (mergeOverrides rest) last;
17+
autoPatchelfHook = import ./mach_nix/nix/auto_patchelf_hook.nix {inherit (pkgs) fetchurl makeSetupHook writeText;};
518
in
619
rec {
20+
# the mach-nix cmdline tool derivation
721
mach-nix = python.pkgs.buildPythonPackage rec {
822
pname = "mach-nix";
923
version = builtins.readFile ./mach_nix/VERSION;
@@ -13,12 +27,47 @@ rec {
1327
doCheck = false;
1428
};
1529

16-
# call this to generate a nix expression defnining a python environment
17-
mkPythonExpr = args: import ./mach_nix/nix/expression.nix args;
30+
inherit mergeOverrides;
1831

19-
# call this to generate a python environment
20-
mkPython = args: import "${mkPythonExpr args}/share/expr.nix";
32+
# User might want to access it to choose python version
33+
nixpkgs = pkgs;
34+
35+
# call this to generate a nix expression which contains the python overrides
36+
machNixFile = args: import ./mach_nix/nix/mach.nix args;
37+
38+
# Returns `overrides` and `select_pkgs` which satisfy your requirements
39+
machNix = args: import "${machNixFile args}/share/mach_nix_file.nix";
2140

2241
# call this to use the python environment with nix-shell
2342
mkPythonShell = args: (mkPython args).env;
43+
44+
# (High level API) generates a python environment with minimal user effort
45+
mkPython =
46+
{
47+
requirements, # content from a requirements.txt file
48+
disable_checks ? true, # Disable tests wherever possible to decrease build time.
49+
overrides_pre ? [], # list of pythonOverrides to apply before the machnix overrides
50+
overrides_post ? [], # list of pythonOverrides to apply after the machnix overrides
51+
pkgs ? nixpkgs, # pass custom nixpkgs. Only used for manylinux wheel dependencies
52+
providers ? {}, # define provider preferences
53+
pypi_deps_db_commit ? builtins.readFile ./mach_nix/nix/PYPI_DEPS_DB_COMMIT, # python dependency DB version
54+
pypi_deps_db_sha256 ? builtins.readFile ./mach_nix/nix/PYPI_DEPS_DB_SHA256,
55+
python ? pkgs.python3, # select custom python to base overrides on. Should be from nixpkgs >= 20.03
56+
_provider_defaults ? with builtins; fromTOML (readFile ./mach_nix/provider_defaults.toml)
57+
}:
58+
let
59+
py = python.override { packageOverrides = mergeOverrides overrides_pre; };
60+
result = machNix {
61+
inherit requirements disable_checks providers pypi_deps_db_commit pypi_deps_db_sha256 _provider_defaults;
62+
python = py;
63+
};
64+
overrides_machnix = result.overrides pkgs.pythonManylinuxPackages.manylinux1 autoPatchelfHook;
65+
py_final = python.override { packageOverrides = mergeOverrides (
66+
overrides_pre ++ [
67+
overrides_machnix
68+
] ++ overrides_post
69+
);};
70+
in
71+
py_final.withPackages (ps: result.select_pkgs ps)
72+
;
2473
}

example/advanced-usage.nix

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

example/simple-usage-expression.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
let
22
mach-nix = import (builtins.fetchGit {
33
url = "https://github.com/DavHau/mach-nix/";
4-
ref = "1.0.0";
4+
ref = "2.0.0";
55
});
66
in mach-nix.mkPythonExpr {
77
requirements = builtins.readFile ./requirements.txt;

example/simple-usage-shell.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
let
22
mach-nix = import (builtins.fetchGit {
33
url = "https://github.com/DavHau/mach-nix/";
4-
ref = "1.0.0";
4+
ref = "2.0.0";
55
});
66
in mach-nix.mkPythonShell {
77
requirements = builtins.readFile ./requirements.txt;

0 commit comments

Comments
 (0)