push sheeet
Some checks failed
Periodic Merges (6h) / master → staging-nixos (push) Failing after 12m50s
Periodic Merges (6h) / master → staging-next (push) Failing after 12m54s
Periodic Merges (24h) / merge-base(master,staging) → haskell-updates (push) Failing after 11m54s
Periodic Merges (6h) / staging-next → staging (push) Failing after 12m13s
Periodic Merges (24h) / staging-next-25.05 → staging-25.05 (push) Failing after 13m24s
Periodic Merges (24h) / release-25.05 → staging-next-25.05 (push) Failing after 14m28s

This commit is contained in:
Dark Steveneq
2025-10-09 14:15:47 +02:00
commit 646b892680
49168 changed files with 5897842 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
# Setup hook to use in case a conda binary package is installed
echo "Sourcing conda install hook"
condaInstallPhase() {
echo "Executing condaInstallPhase"
runHook preInstall
# There are two different formats of conda packages.
# It either contains only a site-packages directory
# or multiple top level directories.
siteDir=@pythonSitePackages@
if [ -e ./site-packages ]; then
mkdir -p $out/$siteDir
cp -r ./site-packages/* $out/$siteDir
else
cp -r . $out
rm $out/env-vars
fi
runHook postInstall
echo "Finished executing condaInstallPhase"
}
if [ -z "${installPhase-}" ]; then
echo "Using condaInstallPhase"
installPhase=condaInstallPhase
fi

View File

@@ -0,0 +1,18 @@
# Setup hook to use in case a conda binary package is fetched
echo "Sourcing conda unpack hook"
condaUnpackPhase() {
echo "Executing condaUnpackPhase"
runHook preUnpack
# use lbzip2 for parallel decompression (bz2 is slow)
lbzip2 -dc -n $NIX_BUILD_CORES $src | tar --exclude='info' -x
# runHook postUnpack # Calls find...?
echo "Finished executing condaUnpackPhase"
}
if [ -z "${unpackPhase-}" ]; then
echo "Using condaUnpackPhase"
unpackPhase=condaUnpackPhase
fi

View File

@@ -0,0 +1,506 @@
self: dontUse:
with self;
let
inherit (python) pythonOnBuildForHost;
inherit (pkgs) runCommand;
pythonInterpreter = pythonOnBuildForHost.interpreter;
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);
condaInstallHook = callPackage (
{
makePythonHook,
gnutar,
lbzip2,
}:
makePythonHook {
name = "conda-install-hook";
propagatedBuildInputs = [
gnutar
lbzip2
];
substitutions = {
inherit pythonSitePackages;
};
} ./conda-install-hook.sh
) { };
condaUnpackHook = callPackage (
{ makePythonHook }:
makePythonHook {
name = "conda-unpack-hook";
propagatedBuildInputs = [ ];
} ./conda-unpack-hook.sh
) { };
eggBuildHook = callPackage (
{ makePythonHook }:
makePythonHook {
name = "egg-build-hook.sh";
propagatedBuildInputs = [ ];
} ./egg-build-hook.sh
) { };
eggInstallHook = callPackage (
{ makePythonHook, setuptools }:
makePythonHook {
name = "egg-install-hook.sh";
propagatedBuildInputs = [ setuptools ];
substitutions = {
inherit pythonInterpreter pythonSitePackages;
};
} ./egg-install-hook.sh
) { };
eggUnpackHook = callPackage (
{ makePythonHook }:
makePythonHook {
name = "egg-unpack-hook.sh";
propagatedBuildInputs = [ ];
} ./egg-unpack-hook.sh
) { };
pipBuildHook = callPackage (
{
makePythonHook,
pip,
wheel,
}:
makePythonHook {
name = "pip-build-hook.sh";
propagatedBuildInputs = [
pip
wheel
];
substitutions = {
inherit pythonInterpreter pythonSitePackages;
};
} ./pip-build-hook.sh
) { };
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;
};
pipInstallHook = callPackage (
{ makePythonHook, pip }:
makePythonHook {
name = "pip-install-hook";
propagatedBuildInputs = [ pip ];
substitutions = {
inherit pythonInterpreter pythonSitePackages;
};
} ./pip-install-hook.sh
) { };
pypaInstallHook =
callPackage
(
{ makePythonHook, installer }:
makePythonHook {
name = "pypa-install-hook";
propagatedBuildInputs = [ installer ];
substitutions = {
inherit pythonInterpreter pythonSitePackages;
};
} ./pypa-install-hook.sh
)
{
inherit (pythonOnBuildForHost.pkgs) installer;
};
pytestCheckHook = callPackage (
{
makePythonHook,
pytest,
# For package tests
testers,
objprint,
}:
makePythonHook {
name = "pytest-check-hook";
propagatedBuildInputs = [ pytest ];
substitutions = {
inherit pythonCheckInterpreter;
};
passthru = {
tests = {
basic = objprint.overridePythonAttrs (previousPythonAttrs: {
pname = "test-pytestCheckHook-basic-${previousPythonAttrs.pname}";
});
disabledTests = objprint.overridePythonAttrs (previousPythonAttrs: {
pname = "test-pytestCheckHook-disabledTests-${previousPythonAttrs.pname}";
disabledTests = [
"test_print"
]
++ previousPythonAttrs.disabledTests or [ ];
});
disabledTests-expression = objprint.overridePythonAttrs (previousPythonAttrs: {
__structuredAttrs = true;
pname = "test-pytestCheckHook-disabledTests-expression-${previousPythonAttrs.pname}";
disabledTests = [
"TestBasic and test_print"
"test_str"
]
++ previousPythonAttrs.disabledTests or [ ];
});
disabledTestPaths = objprint.overridePythonAttrs (previousPythonAttrs: {
pname = "test-pytestCheckHook-disabledTestPaths-${previousPythonAttrs.pname}";
disabledTestPaths = [
"tests/test_basic.py"
]
++ previousPythonAttrs.disabledTestPaths or [ ];
});
disabledTestPaths-nonexistent = testers.testBuildFailure (
objprint.overridePythonAttrs (previousPythonAttrs: {
pname = "test-pytestCheckHook-disabledTestPaths-nonexistent-${previousPythonAttrs.pname}";
disabledTestPaths = [
"tests/test_foo.py"
]
++ previousPythonAttrs.disabledTestPaths or [ ];
})
);
disabledTestPaths-item = objprint.overridePythonAttrs (previousPythonAttrs: {
pname = "test-pytestCheckHook-disabledTestPaths-item-${previousPythonAttrs.pname}";
disabledTestPaths = [
"tests/test_basic.py::TestBasic"
]
++ previousPythonAttrs.disabledTestPaths or [ ];
});
disabledTestPaths-glob = objprint.overridePythonAttrs (previousPythonAttrs: {
pname = "test-pytestCheckHook-disabledTestPaths-glob-${previousPythonAttrs.pname}";
disabledTestPaths = [
"tests/test_obj*.py"
]
++ previousPythonAttrs.disabledTestPaths or [ ];
});
disabledTestPaths-glob-nonexistent = testers.testBuildFailure (
objprint.overridePythonAttrs (previousPythonAttrs: {
pname = "test-pytestCheckHook-disabledTestPaths-glob-nonexistent-${previousPythonAttrs.pname}";
disabledTestPaths = [
"tests/test_foo*.py"
]
++ previousPythonAttrs.disabledTestPaths or [ ];
})
);
enabledTests = objprint.overridePythonAttrs (previousPythonAttrs: {
pname = "test-pytestCheckHook-enabledTests-${previousPythonAttrs.pname}";
enabledTests = [
"TestBasic"
]
++ previousPythonAttrs.disabledTests or [ ];
});
enabledTests-expression = objprint.overridePythonAttrs (previousPythonAttrs: {
__structuredAttrs = true;
pname = "test-pytestCheckHook-enabledTests-expression-${previousPythonAttrs.pname}";
enabledTests = [
"TestBasic and test_print"
"test_str"
]
++ previousPythonAttrs.disabledTests or [ ];
});
enabledTests-disabledTests = objprint.overridePythonAttrs (previousPythonAttrs: {
pname = "test-pytestCheckHook-enabledTests-disabledTests-${previousPythonAttrs.pname}";
enabledTests = [
"TestBasic"
]
++ previousPythonAttrs.disabledTests or [ ];
disabledTests = [
"test_print"
]
++ previousPythonAttrs.disabledTests or [ ];
});
enabledTestPaths = objprint.overridePythonAttrs (previousPythonAttrs: {
pname = "test-pytestCheckHook-enabledTestPaths-${previousPythonAttrs.pname}";
enabledTestPaths = [
"tests/test_basic.py"
]
++ previousPythonAttrs.enabledTestPaths or [ ];
});
enabledTestPaths-nonexistent = testers.testBuildFailure (
objprint.overridePythonAttrs (previousPythonAttrs: {
pname = "test-pytestCheckHook-enabledTestPaths-nonexistent-${previousPythonAttrs.pname}";
enabledTestPaths = [
"tests/test_foo.py"
]
++ previousPythonAttrs.enabledTestPaths or [ ];
})
);
enabledTestPaths-dir = objprint.overridePythonAttrs (previousPythonAttrs: {
pname = "test-pytestCheckHook-enabledTestPaths-dir-${previousPythonAttrs.pname}";
enabledTestPaths = [
"tests"
]
++ previousPythonAttrs.enabledTestPaths or [ ];
});
enabledTestPaths-dir-disabledTestPaths = objprint.overridePythonAttrs (previousPythonAttrs: {
pname = "test-pytestCheckHook-enabledTestPaths-dir-disabledTestPaths-${previousPythonAttrs.pname}";
enabledTestPaths = [
"tests"
]
++ previousPythonAttrs.enabledTestPaths or [ ];
disabledTestPaths = [
"tests/test_basic.py"
]
++ previousPythonAttrs.disabledTestPaths or [ ];
});
enabledTestPaths-glob = objprint.overridePythonAttrs (previousPythonAttrs: {
pname = "test-pytestCheckHook-enabledTestPaths-glob-${previousPythonAttrs.pname}";
enabledTestPaths = [
"tests/test_obj*.py"
]
++ previousPythonAttrs.enabledTestPaths or [ ];
});
enabledTestPaths-glob-nonexistent = testers.testBuildFailure (
objprint.overridePythonAttrs (previousPythonAttrs: {
pname = "test-pytestCheckHook-enabledTestPaths-glob-nonexistent-${previousPythonAttrs.pname}";
enabledTestPaths = [
"tests/test_foo*.py"
]
++ previousPythonAttrs.enabledTestPaths or [ ];
})
);
enabledTestPaths-item = objprint.overridePythonAttrs (previousPythonAttrs: {
pname = "test-pytestCheckHook-enabledTestPaths-item-${previousPythonAttrs.pname}";
enabledTestPaths = [
"tests/test_basic.py::TestBasic"
]
++ previousPythonAttrs.enabledTestPaths or [ ];
});
};
};
} ./pytest-check-hook.sh
) { };
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;
};
passthru.tests = import ./python-catch-conflicts-hook-tests.nix {
inherit pythonOnBuildForHost runCommand;
inherit lib;
inherit (pkgs) coreutils gnugrep writeShellScript;
};
} ./python-catch-conflicts-hook.sh
) { };
pythonImportsCheckHook = callPackage (
{ makePythonHook }:
makePythonHook {
name = "python-imports-check-hook.sh";
substitutions = {
inherit pythonCheckInterpreter pythonSitePackages;
};
} ./python-imports-check-hook.sh
) { };
pythonNamespacesHook = callPackage (
{ makePythonHook, buildPackages }:
makePythonHook {
name = "python-namespaces-hook.sh";
substitutions = {
inherit pythonSitePackages;
inherit (buildPackages) findutils;
};
} ./python-namespaces-hook.sh
) { };
pythonOutputDistHook = callPackage (
{ makePythonHook }:
makePythonHook {
name = "python-output-dist-hook";
} ./python-output-dist-hook.sh
) { };
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" ]
);
bytecodeName = if isPy3k then "__pycache__" else "*.pyc";
};
} ./python-recompile-bytecode-hook.sh
) { };
pythonRelaxDepsHook = callPackage (
{ makePythonHook, wheel }:
makePythonHook {
name = "python-relax-deps-hook";
substitutions = {
inherit pythonInterpreter pythonSitePackages wheel;
};
} ./python-relax-deps-hook.sh
) { };
pythonRemoveBinBytecodeHook = callPackage (
{ makePythonHook }:
makePythonHook {
name = "python-remove-bin-bytecode-hook";
} ./python-remove-bin-bytecode-hook.sh
) { };
pythonRemoveTestsDirHook = callPackage (
{ makePythonHook }:
makePythonHook {
name = "python-remove-tests-dir-hook";
substitutions = {
inherit pythonSitePackages;
};
} ./python-remove-tests-dir-hook.sh
) { };
pythonRuntimeDepsCheckHook = callPackage (
{ makePythonHook, packaging }:
makePythonHook {
name = "python-runtime-deps-check-hook.sh";
propagatedBuildInputs = [ packaging ];
substitutions = {
inherit pythonInterpreter pythonSitePackages;
hook = ./python-runtime-deps-check-hook.py;
};
} ./python-runtime-deps-check-hook.sh
) { };
setuptoolsBuildHook = callPackage (
{
makePythonHook,
setuptools,
wheel,
}:
makePythonHook {
name = "setuptools-build-hook";
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
) { };
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 }:
makePythonHook {
name = "unittest-check-hook";
substitutions = {
inherit pythonCheckInterpreter;
};
} ./unittest-check-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 }:
makePythonHook {
name = "wheel-unpack-hook.sh";
propagatedBuildInputs = [ wheel ];
} ./wheel-unpack-hook.sh
) { };
wrapPython = callPackage ../wrap-python.nix {
inherit (pkgs.buildPackages) makeWrapper;
};
sphinxHook = callPackage (
{ makePythonHook, installShellFiles }:
makePythonHook {
name = "python${python.pythonVersion}-sphinx-hook";
propagatedBuildInputs = [
pythonOnBuildForHost.pkgs.sphinx
installShellFiles
];
substitutions = {
sphinxBuild = "${pythonOnBuildForHost.pkgs.sphinx}/bin/sphinx-build";
};
} ./sphinx-hook.sh
) { };
}

View File

@@ -0,0 +1,15 @@
# Setup hook to use for eggs
echo "Sourcing egg-build-hook"
eggBuildPhase() {
echo "Executing eggBuildPhase"
runHook preBuild
runHook postBuild
echo "Finished executing eggBuildPhase"
}
if [ -z "${dontUseEggBuild-}" ] && [ -z "${buildPhase-}" ]; then
echo "Using eggBuildPhase"
buildPhase=eggBuildPhase
fi

View File

@@ -0,0 +1,21 @@
# Setup hook for eggs
echo "Sourcing egg-install-hook"
eggInstallPhase() {
echo "Executing eggInstallPhase"
runHook preInstall
mkdir -p "$out/@pythonSitePackages@"
export PYTHONPATH="$out/@pythonSitePackages@:$PYTHONPATH"
find
@pythonInterpreter@ -m easy_install --prefix="$out" *.egg
runHook postInstall
echo "Finished executing eggInstallPhase"
}
if [ -z "${dontUseEggInstall-}" ] && [ -z "${installPhase-}" ]; then
echo "Using eggInstallPhase"
installPhase=eggInstallPhase
fi

View File

@@ -0,0 +1,17 @@
# Setup hook to use in case an egg is fetched
echo "Sourcing egg setup hook"
eggUnpackPhase() {
echo "Executing eggUnpackPhase"
runHook preUnpack
cp "$src" "$(stripHash "$src")"
# runHook postUnpack # Calls find...?
echo "Finished executing eggUnpackPhase"
}
if [ -z "${dontUseEggUnpack-}" ] && [ -z "${unpackPhase-}" ]; then
echo "Using eggUnpackPhase"
unpackPhase=eggUnpackPhase
fi

View File

@@ -0,0 +1,57 @@
# Setup hook to use for pip projects
# shellcheck shell=bash
echo "Sourcing pip-build-hook"
pipBuildPhase() {
echo "Executing pipBuildPhase"
runHook preBuild
mkdir -p dist
local -a flagsArray=(
--verbose
--no-index
--no-deps
--no-clean
--no-build-isolation
--wheel-dir dist
)
concatTo flagsArray pipBuildFlags
echo "Creating a wheel..."
echoCmd 'pip build flags' "${flagsArray[@]}"
@pythonInterpreter@ -m pip wheel "${flagsArray[@]}" .
echo "Finished creating a wheel..."
runHook postBuild
echo "Finished executing pipBuildPhase"
}
pipShellHook() {
echo "Executing pipShellHook"
runHook preShellHook
# Long-term setup.py should be dropped.
if [ -e pyproject.toml ]; then
tmp_path=$(mktemp -d)
export PATH="$tmp_path/bin:$PATH"
export PYTHONPATH="$tmp_path/@pythonSitePackages@:$PYTHONPATH"
mkdir -p "$tmp_path/@pythonSitePackages@"
@pythonInterpreter@ -m pip install -e . --prefix "$tmp_path" \
--no-build-isolation >&2
fi
runHook postShellHook
echo "Finished executing pipShellHook"
}
if [ -z "${dontUsePipBuild-}" ] && [ -z "${buildPhase-}" ]; then
echo "Using pipBuildPhase"
buildPhase=pipBuildPhase
fi
if [ -z "${shellHook-}" ]; then
echo "Using pipShellHook"
shellHook=pipShellHook
fi

View File

@@ -0,0 +1,34 @@
# Setup hook for pip.
# shellcheck shell=bash
echo "Sourcing pip-install-hook"
pipInstallPhase() {
echo "Executing pipInstallPhase"
runHook preInstall
# shellcheck disable=SC2154
mkdir -p "$out/@pythonSitePackages@"
export PYTHONPATH="$out/@pythonSitePackages@:$PYTHONPATH"
local -a flagsArray=(
--no-index
--no-warn-script-location
--prefix="$out"
--no-cache
)
concatTo flagsArray pipInstallFlags
pushd dist || return 1
echoCmd 'pip install flags' "${flagsArray[@]}"
@pythonInterpreter@ -m pip install ./*.whl "${flagsArray[@]}"
popd || return 1
runHook postInstall
echo "Finished executing pipInstallPhase"
}
if [ -z "${dontUsePipInstall-}" ] && [ -z "${installPhase-}" ]; then
echo "Using pipInstallPhase"
installPhase=pipInstallPhase
fi

View File

@@ -0,0 +1,36 @@
{ 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 {
pname = "dont-propagate-conflicting-deps";
version = "0.0.0";
src = projectSource;
pyproject = true;
dependencies = [
# At least one dependency of `build` should be included here to
# keep the test meaningful
(mkConflict pythonOnBuildForHost.pkgs.tomli)
];
build-system = [
# setuptools is also needed to build the example project
pythonOnBuildForHost.pkgs.setuptools
];
};
}

View File

@@ -0,0 +1,29 @@
# Setup hook to use for pypa/build projects
# shellcheck shell=bash
echo "Sourcing pypa-build-hook"
pypaBuildPhase() {
echo "Executing pypaBuildPhase"
runHook preBuild
local -a flagsArray=(
--no-isolation
--outdir dist/
--wheel
)
concatTo flagsArray pypaBuildFlags
echo "Creating a wheel..."
echoCmd 'pypa build flags' "${flagsArray[@]}"
@build@/bin/pyproject-build "${flagsArray[@]}"
echo "Finished creating a wheel..."
runHook postBuild
echo "Finished executing pypaBuildPhase"
}
if [ -z "${dontUsePypaBuild-}" ] && [ -z "${buildPhase-}" ]; then
echo "Using pypaBuildPhase"
buildPhase=pypaBuildPhase
fi

View File

@@ -0,0 +1,26 @@
# Setup hook for PyPA installer.
echo "Sourcing pypa-install-hook"
pypaInstallPhase() {
echo "Executing pypaInstallPhase"
runHook preInstall
pushd dist >/dev/null
for wheel in *.whl; do
@pythonInterpreter@ -m installer --prefix "$out" "$wheel"
echo "Successfully installed $wheel"
done
popd >/dev/null
export PYTHONPATH="$out/@pythonSitePackages@:$PYTHONPATH"
runHook postInstall
echo "Finished executing pypaInstallPhase"
}
if [ -z "${dontUsePypaInstall-}" ] && [ -z "${installPhase-}" ]; then
echo "Using pypaInstallPhase"
installPhase=pypaInstallPhase
fi

View File

@@ -0,0 +1,100 @@
# Setup hook for pytest
# shellcheck shell=bash
echo "Sourcing pytest-check-hook"
function _pytestIncludeExcludeExpr() {
local includeListName="$1"
local -n includeListRef="$includeListName"
local excludeListName="$2"
local -n excludeListRef="$excludeListName"
local includeString excludeString
if [[ -n "${includeListRef[*]-}" ]]; then
# ((element1) or (element2))
includeString="(($(concatStringsSep ") or (" "$includeListName")))"
fi
if [[ -n "${excludeListRef[*]-}" ]]; then
# and not (element1) and not (element2)
excludeString="${includeString:+ and }not ($(concatStringsSep ") and not (" "$excludeListName"))"
fi
echo "$includeString$excludeString"
}
function pytestCheckPhase() {
echo "Executing pytestCheckPhase"
runHook preCheck
# Compose arguments
local -a flagsArray=(-m pytest)
local -a _pathsArray
local path
_pathsArray=()
concatTo _pathsArray enabledTestPaths
for path in "${_pathsArray[@]}"; do
if [[ "$path" =~ "::" ]]; then
flagsArray+=("$path")
else
# The `|| kill "$$"` trick propagates the errors from the process substitutiton subshell,
# which is suggested by a StackOverflow answer: https://unix.stackexchange.com/a/217643
readarray -t -O"${#flagsArray[@]}" flagsArray < <(
@pythonCheckInterpreter@ - "$path" <<EOF || kill "$$"
import glob
import sys
path_glob=sys.argv[1]
if not len(path_glob):
sys.exit('Got an empty enabled tests path glob. Aborting')
path_expanded = glob.glob(path_glob)
if not len(path_expanded):
sys.exit('Enabled tests path glob "{}" does not match any paths. Aborting'.format(path_glob))
for path in path_expanded:
print(path)
EOF
)
fi
done
_pathsArray=()
concatTo _pathsArray disabledTestPaths
for path in "${_pathsArray[@]}"; do
if [[ "$path" =~ "::" ]]; then
flagsArray+=("--deselect=$path")
else
# Check if every path glob matches at least one path
@pythonCheckInterpreter@ - "$path" <<EOF
import glob
import sys
path_glob=sys.argv[1]
if not len(path_glob):
sys.exit('Got an empty disabled tests path glob. Aborting')
if next(glob.iglob(path_glob), None) is None:
sys.exit('Disabled tests path glob "{}" does not match any paths. Aborting'.format(path_glob))
EOF
flagsArray+=("--ignore-glob=$path")
fi
done
if [[ -n "${enabledTests[*]-}" ]] || [[ -n "${disabledTests[*]-}" ]]; then
flagsArray+=(-k "$(_pytestIncludeExcludeExpr enabledTests disabledTests)")
fi
if [[ -n "${enabledTestMarks[*]-}" ]] || [[ -n "${disabledTestMarks[*]-}" ]]; then
flagsArray+=(-m "$(_pytestIncludeExcludeExpr enabledTestMarks disabledTestMarks)")
fi
# Compatibility layer to the obsolete pytestFlagsArray
eval "flagsArray+=(${pytestFlagsArray[*]-})"
concatTo flagsArray pytestFlags
echoCmd 'pytest flags' "${flagsArray[@]}"
@pythonCheckInterpreter@ "${flagsArray[@]}"
runHook postCheck
echo "Finished executing pytestCheckPhase"
}
if [ -z "${dontUsePytestCheck-}" ] && [ -z "${installCheckPhase-}" ]; then
echo "Using pytestCheckPhase"
appendToVar preDistPhases pytestCheckPhase
fi

View File

@@ -0,0 +1,212 @@
{
lib,
pythonOnBuildForHost,
runCommand,
writeShellScript,
coreutils,
gnugrep,
}:
let
pythonPkgs = pythonOnBuildForHost.pkgs;
### UTILITIES
# customize a package so that its store paths differs
customize = pkg: pkg.overrideAttrs { some_modification = true; };
# generates minimal pyproject.toml
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
'';
# 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
);
# 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
{
### TEST CASES
# Test case which must not trigger any conflicts.
# 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)
];
};
# multi-output derivation with dependency on itself must not crash
cyclic-dependencies = generatePythonPackage {
pname = "cyclic-dependencies";
preFixup = ''
appendToVar 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
expectFailure package "Found duplicated packages in closure for dependency 'packaging'";
/*
More complex test case with a transitive conflict
Test sets up this dependency tree:
toplevel
dep1
leaf
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
expectFailure toplevel "Found duplicated packages in closure for dependency 'leaf'";
/*
Transitive conflict with multiple dependency chains leading to the
conflicting package.
Test sets up this dependency tree:
toplevel
dep1
leaf
dep2
leaf
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
expectFailure toplevel "Found duplicated packages in closure for dependency 'leaf'";
}

View File

@@ -0,0 +1,10 @@
# Setup hook for detecting conflicts in Python packages
echo "Sourcing python-catch-conflicts-hook.sh"
pythonCatchConflictsPhase() {
PYTHONPATH="@setuptools@/@pythonSitePackages@:$PYTHONPATH" @pythonInterpreter@ @catchConflicts@
}
if [ -z "${dontUsePythonCatchConflicts-}" ]; then
appendToVar preDistPhases pythonCatchConflictsPhase
fi

View File

@@ -0,0 +1,28 @@
# shellcheck shell=bash
# Setup hook for checking whether Python imports succeed
echo "Sourcing python-imports-check-hook.sh"
pythonImportsCheckPhase() {
echo "Executing pythonImportsCheckPhase"
if [[ -n "${pythonImportsCheck[*]-}" ]]; then
echo "Check whether the following modules can be imported: ${pythonImportsCheck[*]}"
# shellcheck disable=SC2154
pythonImportsCheckOutput="$out"
if [[ -n "${python-}" ]]; then
echo "Using python specific output \$python for imports check"
pythonImportsCheckOutput=$python
fi
export PYTHONPATH="$pythonImportsCheckOutput/@pythonSitePackages@:$PYTHONPATH"
# Python modules and namespaces names are Python identifiers, which must not contain spaces.
# See https://docs.python.org/3/reference/lexical_analysis.html
# shellcheck disable=SC2048,SC2086
(cd "$pythonImportsCheckOutput" && @pythonCheckInterpreter@ -c 'import sys; import importlib; list(map(lambda mod: importlib.import_module(mod), sys.argv[1:]))' ${pythonImportsCheck[*]})
fi
}
if [[ -z "${dontUsePythonImportsCheck-}" ]]; then
echo "Using pythonImportsCheckPhase"
appendToVar preDistPhases pythonImportsCheckPhase
fi

View File

@@ -0,0 +1,57 @@
# Clean up __init__.py's found in namespace directories
# shellcheck shell=bash
echo "Sourcing python-namespaces-hook"
pythonNamespacesHook() {
echo "Executing pythonNamespacesHook"
# Python namespaces names are Python identifiers, which must not contain spaces.
# See https://docs.python.org/3/reference/lexical_analysis.html
# shellcheck disable=SC2048
for namespace in ${pythonNamespaces[*]-}; do
echo "Enforcing PEP420 namespace: ${namespace}"
# split namespace into segments. "azure.mgmt" -> "azure mgmt"
IFS='.' read -ra pathSegments <<<"$namespace"
# shellcheck disable=SC2154
constructedPath=$out/@pythonSitePackages@
# Need to remove the __init__.py at each namespace level
# E.g `azure/__init__.py` and `azure/mgmt/__init__.py`
# The __pycache__ entry also needs to be removed
for pathSegment in "${pathSegments[@]}"; do
constructedPath=${constructedPath}/${pathSegment}
pathToRemove=${constructedPath}/__init__.py
pycachePath=${constructedPath}/__pycache__/
# remove __init__.py
if [ -f "$pathToRemove" ]; then
rm -v "$pathToRemove"
fi
# remove ${pname}-${version}-${python-interpeter}-nspkg.pth
#
# Still need to check that parent directory exists in the
# event of a "meta-package" package, which will just install
# other packages, but not produce anything in site-packages
# besides meta information
if [[ -d "${constructedPath}/../" ]] && [[ -z "${dontRemovePth-}" ]]; then
# .pth files are located in the parent directory of a module
@findutils@/bin/find "${constructedPath}/../" -name '*-nspkg.pth' -exec rm -v "{}" +
fi
# remove __pycache__/ entry, can be interpreter specific. E.g. __init__.cpython-38.pyc
# use null characters to perserve potential whitespace in filepath
if [ -d "$pycachePath" ]; then
@findutils@/bin/find "$pycachePath" -name '__init__*' -exec rm -v "{}" +
fi
done
done
echo "Finished executing pythonNamespacesHook"
}
if [[ -z "${dontUsePythonNamespacesHook-}" ]] && [[ -n "${pythonNamespaces-}" ]]; then
postFixupHooks+=(pythonNamespacesHook)
fi

View File

@@ -0,0 +1,27 @@
# Setup hook for storing dist folder (wheels/sdists) in a separate output
# shellcheck shell=bash
echo "Sourcing python-catch-conflicts-hook.sh"
pythonOutputDistPhase() {
echo "Executing pythonOutputDistPhase"
if [[ -d dist ]]; then
# shellcheck disable=SC2154
mv "dist" "$dist"
else
cat >&2 <<EOF
The build contains no ./dist directory.
If this project is not setuptools-based, pass
format = "other";
to buildPythonApplication/buildPythonPackage or another appropriate value as described here:
https://nixos.org/manual/nixpkgs/stable/#buildpythonpackage-function
EOF
false
fi
echo "Finished executing pythonOutputDistPhase"
}
appendToVar preFixupPhases pythonOutputDistPhase

View File

@@ -0,0 +1,24 @@
# Setup hook for recompiling bytecode.
# https://github.com/NixOS/nixpkgs/issues/81441
echo "Sourcing python-recompile-bytecode-hook.sh"
# Remove all bytecode from the $out output. Then, recompile only site packages folder
# Note this effectively duplicates `python-remove-bin-bytecode`, but long-term
# this hook should be removed again.
pythonRecompileBytecodePhase() {
# TODO: consider other outputs than $out
items="$(find "$out" -name "@bytecodeName@")"
if [[ -n $items ]]; then
for pycache in $items; do
rm -rf "$pycache"
done
fi
find "$out"/@pythonSitePackages@ -name "*.py" -exec @pythonInterpreter@ -OO -m compileall @compileArgs@ {} +
}
if [ -z "${dontUsePythonRecompileBytecode-}" ]; then
appendToVar postPhases pythonRecompileBytecodePhase
fi

View File

@@ -0,0 +1,112 @@
# shellcheck shell=bash
# Setup hook that modifies Python dependencies versions.
#
# Example usage in a derivation:
#
# { …, python3Packages, … }:
#
# python3Packages.buildPythonPackage {
# …
# # This will relax the dependency restrictions
# # e.g.: abc>1,<=2 -> abc
# pythonRelaxDeps = [ "abc" ];
# # This will relax all dependencies restrictions instead
# # pythonRelaxDeps = true;
# # This will remove the dependency
# # e.g.: cde>1,<=2 -> <nothing>
# pythonRemoveDeps = [ "cde" ];
# # This will remove all dependencies from the project
# # pythonRemoveDeps = true;
# …
# }
#
# IMPLEMENTATION NOTES:
#
# The "Requires-Dist" dependency specification format is described in PEP 508.
# Examples that the regular expressions in this hook needs to support:
#
# Requires-Dist: foo
# -> foo
# Requires-Dist: foo[optional]
# -> foo[optional]
# Requires-Dist: foo[optional]~=1.2.3
# -> foo[optional]
# Requires-Dist: foo[optional, xyz] (~=1.2.3)
# -> foo[optional, xyz]
# Requires-Dist: foo[optional]~=1.2.3 ; os_name = "posix"
# -> foo[optional] ; os_name = "posix"
#
# Currently unsupported: URL specs (foo @ https://example.com/a.zip).
_pythonRelaxDeps() {
local -r metadata_file="$1"
if [[ -z "${pythonRelaxDeps[*]-}" ]] || [[ "$pythonRelaxDeps" == 0 ]]; then
return
elif [[ "$pythonRelaxDeps" == 1 ]]; then
sed -i "$metadata_file" -r \
-e 's/(Requires-Dist: [a-zA-Z0-9_.-]+\s*(\[[^]]+\])?)[^;]*(;.*)?/\1\3/'
else
# shellcheck disable=SC2048
for dep in ${pythonRelaxDeps[*]}; do
sed -i "$metadata_file" -r \
-e "s/(Requires-Dist: $dep\s*(\[[^]]+\])?)[^;]*(;.*)?/\1\3/i"
done
fi
}
_pythonRemoveDeps() {
local -r metadata_file="$1"
if [[ -z "${pythonRemoveDeps[*]-}" ]] || [[ "$pythonRemoveDeps" == 0 ]]; then
return
elif [[ "$pythonRemoveDeps" == 1 ]]; then
sed -i "$metadata_file" \
-e '/Requires-Dist:.*/d'
else
# shellcheck disable=SC2048
for dep in ${pythonRemoveDeps[*]-}; do
sed -i "$metadata_file" \
-e "/Requires-Dist: $dep/d"
done
fi
}
pythonRelaxDepsHook() {
pushd dist
local -r unpack_dir="unpacked"
local -r metadata_file="$unpack_dir/*/*.dist-info/METADATA"
# We generally shouldn't have multiple wheel files, but let's be safer here
for wheel in *".whl"; do
PYTHONPATH="@wheel@/@pythonSitePackages@:$PYTHONPATH" \
@pythonInterpreter@ -m wheel unpack --dest "$unpack_dir" "$wheel"
rm -rf "$wheel"
# Using no quotes on purpose since we need to expand the glob from `$metadata_file`
# shellcheck disable=SC2086
_pythonRelaxDeps $metadata_file
# shellcheck disable=SC2086
_pythonRemoveDeps $metadata_file
if (("${NIX_DEBUG:-0}" >= 1)); then
echo "pythonRelaxDepsHook: resulting METADATA for '$wheel':"
# shellcheck disable=SC2086
cat $metadata_file
fi
PYTHONPATH="@wheel@/@pythonSitePackages@:$PYTHONPATH" \
@pythonInterpreter@ -m wheel pack "$unpack_dir/"*
done
# Remove the folder since it will otherwise be in the dist output.
rm -rf "$unpack_dir"
popd
}
postBuild+=" pythonRelaxDepsHook"

