at 16.09-beta 3.5 kB view raw
1/* This function provides a generic Python package builder. It is 2 intended to work with packages that use `distutils/setuptools' 3 (http://pypi.python.org/pypi/setuptools/), which represents a large 4 number of Python packages nowadays. */ 5 6{ lib 7, python 8, mkPythonDerivation 9, bootstrapped-pip 10}: 11 12{ buildInputs ? [] 13 14# propagate build dependencies so in case we have A -> B -> C, 15# C can import package A propagated by B 16#, propagatedBuildInputs ? [] 17 18# passed to "python setup.py build_ext" 19# https://github.com/pypa/pip/issues/881 20, setupPyBuildFlags ? [] 21 22# Execute before shell hook 23, preShellHook ? "" 24 25# Execute after shell hook 26, postShellHook ? "" 27 28# Additional flags to pass to "pip install". 29, installFlags ? [] 30 31, format ? "setup" 32 33, ... } @ attrs: 34 35 36 37 38let 39 # use setuptools shim (so that setuptools is imported before distutils) 40 # pip does the same thing: https://github.com/pypa/pip/pull/3265 41 setuppy = ./run_setup.py; 42 43 formatspecific = 44 if format == "wheel" then 45 { 46 unpackPhase = '' 47 mkdir dist 48 cp $src dist/"''${src#*-}" 49 ''; 50 51 # Wheels are pre-compiled 52 buildPhase = attrs.buildPhase or ":"; 53 installCheckPhase = attrs.checkPhase or ":"; 54 55 # Wheels don't have any checks to run 56 doCheck = attrs.doCheck or false; 57 } 58 else if format == "setup" then 59 { 60 # we copy nix_run_setup.py over so it's executed relative to the root of the source 61 # many project make that assumption 62 buildPhase = attrs.buildPhase or '' 63 runHook preBuild 64 cp ${setuppy} nix_run_setup.py 65 ${python.interpreter} nix_run_setup.py ${lib.optionalString (setupPyBuildFlags != []) ("build_ext " + (lib.concatStringsSep " " setupPyBuildFlags))} bdist_wheel 66 runHook postBuild 67 ''; 68 69 installCheckPhase = attrs.checkPhase or '' 70 runHook preCheck 71 ${python.interpreter} nix_run_setup.py test 72 runHook postCheck 73 ''; 74 75 # Python packages that are installed with setuptools 76 # are typically distributed with tests. 77 # With Python it's a common idiom to run the tests 78 # after the software has been installed. 79 doCheck = attrs.doCheck or true; 80 } 81 else 82 throw "Unsupported format ${format}"; 83 84in mkPythonDerivation ( attrs // { 85 86 # To build and install a wheel we need pip 87 buildInputs = buildInputs ++ [ bootstrapped-pip ]; 88 89#inherit propagatedBuildInputs; 90 91 configurePhase = attrs.configurePhase or '' 92 runHook preConfigure 93 94 # patch python interpreter to write null timestamps when compiling python files 95 # this way python doesn't try to update them when we freeze timestamps in nix store 96 export DETERMINISTIC_BUILD=1 97 98 runHook postConfigure 99 ''; 100 101 installPhase = attrs.installPhase or '' 102 runHook preInstall 103 104 mkdir -p "$out/${python.sitePackages}" 105 export PYTHONPATH="$out/${python.sitePackages}:$PYTHONPATH" 106 107 pushd dist 108 ${bootstrapped-pip}/bin/pip install *.whl --no-index --prefix=$out --no-cache ${toString installFlags} 109 popd 110 111 runHook postInstall 112 ''; 113 114 shellHook = attrs.shellHook or '' 115 ${preShellHook} 116 if test -e setup.py; then 117 tmp_path=$(mktemp -d) 118 export PATH="$tmp_path/bin:$PATH" 119 export PYTHONPATH="$tmp_path/${python.sitePackages}:$PYTHONPATH" 120 mkdir -p $tmp_path/${python.sitePackages} 121 ${bootstrapped-pip}/bin/pip install -e . --prefix $tmp_path 122 fi 123 ${postShellHook} 124 ''; 125 126} // formatspecific)