treewide: format all inactive Nix files

After final improvements to the official formatter implementation,
this commit now performs the first treewide reformat of Nix files using it.
This is part of the implementation of RFC 166.

Only "inactive" files are reformatted, meaning only files that
aren't being touched by any PR with activity in the past 2 months.
This is to avoid conflicts for PRs that might soon be merged.
Later we can do a full treewide reformat to get the rest,
which should not cause as many conflicts.

A CI check has already been running for some time to ensure that new and
already-formatted files are formatted, so the files being reformatted here
should also stay formatted.

This commit was automatically created and can be verified using

    nix-build https://github.com/infinisil/treewide-nixpkgs-reformat-script/archive/a08b3a4d199c6124ac5b36a889d9099b4383463f.tar.gz \
      --argstr baseRev b32a094368
    result/bin/apply-formatting $NIXPKGS_PATH
This commit is contained in:
Silvan Mosberger
2024-12-10 20:26:33 +01:00
parent b32a094368
commit 4f0dadbf38
21293 changed files with 701276 additions and 428232 deletions
@@ -1,25 +1,29 @@
{ pkgs }: {
{ pkgs }:
{
# List of libraries that are needed for conda binary packages.
# When installing a conda binary package, just extend
# the `buildInputs` with `condaAutopatchLibs`.
condaPatchelfLibs = builtins.map (p: p.lib or p) ([
pkgs.alsa-lib
pkgs.cups
pkgs.gcc-unwrapped
pkgs.libGL
] ++ (with pkgs.xorg; [
libSM
libICE
libX11
libXau
libXdamage
libXi
libXrender
libXrandr
libXcomposite
libXcursor
libXtst
libXScrnSaver])
condaPatchelfLibs = builtins.map (p: p.lib or p) (
[
pkgs.alsa-lib
pkgs.cups
pkgs.gcc-unwrapped
pkgs.libGL
]
++ (with pkgs.xorg; [
libSM
libICE
libX11
libXau
libXdamage
libXi
libXrender
libXrandr
libXcomposite
libXcursor
libXtst
libXScrnSaver
])
);
}
@@ -1,6 +1,10 @@
# This file was generated and will be overwritten by ./generate.sh
{ stdenv, lib, fetchurl }:
{
stdenv,
lib,
fetchurl,
}:
stdenv.mkDerivation {
pname = "python310-docs-texinfo";
@@ -1,4 +1,5 @@
self: dontUse: with self;
self: dontUse:
with self;
let
inherit (python) pythonOnBuildForHost;
@@ -7,180 +8,257 @@ let
pythonSitePackages = python.sitePackages;
pythonCheckInterpreter = python.interpreter;
setuppy = ../run_setup.py;
in {
makePythonHook = let
defaultArgs = { passthru.provides.setupHook = true; };
in args: pkgs.makeSetupHook (lib.recursiveUpdate defaultArgs args);
in
{
makePythonHook =
let
defaultArgs = {
passthru.provides.setupHook = true;
};
in
args: pkgs.makeSetupHook (lib.recursiveUpdate defaultArgs args);
condaInstallHook = callPackage ({ makePythonHook, gnutar, lbzip2 }:
condaInstallHook = callPackage (
{
makePythonHook,
gnutar,
lbzip2,
}:
makePythonHook {
name = "conda-install-hook";
propagatedBuildInputs = [ gnutar lbzip2 ];
propagatedBuildInputs = [
gnutar
lbzip2
];
substitutions = {
inherit pythonSitePackages;
};
} ./conda-install-hook.sh) {};
} ./conda-install-hook.sh
) { };
condaUnpackHook = callPackage ({ makePythonHook }:
condaUnpackHook = callPackage (
{ makePythonHook }:
makePythonHook {
name = "conda-unpack-hook";
propagatedBuildInputs = [];
} ./conda-unpack-hook.sh) {};
propagatedBuildInputs = [ ];
} ./conda-unpack-hook.sh
) { };
eggBuildHook = callPackage ({ makePythonHook }:
eggBuildHook = callPackage (
{ makePythonHook }:
makePythonHook {
name = "egg-build-hook.sh";
propagatedBuildInputs = [ ];
} ./egg-build-hook.sh) {};
} ./egg-build-hook.sh
) { };
eggInstallHook = callPackage ({ makePythonHook, setuptools }:
eggInstallHook = callPackage (
{ makePythonHook, setuptools }:
makePythonHook {
name = "egg-install-hook.sh";
propagatedBuildInputs = [ setuptools ];
substitutions = {
inherit pythonInterpreter pythonSitePackages;
};
} ./egg-install-hook.sh) {};
} ./egg-install-hook.sh
) { };
eggUnpackHook = callPackage ({ makePythonHook, }:
eggUnpackHook = callPackage (
{ makePythonHook }:
makePythonHook {
name = "egg-unpack-hook.sh";
propagatedBuildInputs = [ ];
} ./egg-unpack-hook.sh) {};
} ./egg-unpack-hook.sh
) { };
pipBuildHook = callPackage ({ makePythonHook, pip, wheel }:
pipBuildHook = callPackage (
{
makePythonHook,
pip,
wheel,
}:
makePythonHook {
name = "pip-build-hook.sh";
propagatedBuildInputs = [ pip wheel ];
propagatedBuildInputs = [
pip
wheel
];
substitutions = {
inherit pythonInterpreter pythonSitePackages;
};
} ./pip-build-hook.sh) {};
} ./pip-build-hook.sh
) { };
pypaBuildHook = callPackage ({ makePythonHook, build, wheel }:
makePythonHook {
name = "pypa-build-hook.sh";
propagatedBuildInputs = [ wheel ];
substitutions = {
inherit build;
pypaBuildHook =
callPackage
(
{
makePythonHook,
build,
wheel,
}:
makePythonHook {
name = "pypa-build-hook.sh";
propagatedBuildInputs = [ wheel ];
substitutions = {
inherit build;
};
# A test to ensure that this hook never propagates any of its dependencies
# into the build environment.
# This prevents false positive alerts raised by catchConflictsHook.
# Such conflicts don't happen within the standard nixpkgs python package
# set, but in downstream projects that build packages depending on other
# versions of this hook's dependencies.
passthru.tests = callPackage ./pypa-build-hook-test.nix {
inherit pythonOnBuildForHost;
};
} ./pypa-build-hook.sh
)
{
inherit (pythonOnBuildForHost.pkgs) build;
};
# A test to ensure that this hook never propagates any of its dependencies
# into the build environment.
# This prevents false positive alerts raised by catchConflictsHook.
# Such conflicts don't happen within the standard nixpkgs python package
# set, but in downstream projects that build packages depending on other
# versions of this hook's dependencies.
passthru.tests = callPackage ./pypa-build-hook-test.nix {
inherit pythonOnBuildForHost;
};
} ./pypa-build-hook.sh) {
inherit (pythonOnBuildForHost.pkgs) build;
};
pipInstallHook = callPackage ({ makePythonHook, pip }:
pipInstallHook = callPackage (
{ makePythonHook, pip }:
makePythonHook {
name = "pip-install-hook";
propagatedBuildInputs = [ pip ];
substitutions = {
inherit pythonInterpreter pythonSitePackages;
};
} ./pip-install-hook.sh) {};
} ./pip-install-hook.sh
) { };
pypaInstallHook = callPackage ({ makePythonHook, installer }:
makePythonHook {
name = "pypa-install-hook";
propagatedBuildInputs = [ installer ];
substitutions = {
inherit pythonInterpreter pythonSitePackages;
pypaInstallHook =
callPackage
(
{ makePythonHook, installer }:
makePythonHook {
name = "pypa-install-hook";
propagatedBuildInputs = [ installer ];
substitutions = {
inherit pythonInterpreter pythonSitePackages;
};
} ./pypa-install-hook.sh
)
{
inherit (pythonOnBuildForHost.pkgs) installer;
};
} ./pypa-install-hook.sh) {
inherit (pythonOnBuildForHost.pkgs) installer;
};
pytestCheckHook = callPackage ({ makePythonHook, pytest }:
pytestCheckHook = callPackage (
{ makePythonHook, pytest }:
makePythonHook {
name = "pytest-check-hook";
propagatedBuildInputs = [ pytest ];
substitutions = {
inherit pythonCheckInterpreter;
};
} ./pytest-check-hook.sh) {};
} ./pytest-check-hook.sh
) { };
pythonCatchConflictsHook = callPackage ({ makePythonHook, setuptools }:
pythonCatchConflictsHook = callPackage (
{ makePythonHook, setuptools }:
makePythonHook {
name = "python-catch-conflicts-hook";
substitutions = let
useLegacyHook = lib.versionOlder python.pythonVersion "3";
in {
inherit pythonInterpreter pythonSitePackages;
catchConflicts = if useLegacyHook then
../catch_conflicts/catch_conflicts_py2.py
else
../catch_conflicts/catch_conflicts.py;
} // lib.optionalAttrs useLegacyHook {
inherit setuptools;
};
substitutions =
let
useLegacyHook = lib.versionOlder python.pythonVersion "3";
in
{
inherit pythonInterpreter pythonSitePackages;
catchConflicts =
if useLegacyHook then
../catch_conflicts/catch_conflicts_py2.py
else
../catch_conflicts/catch_conflicts.py;
}
// lib.optionalAttrs useLegacyHook {
inherit setuptools;
};
passthru.tests = import ./python-catch-conflicts-hook-tests.nix {
inherit pythonOnBuildForHost runCommand;
inherit lib;
inherit (pkgs) coreutils gnugrep writeShellScript;
};
} ./python-catch-conflicts-hook.sh) {};
} ./python-catch-conflicts-hook.sh
) { };
pythonImportsCheckHook = callPackage ({ makePythonHook }:
pythonImportsCheckHook = callPackage (
{ makePythonHook }:
makePythonHook {
name = "python-imports-check-hook.sh";
substitutions = {
inherit pythonCheckInterpreter pythonSitePackages;
};
} ./python-imports-check-hook.sh) {};
} ./python-imports-check-hook.sh
) { };
pythonNamespacesHook = callPackage ({ makePythonHook, buildPackages }:
pythonNamespacesHook = callPackage (
{ makePythonHook, buildPackages }:
makePythonHook {
name = "python-namespaces-hook.sh";
substitutions = {
inherit pythonSitePackages;
inherit (buildPackages) findutils;
};
} ./python-namespaces-hook.sh) {};
} ./python-namespaces-hook.sh
) { };
pythonOutputDistHook = callPackage ({ makePythonHook }:
pythonOutputDistHook = callPackage (
{ makePythonHook }:
makePythonHook {
name = "python-output-dist-hook";
} ./python-output-dist-hook.sh ) {};
} ./python-output-dist-hook.sh
) { };
pythonRecompileBytecodeHook = callPackage ({ makePythonHook }:
pythonRecompileBytecodeHook = callPackage (
{ makePythonHook }:
makePythonHook {
name = "python-recompile-bytecode-hook";
substitutions = {
inherit pythonInterpreter pythonSitePackages;
compileArgs = lib.concatStringsSep " " (["-q" "-f" "-i -"] ++ lib.optionals isPy3k ["-j $NIX_BUILD_CORES"]);
compileArgs = lib.concatStringsSep " " (
[
"-q"
"-f"
"-i -"
]
++ lib.optionals isPy3k [ "-j $NIX_BUILD_CORES" ]
);
bytecodeName = if isPy3k then "__pycache__" else "*.pyc";
};
} ./python-recompile-bytecode-hook.sh ) {};
} ./python-recompile-bytecode-hook.sh
) { };
pythonRelaxDepsHook = callPackage ({ makePythonHook, wheel }:
pythonRelaxDepsHook = callPackage (
{ makePythonHook, wheel }:
makePythonHook {
name = "python-relax-deps-hook";
substitutions = {
inherit pythonInterpreter pythonSitePackages wheel;
};
} ./python-relax-deps-hook.sh) {};
} ./python-relax-deps-hook.sh
) { };
pythonRemoveBinBytecodeHook = callPackage ({ makePythonHook }:
pythonRemoveBinBytecodeHook = callPackage (
{ makePythonHook }:
makePythonHook {
name = "python-remove-bin-bytecode-hook";
} ./python-remove-bin-bytecode-hook.sh) {};
} ./python-remove-bin-bytecode-hook.sh
) { };
pythonRemoveTestsDirHook = callPackage ({ makePythonHook }:
pythonRemoveTestsDirHook = callPackage (
{ makePythonHook }:
makePythonHook {
name = "python-remove-tests-dir-hook";
substitutions = {
inherit pythonSitePackages;
};
} ./python-remove-tests-dir-hook.sh) {};
} ./python-remove-tests-dir-hook.sh
) { };
pythonRuntimeDepsCheckHook = callPackage ({ makePythonHook, packaging }:
pythonRuntimeDepsCheckHook = callPackage (
{ makePythonHook, packaging }:
makePythonHook {
name = "python-runtime-deps-check-hook.sh";
propagatedBuildInputs = [ packaging ];
@@ -188,66 +266,91 @@ in {
inherit pythonInterpreter pythonSitePackages;
hook = ./python-runtime-deps-check-hook.py;
};
} ./python-runtime-deps-check-hook.sh) {};
} ./python-runtime-deps-check-hook.sh
) { };
setuptoolsBuildHook = callPackage ({ makePythonHook, setuptools, wheel }:
setuptoolsBuildHook = callPackage (
{
makePythonHook,
setuptools,
wheel,
}:
makePythonHook {
name = "setuptools-build-hook";
propagatedBuildInputs = [ setuptools wheel ];
propagatedBuildInputs = [
setuptools
wheel
];
substitutions = {
inherit pythonInterpreter setuppy;
# python2.pkgs.setuptools does not support parallelism
setuptools_has_parallel = setuptools != null && lib.versionAtLeast setuptools.version "69";
};
} ./setuptools-build-hook.sh) {};
} ./setuptools-build-hook.sh
) { };
setuptoolsCheckHook = throw "The setuptoolsCheckHook has been removed, since the test command has been removed in setuptools 72.0";
setuptoolsRustBuildHook = callPackage ({ makePythonHook, setuptools-rust }:
makePythonHook {
name = "setuptools-rust-setup-hook";
propagatedBuildInputs = [ setuptools-rust ];
substitutions = {
pyLibDir = "${python}/lib/${python.libPrefix}";
cargoBuildTarget = stdenv.hostPlatform.rust.rustcTargetSpec;
cargoLinkerVar = stdenv.hostPlatform.rust.cargoEnvVarTarget;
targetLinker = "${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc";
};
} ./setuptools-rust-hook.sh) {};
setuptoolsRustBuildHook = callPackage (
{ makePythonHook, setuptools-rust }:
makePythonHook {
name = "setuptools-rust-setup-hook";
propagatedBuildInputs = [ setuptools-rust ];
substitutions = {
pyLibDir = "${python}/lib/${python.libPrefix}";
cargoBuildTarget = stdenv.hostPlatform.rust.rustcTargetSpec;
cargoLinkerVar = stdenv.hostPlatform.rust.cargoEnvVarTarget;
targetLinker = "${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc";
};
} ./setuptools-rust-hook.sh
) { };
unittestCheckHook = callPackage ({ makePythonHook }:
unittestCheckHook = callPackage (
{ makePythonHook }:
makePythonHook {
name = "unittest-check-hook";
substitutions = {
inherit pythonCheckInterpreter;
};
} ./unittest-check-hook.sh) {};
} ./unittest-check-hook.sh
) { };
venvShellHook = disabledIf (!isPy3k) (callPackage ({ makePythonHook, ensureNewerSourcesForZipFilesHook }:
makePythonHook {
name = "venv-shell-hook";
propagatedBuildInputs = [ ensureNewerSourcesForZipFilesHook ];
substitutions = {
inherit pythonInterpreter;
};
} ./venv-shell-hook.sh) {});
venvShellHook = disabledIf (!isPy3k) (
callPackage (
{ makePythonHook, ensureNewerSourcesForZipFilesHook }:
makePythonHook {
name = "venv-shell-hook";
propagatedBuildInputs = [ ensureNewerSourcesForZipFilesHook ];
substitutions = {
inherit pythonInterpreter;
};
} ./venv-shell-hook.sh
) { }
);
wheelUnpackHook = callPackage ({ makePythonHook, wheel }:
wheelUnpackHook = callPackage (
{ makePythonHook, wheel }:
makePythonHook {
name = "wheel-unpack-hook.sh";
propagatedBuildInputs = [ wheel ];
} ./wheel-unpack-hook.sh) {};
} ./wheel-unpack-hook.sh
) { };
wrapPython = callPackage ../wrap-python.nix {
inherit (pkgs.buildPackages) makeWrapper;
};
sphinxHook = callPackage ({ makePythonHook, installShellFiles }:
sphinxHook = callPackage (
{ makePythonHook, installShellFiles }:
makePythonHook {
name = "python${python.pythonVersion}-sphinx-hook";
propagatedBuildInputs = [ pythonOnBuildForHost.pkgs.sphinx installShellFiles ];
propagatedBuildInputs = [
pythonOnBuildForHost.pkgs.sphinx
installShellFiles
];
substitutions = {
sphinxBuild = "${pythonOnBuildForHost.pkgs.sphinx}/bin/sphinx-build";
};
} ./sphinx-hook.sh) {};
} ./sphinx-hook.sh
) { };
}
@@ -1,19 +1,21 @@
{ pythonOnBuildForHost, runCommand }: {
dont-propagate-conflicting-deps = let
# customize a package so that its store paths differs
mkConflict = pkg: pkg.overrideAttrs { some_modification = true; };
# minimal pyproject.toml for the example project
pyprojectToml = builtins.toFile "pyproject.toml" ''
[project]
name = "my-project"
version = "1.0.0"
'';
# the source of the example project
projectSource = runCommand "my-project-source" {} ''
mkdir -p $out/src/my_project
cp ${pyprojectToml} $out/pyproject.toml
touch $out/src/my_project/__init__.py
'';
{ pythonOnBuildForHost, runCommand }:
{
dont-propagate-conflicting-deps =
let
# customize a package so that its store paths differs
mkConflict = pkg: pkg.overrideAttrs { some_modification = true; };
# minimal pyproject.toml for the example project
pyprojectToml = builtins.toFile "pyproject.toml" ''
[project]
name = "my-project"
version = "1.0.0"
'';
# the source of the example project
projectSource = runCommand "my-project-source" { } ''
mkdir -p $out/src/my_project
cp ${pyprojectToml} $out/pyproject.toml
touch $out/src/my_project/__init__.py
'';
in
# this build must never triger conflicts
pythonOnBuildForHost.pkgs.buildPythonPackage {
@@ -1,4 +1,12 @@
{ lib, pythonOnBuildForHost, runCommand, writeShellScript, coreutils, gnugrep }: let
{
lib,
pythonOnBuildForHost,
runCommand,
writeShellScript,
coreutils,
gnugrep,
}:
let
pythonPkgs = pythonOnBuildForHost.pkgs;
@@ -8,52 +16,61 @@
customize = pkg: pkg.overrideAttrs { some_modification = true; };
# generates minimal pyproject.toml
pyprojectToml = pname: builtins.toFile "pyproject.toml" ''
[project]
name = "${pname}"
version = "1.0.0"
'';
pyprojectToml =
pname:
builtins.toFile "pyproject.toml" ''
[project]
name = "${pname}"
version = "1.0.0"
'';
# generates source for a python project
projectSource = pname: runCommand "my-project-source" {} ''
mkdir -p $out/src
cp ${pyprojectToml pname} $out/pyproject.toml
touch $out/src/__init__.py
'';
projectSource =
pname:
runCommand "my-project-source" { } ''
mkdir -p $out/src
cp ${pyprojectToml pname} $out/pyproject.toml
touch $out/src/__init__.py
'';
# helper to reduce boilerplate
generatePythonPackage = args: pythonPkgs.buildPythonPackage (
{
version = "1.0.0";
src = runCommand "my-project-source" {} ''
mkdir -p $out/src
cp ${pyprojectToml args.pname} $out/pyproject.toml
touch $out/src/__init__.py
'';
pyproject = true;
catchConflicts = true;
buildInputs = [ pythonPkgs.setuptools ];
}
// args
);
generatePythonPackage =
args:
pythonPkgs.buildPythonPackage (
{
version = "1.0.0";
src = runCommand "my-project-source" { } ''
mkdir -p $out/src
cp ${pyprojectToml args.pname} $out/pyproject.toml
touch $out/src/__init__.py
'';
pyproject = true;
catchConflicts = true;
buildInputs = [ pythonPkgs.setuptools ];
}
// args
);
# in order to test for a failing build, wrap it in a shell script
expectFailure = build: errorMsg: lib.overrideDerivation build (old: {
builder = writeShellScript "test-for-failure" ''
export PATH=${coreutils}/bin:${gnugrep}/bin:$PATH
${old.builder} "$@" > ./log 2>&1
status=$?
cat ./log
if [ $status -eq 0 ] || ! grep -q "${errorMsg}" ./log; then
echo "The build should have failed with '${errorMsg}', but it didn't"
exit 1
else
echo "The build failed as expected with: ${errorMsg}"
mkdir -p $out
fi
'';
});
in {
expectFailure =
build: errorMsg:
lib.overrideDerivation build (old: {
builder = writeShellScript "test-for-failure" ''
export PATH=${coreutils}/bin:${gnugrep}/bin:$PATH
${old.builder} "$@" > ./log 2>&1
status=$?
cat ./log
if [ $status -eq 0 ] || ! grep -q "${errorMsg}" ./log; then
echo "The build should have failed with '${errorMsg}', but it didn't"
exit 1
else
echo "The build failed as expected with: ${errorMsg}"
mkdir -p $out
fi
'';
});
in
{
### TEST CASES
@@ -61,55 +78,53 @@ in {
# This derivation has runtime dependencies on custom versions of multiple build tools.
# This scenario is relevant for lang2nix tools which do not override the nixpkgs fix-point.
# see https://github.com/NixOS/nixpkgs/issues/283695
ignores-build-time-deps =
generatePythonPackage {
pname = "ignores-build-time-deps";
buildInputs = [
pythonPkgs.build
pythonPkgs.packaging
pythonPkgs.setuptools
pythonPkgs.wheel
];
propagatedBuildInputs = [
# Add customized versions of build tools as runtime deps
(customize pythonPkgs.packaging)
(customize pythonPkgs.setuptools)
(customize pythonPkgs.wheel)
];
};
ignores-build-time-deps = generatePythonPackage {
pname = "ignores-build-time-deps";
buildInputs = [
pythonPkgs.build
pythonPkgs.packaging
pythonPkgs.setuptools
pythonPkgs.wheel
];
propagatedBuildInputs = [
# Add customized versions of build tools as runtime deps
(customize pythonPkgs.packaging)
(customize pythonPkgs.setuptools)
(customize pythonPkgs.wheel)
];
};
# multi-output derivation with dependency on itself must not crash
cyclic-dependencies =
generatePythonPackage {
pname = "cyclic-dependencies";
preFixup = ''
propagatedBuildInputs+=("$out")
'';
};
cyclic-dependencies = generatePythonPackage {
pname = "cyclic-dependencies";
preFixup = ''
propagatedBuildInputs+=("$out")
'';
};
# Simplest test case that should trigger a conflict
catches-simple-conflict = let
# this build must fail due to conflicts
package = pythonPkgs.buildPythonPackage rec {
pname = "catches-simple-conflict";
version = "0.0.0";
src = projectSource pname;
pyproject = true;
catchConflicts = true;
buildInputs = [
pythonPkgs.setuptools
];
# depend on two different versions of packaging
# (an actual runtime dependency conflict)
propagatedBuildInputs = [
pythonPkgs.packaging
(customize pythonPkgs.packaging)
];
};
in
catches-simple-conflict =
let
# this build must fail due to conflicts
package = pythonPkgs.buildPythonPackage rec {
pname = "catches-simple-conflict";
version = "0.0.0";
src = projectSource pname;
pyproject = true;
catchConflicts = true;
buildInputs = [
pythonPkgs.setuptools
];
# depend on two different versions of packaging
# (an actual runtime dependency conflict)
propagatedBuildInputs = [
pythonPkgs.packaging
(customize pythonPkgs.packaging)
];
};
in
expectFailure package "Found duplicated packages in closure for dependency 'packaging'";
/*
More complex test case with a transitive conflict
@@ -121,27 +136,31 @@ in {
dep2
leaf (customized version -> conflicting)
*/
catches-transitive-conflict = let
# package depending on both dependency1 and dependency2
toplevel = generatePythonPackage {
pname = "catches-transitive-conflict";
propagatedBuildInputs = [ dep1 dep2 ];
};
# dep1 package depending on leaf
dep1 = generatePythonPackage {
pname = "dependency1";
propagatedBuildInputs = [ leaf ];
};
# dep2 package depending on conflicting version of leaf
dep2 = generatePythonPackage {
pname = "dependency2";
propagatedBuildInputs = [ (customize leaf) ];
};
# some leaf package
leaf = generatePythonPackage {
pname = "leaf";
};
in
catches-transitive-conflict =
let
# package depending on both dependency1 and dependency2
toplevel = generatePythonPackage {
pname = "catches-transitive-conflict";
propagatedBuildInputs = [
dep1
dep2
];
};
# dep1 package depending on leaf
dep1 = generatePythonPackage {
pname = "dependency1";
propagatedBuildInputs = [ leaf ];
};
# dep2 package depending on conflicting version of leaf
dep2 = generatePythonPackage {
pname = "dependency2";
propagatedBuildInputs = [ (customize leaf) ];
};
# some leaf package
leaf = generatePythonPackage {
pname = "leaf";
};
in
expectFailure toplevel "Found duplicated packages in closure for dependency 'leaf'";
/*
@@ -158,31 +177,36 @@ in {
dep3
leaf (customized version -> conflicting)
*/
catches-conflict-multiple-chains = let
# package depending on dependency1, dependency2 and dependency3
toplevel = generatePythonPackage {
pname = "catches-conflict-multiple-chains";
propagatedBuildInputs = [ dep1 dep2 dep3 ];
};
# dep1 package depending on leaf
dep1 = generatePythonPackage {
pname = "dependency1";
propagatedBuildInputs = [ leaf ];
};
# dep2 package depending on leaf
dep2 = generatePythonPackage {
pname = "dependency2";
propagatedBuildInputs = [ leaf ];
};
# dep3 package depending on conflicting version of leaf
dep3 = generatePythonPackage {
pname = "dependency3";
propagatedBuildInputs = [ (customize leaf) ];
};
# some leaf package
leaf = generatePythonPackage {
pname = "leaf";
};
in
catches-conflict-multiple-chains =
let
# package depending on dependency1, dependency2 and dependency3
toplevel = generatePythonPackage {
pname = "catches-conflict-multiple-chains";
propagatedBuildInputs = [
dep1
dep2
dep3
];
};
# dep1 package depending on leaf
dep1 = generatePythonPackage {
pname = "dependency1";
propagatedBuildInputs = [ leaf ];
};
# dep2 package depending on leaf
dep2 = generatePythonPackage {
pname = "dependency2";
propagatedBuildInputs = [ leaf ];
};
# dep3 package depending on conflicting version of leaf
dep3 = generatePythonPackage {
pname = "dependency3";
propagatedBuildInputs = [ (customize leaf) ];
};
# some leaf package
leaf = generatePythonPackage {
pname = "leaf";
};
in
expectFailure toplevel "Found duplicated packages in closure for dependency 'leaf'";
}
@@ -2,75 +2,87 @@
let
# Create a derivation that links all desired manylinux libraries
createManyLinuxPackage = name: libs: let
drvs = lib.unique (lib.attrValues libs);
names = lib.attrNames libs;
in pkgs.runCommand name {
buildInputs = drvs;
} ''
mkdir -p $out/lib
num_found=0
createManyLinuxPackage =
name: libs:
let
drvs = lib.unique (lib.attrValues libs);
names = lib.attrNames libs;
in
pkgs.runCommand name
{
buildInputs = drvs;
}
''
mkdir -p $out/lib
num_found=0
IFS=:
export DESIRED_LIBRARIES=${lib.concatStringsSep ":" names}
export LIBRARY_PATH=${lib.makeLibraryPath drvs}
for desired in $DESIRED_LIBRARIES; do
for path in $LIBRARY_PATH; do
if [ -e $path/$desired ]; then
echo "FOUND $path/$desired"
ln -s $path/$desired $out/lib/$desired
num_found=$((num_found+1))
break
IFS=:
export DESIRED_LIBRARIES=${lib.concatStringsSep ":" names}
export LIBRARY_PATH=${lib.makeLibraryPath drvs}
for desired in $DESIRED_LIBRARIES; do
for path in $LIBRARY_PATH; do
if [ -e $path/$desired ]; then
echo "FOUND $path/$desired"
ln -s $path/$desired $out/lib/$desired
num_found=$((num_found+1))
break
fi
done
done
num_desired=${toString (lib.length names)}
echo "Found $num_found of $num_desired libraries"
if [ "$num_found" -ne "$num_desired" ]; then
echo "Error: not all desired libraries were found"
exit 1
fi
done
done
num_desired=${toString (lib.length names)}
echo "Found $num_found of $num_desired libraries"
if [ "$num_found" -ne "$num_desired" ]; then
echo "Error: not all desired libraries were found"
exit 1
fi
'';
'';
getLibOutputs = lib.mapAttrs (k: v: lib.getLib v);
# https://www.python.org/dev/peps/pep-0599/
manylinux2014Libs = getLibOutputs(with pkgs; {
"libgcc_s.so.1" = glibc;
"libstdc++.so.6" = stdenv.cc.cc;
"libm.so.6" = glibc;
"libdl.so.2" = glibc;
"librt.so.1" = glibc;
"libc.so.6" = glibc;
"libnsl.so.1" = glibc;
"libutil.so.1" = glibc;
"libpthread.so.0" = glibc;
"libresolv.so.2" = glibc;
"libX11.so.6" = xorg.libX11;
"libXext.so.6" = xorg.libXext;
"libXrender.so.1" = xorg.libXrender;
"libICE.so.6" = xorg.libICE;
"libSM.so.6" = xorg.libSM;
"libGL.so.1" = libGL;
"libgobject-2.0.so.0" = glib;
"libgthread-2.0.so.0" = glib;
"libglib-2.0.so.0" = glib;
"libz.so.1" = zlib;
"libexpat.so.1" = expat;
});
manylinux2014Libs = getLibOutputs (
with pkgs;
{
"libgcc_s.so.1" = glibc;
"libstdc++.so.6" = stdenv.cc.cc;
"libm.so.6" = glibc;
"libdl.so.2" = glibc;
"librt.so.1" = glibc;
"libc.so.6" = glibc;
"libnsl.so.1" = glibc;
"libutil.so.1" = glibc;
"libpthread.so.0" = glibc;
"libresolv.so.2" = glibc;
"libX11.so.6" = xorg.libX11;
"libXext.so.6" = xorg.libXext;
"libXrender.so.1" = xorg.libXrender;
"libICE.so.6" = xorg.libICE;
"libSM.so.6" = xorg.libSM;
"libGL.so.1" = libGL;
"libgobject-2.0.so.0" = glib;
"libgthread-2.0.so.0" = glib;
"libglib-2.0.so.0" = glib;
"libz.so.1" = zlib;
"libexpat.so.1" = expat;
}
);
# https://www.python.org/dev/peps/pep-0571/
manylinux2010Libs = manylinux2014Libs;
# https://www.python.org/dev/peps/pep-0513/
manylinux1Libs = getLibOutputs(manylinux2010Libs // (with pkgs; {
"libpanelw.so.5" = ncurses5;
"libncursesw.so.5" = ncurses5;
"libcrypt.so.1" = libxcrypt;
}));
manylinux1Libs = getLibOutputs (
manylinux2010Libs
// (with pkgs; {
"libpanelw.so.5" = ncurses5;
"libncursesw.so.5" = ncurses5;
"libcrypt.so.1" = libxcrypt;
})
);
in {
in
{
# List of libraries that are needed for manylinux compatibility.
# When using a wheel that is manylinux1 compatible, just extend
# the `buildInputs` with one of these `manylinux` lists.
@@ -1,45 +1,63 @@
# Generic builder.
{ lib
, config
, python
, wrapPython
, unzip
, ensureNewerSourcesForZipFilesHook
# Whether the derivation provides a Python module or not.
, toPythonModule
, namePrefix
, update-python-libraries
, setuptools
, pypaBuildHook
, pypaInstallHook
, pythonCatchConflictsHook
, pythonImportsCheckHook
, pythonNamespacesHook
, pythonOutputDistHook
, pythonRelaxDepsHook
, pythonRemoveBinBytecodeHook
, pythonRemoveTestsDirHook
, pythonRuntimeDepsCheckHook
, setuptoolsBuildHook
, wheelUnpackHook
, eggUnpackHook
, eggBuildHook
, eggInstallHook
{
lib,
config,
python,
wrapPython,
unzip,
ensureNewerSourcesForZipFilesHook,
# Whether the derivation provides a Python module or not.
toPythonModule,
namePrefix,
update-python-libraries,
setuptools,
pypaBuildHook,
pypaInstallHook,
pythonCatchConflictsHook,
pythonImportsCheckHook,
pythonNamespacesHook,
pythonOutputDistHook,
pythonRelaxDepsHook,
pythonRemoveBinBytecodeHook,
pythonRemoveTestsDirHook,
pythonRuntimeDepsCheckHook,
setuptoolsBuildHook,
wheelUnpackHook,
eggUnpackHook,
eggBuildHook,
eggInstallHook,
}:
let
inherit (builtins) unsafeGetAttrPos;
inherit (lib)
elem optionalString max stringLength fixedWidthString getName
optional optionals optionalAttrs hasSuffix escapeShellArgs
extendDerivation head splitString isBool;
elem
optionalString
max
stringLength
fixedWidthString
getName
optional
optionals
optionalAttrs
hasSuffix
escapeShellArgs
extendDerivation
head
splitString
isBool
;
leftPadName = name: against: let
leftPadName =
name: against:
let
len = max (stringLength name) (stringLength against);
in fixedWidthString len " " name;
in
fixedWidthString len " " name;
isPythonModule = drv:
isPythonModule =
drv:
# all pythonModules have the pythonModule attribute
(drv ? "pythonModule")
# Some pythonModules are turned in to a pythonApplication by setting the field to false
@@ -47,121 +65,152 @@ let
isMismatchedPython = drv: drv.pythonModule != python;
withDistOutput' = lib.flip elem ["pyproject" "setuptools" "wheel"];
withDistOutput' = lib.flip elem [
"pyproject"
"setuptools"
"wheel"
];
isBootstrapInstallPackage' = lib.flip elem [ "flit-core" "installer" ];
isBootstrapInstallPackage' = lib.flip elem [
"flit-core"
"installer"
];
isBootstrapPackage' = lib.flip elem ([
"build" "packaging" "pyproject-hooks" "wheel"
] ++ optionals (python.pythonOlder "3.11") [
"tomli"
]);
isBootstrapPackage' = lib.flip elem (
[
"build"
"packaging"
"pyproject-hooks"
"wheel"
]
++ optionals (python.pythonOlder "3.11") [
"tomli"
]
);
isSetuptoolsDependency' = lib.flip elem [ "setuptools" "wheel" ];
isSetuptoolsDependency' = lib.flip elem [
"setuptools"
"wheel"
];
cleanAttrs = lib.flip removeAttrs [
"disabled" "checkPhase" "checkInputs" "nativeCheckInputs" "doCheck" "doInstallCheck" "dontWrapPythonPrograms" "catchConflicts" "pyproject" "format"
"disabledTestPaths" "disabledTests" "pytestFlagsArray" "unittestFlagsArray" "outputs" "stdenv"
"dependencies" "optional-dependencies" "build-system"
"disabled"
"checkPhase"
"checkInputs"
"nativeCheckInputs"
"doCheck"
"doInstallCheck"
"dontWrapPythonPrograms"
"catchConflicts"
"pyproject"
"format"
"disabledTestPaths"
"disabledTests"
"pytestFlagsArray"
"unittestFlagsArray"
"outputs"
"stdenv"
"dependencies"
"optional-dependencies"
"build-system"
];
in
{ name ? "${attrs.pname}-${attrs.version}"
{
name ? "${attrs.pname}-${attrs.version}",
# Build-time dependencies for the package
, nativeBuildInputs ? []
# Build-time dependencies for the package
nativeBuildInputs ? [ ],
# Run-time dependencies for the package
, buildInputs ? []
# Run-time dependencies for the package
buildInputs ? [ ],
# Dependencies needed for running the checkPhase.
# These are added to buildInputs when doCheck = true.
, checkInputs ? []
, nativeCheckInputs ? []
# Dependencies needed for running the checkPhase.
# These are added to buildInputs when doCheck = true.
checkInputs ? [ ],
nativeCheckInputs ? [ ],
# propagate build dependencies so in case we have A -> B -> C,
# C can import package A propagated by B
, propagatedBuildInputs ? []
# propagate build dependencies so in case we have A -> B -> C,
# C can import package A propagated by B
propagatedBuildInputs ? [ ],
# Python module dependencies.
# These are named after PEP-621.
, dependencies ? []
, optional-dependencies ? {}
# Python module dependencies.
# These are named after PEP-621.
dependencies ? [ ],
optional-dependencies ? { },
# Python PEP-517 build systems.
, build-system ? []
# Python PEP-517 build systems.
build-system ? [ ],
# DEPRECATED: use propagatedBuildInputs
, pythonPath ? []
# DEPRECATED: use propagatedBuildInputs
pythonPath ? [ ],
# Enabled to detect some (native)BuildInputs mistakes
, strictDeps ? true
# Enabled to detect some (native)BuildInputs mistakes
strictDeps ? true,
, outputs ? [ "out" ]
outputs ? [ "out" ],
# used to disable derivation, useful for specific python versions
, disabled ? false
# used to disable derivation, useful for specific python versions
disabled ? false,
# Raise an error if two packages are installed with the same name
# TODO: For cross we probably need a different PYTHONPATH, or not
# add the runtime deps until after buildPhase.
, catchConflicts ? (python.stdenv.hostPlatform == python.stdenv.buildPlatform)
# Raise an error if two packages are installed with the same name
# TODO: For cross we probably need a different PYTHONPATH, or not
# add the runtime deps until after buildPhase.
catchConflicts ? (python.stdenv.hostPlatform == python.stdenv.buildPlatform),
# Additional arguments to pass to the makeWrapper function, which wraps
# generated binaries.
, makeWrapperArgs ? []
# Additional arguments to pass to the makeWrapper function, which wraps
# generated binaries.
makeWrapperArgs ? [ ],
# Skip wrapping of python programs altogether
, dontWrapPythonPrograms ? false
# Skip wrapping of python programs altogether
dontWrapPythonPrograms ? false,
# Don't use Pip to install a wheel
# Note this is actually a variable for the pipInstallPhase in pip's setupHook.
# It's included here to prevent an infinite recursion.
, dontUsePipInstall ? false
# Don't use Pip to install a wheel
# Note this is actually a variable for the pipInstallPhase in pip's setupHook.
# It's included here to prevent an infinite recursion.
dontUsePipInstall ? false,
# Skip setting the PYTHONNOUSERSITE environment variable in wrapped programs
, permitUserSite ? false
# Skip setting the PYTHONNOUSERSITE environment variable in wrapped programs
permitUserSite ? false,
# Remove bytecode from bin folder.
# When a Python script has the extension `.py`, bytecode is generated
# Typically, executables in bin have no extension, so no bytecode is generated.
# However, some packages do provide executables with extensions, and thus bytecode is generated.
, removeBinBytecode ? true
# Remove bytecode from bin folder.
# When a Python script has the extension `.py`, bytecode is generated
# Typically, executables in bin have no extension, so no bytecode is generated.
# However, some packages do provide executables with extensions, and thus bytecode is generated.
removeBinBytecode ? true,
# pyproject = true <-> format = "pyproject"
# pyproject = false <-> format = "other"
# https://github.com/NixOS/nixpkgs/issues/253154
, pyproject ? null
# pyproject = true <-> format = "pyproject"
# pyproject = false <-> format = "other"
# https://github.com/NixOS/nixpkgs/issues/253154
pyproject ? null,
# Several package formats are supported.
# "setuptools" : Install a common setuptools/distutils based package. This builds a wheel.
# "wheel" : Install from a pre-compiled wheel.
# "pyproject": Install a package using a ``pyproject.toml`` file (PEP517). This builds a wheel.
# "egg": Install a package from an egg.
# "other" : Provide your own buildPhase and installPhase.
, format ? null
# Several package formats are supported.
# "setuptools" : Install a common setuptools/distutils based package. This builds a wheel.
# "wheel" : Install from a pre-compiled wheel.
# "pyproject": Install a package using a ``pyproject.toml`` file (PEP517). This builds a wheel.
# "egg": Install a package from an egg.
# "other" : Provide your own buildPhase and installPhase.
format ? null,
, meta ? {}
meta ? { },
, doCheck ? true
doCheck ? true,
, disabledTestPaths ? []
disabledTestPaths ? [ ],
# Allow passing in a custom stdenv to buildPython*
, stdenv ? python.stdenv
# Allow passing in a custom stdenv to buildPython*
stdenv ? python.stdenv,
, ... } @ attrs:
...
}@attrs:
assert (pyproject != null) -> (format == null);
let
format' =
if pyproject != null then
if pyproject then
"pyproject"
else
"other"
if pyproject then "pyproject" else "other"
else if format != null then
format
else
@@ -169,45 +218,52 @@ let
withDistOutput = withDistOutput' format';
validatePythonMatches = let
throwMismatch = attrName: drv: let
myName = "'${namePrefix}${name}'";
theirName = "'${drv.name}'";
optionalLocation = let
pos = unsafeGetAttrPos (if attrs ? "pname" then "pname" else "name") attrs;
in optionalString (pos != null) " at ${pos.file}:${toString pos.line}:${toString pos.column}";
in throw ''
Python version mismatch in ${myName}:
validatePythonMatches =
let
throwMismatch =
attrName: drv:
let
myName = "'${namePrefix}${name}'";
theirName = "'${drv.name}'";
optionalLocation =
let
pos = unsafeGetAttrPos (if attrs ? "pname" then "pname" else "name") attrs;
in
optionalString (pos != null) " at ${pos.file}:${toString pos.line}:${toString pos.column}";
in
throw ''
Python version mismatch in ${myName}:
The Python derivation ${myName} depends on a Python derivation
named ${theirName}, but the two derivations use different versions
of Python:
The Python derivation ${myName} depends on a Python derivation
named ${theirName}, but the two derivations use different versions
of Python:
${leftPadName myName theirName} uses ${python}
${leftPadName theirName myName} uses ${toString drv.pythonModule}
${leftPadName myName theirName} uses ${python}
${leftPadName theirName myName} uses ${toString drv.pythonModule}
Possible solutions:
Possible solutions:
* If ${theirName} is a Python library, change the reference to ${theirName}
in the ${attrName} of ${myName} to use a ${theirName} built from the same
version of Python
* If ${theirName} is a Python library, change the reference to ${theirName}
in the ${attrName} of ${myName} to use a ${theirName} built from the same
version of Python
* If ${theirName} is used as a tool during the build, move the reference to
${theirName} in ${myName} from ${attrName} to nativeBuildInputs
* If ${theirName} is used as a tool during the build, move the reference to
${theirName} in ${myName} from ${attrName} to nativeBuildInputs
* If ${theirName} provides executables that are called at run time, pass its
bin path to makeWrapperArgs:
* If ${theirName} provides executables that are called at run time, pass its
bin path to makeWrapperArgs:
makeWrapperArgs = [ "--prefix PATH : ''${lib.makeBinPath [ ${getName drv } ] }" ];
makeWrapperArgs = [ "--prefix PATH : ''${lib.makeBinPath [ ${getName drv} ] }" ];
${optionalLocation}
'';
${optionalLocation}
'';
checkDrv = attrName: drv:
if (isPythonModule drv) && (isMismatchedPython drv) then throwMismatch attrName drv
else drv;
checkDrv =
attrName: drv:
if (isPythonModule drv) && (isMismatchedPython drv) then throwMismatch attrName drv else drv;
in attrName: inputs: map (checkDrv attrName) inputs;
in
attrName: inputs: map (checkDrv attrName) inputs;
isBootstrapInstallPackage = isBootstrapInstallPackage' (attrs.pname or null);
@@ -216,137 +272,183 @@ let
isSetuptoolsDependency = isSetuptoolsDependency' (attrs.pname or null);
# Keep extra attributes from `attrs`, e.g., `patchPhase', etc.
self = toPythonModule (stdenv.mkDerivation ((cleanAttrs attrs) // {
self = toPythonModule (
stdenv.mkDerivation (
(cleanAttrs attrs)
// {
name = namePrefix + name;
name = namePrefix + name;
nativeBuildInputs = [
python
wrapPython
ensureNewerSourcesForZipFilesHook # move to wheel installer (pip) or builder (setuptools, flit, ...)?
pythonRemoveTestsDirHook
] ++ optionals (catchConflicts && !isBootstrapPackage && !isSetuptoolsDependency) [
#
# 1. When building a package that is also part of the bootstrap chain, we
# must ignore conflicts after installation, because there will be one with
# the package in the bootstrap.
#
# 2. When a package is a dependency of setuptools, we must ignore conflicts
# because the hook that checks for conflicts uses setuptools.
#
pythonCatchConflictsHook
] ++ optionals (attrs ? pythonRelaxDeps || attrs ? pythonRemoveDeps) [
pythonRelaxDepsHook
] ++ optionals removeBinBytecode [
pythonRemoveBinBytecodeHook
] ++ optionals (hasSuffix "zip" (attrs.src.name or "")) [
unzip
] ++ optionals (format' == "setuptools") [
setuptoolsBuildHook
] ++ optionals (format' == "pyproject") [(
if isBootstrapPackage then
pypaBuildHook.override {
inherit (python.pythonOnBuildForHost.pkgs.bootstrap) build;
wheel = null;
nativeBuildInputs =
[
python
wrapPython
ensureNewerSourcesForZipFilesHook # move to wheel installer (pip) or builder (setuptools, flit, ...)?
pythonRemoveTestsDirHook
]
++ optionals (catchConflicts && !isBootstrapPackage && !isSetuptoolsDependency) [
#
# 1. When building a package that is also part of the bootstrap chain, we
# must ignore conflicts after installation, because there will be one with
# the package in the bootstrap.
#
# 2. When a package is a dependency of setuptools, we must ignore conflicts
# because the hook that checks for conflicts uses setuptools.
#
pythonCatchConflictsHook
]
++ optionals (attrs ? pythonRelaxDeps || attrs ? pythonRemoveDeps) [
pythonRelaxDepsHook
]
++ optionals removeBinBytecode [
pythonRemoveBinBytecodeHook
]
++ optionals (hasSuffix "zip" (attrs.src.name or "")) [
unzip
]
++ optionals (format' == "setuptools") [
setuptoolsBuildHook
]
++ optionals (format' == "pyproject") [
(
if isBootstrapPackage then
pypaBuildHook.override {
inherit (python.pythonOnBuildForHost.pkgs.bootstrap) build;
wheel = null;
}
else
pypaBuildHook
)
(
if isBootstrapPackage then
pythonRuntimeDepsCheckHook.override {
inherit (python.pythonOnBuildForHost.pkgs.bootstrap) packaging;
}
else
pythonRuntimeDepsCheckHook
)
]
++ optionals (format' == "wheel") [
wheelUnpackHook
]
++ optionals (format' == "egg") [
eggUnpackHook
eggBuildHook
eggInstallHook
]
++ optionals (format' != "other") [
(
if isBootstrapInstallPackage then
pypaInstallHook.override {
inherit (python.pythonOnBuildForHost.pkgs.bootstrap) installer;
}
else
pypaInstallHook
)
]
++ optionals (stdenv.buildPlatform == stdenv.hostPlatform) [
# This is a test, however, it should be ran independent of the checkPhase and checkInputs
pythonImportsCheckHook
]
++ optionals (python.pythonAtLeast "3.3") [
# Optionally enforce PEP420 for python3
pythonNamespacesHook
]
++ optionals withDistOutput [
pythonOutputDistHook
]
++ nativeBuildInputs
++ build-system;
buildInputs = validatePythonMatches "buildInputs" (buildInputs ++ pythonPath);
propagatedBuildInputs = validatePythonMatches "propagatedBuildInputs" (
propagatedBuildInputs
++ dependencies
++ [
# we propagate python even for packages transformed with 'toPythonApplication'
# this pollutes the PATH but avoids rebuilds
# see https://github.com/NixOS/nixpkgs/issues/170887 for more context
python
]
);
inherit strictDeps;
LANG = "${if python.stdenv.hostPlatform.isDarwin then "en_US" else "C"}.UTF-8";
# Python packages don't have a checkPhase, only an installCheckPhase
doCheck = false;
doInstallCheck = attrs.doCheck or true;
nativeInstallCheckInputs = nativeCheckInputs;
installCheckInputs = checkInputs;
postFixup =
optionalString (!dontWrapPythonPrograms) ''
wrapPythonPrograms
''
+ attrs.postFixup or "";
# Python packages built through cross-compilation are always for the host platform.
disallowedReferences = optionals (python.stdenv.hostPlatform != python.stdenv.buildPlatform) [
python.pythonOnBuildForHost
];
outputs = outputs ++ optional withDistOutput "dist";
passthru =
attrs.passthru or { }
// {
updateScript =
let
filename = head (splitString ":" self.meta.position);
in
attrs.passthru.updateScript or [
update-python-libraries
filename
];
}
// optionalAttrs (dependencies != [ ]) {
inherit dependencies;
}
// optionalAttrs (optional-dependencies != { }) {
inherit optional-dependencies;
}
// optionalAttrs (build-system != [ ]) {
inherit build-system;
};
meta = {
# default to python's platforms
platforms = python.meta.platforms;
isBuildPythonPackage = python.meta.platforms;
} // meta;
}
// optionalAttrs (attrs ? checkPhase) {
# If given use the specified checkPhase, otherwise use the setup hook.
# Longer-term we should get rid of `checkPhase` and use `installCheckPhase`.
installCheckPhase = attrs.checkPhase;
}
// optionalAttrs (attrs.doCheck or true) (
optionalAttrs (disabledTestPaths != [ ]) {
disabledTestPaths = escapeShellArgs disabledTestPaths;
}
else
pypaBuildHook
) (
if isBootstrapPackage then
pythonRuntimeDepsCheckHook.override {
inherit (python.pythonOnBuildForHost.pkgs.bootstrap) packaging;
// optionalAttrs (attrs ? disabledTests) {
# `escapeShellArgs` should be used as well as `disabledTestPaths`,
# but some packages rely on existing raw strings.
disabledTests = attrs.disabledTests;
}
else
pythonRuntimeDepsCheckHook
)] ++ optionals (format' == "wheel") [
wheelUnpackHook
] ++ optionals (format' == "egg") [
eggUnpackHook eggBuildHook eggInstallHook
] ++ optionals (format' != "other") [(
if isBootstrapInstallPackage then
pypaInstallHook.override {
inherit (python.pythonOnBuildForHost.pkgs.bootstrap) installer;
// optionalAttrs (attrs ? pytestFlagsArray) {
pytestFlagsArray = attrs.pytestFlagsArray;
}
else
pypaInstallHook
)] ++ optionals (stdenv.buildPlatform == stdenv.hostPlatform) [
# This is a test, however, it should be ran independent of the checkPhase and checkInputs
pythonImportsCheckHook
] ++ optionals (python.pythonAtLeast "3.3") [
# Optionally enforce PEP420 for python3
pythonNamespacesHook
] ++ optionals withDistOutput [
pythonOutputDistHook
] ++ nativeBuildInputs ++ build-system;
// optionalAttrs (attrs ? unittestFlagsArray) {
unittestFlagsArray = attrs.unittestFlagsArray;
}
)
)
);
buildInputs = validatePythonMatches "buildInputs" (buildInputs ++ pythonPath);
propagatedBuildInputs = validatePythonMatches "propagatedBuildInputs" (propagatedBuildInputs ++ dependencies ++ [
# we propagate python even for packages transformed with 'toPythonApplication'
# this pollutes the PATH but avoids rebuilds
# see https://github.com/NixOS/nixpkgs/issues/170887 for more context
python
]);
inherit strictDeps;
LANG = "${if python.stdenv.hostPlatform.isDarwin then "en_US" else "C"}.UTF-8";
# Python packages don't have a checkPhase, only an installCheckPhase
doCheck = false;
doInstallCheck = attrs.doCheck or true;
nativeInstallCheckInputs = nativeCheckInputs;
installCheckInputs = checkInputs;
postFixup = optionalString (!dontWrapPythonPrograms) ''
wrapPythonPrograms
'' + attrs.postFixup or "";
# Python packages built through cross-compilation are always for the host platform.
disallowedReferences = optionals (python.stdenv.hostPlatform != python.stdenv.buildPlatform) [ python.pythonOnBuildForHost ];
outputs = outputs ++ optional withDistOutput "dist";
passthru = attrs.passthru or { }
// {
updateScript = let
filename = head (splitString ":" self.meta.position);
in attrs.passthru.updateScript or [ update-python-libraries filename ];
}
// optionalAttrs (dependencies != []) {
inherit dependencies;
}
// optionalAttrs (optional-dependencies != {}) {
inherit optional-dependencies;
}
// optionalAttrs (build-system != []) {
inherit build-system;
};
meta = {
# default to python's platforms
platforms = python.meta.platforms;
isBuildPythonPackage = python.meta.platforms;
} // meta;
} // optionalAttrs (attrs?checkPhase) {
# If given use the specified checkPhase, otherwise use the setup hook.
# Longer-term we should get rid of `checkPhase` and use `installCheckPhase`.
installCheckPhase = attrs.checkPhase;
} // optionalAttrs (attrs.doCheck or true) (
optionalAttrs (disabledTestPaths != []) {
disabledTestPaths = escapeShellArgs disabledTestPaths;
} // optionalAttrs (attrs ? disabledTests) {
# `escapeShellArgs` should be used as well as `disabledTestPaths`,
# but some packages rely on existing raw strings.
disabledTests = attrs.disabledTests;
} // optionalAttrs (attrs ? pytestFlagsArray) {
pytestFlagsArray = attrs.pytestFlagsArray;
} // optionalAttrs (attrs ? unittestFlagsArray) {
unittestFlagsArray = attrs.unittestFlagsArray;
}
)));
in extendDerivation
(disabled -> throw "${name} not supported for interpreter ${python.executable}")
{ }
self
in
extendDerivation (
disabled -> throw "${name} not supported for interpreter ${python.executable}"
) { } self
@@ -1,101 +1,152 @@
{ lib, stdenv, callPackage, pythonPackagesExtensions, config, makeScopeWithSplicing', ... }:
{
lib,
stdenv,
callPackage,
pythonPackagesExtensions,
config,
makeScopeWithSplicing',
...
}:
{ implementation
, libPrefix
, executable
, sourceVersion
, pythonVersion
, packageOverrides
, sitePackages
, hasDistutilsCxxPatch
, pythonOnBuildForBuild
, pythonOnBuildForHost
, pythonOnBuildForTarget
, pythonOnHostForHost
, pythonOnTargetForTarget
, pythonAttr ? null
, self # is pythonOnHostForTarget
}: let
pythonPackages = let
ensurePythonModules = items: let
exceptions = [
stdenv
];
providesSetupHook = lib.attrByPath [ "provides" "setupHook"] false;
valid = value: pythonPackages.hasPythonModule value || providesSetupHook value || lib.elem value exceptions;
func = name: value:
if lib.isDerivation value then
lib.extendDerivation (valid value || throw "${name} should use `buildPythonPackage` or `toPythonModule` if it is to be part of the Python packages set.") {} value
else
value;
in lib.mapAttrs func items;
in ensurePythonModules (callPackage
# Function that when called
# - imports python-packages.nix
# - adds spliced package sets to the package set
# - applies overrides from `packageOverrides` and `pythonPackagesOverlays`.
({ pkgs, stdenv, python, overrides }: let
pythonPackagesFun = import ./python-packages-base.nix {
inherit stdenv pkgs lib;
python = self;
};
otherSplices = {
selfBuildBuild = pythonOnBuildForBuild.pkgs;
selfBuildHost = pythonOnBuildForHost.pkgs;
selfBuildTarget = pythonOnBuildForTarget.pkgs;
selfHostHost = pythonOnHostForHost.pkgs;
selfTargetTarget = pythonOnTargetForTarget.pkgs or {}; # There is no Python TargetTarget.
};
hooks = import ./hooks/default.nix;
keep = self: hooks self {};
optionalExtensions = cond: as: lib.optionals cond as;
pythonExtension = import ../../../top-level/python-packages.nix;
python2Extension = import ../../../top-level/python2-packages.nix;
extensions = lib.composeManyExtensions ([
hooks
pythonExtension
] ++ (optionalExtensions (!self.isPy3k) [
python2Extension
]) ++ pythonPackagesExtensions ++ [
overrides
]);
aliases = self: super: lib.optionalAttrs config.allowAliases (import ../../../top-level/python-aliases.nix lib self super);
in makeScopeWithSplicing' {
inherit otherSplices keep;
f = lib.extends (lib.composeExtensions aliases extensions) pythonPackagesFun;
}) {
overrides = packageOverrides;
python = self;
});
pythonOnBuildForHost_overridden =
pythonOnBuildForHost.override { inherit packageOverrides; self = pythonOnBuildForHost_overridden; };
in rec {
isPy27 = pythonVersion == "2.7";
isPy37 = pythonVersion == "3.7";
isPy38 = pythonVersion == "3.8";
isPy39 = pythonVersion == "3.9";
isPy310 = pythonVersion == "3.10";
isPy311 = pythonVersion == "3.11";
isPy312 = pythonVersion == "3.12";
isPy2 = lib.strings.substring 0 1 pythonVersion == "2";
isPy3 = lib.strings.substring 0 1 pythonVersion == "3";
isPy3k = isPy3;
isPyPy = lib.hasInfix "pypy" interpreter;
{
implementation,
libPrefix,
executable,
sourceVersion,
pythonVersion,
packageOverrides,
sitePackages,
hasDistutilsCxxPatch,
pythonOnBuildForBuild,
pythonOnBuildForHost,
pythonOnBuildForTarget,
pythonOnHostForHost,
pythonOnTargetForTarget,
pythonAttr ? null,
self, # is pythonOnHostForTarget
}:
let
pythonPackages =
let
ensurePythonModules =
items:
let
exceptions = [
stdenv
];
providesSetupHook = lib.attrByPath [ "provides" "setupHook" ] false;
valid =
value: pythonPackages.hasPythonModule value || providesSetupHook value || lib.elem value exceptions;
func =
name: value:
if lib.isDerivation value then
lib.extendDerivation (
valid value
|| throw "${name} should use `buildPythonPackage` or `toPythonModule` if it is to be part of the Python packages set."
) { } value
else
value;
in
lib.mapAttrs func items;
in
ensurePythonModules (
callPackage
# Function that when called
# - imports python-packages.nix
# - adds spliced package sets to the package set
# - applies overrides from `packageOverrides` and `pythonPackagesOverlays`.
(
{
pkgs,
stdenv,
python,
overrides,
}:
let
pythonPackagesFun = import ./python-packages-base.nix {
inherit stdenv pkgs lib;
python = self;
};
otherSplices = {
selfBuildBuild = pythonOnBuildForBuild.pkgs;
selfBuildHost = pythonOnBuildForHost.pkgs;
selfBuildTarget = pythonOnBuildForTarget.pkgs;
selfHostHost = pythonOnHostForHost.pkgs;
selfTargetTarget = pythonOnTargetForTarget.pkgs or { }; # There is no Python TargetTarget.
};
hooks = import ./hooks/default.nix;
keep = self: hooks self { };
optionalExtensions = cond: as: lib.optionals cond as;
pythonExtension = import ../../../top-level/python-packages.nix;
python2Extension = import ../../../top-level/python2-packages.nix;
extensions = lib.composeManyExtensions (
[
hooks
pythonExtension
]
++ (optionalExtensions (!self.isPy3k) [
python2Extension
])
++ pythonPackagesExtensions
++ [
overrides
]
);
aliases =
self: super:
lib.optionalAttrs config.allowAliases (import ../../../top-level/python-aliases.nix lib self super);
in
makeScopeWithSplicing' {
inherit otherSplices keep;
f = lib.extends (lib.composeExtensions aliases extensions) pythonPackagesFun;
}
)
{
overrides = packageOverrides;
python = self;
}
);
pythonOnBuildForHost_overridden = pythonOnBuildForHost.override {
inherit packageOverrides;
self = pythonOnBuildForHost_overridden;
};
in
rec {
isPy27 = pythonVersion == "2.7";
isPy37 = pythonVersion == "3.7";
isPy38 = pythonVersion == "3.8";
isPy39 = pythonVersion == "3.9";
isPy310 = pythonVersion == "3.10";
isPy311 = pythonVersion == "3.11";
isPy312 = pythonVersion == "3.12";
isPy2 = lib.strings.substring 0 1 pythonVersion == "2";
isPy3 = lib.strings.substring 0 1 pythonVersion == "3";
isPy3k = isPy3;
isPyPy = lib.hasInfix "pypy" interpreter;
buildEnv = callPackage ./wrapper.nix { python = self; inherit (pythonPackages) requiredPythonModules; };
withPackages = import ./with-packages.nix { inherit buildEnv pythonPackages;};
pkgs = pythonPackages;
interpreter = "${self}/bin/${executable}";
inherit executable implementation libPrefix pythonVersion sitePackages;
inherit sourceVersion;
pythonAtLeast = lib.versionAtLeast pythonVersion;
pythonOlder = lib.versionOlder pythonVersion;
inherit hasDistutilsCxxPatch;
pythonOnBuildForHost = pythonOnBuildForHost_overridden;
buildEnv = callPackage ./wrapper.nix {
python = self;
inherit (pythonPackages) requiredPythonModules;
};
withPackages = import ./with-packages.nix { inherit buildEnv pythonPackages; };
pkgs = pythonPackages;
interpreter = "${self}/bin/${executable}";
inherit
executable
implementation
libPrefix
pythonVersion
sitePackages
;
inherit sourceVersion;
pythonAtLeast = lib.versionAtLeast pythonVersion;
pythonOlder = lib.versionOlder pythonVersion;
inherit hasDistutilsCxxPatch;
pythonOnBuildForHost = pythonOnBuildForHost_overridden;
tests = callPackage ./tests.nix {
python = self;
};
tests = callPackage ./tests.nix {
python = self;
};
inherit pythonAttr;
inherit pythonAttr;
}
@@ -1,7 +1,8 @@
{ pkgs
, stdenv
, lib
, python
{
pkgs,
stdenv,
lib,
python,
}:
self:
@@ -13,47 +14,61 @@ let
# Derivations built with `buildPythonPackage` can already be overridden with `override`, `overrideAttrs`, and `overrideDerivation`.
# This function introduces `overridePythonAttrs` and it overrides the call to `buildPythonPackage`.
makeOverridablePythonPackage = f: lib.mirrorFunctionArgs f (origArgs:
let
args = lib.fix (lib.extends
(_: previousAttrs: {
passthru = (previousAttrs.passthru or { }) // {
overridePythonAttrs = newArgs: makeOverridablePythonPackage f (overrideWith newArgs);
};
})
(_: origArgs));
result = f args;
overrideWith = newArgs: args // (if pkgs.lib.isFunction newArgs then newArgs args else newArgs);
in
if builtins.isAttrs result then result
else if builtins.isFunction result then {
overridePythonAttrs = newArgs: makeOverridablePythonPackage f (overrideWith newArgs);
__functor = self: result;
}
else result);
makeOverridablePythonPackage =
f:
lib.mirrorFunctionArgs f (
origArgs:
let
args = lib.fix (
lib.extends (_: previousAttrs: {
passthru = (previousAttrs.passthru or { }) // {
overridePythonAttrs = newArgs: makeOverridablePythonPackage f (overrideWith newArgs);
};
}) (_: origArgs)
);
result = f args;
overrideWith = newArgs: args // (if pkgs.lib.isFunction newArgs then newArgs args else newArgs);
in
if builtins.isAttrs result then
result
else if builtins.isFunction result then
{
overridePythonAttrs = newArgs: makeOverridablePythonPackage f (overrideWith newArgs);
__functor = self: result;
}
else
result
);
mkPythonDerivation = if python.isPy3k then
./mk-python-derivation.nix
else
./python2/mk-python-derivation.nix;
mkPythonDerivation =
if python.isPy3k then ./mk-python-derivation.nix else ./python2/mk-python-derivation.nix;
buildPythonPackage = makeOverridablePythonPackage (callPackage mkPythonDerivation {
inherit namePrefix; # We want Python libraries to be named like e.g. "python3.6-${name}"
inherit toPythonModule; # Libraries provide modules
});
buildPythonPackage = makeOverridablePythonPackage (
callPackage mkPythonDerivation {
inherit namePrefix; # We want Python libraries to be named like e.g. "python3.6-${name}"
inherit toPythonModule; # Libraries provide modules
}
);
buildPythonApplication = makeOverridablePythonPackage (callPackage mkPythonDerivation {
namePrefix = ""; # Python applications should not have any prefix
toPythonModule = x: x; # Application does not provide modules.
});
buildPythonApplication = makeOverridablePythonPackage (
callPackage mkPythonDerivation {
namePrefix = ""; # Python applications should not have any prefix
toPythonModule = x: x; # Application does not provide modules.
}
);
# Check whether a derivation provides a Python module.
hasPythonModule = drv: drv?pythonModule && drv.pythonModule == python;
hasPythonModule = drv: drv ? pythonModule && drv.pythonModule == python;
# Get list of required Python modules given a list of derivations.
requiredPythonModules = drvs: let
modules = lib.filter hasPythonModule drvs;
in lib.unique ([python] ++ modules ++ lib.concatLists (lib.catAttrs "requiredPythonModules" modules));
requiredPythonModules =
drvs:
let
modules = lib.filter hasPythonModule drvs;
in
lib.unique (
[ python ] ++ modules ++ lib.concatLists (lib.catAttrs "requiredPythonModules" modules)
);
# Create a PYTHONPATH from a list of derivations. This function recurses into the items to find derivations
# providing Python modules.
@@ -66,23 +81,24 @@ let
mkPythonMetaPackage = callPackage ./meta-package.nix { };
# Convert derivation to a Python module.
toPythonModule = drv:
drv.overrideAttrs( oldAttrs: {
toPythonModule =
drv:
drv.overrideAttrs (oldAttrs: {
# Use passthru in order to prevent rebuilds when possible.
passthru = (oldAttrs.passthru or {})// {
passthru = (oldAttrs.passthru or { }) // {
pythonModule = python;
pythonPath = [ ]; # Deprecated, for compatibility.
requiredPythonModules =
builtins.addErrorContext
"while calculating requiredPythonModules for ${drv.name or drv.pname}:"
(requiredPythonModules drv.propagatedBuildInputs);
requiredPythonModules = builtins.addErrorContext "while calculating requiredPythonModules for ${drv.name or drv.pname}:" (
requiredPythonModules drv.propagatedBuildInputs
);
};
});
# Convert a Python library to an application.
toPythonApplication = drv:
drv.overrideAttrs( oldAttrs: {
passthru = (oldAttrs.passthru or {}) // {
toPythonApplication =
drv:
drv.overrideAttrs (oldAttrs: {
passthru = (oldAttrs.passthru or { }) // {
# Remove Python prefix from name so we have a "normal" name.
# While the prefix shows up in the store path, it won't be
# used by `nix-env`.
@@ -91,15 +107,38 @@ let
};
});
disabled = drv: throw "${removePythonPrefix (drv.pname or drv.name)} not supported for interpreter ${python.executable}";
disabled =
drv:
throw "${
removePythonPrefix (drv.pname or drv.name)
} not supported for interpreter ${python.executable}";
disabledIf = x: drv: if x then disabled drv else drv;
in {
in
{
inherit lib pkgs stdenv;
inherit (python.passthru) isPy27 isPy37 isPy38 isPy39 isPy310 isPy311 isPy312 isPy3k isPyPy pythonAtLeast pythonOlder;
inherit (python.passthru)
isPy27
isPy37
isPy38
isPy39
isPy310
isPy311
isPy312
isPy3k
isPyPy
pythonAtLeast
pythonOlder
;
inherit buildPythonPackage buildPythonApplication;
inherit hasPythonModule requiredPythonModules makePythonPath disabled disabledIf;
inherit
hasPythonModule
requiredPythonModules
makePythonPath
disabled
disabledIf
;
inherit toPythonModule toPythonApplication;
inherit mkPythonMetaPackage mkPythonEditablePackage;
@@ -107,5 +146,7 @@ in {
# Don't take pythonPackages from "global" pkgs scope to avoid mixing python versions.
# Prevent `pkgs/top-level/release-attrpaths-superset.nix` from recursing more than one level here.
pythonPackages = self // { __attrsFailEvaluation = true; };
pythonPackages = self // {
__attrsFailEvaluation = true;
};
}
@@ -1,243 +1,301 @@
# Generic builder only used for EOL and deprecated Python 2.
{ lib
, config
, python
, wrapPython
, unzip
, ensureNewerSourcesForZipFilesHook
# Whether the derivation provides a Python module or not.
, toPythonModule
, namePrefix
, update-python-libraries
, setuptools
, pipBuildHook
, pipInstallHook
, pythonCatchConflictsHook
, pythonImportsCheckHook
, pythonOutputDistHook
, pythonRemoveBinBytecodeHook
, pythonRemoveTestsDirHook
, setuptoolsBuildHook
, wheelUnpackHook
, eggUnpackHook
, eggBuildHook
, eggInstallHook
{
lib,
config,
python,
wrapPython,
unzip,
ensureNewerSourcesForZipFilesHook,
# Whether the derivation provides a Python module or not.
toPythonModule,
namePrefix,
update-python-libraries,
setuptools,
pipBuildHook,
pipInstallHook,
pythonCatchConflictsHook,
pythonImportsCheckHook,
pythonOutputDistHook,
pythonRemoveBinBytecodeHook,
pythonRemoveTestsDirHook,
setuptoolsBuildHook,
wheelUnpackHook,
eggUnpackHook,
eggBuildHook,
eggInstallHook,
}:
{ name ? "${attrs.pname}-${attrs.version}"
{
name ? "${attrs.pname}-${attrs.version}",
# Build-time dependencies for the package
, nativeBuildInputs ? []
# Build-time dependencies for the package
nativeBuildInputs ? [ ],
# Run-time dependencies for the package
, buildInputs ? []
# Run-time dependencies for the package
buildInputs ? [ ],
# Dependencies needed for running the checkPhase.
# These are added to buildInputs when doCheck = true.
, checkInputs ? []
, nativeCheckInputs ? []
# Dependencies needed for running the checkPhase.
# These are added to buildInputs when doCheck = true.
checkInputs ? [ ],
nativeCheckInputs ? [ ],
# propagate build dependencies so in case we have A -> B -> C,
# C can import package A propagated by B
, propagatedBuildInputs ? []
# propagate build dependencies so in case we have A -> B -> C,
# C can import package A propagated by B
propagatedBuildInputs ? [ ],
# DEPRECATED: use propagatedBuildInputs
, pythonPath ? []
# DEPRECATED: use propagatedBuildInputs
pythonPath ? [ ],
# Enabled to detect some (native)BuildInputs mistakes
, strictDeps ? true
# Enabled to detect some (native)BuildInputs mistakes
strictDeps ? true,
, outputs ? [ "out" ]
outputs ? [ "out" ],
# used to disable derivation, useful for specific python versions
, disabled ? false
# used to disable derivation, useful for specific python versions
disabled ? false,
# Raise an error if two packages are installed with the same name
# TODO: For cross we probably need a different PYTHONPATH, or not
# add the runtime deps until after buildPhase.
, catchConflicts ? (python.stdenv.hostPlatform == python.stdenv.buildPlatform)
# Raise an error if two packages are installed with the same name
# TODO: For cross we probably need a different PYTHONPATH, or not
# add the runtime deps until after buildPhase.
catchConflicts ? (python.stdenv.hostPlatform == python.stdenv.buildPlatform),
# Additional arguments to pass to the makeWrapper function, which wraps
# generated binaries.
, makeWrapperArgs ? []
# Additional arguments to pass to the makeWrapper function, which wraps
# generated binaries.
makeWrapperArgs ? [ ],
# Skip wrapping of python programs altogether
, dontWrapPythonPrograms ? false
# Skip wrapping of python programs altogether
dontWrapPythonPrograms ? false,
# Don't use Pip to install a wheel
# Note this is actually a variable for the pipInstallPhase in pip's setupHook.
# It's included here to prevent an infinite recursion.
, dontUsePipInstall ? false
# Don't use Pip to install a wheel
# Note this is actually a variable for the pipInstallPhase in pip's setupHook.
# It's included here to prevent an infinite recursion.
dontUsePipInstall ? false,
# Skip setting the PYTHONNOUSERSITE environment variable in wrapped programs
, permitUserSite ? false
# Skip setting the PYTHONNOUSERSITE environment variable in wrapped programs
permitUserSite ? false,
# Remove bytecode from bin folder.
# When a Python script has the extension `.py`, bytecode is generated
# Typically, executables in bin have no extension, so no bytecode is generated.
# However, some packages do provide executables with extensions, and thus bytecode is generated.
, removeBinBytecode ? true
# Remove bytecode from bin folder.
# When a Python script has the extension `.py`, bytecode is generated
# Typically, executables in bin have no extension, so no bytecode is generated.
# However, some packages do provide executables with extensions, and thus bytecode is generated.
removeBinBytecode ? true,
# Several package formats are supported.
# "setuptools" : Install a common setuptools/distutils based package. This builds a wheel.
# "wheel" : Install from a pre-compiled wheel.
# "pyproject": Install a package using a ``pyproject.toml`` file (PEP517). This builds a wheel.
# "egg": Install a package from an egg.
# "other" : Provide your own buildPhase and installPhase.
, format ? "setuptools"
# Several package formats are supported.
# "setuptools" : Install a common setuptools/distutils based package. This builds a wheel.
# "wheel" : Install from a pre-compiled wheel.
# "pyproject": Install a package using a ``pyproject.toml`` file (PEP517). This builds a wheel.
# "egg": Install a package from an egg.
# "other" : Provide your own buildPhase and installPhase.
format ? "setuptools",
, meta ? {}
meta ? { },
, passthru ? {}
passthru ? { },
, doCheck ? true
doCheck ? true,
, disabledTestPaths ? []
disabledTestPaths ? [ ],
, ... } @ attrs:
...
}@attrs:
let
inherit (python) stdenv;
withDistOutput = lib.elem format ["pyproject" "setuptools" "wheel"];
withDistOutput = lib.elem format [
"pyproject"
"setuptools"
"wheel"
];
name_ = name;
validatePythonMatches = attrName: let
isPythonModule = drv:
# all pythonModules have the pythonModule attribute
(drv ? "pythonModule")
# Some pythonModules are turned in to a pythonApplication by setting the field to false
&& (!builtins.isBool drv.pythonModule);
isMismatchedPython = drv: drv.pythonModule != python;
validatePythonMatches =
attrName:
let
isPythonModule =
drv:
# all pythonModules have the pythonModule attribute
(drv ? "pythonModule")
# Some pythonModules are turned in to a pythonApplication by setting the field to false
&& (!builtins.isBool drv.pythonModule);
isMismatchedPython = drv: drv.pythonModule != python;
optionalLocation = let
pos = builtins.unsafeGetAttrPos (if attrs ? "pname" then "pname" else "name") attrs;
in lib.optionalString (pos != null) " at ${pos.file}:${toString pos.line}:${toString pos.column}";
optionalLocation =
let
pos = builtins.unsafeGetAttrPos (if attrs ? "pname" then "pname" else "name") attrs;
in
lib.optionalString (pos != null) " at ${pos.file}:${toString pos.line}:${toString pos.column}";
leftPadName = name: against: let
len = lib.max (lib.stringLength name) (lib.stringLength against);
in lib.strings.fixedWidthString len " " name;
leftPadName =
name: against:
let
len = lib.max (lib.stringLength name) (lib.stringLength against);
in
lib.strings.fixedWidthString len " " name;
throwMismatch = drv: let
myName = "'${namePrefix}${name}'";
theirName = "'${drv.name}'";
in throw ''
Python version mismatch in ${myName}:
throwMismatch =
drv:
let
myName = "'${namePrefix}${name}'";
theirName = "'${drv.name}'";
in
throw ''
Python version mismatch in ${myName}:
The Python derivation ${myName} depends on a Python derivation
named ${theirName}, but the two derivations use different versions
of Python:
The Python derivation ${myName} depends on a Python derivation
named ${theirName}, but the two derivations use different versions
of Python:
${leftPadName myName theirName} uses ${python}
${leftPadName theirName myName} uses ${toString drv.pythonModule}
${leftPadName myName theirName} uses ${python}
${leftPadName theirName myName} uses ${toString drv.pythonModule}
Possible solutions:
Possible solutions:
* If ${theirName} is a Python library, change the reference to ${theirName}
in the ${attrName} of ${myName} to use a ${theirName} built from the same
version of Python
* If ${theirName} is a Python library, change the reference to ${theirName}
in the ${attrName} of ${myName} to use a ${theirName} built from the same
version of Python
* If ${theirName} is used as a tool during the build, move the reference to
${theirName} in ${myName} from ${attrName} to nativeBuildInputs
* If ${theirName} is used as a tool during the build, move the reference to
${theirName} in ${myName} from ${attrName} to nativeBuildInputs
* If ${theirName} provides executables that are called at run time, pass its
bin path to makeWrapperArgs:
* If ${theirName} provides executables that are called at run time, pass its
bin path to makeWrapperArgs:
makeWrapperArgs = [ "--prefix PATH : ''${lib.makeBinPath [ ${lib.getName drv } ] }" ];
makeWrapperArgs = [ "--prefix PATH : ''${lib.makeBinPath [ ${lib.getName drv} ] }" ];
${optionalLocation}
'';
${optionalLocation}
'';
checkDrv = drv:
if (isPythonModule drv) && (isMismatchedPython drv)
then throwMismatch drv
else drv;
checkDrv = drv: if (isPythonModule drv) && (isMismatchedPython drv) then throwMismatch drv else drv;
in inputs: builtins.map (checkDrv) inputs;
in
inputs: builtins.map (checkDrv) inputs;
# Keep extra attributes from `attrs`, e.g., `patchPhase', etc.
self = toPythonModule (stdenv.mkDerivation ((builtins.removeAttrs attrs [
"disabled" "checkPhase" "checkInputs" "nativeCheckInputs" "doCheck" "doInstallCheck" "dontWrapPythonPrograms" "catchConflicts" "format"
"disabledTestPaths" "outputs"
]) // {
self = toPythonModule (
stdenv.mkDerivation (
(builtins.removeAttrs attrs [
"disabled"
"checkPhase"
"checkInputs"
"nativeCheckInputs"
"doCheck"
"doInstallCheck"
"dontWrapPythonPrograms"
"catchConflicts"
"format"
"disabledTestPaths"
"outputs"
])
// {
name = namePrefix + name_;
name = namePrefix + name_;
nativeBuildInputs = [
python
wrapPython
ensureNewerSourcesForZipFilesHook # move to wheel installer (pip) or builder (setuptools, ...)?
pythonRemoveTestsDirHook
] ++ lib.optionals catchConflicts [
pythonCatchConflictsHook
] ++ lib.optionals removeBinBytecode [
pythonRemoveBinBytecodeHook
] ++ lib.optionals (lib.hasSuffix "zip" (attrs.src.name or "")) [
unzip
] ++ lib.optionals (format == "setuptools") [
setuptoolsBuildHook
] ++ lib.optionals (format == "pyproject") [(
pipBuildHook
)] ++ lib.optionals (format == "wheel") [
wheelUnpackHook
] ++ lib.optionals (format == "egg") [
eggUnpackHook eggBuildHook eggInstallHook
] ++ lib.optionals (format != "other") [(
pipInstallHook
)] ++ lib.optionals (stdenv.buildPlatform == stdenv.hostPlatform) [
# This is a test, however, it should be ran independent of the checkPhase and checkInputs
pythonImportsCheckHook
] ++ lib.optionals withDistOutput [
pythonOutputDistHook
] ++ nativeBuildInputs;
nativeBuildInputs =
[
python
wrapPython
ensureNewerSourcesForZipFilesHook # move to wheel installer (pip) or builder (setuptools, ...)?
pythonRemoveTestsDirHook
]
++ lib.optionals catchConflicts [
pythonCatchConflictsHook
]
++ lib.optionals removeBinBytecode [
pythonRemoveBinBytecodeHook
]
++ lib.optionals (lib.hasSuffix "zip" (attrs.src.name or "")) [
unzip
]
++ lib.optionals (format == "setuptools") [
setuptoolsBuildHook
]
++ lib.optionals (format == "pyproject") [
(pipBuildHook)
]
++ lib.optionals (format == "wheel") [
wheelUnpackHook
]
++ lib.optionals (format == "egg") [
eggUnpackHook
eggBuildHook
eggInstallHook
]
++ lib.optionals (format != "other") [
(pipInstallHook)
]
++ lib.optionals (stdenv.buildPlatform == stdenv.hostPlatform) [
# This is a test, however, it should be ran independent of the checkPhase and checkInputs
pythonImportsCheckHook
]
++ lib.optionals withDistOutput [
pythonOutputDistHook
]
++ nativeBuildInputs;
buildInputs = validatePythonMatches "buildInputs" (buildInputs ++ pythonPath);
buildInputs = validatePythonMatches "buildInputs" (buildInputs ++ pythonPath);
propagatedBuildInputs = validatePythonMatches "propagatedBuildInputs" (propagatedBuildInputs ++ [
# we propagate python even for packages transformed with 'toPythonApplication'
# this pollutes the PATH but avoids rebuilds
# see https://github.com/NixOS/nixpkgs/issues/170887 for more context
python
]);
propagatedBuildInputs = validatePythonMatches "propagatedBuildInputs" (
propagatedBuildInputs
++ [
# we propagate python even for packages transformed with 'toPythonApplication'
# this pollutes the PATH but avoids rebuilds
# see https://github.com/NixOS/nixpkgs/issues/170887 for more context
python
]
);
inherit strictDeps;
inherit strictDeps;
LANG = "${if python.stdenv.hostPlatform.isDarwin then "en_US" else "C"}.UTF-8";
LANG = "${if python.stdenv.hostPlatform.isDarwin then "en_US" else "C"}.UTF-8";
# Python packages don't have a checkPhase, only an installCheckPhase
doCheck = false;
doInstallCheck = attrs.doCheck or true;
nativeInstallCheckInputs = nativeCheckInputs;
installCheckInputs = checkInputs;
# Python packages don't have a checkPhase, only an installCheckPhase
doCheck = false;
doInstallCheck = attrs.doCheck or true;
nativeInstallCheckInputs = nativeCheckInputs;
installCheckInputs = checkInputs;
postFixup = lib.optionalString (!dontWrapPythonPrograms) ''
wrapPythonPrograms
'' + attrs.postFixup or "";
postFixup =
lib.optionalString (!dontWrapPythonPrograms) ''
wrapPythonPrograms
''
+ attrs.postFixup or "";
# Python packages built through cross-compilation are always for the host platform.
disallowedReferences = lib.optionals (python.stdenv.hostPlatform != python.stdenv.buildPlatform) [ python.pythonOnBuildForHost ];
# Python packages built through cross-compilation are always for the host platform.
disallowedReferences = lib.optionals (python.stdenv.hostPlatform != python.stdenv.buildPlatform) [
python.pythonOnBuildForHost
];
outputs = outputs ++ lib.optional withDistOutput "dist";
outputs = outputs ++ lib.optional withDistOutput "dist";
meta = {
# default to python's platforms
platforms = python.meta.platforms;
isBuildPythonPackage = python.meta.platforms;
} // meta;
} // lib.optionalAttrs (attrs?checkPhase) {
# If given use the specified checkPhase, otherwise use the setup hook.
# Longer-term we should get rid of `checkPhase` and use `installCheckPhase`.
installCheckPhase = attrs.checkPhase;
} // lib.optionalAttrs (disabledTestPaths != []) {
disabledTestPaths = lib.escapeShellArgs disabledTestPaths;
}));
meta = {
# default to python's platforms
platforms = python.meta.platforms;
isBuildPythonPackage = python.meta.platforms;
} // meta;
}
// lib.optionalAttrs (attrs ? checkPhase) {
# If given use the specified checkPhase, otherwise use the setup hook.
# Longer-term we should get rid of `checkPhase` and use `installCheckPhase`.
installCheckPhase = attrs.checkPhase;
}
// lib.optionalAttrs (disabledTestPaths != [ ]) {
disabledTestPaths = lib.escapeShellArgs disabledTestPaths;
}
)
);
passthru.updateScript = let
passthru.updateScript =
let
filename = builtins.head (lib.splitString ":" self.meta.position);
in attrs.passthru.updateScript or [ update-python-libraries filename ];
in lib.extendDerivation
(disabled -> throw "${name} not supported for interpreter ${python.executable}")
passthru
self
in
attrs.passthru.updateScript or [
update-python-libraries
filename
];
in
lib.extendDerivation (
disabled -> throw "${name} not supported for interpreter ${python.executable}"
) passthru self
@@ -1,9 +1,10 @@
{ lib
, stdenv
, rustPlatform
, fetchFromGitHub
, SystemConfiguration
, python3
{
lib,
stdenv,
rustPlatform,
fetchFromGitHub,
SystemConfiguration,
python3,
}:
rustPlatform.buildRustPackage rec {
@@ -4,13 +4,16 @@ sitePackages:
let
hook = ./setup-hook.sh;
in runCommand "python-setup-hook.sh" {
strictDeps = true;
env = {
inherit sitePackages;
};
} ''
cp ${hook} hook.sh
substituteAllInPlace hook.sh
mv hook.sh $out
''
in
runCommand "python-setup-hook.sh"
{
strictDeps = true;
env = {
inherit sitePackages;
};
}
''
cp ${hook} hook.sh
substituteAllInPlace hook.sh
mv hook.sh $out
''
@@ -1,4 +1,9 @@
{ interpreter, gdb, writeText, runCommand }:
{
interpreter,
gdb,
writeText,
runCommand,
}:
let
crashme-py = writeText "crashme.py" ''
@@ -9,7 +14,8 @@ let
sentinel_foo_bar()
'';
in runCommand "python-gdb" {} ''
in
runCommand "python-gdb" { } ''
# test that gdb is able to recover the python stack frame of this segfault
${gdb}/bin/gdb -batch -ex 'set debug-file-directory ${interpreter.debug}/lib/debug' \
-ex 'source ${interpreter}/share/gdb/libpython.py' \
@@ -1,14 +1,23 @@
{ interpreter, writeText, runCommand }:
{
interpreter,
writeText,
runCommand,
}:
let
python = let
packageOverrides = self: super: {
typeddep = self.callPackage ./typeddep {};
python =
let
packageOverrides = self: super: {
typeddep = self.callPackage ./typeddep { };
};
in
interpreter.override {
inherit packageOverrides;
self = python;
};
in interpreter.override {inherit packageOverrides; self = python;};
pythonEnv = python.withPackages(ps: [
pythonEnv = python.withPackages (ps: [
ps.typeddep
ps.mypy
]);
@@ -19,7 +28,8 @@ let
print(s)
'';
in runCommand "${interpreter.name}-site-prefix-mypy-test" {} ''
in
runCommand "${interpreter.name}-site-prefix-mypy-test" { } ''
${pythonEnv}/bin/mypy ${pythonScript}
touch $out
''
@@ -1,5 +1,8 @@
{ lib, buildPythonPackage, pythonOlder }:
{
lib,
buildPythonPackage,
pythonOlder,
}:
buildPythonPackage {
@@ -1,8 +1,12 @@
{ interpreter, writeText, runCommand }:
{
interpreter,
writeText,
runCommand,
}:
let
pythonEnv = interpreter.withPackages(ps: [
pythonEnv = interpreter.withPackages (ps: [
ps.tkinter
]);
@@ -11,7 +15,8 @@ let
print(tkinter)
'';
in runCommand "${interpreter.name}-tkinter-test" {} ''
in
runCommand "${interpreter.name}-tkinter-test" { } ''
${pythonEnv}/bin/python ${pythonScript}
touch $out
''
@@ -1,3 +1,7 @@
{ buildEnv, pythonPackages }:
f: let packages = f pythonPackages; in buildEnv.override { extraLibs = packages; }
f:
let
packages = f pythonPackages;
in
buildEnv.override { extraLibs = packages; }