Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)

Python: separate buildPythonPackage into two functions

1. mkDerivation which is used when the source is without setup.py and
not a wheel
2. buildPythonPackage which is used as before and calls mkDerivation

+219 -177
+1 -1
doc/languages-frameworks/python.md
··· 481 #### `buildPythonPackage` function 482 483 The `buildPythonPackage` function is implemented in 484 - `pkgs/development/interpreters/python/buildpythonpackage.nix` 485 486 and can be used as: 487
··· 481 #### `buildPythonPackage` function 482 483 The `buildPythonPackage` function is implemented in 484 + `pkgs/development/interpreters/python/build-python-package.nix` 485 486 and can be used as: 487
+126
pkgs/development/interpreters/python/build-python-package.nix
···
··· 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 + 38 + let 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 + 84 + in 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)
-174
pkgs/development/interpreters/python/buildpythonpackage.nix
··· 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 - { python, setuptools, unzip, wrapPython, lib, bootstrapped-pip 7 - , ensureNewerSourcesHook }: 8 - 9 - { name 10 - 11 - # by default prefix `name` e.g. "python3.3-${name}" 12 - , namePrefix ? python.libPrefix + "-" 13 - 14 - , buildInputs ? [] 15 - 16 - # propagate build dependencies so in case we have A -> B -> C, 17 - # C can import package A propagated by B 18 - , propagatedBuildInputs ? [] 19 - 20 - # passed to "python setup.py build_ext" 21 - # https://github.com/pypa/pip/issues/881 22 - , setupPyBuildFlags ? [] 23 - 24 - # DEPRECATED: use propagatedBuildInputs 25 - , pythonPath ? [] 26 - 27 - # used to disable derivation, useful for specific python versions 28 - , disabled ? false 29 - 30 - , meta ? {} 31 - 32 - # Execute before shell hook 33 - , preShellHook ? "" 34 - 35 - # Execute after shell hook 36 - , postShellHook ? "" 37 - 38 - # Additional arguments to pass to the makeWrapper function, which wraps 39 - # generated binaries. 40 - , makeWrapperArgs ? [] 41 - 42 - # Additional flags to pass to "pip install". 43 - , installFlags ? [] 44 - 45 - # Raise an error if two packages are installed with the same name 46 - , catchConflicts ? true 47 - 48 - , format ? "setup" 49 - 50 - , ... } @ attrs: 51 - 52 - 53 - # Keep extra attributes from `attrs`, e.g., `patchPhase', etc. 54 - if disabled 55 - then throw "${name} not supported for interpreter ${python.executable}" 56 - else 57 - 58 - let 59 - # use setuptools shim (so that setuptools is imported before distutils) 60 - # pip does the same thing: https://github.com/pypa/pip/pull/3265 61 - setuppy = ./run_setup.py; 62 - 63 - formatspecific = 64 - if format == "wheel" then 65 - { 66 - unpackPhase = '' 67 - mkdir dist 68 - cp $src dist/"''${src#*-}" 69 - ''; 70 - 71 - # Wheels are pre-compiled 72 - buildPhase = attrs.buildPhase or ":"; 73 - installCheckPhase = attrs.checkPhase or ":"; 74 - 75 - # Wheels don't have any checks to run 76 - doInstallCheck = attrs.doCheck or false; 77 - } 78 - else if format == "setup" then 79 - { 80 - # propagate python/setuptools to active setup-hook in nix-shell 81 - propagatedBuildInputs = 82 - propagatedBuildInputs ++ [ python setuptools ]; 83 - 84 - # we copy nix_run_setup.py over so it's executed relative to the root of the source 85 - # many project make that assumption 86 - buildPhase = attrs.buildPhase or '' 87 - runHook preBuild 88 - cp ${setuppy} nix_run_setup.py 89 - ${python.interpreter} nix_run_setup.py ${lib.optionalString (setupPyBuildFlags != []) ("build_ext " + (lib.concatStringsSep " " setupPyBuildFlags))} bdist_wheel 90 - runHook postBuild 91 - ''; 92 - 93 - installCheckPhase = attrs.checkPhase or '' 94 - runHook preCheck 95 - ${python.interpreter} nix_run_setup.py test 96 - runHook postCheck 97 - ''; 98 - 99 - # Python packages that are installed with setuptools 100 - # are typically distributed with tests. 101 - # With Python it's a common idiom to run the tests 102 - # after the software has been installed. 103 - 104 - # For backwards compatibility, let's use an alias 105 - doInstallCheck = attrs.doCheck or true; 106 - } 107 - else 108 - throw "Unsupported format ${format}"; 109 - in 110 - python.stdenv.mkDerivation (builtins.removeAttrs attrs ["disabled" "doCheck"] // { 111 - name = namePrefix + name; 112 - 113 - buildInputs = [ wrapPython bootstrapped-pip ] ++ buildInputs ++ pythonPath 114 - ++ [ (ensureNewerSourcesHook { year = "1980"; }) ] 115 - ++ (lib.optional (lib.hasSuffix "zip" attrs.src.name or "") unzip); 116 - 117 - pythonPath = pythonPath; 118 - 119 - configurePhase = attrs.configurePhase or '' 120 - runHook preConfigure 121 - 122 - # patch python interpreter to write null timestamps when compiling python files 123 - # this way python doesn't try to update them when we freeze timestamps in nix store 124 - export DETERMINISTIC_BUILD=1 125 - 126 - runHook postConfigure 127 - ''; 128 - 129 - # Python packages don't have a checkPhase, only an installCheckPhase 130 - doCheck = false; 131 - 132 - installPhase = attrs.installPhase or '' 133 - runHook preInstall 134 - 135 - mkdir -p "$out/${python.sitePackages}" 136 - export PYTHONPATH="$out/${python.sitePackages}:$PYTHONPATH" 137 - 138 - pushd dist 139 - ${bootstrapped-pip}/bin/pip install *.whl --no-index --prefix=$out --no-cache ${toString installFlags} 140 - popd 141 - 142 - runHook postInstall 143 - ''; 144 - 145 - postFixup = attrs.postFixup or '' 146 - wrapPythonPrograms 147 - '' + lib.optionalString catchConflicts '' 148 - # check if we have two packages with the same name in closure and fail 149 - # this shouldn't happen, something went wrong with dependencies specs 150 - ${python.interpreter} ${./catch_conflicts.py} 151 - ''; 152 - 153 - shellHook = attrs.shellHook or '' 154 - ${preShellHook} 155 - if test -e setup.py; then 156 - tmp_path=$(mktemp -d) 157 - export PATH="$tmp_path/bin:$PATH" 158 - export PYTHONPATH="$tmp_path/${python.sitePackages}:$PYTHONPATH" 159 - mkdir -p $tmp_path/${python.sitePackages} 160 - ${bootstrapped-pip}/bin/pip install -e . --prefix $tmp_path 161 - fi 162 - ${postShellHook} 163 - ''; 164 - 165 - meta = with lib.maintainers; { 166 - # default to python's platforms 167 - platforms = python.meta.platforms; 168 - } // meta // { 169 - # add extra maintainer(s) to every package 170 - maintainers = (meta.maintainers or []) ++ [ chaoflow domenkozar ]; 171 - # a marker for release utilities to discover python packages 172 - isBuildPythonPackage = python.meta.platforms; 173 - }; 174 - } // formatspecific)
···
+87
pkgs/development/interpreters/python/mk-python-derivation.nix
···
··· 1 + /* Generic builder for Python packages that come without a setup.py. */ 2 + 3 + { lib 4 + , python 5 + , wrapPython 6 + , setuptools 7 + , unzip 8 + , ensureNewerSourcesHook 9 + }: 10 + 11 + { name 12 + 13 + # by default prefix `name` e.g. "python3.3-${name}" 14 + , namePrefix ? python.libPrefix + "-" 15 + 16 + , buildInputs ? [] 17 + 18 + # propagate build dependencies so in case we have A -> B -> C, 19 + # C can import package A propagated by B 20 + , propagatedBuildInputs ? [] 21 + 22 + # DEPRECATED: use propagatedBuildInputs 23 + , pythonPath ? [] 24 + 25 + # used to disable derivation, useful for specific python versions 26 + , disabled ? false 27 + 28 + # Raise an error if two packages are installed with the same name 29 + , catchConflicts ? true 30 + 31 + # Additional arguments to pass to the makeWrapper function, which wraps 32 + # generated binaries. 33 + , makeWrapperArgs ? [] 34 + 35 + , meta ? {} 36 + 37 + , passthru ? {} 38 + 39 + , ... } @ attrs: 40 + 41 + 42 + # Keep extra attributes from `attrs`, e.g., `patchPhase', etc. 43 + if disabled 44 + then throw "${name} not supported for interpreter ${python.executable}" 45 + else 46 + 47 + python.stdenv.mkDerivation (builtins.removeAttrs attrs ["disabled"] // { 48 + 49 + name = namePrefix + name; 50 + 51 + inherit pythonPath; 52 + 53 + buildInputs = [ wrapPython ] ++ buildInputs ++ pythonPath 54 + ++ [ (ensureNewerSourcesHook { year = "1980"; }) ] 55 + ++ (lib.optional (lib.hasSuffix "zip" attrs.src.name or "") unzip); 56 + 57 + # propagate python/setuptools to active setup-hook in nix-shell 58 + propagatedBuildInputs = propagatedBuildInputs ++ [ python setuptools ]; 59 + 60 + # Python packages don't have a checkPhase, only an installCheckPhase 61 + doCheck = false; 62 + doInstallCheck = attrs.doCheck or false; 63 + 64 + postFixup = attrs.postFixup or '' 65 + wrapPythonPrograms 66 + '' + lib.optionalString catchConflicts '' 67 + # check if we have two packages with the same name in closure and fail 68 + # this shouldn't happen, something went wrong with dependencies specs 69 + ${python.interpreter} ${./catch_conflicts.py} 70 + ''; 71 + 72 + passthru = { 73 + inherit python; # The python interpreter 74 + } // passthru; 75 + 76 + meta = with lib.maintainers; { 77 + # default to python's platforms 78 + platforms = python.meta.platforms; 79 + } // meta // { 80 + # add extra maintainer(s) to every package 81 + maintainers = (meta.maintainers or []) ++ [ chaoflow domenkozar ]; 82 + # a marker for release utilities to discover python packages 83 + isBuildPythonPackage = python.meta.platforms; 84 + }; 85 + }) 86 + 87 +
+5 -2
pkgs/top-level/python-packages.nix
··· 18 19 bootstrapped-pip = callPackage ../development/python-modules/bootstrapped-pip { }; 20 21 - buildPythonPackage = makeOverridable (callPackage ../development/interpreters/python/buildpythonpackage.nix { 22 inherit bootstrapped-pip; 23 }); 24 ··· 34 35 in modules // { 36 37 - inherit python bootstrapped-pip isPy26 isPy27 isPy33 isPy34 isPy35 isPy36 isPyPy isPy3k buildPythonPackage buildPythonApplication; 38 39 # helpers 40
··· 18 19 bootstrapped-pip = callPackage ../development/python-modules/bootstrapped-pip { }; 20 21 + mkPythonDerivation = makeOverridable( callPackage ../development/interpreters/python/mk-python-derivation.nix { 22 + }); 23 + buildPythonPackage = makeOverridable (callPackage ../development/interpreters/python/build-python-package.nix { 24 + inherit mkPythonDerivation; 25 inherit bootstrapped-pip; 26 }); 27 ··· 37 38 in modules // { 39 40 + inherit python bootstrapped-pip isPy26 isPy27 isPy33 isPy34 isPy35 isPy36 isPyPy isPy3k mkPythonDerivation buildPythonPackage buildPythonApplication; 41 42 # helpers 43