Interactive online version Binder badge. Generated from tutorials/02-python/01-using-and-creating-python-packages.ipynb.

Using and creating Python packages

This tutorial will show how to use Python packages from Nixpkgs and create new ones. For reference material on Python in Nixpkgs, see the Python section in the Nixpkgs manual

Python interpreters

Nixpkgs contains recipes for various Python interpreters. Multiple versions are available of the official reference implementation also known as CPython. Interpreters can be installed into a profile, used as part of a build or used temporary in a nix-shell or nix run session.

Python applications, libraries and environments

In Nixpkgs a distinction is made between applications, libraries and environments. - Applications are programs for end-users such as Calibre the e-book manager. - Libraries are packages providing importable modules. Additionally, tools used for development of libraries are also considered libraries. - Environments are a Python interpreter along with libraries, typically used for development or as dependency for other programs.

Python application

Let’s consider first a Python application, the version control system Mercurial. The following recipe shows how to build it. For build and run-time dependencies we use the recipes provided by Nixpkgs. We then create a builder function for building our package. Finally, we call it.

[1]:
%%file default.nix

let
  nixpkgs = fetchTarball "channel:nixos-20.03";
  pkgs = import nixpkgs {};

  recipe = { python3, fetchurl }:
    with python3.pkgs;

    buildPythonApplication rec {
      pname = "mercurial";
      version = "5.2.2";

      src = fetchurl {
        url = "https://mercurial-scm.org/release/mercurial-${version}.tar.gz";
        sha256 = "0fy00q0k4f0q64jjlnb7cl6m0sglivq9jgdddsp5sywc913zzigz";
      };

      # By default tests are executed, but they need to be invoked differently for this package
      dontUseSetuptoolsCheck = true;
    };

in pkgs.callPackage recipe {}

Writing default.nix

Let’s build it. Note we suppress the build-output because of the amount.

[2]:
! nix-build --no-build-output
unpacking 'https://nixos.org/channels/nixos-20.03/nixexprs.tar.xz'...
these derivations will be built:
  /nix/store/if0ar51j69f690p00bwbvmjn7y3ia27a-mercurial-5.2.2.drv
