From 303e9762451cb347e125197759bd7604a8e319a3 Mon Sep 17 00:00:00 2001 From: Frederik Rietdijk Date: Tue, 26 Apr 2016 17:57:13 +0200 Subject: [PATCH] Python: allow installing wheels By passing `format="wheel"` it is now possible to install a wheel. It's not recommended, but it can be useful. --- doc/languages-frameworks/python.md | 1 + .../python-modules/generic/default.nix | 77 ++++++++++++------- 2 files changed, 51 insertions(+), 27 deletions(-) diff --git a/doc/languages-frameworks/python.md b/doc/languages-frameworks/python.md index 81da5c704395..a04ca75a2fbb 100644 --- a/doc/languages-frameworks/python.md +++ b/doc/languages-frameworks/python.md @@ -534,6 +534,7 @@ All parameters from `mkDerivation` function are still supported. * `postShellHook`: Hook to execute commands after `shellHook`. * `makeWrapperArgs`: A list of strings. Arguments to be passed to `makeWrapper`, which wraps generated binaries. By default, the arguments to `makeWrapper` set `PATH` and `PYTHONPATH` environment variables before calling the binary. Additional arguments here can allow a developer to set environment variables which will be available when the binary is run. For example, `makeWrapperArgs = ["--set FOO BAR" "--set BAZ QUX"]`. * `installFlags`: A list of strings. Arguments to be passed to `pip install`. To pass options to `python setup.py install`, use `--install-option`. E.g., `installFlags=["--install-option='--cpp_implementation'"]. +* `format`: Format of the source. Options are `setup` for when the source has a `setup.py` and `setuptools` is used to build a wheel, and `wheel` in case the source is already a binary wheel. The default value is `setup`. #### `buildPythonApplication` function diff --git a/pkgs/development/python-modules/generic/default.nix b/pkgs/development/python-modules/generic/default.nix index 1fdbd4ffc0bd..b8e1e8cad71b 100644 --- a/pkgs/development/python-modules/generic/default.nix +++ b/pkgs/development/python-modules/generic/default.nix @@ -21,9 +21,6 @@ # https://github.com/pypa/pip/issues/881 , setupPyBuildFlags ? [] -# enable tests by default -, doCheck ? true - # DEPRECATED: use propagatedBuildInputs , pythonPath ? [] @@ -45,6 +42,8 @@ # Additional flags to pass to "pip install". , installFlags ? [] +, format ? "setup" + , ... } @ attrs: @@ -57,8 +56,51 @@ let # use setuptools shim (so that setuptools is imported before distutils) # pip does the same thing: https://github.com/pypa/pip/pull/3265 setuppy = ./run_setup.py; - # For backwards compatibility, let's use an alias - doInstallCheck = doCheck; + + formatspecific = + if format == "wheel" then + { + unpackPhase = '' + mkdir dist + cp $src dist/"''${src#*-}" + ''; + + # Wheels are pre-compiled + buildPhase = attrs.buildPhase or ":"; + installCheckPhase = attrs.checkPhase or ":"; + + # Wheels don't have any checks to run + doInstallCheck = attrs.doCheck or false; + } + else if format == "setup" then + { + # propagate python/setuptools to active setup-hook in nix-shell + propagatedBuildInputs = + propagatedBuildInputs ++ [ python setuptools ]; + + # we copy nix_run_setup.py over so it's executed relative to the root of the source + # many project make that assumption + buildPhase = attrs.buildPhase or '' + runHook preBuild + cp ${setuppy} nix_run_setup.py + ${python.interpreter} nix_run_setup.py ${lib.optionalString (setupPyBuildFlags != []) ("build_ext " + (lib.concatStringsSep " " setupPyBuildFlags))} bdist_wheel + runHook postBuild + ''; + + installCheckPhase = attrs.checkPhase or '' + runHook preCheck + ${python.interpreter} nix_run_setup.py test + runHook postCheck + ''; + + # We run all tests after software has been installed since that is + # a common idiom in Python + # + # For backwards compatibility, let's use an alias + doInstallCheck = attrs.doCheck or false; + } + else + throw "Unsupported format ${format}"; in python.stdenv.mkDerivation (builtins.removeAttrs attrs ["disabled" "doCheck"] // { name = namePrefix + name; @@ -67,9 +109,6 @@ python.stdenv.mkDerivation (builtins.removeAttrs attrs ["disabled" "doCheck"] // ++ [ (ensureNewerSourcesHook { year = "1980"; }) ] ++ (lib.optional (lib.hasSuffix "zip" attrs.src.name or "") unzip); - # propagate python/setuptools to active setup-hook in nix-shell - propagatedBuildInputs = propagatedBuildInputs ++ [ python setuptools ]; - pythonPath = pythonPath; configurePhase = attrs.configurePhase or '' @@ -82,14 +121,8 @@ python.stdenv.mkDerivation (builtins.removeAttrs attrs ["disabled" "doCheck"] // runHook postConfigure ''; - # we copy nix_run_setup.py over so it's executed relative to the root of the source - # many project make that assumption - buildPhase = attrs.buildPhase or '' - runHook preBuild - cp ${setuppy} nix_run_setup.py - ${python.interpreter} nix_run_setup.py ${lib.optionalString (setupPyBuildFlags != []) ("build_ext " + (lib.concatStringsSep " " setupPyBuildFlags))} bdist_wheel - runHook postBuild - ''; + # Python packages don't have a checkPhase, only a installCheckPhase + doCheck = false; installPhase = attrs.installPhase or '' runHook preInstall @@ -104,16 +137,6 @@ python.stdenv.mkDerivation (builtins.removeAttrs attrs ["disabled" "doCheck"] // runHook postInstall ''; - # We run all tests after software has been installed since that is - # a common idiom in Python - doInstallCheck = doInstallCheck; - - installCheckPhase = attrs.checkPhase or '' - runHook preCheck - ${python.interpreter} nix_run_setup.py test - runHook postCheck - ''; - postFixup = attrs.postFixup or '' wrapPythonPrograms @@ -143,4 +166,4 @@ python.stdenv.mkDerivation (builtins.removeAttrs attrs ["disabled" "doCheck"] // # a marker for release utilities to discover python packages isBuildPythonPackage = python.meta.platforms; }; -}) +} // formatspecific)