View File

@@ -0,0 +1,17 @@
# Setup hook for removing bytecode from the bin folder
echo "Sourcing python-remove-bin-bytecode-hook.sh"
# The bin folder is added to $PATH and should only contain executables.
# It may happen there are executables with a .py extension for which
# bytecode is generated. This hook removes that bytecode.
pythonRemoveBinBytecodePhase() {
if [ -d "$out/bin" ]; then
rm -rf "$out/bin/__pycache__" # Python 3
find "$out/bin" -type f -name "*.pyc" -delete # Python 2
fi
}
if [ -z "${dontUsePythonRemoveBinBytecode-}" ]; then
appendToVar preDistPhases pythonRemoveBinBytecodePhase
fi

View File

@@ -0,0 +1,18 @@
# Clean up top-level tests directory in site-package installation.
# shellcheck shell=bash
echo "Sourcing python-remove-tests-dir-hook"
pythonRemoveTestsDir() {
echo "Executing pythonRemoveTestsDir"
# shellcheck disable=SC2154
rm -rf "$out/@pythonSitePackages@/tests"
rm -rf "$out/@pythonSitePackages@/test"
echo "Finished executing pythonRemoveTestsDir"
}
if [ -z "${dontUsePythonRemoveTestsDir-}" ]; then
postFixupHooks+=(pythonRemoveTestsDir)
fi