these paths will be fetched (73.81 MiB download, 314.71 MiB unpacked):
  /nix/store/07zg498fp8a3rr3ln2my9rfrlzikmjfm-pcre-8.43
  /nix/store/1i7hiy0isxixvlv12k1221ff6hzqx51d-hook
  /nix/store/1zf4cnaaidjajwb4gx4mnkqc5dypkcdy-binutils-2.31.1
  /nix/store/2a6l66s159lgcfbkyg8zcp7k11bbmv7w-ed-1.15
  /nix/store/2p6ji9i05dkjz3fgpvymlawl379fw577-glibc-2.30-bin
  /nix/store/2z51w65pm8vap5j0p2hidyss09cyc8m3-gawk-5.0.1
  /nix/store/48jg7qxx2i3ndgr1b67imy6qr2nvsfjx-diffutils-3.7
  /nix/store/4ih4qpvh7ydzw3m5a2q623a6nbp089fp-xz-5.2.4-bin
  /nix/store/4jm7vhm6shfkl2rs71sb5qg79wwvsj0a-mercurial-5.2.2.tar.gz
  /nix/store/55b9ip7xkpimaccw9pa0vacy5q94f5xa-python3-3.7.6
  /nix/store/5gqv9dn7yih5hsz5by9mxhf2384zjsza-gnused-4.8
  /nix/store/64j3k8hzmdb7k2y06px689gnp61p05qs-attr-2.4.48
  /nix/store/6hhxlbabm7xxdfdw9mbxb8llh63k1bxx-linux-headers-4.19.16
  /nix/store/7g6ar24krh7vn66gvfwwv3nq9xsh5c6i-coreutils-8.31
  /nix/store/9hy6c2hv8lcwc6clnc1p2jf09cs5q9dp-glibc-2.30
  /nix/store/9y9hgbczizwqzci2vfl2phnk9rz50fiq-glibc-2.30-dev
  /nix/store/am4jwcz88m2czry78zs00ik66rv8jc83-hook
  /nix/store/axkkr27z9cjzxac1c9s6ngda73kbz063-binutils-wrapper-2.31.1
  /nix/store/b4kbdvdyb80r57jhx7665117k75v4jrl-stdenv-linux
  /nix/store/bdlbkypri7h79m6gnwcp0sq62cj1gvvc-gdbm-1.18.1
  /nix/store/bnrgs6bk2q3rabkbp9dmw177axh0zz70-setuptools-setup-hook
  /nix/store/c98k0shcp2yp69g81mqhbqw3xbxvnk0r-gnutar-1.32
  /nix/store/d5llqjfp8r0984vbmd3sjw53ln3bzpyx-python-catch-conflicts-hook
  /nix/store/f11b0nnm3sxxh3yw3qam4q0h411i28w7-python3.7-setuptools-44.0.0
  /nix/store/f6469v8fzabc2is3fssrlj9dm0zja1m3-expat-2.2.8
  /nix/store/f7dfbkknr2as5vcykilxh840fw9iw3yh-hook
  /nix/store/h7l1m4lvzvyjxx2d35y4ln1v6sa5ar8g-setuptools-check-hook
  /nix/store/hdybipp5dymakgkp14z7gnp5da23n0zf-patchelf-0.9
  /nix/store/hg2mgsivahn1mcjq87l4myv1n6zqa1ii-python3.7-pip-19.3.1
  /nix/store/ijpx1ns1brdpi3wrcyxaz379q6ns3yp7-pip-install-hook
  /nix/store/k5r4w2wlsycpqppf3gpda1hyx6sc62i7-gnumake-4.2.1
  /nix/store/kf2sh7c2fmizvycqq02aad1rfp6xswgv-zlib-1.2.11
  /nix/store/kpw4kmc74djprg3bjc5rxblij46jdmnf-ncurses-6.1-20190112
  /nix/store/lfd97pn9bjid6bihs31m9iimi04szrzn-python-imports-check-hook.sh
  /nix/store/mjvz9b02v42lngkn4dxal6n1xrv8wx9l-gcc-9.2.0
  /nix/store/n496s4scavyilxmdr3sm662hr6chpzx7-expand-response-params
  /nix/store/q9488331pamfzi3zy6wn80pnic30b2b9-readline-6.3p08
  /nix/store/r1hncr91kzyscxiab3c7wlfmvrhx01x6-bzip2-1.0.6.0.1-bin
  /nix/store/rdl0mdfawd3gyv45nml3n6iw134d2g8h-gnugrep-3.4
  /nix/store/rj2642fn2ciqwiihvv607n68fiy4qbdc-gzip-1.10
  /nix/store/rw7mr4n32sacjgd6lvfc91avijdhnlgp-python-remove-bin-bytecode-hook
  /nix/store/s6gl1w6zvgad0i9arlagdv8dngqmbgi9-python3.7-wheel-0.33.6
  /nix/store/s7smd0wk3q3y8ns9wmd2r9612a9dbymf-xz-5.2.4
  /nix/store/smccfl7q9cz2ilzds5rg6f02l41s647p-patch-2.7.6
  /nix/store/v0mg9kimjd2a6wvmfxdxagzz30l80i1r-acl-2.2.53
  /nix/store/w7alid4mirzwx3ck4hj18q7rnr4yslfh-gcc-9.2.0-lib
  /nix/store/w9l2nmg6pclz944f33zg17bpgvq27f4f-findutils-4.7.0
  /nix/store/wbfvkab46lmihf7ninny4nqzxc0j8rq1-openssl-1.1.1g
  /nix/store/wz8mnpr8dbbn9kqfq0qa63x47rg4vcik-hook
  /nix/store/x6sc334nvkl7pr3yqiqs3dzhfsbsgqcd-libffi-3.3
  /nix/store/x7fr0bvnwvqvr3zg60di9jxvfwimcw7m-bash-4.4-p23
  /nix/store/xh3bh8nir5d45zk45dz9xxfs2j95cby4-gcc-wrapper-9.2.0
  /nix/store/xkd8vp4ymb07czc6fap0iyw88qfxwk36-bzip2-1.0.6.0.1
  /nix/store/yph46cx63plkrj99p5qimggc9hcxjk31-sqlite-3.30.1
