nixpkgs/pkgs/development/python-modules/generic/default.nix
Domen Kožar bf5d6fb9b1 Refactor buildPythonPackage to modularize building process.
Before we used `easy_install` command to handle installation
in one shot, now this is split into two phases:

 - buildPhase: python setup.py build
 - installPhase: python setup.py install

Each of those commands have the ability to pass extra
parameters through buildPythonPackage parameters as
`setupPyInstallFlags` and `setupPyBuildFlags`.

Phases now correctly execute post/pre hooks.

In configurePhase we inject setuptools dependency before distutils
is imported to apply monkeypatching by setuptools that is needed
for special features to apply.

We don't have to reorder default phases anymore, as test
phase comes after build and that works.

I rewrote offineDistutils into distutils-cfg with a bit cleaner
syntax and ability to specify extraCfg to the config file.

Plone packages are failing and garbas said he will adopt them to
the new functions. The rest of the packages I fixed and these commits
shouldn't break any package (according to my testings) and they introduce
16 new jobs and fix 38 that were broken before.
2014-02-20 01:19:15 +01:00

140 lines
4.4 KiB
Nix

/* This function provides a generic Python package builder. It is
intended to work with packages that use `distutils/setuptools'
(http://pypi.python.org/pypi/setuptools/), which represents a large
number of Python packages nowadays. */
{ python, setuptools, wrapPython, lib, recursivePthLoader, distutils-cfg }:
{ name
# by default prefix name with python version name, e.g. "python3.3-"
, namePrefix ? python.libPrefix + "-"
, buildInputs ? []
# TODO: document
, distutilsExtraCfg ? ""
# TODO: say what it does
, propagatedBuildInputs ? []
# passed to "python setup.py install"
, setupPyInstallFlags ? []
# passed to "python setup.py build"
, setupPyBuildFlags ? []
# enable tests by default
, doCheck ? true
# List of packages that should be added to the PYTHONPATH
# environment variable in programs built by this function. Packages
# in the standard `propagatedBuildInputs' variable are also added.
# The difference is that `pythonPath' is not propagated to the user
# environment. This is preferrable for programs because it doesn't
# pollute the user environment.
, pythonPath ? []
, meta ? {}
, ... } @ attrs:
# Keep extra attributes from `attrs`, e.g., `patchPhase', etc.
python.stdenv.mkDerivation (attrs // {
inherit doCheck;
name = namePrefix + name;
buildInputs = [ python wrapPython setuptools (distutils-cfg.override { extraCfg = distutilsExtraCfg; }) ] ++ buildInputs ++ pythonPath;
propagatedBuildInputs = propagatedBuildInputs ++ [ recursivePthLoader ];
pythonPath = [ setuptools ] ++ pythonPath;
configurePhase = attrs.configurePhase or ''
runHook preConfigure
# TODO: document
export DETERMINISTIC_BUILD=1
# we need to prepend following line to monkeypatch distutils commands
sed -i '0,/import distutils/s//import setuptools;import distutils/' setup.py
sed -i '0,/from distutils/s//import setuptools;from distutils/' setup.py
runHook postConfigure
'';
checkPhase = attrs.checkPhase or ''
runHook preCheck
${python}/bin/${python.executable} setup.py test -q
runHook postCheck
'';
buildPhase = attrs.buildPhase or ''
runHook preBuild
${python}/bin/${python.executable} setup.py build ${lib.concatStringsSep " " setupPyBuildFlags}
runHook postBuild
'';
installPhase = attrs.installPhase or ''
runHook preInstall
mkdir -p "$out/lib/${python.libPrefix}/site-packages"
export PYTHONPATH="$out/lib/${python.libPrefix}/site-packages:$PYTHONPATH"
${python}/bin/${python.executable} setup.py install --install-lib=$out/lib/${python.libPrefix}/site-packages \
--prefix="$out" ${lib.concatStringsSep " " setupPyInstallFlags}
# A pth file might have been generated to load the package from
# within its own site-packages, rename this package not to
# collide with others.
eapth="$out/lib/${python.libPrefix}"/site-packages/easy-install.pth
if [ -e "$eapth" ]; then
# move colliding easy_install.pth to specifically named one
mv "$eapth" $(dirname "$eapth")/${name}.pth
fi
# Remove any site.py files generated by easy_install as these
# cause collisions. If pth files are to be processed a
# corresponding site.py needs to be included in the PYTHONPATH.
rm -f "$out/lib/${python.libPrefix}"/site-packages/site.py*
runHook postInstall
'';
postFixup =
''
wrapPythonPrograms
# If a user installs a Python package, they probably also wants its
# dependencies in the user environment (since Python modules don't
# have something like an RPATH, so the only way to find the
# dependencies is to have them in the PYTHONPATH variable).
# TODO: better docs
if test -e $out/nix-support/propagated-build-inputs; then
ln -s $out/nix-support/propagated-build-inputs $out/nix-support/propagated-user-env-packages
fi
createBuildInputsPth build-inputs "$buildInputStrings"
for inputsfile in propagated-build-inputs propagated-native-build-inputs; do
if test -e $out/nix-support/$inputsfile; then
createBuildInputsPth $inputsfile "$(cat $out/nix-support/$inputsfile)"
fi
done
'';
meta = {
# default to python's platforms
platforms = python.meta.platforms;
} // meta // {
# add extra maintainer(s) to every package
maintainers = (meta.maintainers or []) ++ [ lib.maintainers.chaoflow lib.maintainers.iElectric ];
};
})