View File

@@ -0,0 +1,105 @@
#!/usr/bin/env python3
"""
The runtimeDependenciesHook validates, that all dependencies specified
in wheel metadata are available in the local environment.
In case that does not hold, it will print missing dependencies and
violated version constraints.
"""
import importlib.metadata
import re
import sys
import tempfile
from argparse import ArgumentParser
from zipfile import ZipFile
from packaging.metadata import Metadata, parse_email
from packaging.requirements import Requirement
argparser = ArgumentParser()
argparser.add_argument("wheel", help="Path to the .whl file to test")
def error(msg: str) -> None:
print(f" - {msg}", file=sys.stderr)
def normalize_name(name: str) -> str:
"""
Normalize package names according to PEP503
"""
return re.sub(r"[-_.]+", "-", name).lower()
def get_manifest_text_from_wheel(wheel: str) -> str:
"""
Given a path to a wheel, this function will try to extract the
METADATA file in the wheels .dist-info directory.
"""
with ZipFile(wheel) as zipfile:
for zipinfo in zipfile.infolist():
if zipinfo.filename.endswith(".dist-info/METADATA"):
with tempfile.TemporaryDirectory() as tmp:
path = zipfile.extract(zipinfo, path=tmp)
with open(path, encoding="utf-8") as fd:
return fd.read()
raise RuntimeError("No METADATA file found in wheel")
def get_metadata(wheel: str) -> Metadata:
"""
Given a path to a wheel, returns a parsed Metadata object.
"""
text = get_manifest_text_from_wheel(wheel)
raw, _ = parse_email(text)
metadata = Metadata.from_raw(raw, validate=False)
return metadata
def test_requirement(requirement: Requirement) -> bool:
"""
Given a requirement specification, tests whether the dependency can
be resolved in the local environment, and whether it satisfies the
specified version constraints.
"""
if requirement.marker and not requirement.marker.evaluate():
# ignore requirements with incompatible markers
return True
package_name = normalize_name(requirement.name)
try:
package = importlib.metadata.distribution(requirement.name)
except importlib.metadata.PackageNotFoundError:
error(f"{package_name} not installed")
return False
# Allow prereleases, to give to give us some wiggle-room
requirement.specifier.prereleases = True
if requirement.specifier and package.version not in requirement.specifier:
error(
f"{package_name}{requirement.specifier} not satisfied by version {package.version}"
)
return False
return True
if __name__ == "__main__":
args = argparser.parse_args()
metadata = get_metadata(args.wheel)
requirements = metadata.requires_dist
if not requirements:
sys.exit(0)
tests = [test_requirement(requirement) for requirement in requirements]
if not all(tests):
sys.exit(1)