copying path '/nix/store/4jm7vhm6shfkl2rs71sb5qg79wwvsj0a-mercurial-5.2.2.tar.gz' from 'https://cache.nixos.org'...
copying path '/nix/store/rw7mr4n32sacjgd6lvfc91avijdhnlgp-python-remove-bin-bytecode-hook' from 'https://cache.nixos.org'...
copying path '/nix/store/9hy6c2hv8lcwc6clnc1p2jf09cs5q9dp-glibc-2.30' from 'https://cache.nixos.org'...
copying path '/nix/store/am4jwcz88m2czry78zs00ik66rv8jc83-hook' from 'https://cache.nixos.org'...
copying path '/nix/store/6hhxlbabm7xxdfdw9mbxb8llh63k1bxx-linux-headers-4.19.16' from 'https://cache.nixos.org'...
copying path '/nix/store/x7fr0bvnwvqvr3zg60di9jxvfwimcw7m-bash-4.4-p23' from 'https://cache.nixos.org'...
copying path '/nix/store/64j3k8hzmdb7k2y06px689gnp61p05qs-attr-2.4.48' from 'https://cache.nixos.org'...
copying path '/nix/store/xkd8vp4ymb07czc6fap0iyw88qfxwk36-bzip2-1.0.6.0.1' from 'https://cache.nixos.org'...
copying path '/nix/store/v0mg9kimjd2a6wvmfxdxagzz30l80i1r-acl-2.2.53' from 'https://cache.nixos.org'...
copying path '/nix/store/r1hncr91kzyscxiab3c7wlfmvrhx01x6-bzip2-1.0.6.0.1-bin' from 'https://cache.nixos.org'...
copying path '/nix/store/2a6l66s159lgcfbkyg8zcp7k11bbmv7w-ed-1.15' from 'https://cache.nixos.org'...
copying path '/nix/store/7g6ar24krh7vn66gvfwwv3nq9xsh5c6i-coreutils-8.31' from 'https://cache.nixos.org'...
copying path '/nix/store/n496s4scavyilxmdr3sm662hr6chpzx7-expand-response-params' from 'https://cache.nixos.org'...
copying path '/nix/store/f6469v8fzabc2is3fssrlj9dm0zja1m3-expat-2.2.8' from 'https://cache.nixos.org'...
copying path '/nix/store/2z51w65pm8vap5j0p2hidyss09cyc8m3-gawk-5.0.1' from 'https://cache.nixos.org'...
copying path '/nix/store/w7alid4mirzwx3ck4hj18q7rnr4yslfh-gcc-9.2.0-lib' from 'https://cache.nixos.org'...
copying path '/nix/store/48jg7qxx2i3ndgr1b67imy6qr2nvsfjx-diffutils-3.7' from 'https://cache.nixos.org'...
copying path '/nix/store/w9l2nmg6pclz944f33zg17bpgvq27f4f-findutils-4.7.0' from 'https://cache.nixos.org'...
copying path '/nix/store/bdlbkypri7h79m6gnwcp0sq62cj1gvvc-gdbm-1.18.1' from 'https://cache.nixos.org'...
copying path '/nix/store/2p6ji9i05dkjz3fgpvymlawl379fw577-glibc-2.30-bin' from 'https://cache.nixos.org'...
copying path '/nix/store/k5r4w2wlsycpqppf3gpda1hyx6sc62i7-gnumake-4.2.1' from 'https://cache.nixos.org'...
copying path '/nix/store/5gqv9dn7yih5hsz5by9mxhf2384zjsza-gnused-4.8' from 'https://cache.nixos.org'...
copying path '/nix/store/c98k0shcp2yp69g81mqhbqw3xbxvnk0r-gnutar-1.32' from 'https://cache.nixos.org'...
copying path '/nix/store/9y9hgbczizwqzci2vfl2phnk9rz50fiq-glibc-2.30-dev' from 'https://cache.nixos.org'...
copying path '/nix/store/rj2642fn2ciqwiihvv607n68fiy4qbdc-gzip-1.10' from 'https://cache.nixos.org'...
copying path '/nix/store/1i7hiy0isxixvlv12k1221ff6hzqx51d-hook' from 'https://cache.nixos.org'...
copying path '/nix/store/wz8mnpr8dbbn9kqfq0qa63x47rg4vcik-hook' from 'https://cache.nixos.org'...
copying path '/nix/store/x6sc334nvkl7pr3yqiqs3dzhfsbsgqcd-libffi-3.3' from 'https://cache.nixos.org'...
copying path '/nix/store/kpw4kmc74djprg3bjc5rxblij46jdmnf-ncurses-6.1-20190112' from 'https://cache.nixos.org'...
copying path '/nix/store/wbfvkab46lmihf7ninny4nqzxc0j8rq1-openssl-1.1.1g' from 'https://cache.nixos.org'...
copying path '/nix/store/smccfl7q9cz2ilzds5rg6f02l41s647p-patch-2.7.6' from 'https://cache.nixos.org'...
copying path '/nix/store/hdybipp5dymakgkp14z7gnp5da23n0zf-patchelf-0.9' from 'https://cache.nixos.org'...
copying path '/nix/store/07zg498fp8a3rr3ln2my9rfrlzikmjfm-pcre-8.43' from 'https://cache.nixos.org'...
copying path '/nix/store/q9488331pamfzi3zy6wn80pnic30b2b9-readline-6.3p08' from 'https://cache.nixos.org'...
copying path '/nix/store/s7smd0wk3q3y8ns9wmd2r9612a9dbymf-xz-5.2.4' from 'https://cache.nixos.org'...
copying path '/nix/store/rdl0mdfawd3gyv45nml3n6iw134d2g8h-gnugrep-3.4' from 'https://cache.nixos.org'...
copying path '/nix/store/kf2sh7c2fmizvycqq02aad1rfp6xswgv-zlib-1.2.11' from 'https://cache.nixos.org'...
copying path '/nix/store/4ih4qpvh7ydzw3m5a2q623a6nbp089fp-xz-5.2.4-bin' from 'https://cache.nixos.org'...
copying path '/nix/store/mjvz9b02v42lngkn4dxal6n1xrv8wx9l-gcc-9.2.0' from 'https://cache.nixos.org'...
copying path '/nix/store/1zf4cnaaidjajwb4gx4mnkqc5dypkcdy-binutils-2.31.1' from 'https://cache.nixos.org'...
copying path '/nix/store/yph46cx63plkrj99p5qimggc9hcxjk31-sqlite-3.30.1' from 'https://cache.nixos.org'...
copying path '/nix/store/axkkr27z9cjzxac1c9s6ngda73kbz063-binutils-wrapper-2.31.1' from 'https://cache.nixos.org'...
copying path '/nix/store/55b9ip7xkpimaccw9pa0vacy5q94f5xa-python3-3.7.6' from 'https://cache.nixos.org'...
copying path '/nix/store/f7dfbkknr2as5vcykilxh840fw9iw3yh-hook' from 'https://cache.nixos.org'...
copying path '/nix/store/lfd97pn9bjid6bihs31m9iimi04szrzn-python-imports-check-hook.sh' from 'https://cache.nixos.org'...
copying path '/nix/store/hg2mgsivahn1mcjq87l4myv1n6zqa1ii-python3.7-pip-19.3.1' from 'https://cache.nixos.org'...
copying path '/nix/store/f11b0nnm3sxxh3yw3qam4q0h411i28w7-python3.7-setuptools-44.0.0' from 'https://cache.nixos.org'...
copying path '/nix/store/ijpx1ns1brdpi3wrcyxaz379q6ns3yp7-pip-install-hook' from 'https://cache.nixos.org'...
copying path '/nix/store/d5llqjfp8r0984vbmd3sjw53ln3bzpyx-python-catch-conflicts-hook' from 'https://cache.nixos.org'...
copying path '/nix/store/s6gl1w6zvgad0i9arlagdv8dngqmbgi9-python3.7-wheel-0.33.6' from 'https://cache.nixos.org'...
copying path '/nix/store/h7l1m4lvzvyjxx2d35y4ln1v6sa5ar8g-setuptools-check-hook' from 'https://cache.nixos.org'...
copying path '/nix/store/bnrgs6bk2q3rabkbp9dmw177axh0zz70-setuptools-setup-hook' from 'https://cache.nixos.org'...
copying path '/nix/store/xh3bh8nir5d45zk45dz9xxfs2j95cby4-gcc-wrapper-9.2.0' from 'https://cache.nixos.org'...
copying path '/nix/store/b4kbdvdyb80r57jhx7665117k75v4jrl-stdenv-linux' from 'https://cache.nixos.org'...
building '/nix/store/if0ar51j69f690p00bwbvmjn7y3ia27a-mercurial-5.2.2.drv'...
/nix/store/8fb07c6jw5dfpgcf602d2137jj4dbkr3-mercurial-5.2.2

We can now execute hg directly from the store path

[3]:
! result/bin/hg --version
Mercurial Distributed SCM (version 5.2.2)
(see https://mercurial-scm.org for more information)

Copyright (C) 2005-2019 Matt Mackall and others
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

or install it in our profile

[4]:
! nix-env -if .
installing 'mercurial-5.2.2'
building '/nix/store/825ld4flhfdqzjjwp46bb3hkarsc3gvq-user-environment.drv'...
created 5 symlinks in user environment

bringing the executable onto $PATH.

[5]:
! hg --version
Mercurial Distributed SCM (version 5.2.2)
(see https://mercurial-scm.org for more information)

Copyright (C) 2005-2019 Matt Mackall and others
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Creating a basic recipe for Mercurial was easy. The recipe used in Nixpkgs is however more elaborate.

[6]:
! nix run -f channel:nixos-20.03 curl --command curl --silent https://raw.githubusercontent.com/NixOS/nixpkgs/nixos-20.03/pkgs/applications/version-management/mercurial/default.nix | pygmentize
[6 copied (3.6 MiB), 14.9 MiB DL]
{ stdenv, fetchurl, python3Packages, makeWrapper, unzip
, guiSupport ? false, tk ? null
, ApplicationServices
}:

let
  inherit (python3Packages) docutils dulwich python;

in python3Packages.buildPythonApplication rec {
  pname = "mercurial";
  version = "5.2.2";

  src = fetchurl {
    url = "https://mercurial-scm.org/release/mercurial-${version}.tar.gz";
    sha256 = "0fy00q0k4f0q64jjlnb7cl6m0sglivq9jgdddsp5sywc913zzigz";
  };

  format = "other";

  inherit python; # pass it so that the same version can be used in hg2git

  buildInputs = [ makeWrapper docutils unzip ]
    ++ stdenv.lib.optionals stdenv.isDarwin [ ApplicationServices ];

  propagatedBuildInputs = [ dulwich ];

  makeFlags = [ "PREFIX=$(out)" ];

  postInstall = (stdenv.lib.optionalString guiSupport ''
    mkdir -p $out/etc/mercurial
    cp contrib/hgk $out/bin
    cat >> $out/etc/mercurial/hgrc << EOF
    [extensions]
    hgk=$out/lib/${python.libPrefix}/site-packages/hgext/hgk.py
    EOF
    # setting HG so that hgk can be run itself as well (not only hg view)
    WRAP_TK=" --set TK_LIBRARY ${tk}/lib/${tk.libPrefix}
              --set HG $out/bin/hg
              --prefix PATH : ${tk}/bin "
  '') + ''
    for i in $(cd $out/bin && ls); do
      wrapProgram $out/bin/$i \
        $WRAP_TK
    done

    # copy hgweb.cgi to allow use in apache
    mkdir -p $out/share/cgi-bin
    cp -v hgweb.cgi contrib/hgweb.wsgi $out/share/cgi-bin
    chmod u+x $out/share/cgi-bin/hgweb.cgi

    # install bash/zsh completions
    install -v -m644 -D contrib/bash_completion $out/share/bash-completion/completions/_hg
    install -v -m644 -D contrib/zsh_completion $out/share/zsh/site-functions/_hg
  '';

  meta = {
    inherit version;
    description = "A fast, lightweight SCM system for very large distributed projects";
    homepage = https://www.mercurial-scm.org;
    downloadPage = https://www.mercurial-scm.org/release/;
    license = stdenv.lib.licenses.gpl2;
    maintainers = [ stdenv.lib.maintainers.eelco ];
    updateWalker = true;
    platforms = stdenv.lib.platforms.unix;
  };
}

Python library

Python uses packages to distribute libraries called modules that are importable. In Nixpkgs all Python 3 libraries are in the attribute set python3.pkgs. The following example shows a recipe for the Python package toolz

[7]:
%%file toolz.nix

{ lib, buildPythonPackage, fetchPypi }:

buildPythonPackage rec {
  pname = "toolz";
  version = "0.10.0";

  src = fetchPypi {
    inherit pname version;
    sha256 = "08fdd5ef7c96480ad11c12d472de21acd32359996f69a5259299b540feba4560";
  };

  doCheck = false;

  meta = with lib; {
    homepage = https://github.com/pytoolz/toolz;
    description = "List processing tools and functional utilities";
    license = licenses.bsd3;
    maintainers = with maintainers; [ fridh ];
  };
}
Writing toolz.nix

Applications or other libraries may want to use this package. In order to make that possible, we need to update the Python packages set to include this package

[8]:
%%file mypython.nix

let
  nixpkgs = fetchTarball "channel:nixos-20.03";
  pkgs = import nixpkgs {};

  mypython = pkgs.python3.override {
    self = mypython;
    packageOverrides = pself: psuper: {
      toolz = pself.callPackage ./toolz.nix {};
    };
  };
in {
  inherit mypython;
}
Writing mypython.nix

We now have a Python interpreter that has a package set that includes our package. Using this type of overriding we can also inject modifications to existing packages that will then be used by all dependents in the set.

Let’s build the package.

[9]:
! nix-build -A mypython.pkgs.toolz mypython.nix
these derivations will be built:
  /nix/store/wx2sbziva7jvxa7djsp2ssij1fgmnqvn-python3.7-toolz-0.10.0.drv
these paths will be fetched (0.05 MiB download, 0.05 MiB unpacked):
  /nix/store/hx82zf49j1wsy3nlc4g786cjhfbjlyz6-toolz-0.10.0.tar.gz
copying path '/nix/store/hx82zf49j1wsy3nlc4g786cjhfbjlyz6-toolz-0.10.0.tar.gz' from 'https://cache.nixos.org'...
building '/nix/store/wx2sbziva7jvxa7djsp2ssij1fgmnqvn-python3.7-toolz-0.10.0.drv'...
Sourcing python-catch-conflicts-hook.sh
Sourcing python-remove-bin-bytecode-hook.sh
Sourcing setuptools-build-hook
Using setuptoolsBuildPhase
Using setuptoolsShellHook
Sourcing pip-install-hook
Using pipInstallPhase
Sourcing python-imports-check-hook.sh
Using pythonImportsCheckPhase
unpacking sources
unpacking source archive /nix/store/hx82zf49j1wsy3nlc4g786cjhfbjlyz6-toolz-0.10.0.tar.gz
source root is toolz-0.10.0
setting SOURCE_DATE_EPOCH to timestamp 1562876547 of file toolz-0.10.0/toolz.egg-info/top_level.txt
patching sources
configuring
no configure script, doing nothing
building
Executing setuptoolsBuildPhase
running bdist_wheel
running build
running build_py
creating build
creating build/lib
creating build/lib/toolz
copying toolz/_signatures.py -> build/lib/toolz
copying toolz/functoolz.py -> build/lib/toolz
copying toolz/__init__.py -> build/lib/toolz
copying toolz/utils.py -> build/lib/toolz
copying toolz/recipes.py -> build/lib/toolz
copying toolz/dicttoolz.py -> build/lib/toolz
copying toolz/compatibility.py -> build/lib/toolz
copying toolz/itertoolz.py -> build/lib/toolz
creating build/lib/toolz/sandbox
copying toolz/sandbox/__init__.py -> build/lib/toolz/sandbox
copying toolz/sandbox/parallel.py -> build/lib/toolz/sandbox
copying toolz/sandbox/core.py -> build/lib/toolz/sandbox
creating build/lib/toolz/curried
copying toolz/curried/operator.py -> build/lib/toolz/curried
copying toolz/curried/exceptions.py -> build/lib/toolz/curried
copying toolz/curried/__init__.py -> build/lib/toolz/curried
creating build/lib/tlz
copying tlz/__init__.py -> build/lib/tlz
copying tlz/_build_tlz.py -> build/lib/tlz
creating build/lib/toolz/tests
copying toolz/tests/test_tlz.py -> build/lib/toolz/tests
copying toolz/tests/test_curried.py -> build/lib/toolz/tests
copying toolz/tests/test_inspect_args.py -> build/lib/toolz/tests
copying toolz/tests/test_recipes.py -> build/lib/toolz/tests
copying toolz/tests/test_itertoolz.py -> build/lib/toolz/tests
copying toolz/tests/test_compatibility.py -> build/lib/toolz/tests
copying toolz/tests/test_dicttoolz.py -> build/lib/toolz/tests
copying toolz/tests/test_signatures.py -> build/lib/toolz/tests
copying toolz/tests/test_serialization.py -> build/lib/toolz/tests
copying toolz/tests/test_functoolz.py -> build/lib/toolz/tests
copying toolz/tests/test_curried_doctests.py -> build/lib/toolz/tests
copying toolz/tests/test_utils.py -> build/lib/toolz/tests
installing to build/bdist.linux-x86_64/wheel
running install
running install_lib
creating build/bdist.linux-x86_64
creating build/bdist.linux-x86_64/wheel
creating build/bdist.linux-x86_64/wheel/tlz
copying build/lib/tlz/__init__.py -> build/bdist.linux-x86_64/wheel/tlz
copying build/lib/tlz/_build_tlz.py -> build/bdist.linux-x86_64/wheel/tlz
creating build/bdist.linux-x86_64/wheel/toolz
copying build/lib/toolz/_signatures.py -> build/bdist.linux-x86_64/wheel/toolz
creating build/bdist.linux-x86_64/wheel/toolz/tests
copying build/lib/toolz/tests/test_tlz.py -> build/bdist.linux-x86_64/wheel/toolz/tests
copying build/lib/toolz/tests/test_curried.py -> build/bdist.linux-x86_64/wheel/toolz/tests
copying build/lib/toolz/tests/test_inspect_args.py -> build/bdist.linux-x86_64/wheel/toolz/tests
copying build/lib/toolz/tests/test_recipes.py -> build/bdist.linux-x86_64/wheel/toolz/tests
copying build/lib/toolz/tests/test_itertoolz.py -> build/bdist.linux-x86_64/wheel/toolz/tests
copying build/lib/toolz/tests/test_compatibility.py -> build/bdist.linux-x86_64/wheel/toolz/tests
copying build/lib/toolz/tests/test_dicttoolz.py -> build/bdist.linux-x86_64/wheel/toolz/tests
copying build/lib/toolz/tests/test_signatures.py -> build/bdist.linux-x86_64/wheel/toolz/tests
copying build/lib/toolz/tests/test_serialization.py -> build/bdist.linux-x86_64/wheel/toolz/tests
copying build/lib/toolz/tests/test_functoolz.py -> build/bdist.linux-x86_64/wheel/toolz/tests
copying build/lib/toolz/tests/test_curried_doctests.py -> build/bdist.linux-x86_64/wheel/toolz/tests
copying build/lib/toolz/tests/test_utils.py -> build/bdist.linux-x86_64/wheel/toolz/tests
copying build/lib/toolz/functoolz.py -> build/bdist.linux-x86_64/wheel/toolz
copying build/lib/toolz/__init__.py -> build/bdist.linux-x86_64/wheel/toolz
copying build/lib/toolz/utils.py -> build/bdist.linux-x86_64/wheel/toolz
creating build/bdist.linux-x86_64/wheel/toolz/sandbox
copying build/lib/toolz/sandbox/__init__.py -> build/bdist.linux-x86_64/wheel/toolz/sandbox
copying build/lib/toolz/sandbox/parallel.py -> build/bdist.linux-x86_64/wheel/toolz/sandbox
copying build/lib/toolz/sandbox/core.py -> build/bdist.linux-x86_64/wheel/toolz/sandbox
copying build/lib/toolz/recipes.py -> build/bdist.linux-x86_64/wheel/toolz
copying build/lib/toolz/dicttoolz.py -> build/bdist.linux-x86_64/wheel/toolz
creating build/bdist.linux-x86_64/wheel/toolz/curried
copying build/lib/toolz/curried/operator.py -> build/bdist.linux-x86_64/wheel/toolz/curried
copying build/lib/toolz/curried/exceptions.py -> build/bdist.linux-x86_64/wheel/toolz/curried
copying build/lib/toolz/curried/__init__.py -> build/bdist.linux-x86_64/wheel/toolz/curried
copying build/lib/toolz/compatibility.py -> build/bdist.linux-x86_64/wheel/toolz
copying build/lib/toolz/itertoolz.py -> build/bdist.linux-x86_64/wheel/toolz
running install_egg_info
running egg_info
writing toolz.egg-info/PKG-INFO
writing dependency_links to toolz.egg-info/dependency_links.txt
writing top-level names to toolz.egg-info/top_level.txt
reading manifest file 'toolz.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'toolz.egg-info/SOURCES.txt'
Copying toolz.egg-info to build/bdist.linux-x86_64/wheel/toolz-0.10.0-py3.7.egg-info
running install_scripts
adding license file "LICENSE.txt" (matched pattern "LICEN[CS]E*")
creating build/bdist.linux-x86_64/wheel/toolz-0.10.0.dist-info/WHEEL
creating 'dist/toolz-0.10.0-py3-none-any.whl' and adding 'build/bdist.linux-x86_64/wheel' to it
adding 'tlz/__init__.py'
adding 'tlz/_build_tlz.py'
adding 'toolz/__init__.py'
adding 'toolz/_signatures.py'
adding 'toolz/compatibility.py'
adding 'toolz/dicttoolz.py'
adding 'toolz/functoolz.py'
adding 'toolz/itertoolz.py'
adding 'toolz/recipes.py'
adding 'toolz/utils.py'
adding 'toolz/curried/__init__.py'
adding 'toolz/curried/exceptions.py'
adding 'toolz/curried/operator.py'
adding 'toolz/sandbox/__init__.py'
adding 'toolz/sandbox/core.py'
adding 'toolz/sandbox/parallel.py'
adding 'toolz/tests/test_compatibility.py'
adding 'toolz/tests/test_curried.py'
adding 'toolz/tests/test_curried_doctests.py'
adding 'toolz/tests/test_dicttoolz.py'
adding 'toolz/tests/test_functoolz.py'
adding 'toolz/tests/test_inspect_args.py'
adding 'toolz/tests/test_itertoolz.py'
adding 'toolz/tests/test_recipes.py'
adding 'toolz/tests/test_serialization.py'
adding 'toolz/tests/test_signatures.py'
adding 'toolz/tests/test_tlz.py'
adding 'toolz/tests/test_utils.py'
adding 'toolz-0.10.0.dist-info/LICENSE.txt'
adding 'toolz-0.10.0.dist-info/METADATA'
adding 'toolz-0.10.0.dist-info/WHEEL'
adding 'toolz-0.10.0.dist-info/top_level.txt'
adding 'toolz-0.10.0.dist-info/RECORD'
removing build/bdist.linux-x86_64/wheel
Finished executing setuptoolsBuildPhase
installing
Executing pipInstallPhase
/build/toolz-0.10.0/dist /build/toolz-0.10.0
Processing ./toolz-0.10.0-py3-none-any.whl
Installing collected packages: toolz
Successfully installed toolz-0.10.0
/build/toolz-0.10.0
Finished executing pipInstallPhase
post-installation fixup
shrinking RPATHs of ELF executables and libraries in /nix/store/c4mw4g3f0gfnxcmpjw37490mgwsbjb87-python3.7-toolz-0.10.0
strip is /nix/store/1zf4cnaaidjajwb4gx4mnkqc5dypkcdy-binutils-2.31.1/bin/strip
stripping (with command strip and flags -S) in /nix/store/c4mw4g3f0gfnxcmpjw37490mgwsbjb87-python3.7-toolz-0.10.0/lib
patching script interpreter paths in /nix/store/c4mw4g3f0gfnxcmpjw37490mgwsbjb87-python3.7-toolz-0.10.0
checking for references to /build/ in /nix/store/c4mw4g3f0gfnxcmpjw37490mgwsbjb87-python3.7-toolz-0.10.0...
pythonCatchConflictsPhase
pythonRemoveBinBytecodePhase
pythonImportsCheckPhase
Executing pythonImportsCheckPhase
/nix/store/c4mw4g3f0gfnxcmpjw37490mgwsbjb87-python3.7-toolz-0.10.0

The log shows the execution of several hooks that are responsible for building, installing and testing the package.

Environments

Now that we know how to build a Python library, we want to use it in an environment, for example a development environment.

The following expression creates a Python environment, quite similar to a virtualenv or venv that includes the interpreter, our package and another package, the test runner pytest

[10]:
%%file myenv.nix

(import ./mypython.nix).mypython.withPackages(ps: with ps; [ toolz pytest ])
Writing myenv.nix
[11]:
! nix run -f myenv.nix --command python3 -c 'import toolz; print(toolz); import pytest; print(pytest)'
[2 built, 14 copied (54.8 MiB), 8.9 MiB DL]
<module 'toolz' from '/nix/store/gwzvpcfzd4r66lh19lkgqvnav1v8d0a7-python3-3.7.6-env/lib/python3.7/site-packages/toolz/__init__.py'>
<module 'pytest' from '/nix/store/gwzvpcfzd4r66lh19lkgqvnav1v8d0a7-python3-3.7.6-env/lib/python3.7/site-packages/pytest/__init__.py'>

The toolz module, just like the pytest module can now be imported.

How does an environment like this look like? If we build the expression we get the link to the store path

[12]:
! find $(nix-build myenv.nix) | tail
/nix/store/gwzvpcfzd4r66lh19lkgqvnav1v8d0a7-python3-3.7.6-env/lib/python3.7/binhex.py
/nix/store/gwzvpcfzd4r66lh19lkgqvnav1v8d0a7-python3-3.7.6-env/lib/python3.7/xdrlib.py
/nix/store/gwzvpcfzd4r66lh19lkgqvnav1v8d0a7-python3-3.7.6-env/lib/python3.7/shelve.py
/nix/store/gwzvpcfzd4r66lh19lkgqvnav1v8d0a7-python3-3.7.6-env/lib/python3.7/macpath.py
/nix/store/gwzvpcfzd4r66lh19lkgqvnav1v8d0a7-python3-3.7.6-env/lib/python3.7/_collections_abc.py
/nix/store/gwzvpcfzd4r66lh19lkgqvnav1v8d0a7-python3-3.7.6-env/lib/python3.7/io.py
/nix/store/gwzvpcfzd4r66lh19lkgqvnav1v8d0a7-python3-3.7.6-env/lib/python3.7/bisect.py
/nix/store/gwzvpcfzd4r66lh19lkgqvnav1v8d0a7-python3-3.7.6-env/lib/libpython3.7m.so
/nix/store/gwzvpcfzd4r66lh19lkgqvnav1v8d0a7-python3-3.7.6-env/lib/libpython3.7m.so.1.0
/nix/store/gwzvpcfzd4r66lh19lkgqvnav1v8d0a7-python3-3.7.6-env/lib/libpython3.so

The environment is essentially a bunch of symbolic links to the packages we’ve included, as well as the interpreter. Executables are also wrapped so that all tools can find each other.