View File

@@ -0,0 +1,20 @@
# Setup hook for PyPA installer.
echo "Sourcing python-runtime-deps-check-hook"
pythonRuntimeDepsCheckHook() {
echo "Executing pythonRuntimeDepsCheck"
export PYTHONPATH="$out/@pythonSitePackages@:$PYTHONPATH"
for wheel in dist/*.whl; do
echo "Checking runtime dependencies for $(basename $wheel)"
@pythonInterpreter@ @hook@ "$wheel"
done
echo "Finished executing pythonRuntimeDepsCheck"
}
if [ -z "${dontCheckRuntimeDeps-}" ]; then
echo "Using pythonRuntimeDepsCheckHook"
appendToVar preInstallPhases pythonRuntimeDepsCheckHook
fi

View File

@@ -0,0 +1,35 @@
# Setup hook for setuptools.
# shellcheck shell=bash
echo "Sourcing setuptools-build-hook"
setuptoolsBuildPhase() {
echo "Executing setuptoolsBuildPhase"
local setuptools_has_parallel=@setuptools_has_parallel@
runHook preBuild
cp -f @setuppy@ nix_run_setup
local -a flagsArray=()
if [ -n "${setupPyGlobalFlags[*]-}" ]; then
concatTo flagsArray setupPyGlobalFlags
fi
if [ -n "$enableParallelBuilding" ]; then
if [ -n "$setuptools_has_parallel" ]; then
appendToVar setupPyBuildFlags --parallel "$NIX_BUILD_CORES"
fi
fi
if [ -n "${setupPyBuildFlags[*]-}" ]; then
flagsArray+=(build_ext)
concatTo flagsArray setupPyBuildFlags
fi
echoCmd 'setup.py build flags' "${flagsArray[@]}"
@pythonInterpreter@ nix_run_setup "${flagsArray[@]}" bdist_wheel
runHook postBuild
echo "Finished executing setuptoolsBuildPhase"
}
if [ -z "${dontUseSetuptoolsBuild-}" ] && [ -z "${buildPhase-}" ]; then
echo "Using setuptoolsBuildPhase"
buildPhase=setuptoolsBuildPhase
fi

View File

@@ -0,0 +1,20 @@
# shellcheck shell=bash
echo "Sourcing setuptools-rust-hook"
setuptoolsRustSetup() {
# This can work only if rustPlatform.cargoSetupHook is also included
if ! command -v cargoSetupPostPatchHook >/dev/null; then
echo "ERROR: setuptools-rust has to be used alongside with rustPlatform.cargoSetupHook!"
exit 1
fi
export PYO3_CROSS_LIB_DIR="@pyLibDir@"
export CARGO_BUILD_TARGET=@cargoBuildTarget@
# TODO theoretically setting linker should not be required because it is
# already set in pkgs/build-support/rust/hooks/default.nix but build fails
# on missing linker without this.
export CARGO_TARGET_@cargoLinkerVar@_LINKER=@targetLinker@
}
preConfigureHooks+=(setuptoolsRustSetup)

View File

@@ -0,0 +1,72 @@
# shellcheck shell=bash
echo "Sourcing sphinx-hook"
declare -a __sphinxBuilders
buildSphinxPhase() {
echo "Executing buildSphinxPhase"
local __sphinxRoot=""
runHook preBuildSphinx
if [[ -n "${sphinxRoot:-}" ]]; then # explicit root
if ! [[ -f "${sphinxRoot}/conf.py" ]]; then
echo 2>&1 "$sphinxRoot/conf.py: no such file"
exit 1
fi
__sphinxRoot=$sphinxRoot
else
for candidate in doc docs doc/source docs/source; do
if [[ -f "$candidate/conf.py" ]]; then
echo "Sphinx documentation found in $candidate"
__sphinxRoot=$candidate
break
fi
done
fi
if [[ -z "${__sphinxRoot}" ]]; then
echo 2>&1 "Sphinx documentation not found, use 'sphinxRoot' variable"
exit 1
fi
if [ -n "${sphinxBuilders-}" ]; then
eval "__sphinxBuilders=($sphinxBuilders)"
else
__sphinxBuilders=(html)
fi
for __builder in "${__sphinxBuilders[@]}"; do
echo "Executing sphinx-build with ${__builder} builder"
@sphinxBuild@ -M "${__builder}" "${__sphinxRoot}" ".sphinx/${__builder}" -v
done
runHook postBuildSphinx
}
installSphinxPhase() {
echo "Executing installSphinxPhase"
local docdir=""
runHook preInstallSphinx
for __builder in "${__sphinxBuilders[@]}"; do
# divert output for man builder
if [ "$__builder" == "man" ]; then
installManPage .sphinx/man/man/*
else
# shellcheck disable=2154
docdir="${doc:-$out}/share/doc/${name}"
mkdir -p "$docdir"
cp -r ".sphinx/${__builder}/${__builder}" "$docdir/"
rm -fr "${docdir}/${__builder}/_sources" "${docdir}/${__builder}/.buildinfo"
fi
done
runHook postInstallSphinx
}
appendToVar preFixupPhases buildSphinxPhase installSphinxPhase

View File

@@ -0,0 +1,26 @@
# Setup hook for unittest.
# shellcheck shell=bash
echo "Sourcing unittest-check-hook"
unittestCheckPhase() {
echo "Executing unittestCheckPhase"
runHook preCheck
local -a flagsArray=()
# Compatibility layer to the obsolete unittestFlagsArray
eval "flagsArray+=(${unittestFlagsArray[*]-})"
concatTo flagsArray unittestFlags
echoCmd 'unittest flags' "${flagsArray[@]}"
@pythonCheckInterpreter@ -m unittest discover "${flagsArray[@]}"
runHook postCheck
echo "Finished executing unittestCheckPhase"
}
if [[ -z "${dontUseUnittestCheck-}" ]] && [[ -z "${installCheckPhase-}" ]]; then
echo "Using unittestCheckPhase"
appendToVar preDistPhases unittestCheckPhase
fi

View File

@@ -0,0 +1,28 @@
venvShellHook() {
echo "Executing venvHook"
runHook preShellHook
if [ -d "${venvDir}" ]; then
echo "Skipping venv creation, '${venvDir}' already exists"
source "${venvDir}/bin/activate"
else
echo "Creating new venv environment in path: '${venvDir}'"
@pythonInterpreter@ -m venv "${venvDir}"
source "${venvDir}/bin/activate"
runHook postVenvCreation
fi
runHook postShellHook
echo "Finished executing venvShellHook"
}
if [ -z "${dontUseVenvShellHook:-}" ] && [ -z "${shellHook-}" ]; then
echo "Using venvShellHook"
if [ -z "${venvDir-}" ]; then
echo "Error: \`venvDir\` should be set when using \`venvShellHook\`."
exit 1
else
shellHook=venvShellHook
fi
fi

View File

@@ -0,0 +1,18 @@
# Setup hook to use in case a wheel is fetched
echo "Sourcing wheel setup hook"
wheelUnpackPhase() {
echo "Executing wheelUnpackPhase"
runHook preUnpack
mkdir -p dist
cp "$src" "dist/$(stripHash "$src")"
# runHook postUnpack # Calls find...?
echo "Finished executing wheelUnpackPhase"
}
if [ -z "${dontUseWheelUnpack-}" ] && [ -z "${unpackPhase-}" ]; then
echo "Using wheelUnpackPhase"
unpackPhase=wheelUnpackPhase
fi