Merge pull request #293151 from adisbladis/mk-python-derivation-refactor
mk-python-derivation: Refactor
This commit is contained in:
commit
cfb98374f3
1 changed files with 77 additions and 65 deletions
|
@ -28,6 +28,45 @@
|
|||
, eggInstallHook
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (builtins) unsafeGetAttrPos;
|
||||
inherit (lib)
|
||||
elem optionalString max stringLength fixedWidthString getName
|
||||
optional optionals optionalAttrs hasSuffix escapeShellArgs
|
||||
extendDerivation head splitString isBool;
|
||||
|
||||
leftPadName = name: against: let
|
||||
len = max (stringLength name) (stringLength against);
|
||||
in fixedWidthString len " " name;
|
||||
|
||||
isPythonModule = drv:
|
||||
# all pythonModules have the pythonModule attribute
|
||||
(drv ? "pythonModule")
|
||||
# Some pythonModules are turned in to a pythonApplication by setting the field to false
|
||||
&& (!isBool drv.pythonModule);
|
||||
|
||||
isMismatchedPython = drv: drv.pythonModule != python;
|
||||
|
||||
withDistOutput' = lib.flip elem ["pyproject" "setuptools" "wheel"];
|
||||
|
||||
isBootstrapInstallPackage' = lib.flip elem [ "flit-core" "installer" ];
|
||||
|
||||
isBootstrapPackage' = lib.flip elem ([
|
||||
"build" "packaging" "pyproject-hooks" "wheel"
|
||||
] ++ optionals (python.pythonOlder "3.11") [
|
||||
"tomli"
|
||||
]);
|
||||
|
||||
isSetuptoolsDependency' = lib.flip elem [ "setuptools" "wheel" ];
|
||||
|
||||
cleanAttrs = lib.flip removeAttrs [
|
||||
"disabled" "checkPhase" "checkInputs" "nativeCheckInputs" "doCheck" "doInstallCheck" "dontWrapPythonPrograms" "catchConflicts" "pyproject" "format"
|
||||
"disabledTestPaths" "outputs" "stdenv"
|
||||
"dependencies" "optional-dependencies" "build-system"
|
||||
];
|
||||
|
||||
in
|
||||
|
||||
{ name ? "${attrs.pname}-${attrs.version}"
|
||||
|
||||
# Build-time dependencies for the package
|
||||
|
@ -128,29 +167,15 @@ let
|
|||
else
|
||||
"setuptools";
|
||||
|
||||
withDistOutput = lib.elem format' ["pyproject" "setuptools" "wheel"];
|
||||
withDistOutput = withDistOutput' format';
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
throwMismatch = drv: let
|
||||
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}:
|
||||
|
||||
|
@ -173,64 +198,51 @@ let
|
|||
* 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 [ ${getName drv } ] }" ];
|
||||
|
||||
${optionalLocation}
|
||||
'';
|
||||
|
||||
checkDrv = drv:
|
||||
if (isPythonModule drv) && (isMismatchedPython drv)
|
||||
then throwMismatch drv
|
||||
checkDrv = attrName: drv:
|
||||
if (isPythonModule drv) && (isMismatchedPython drv) then throwMismatch attrName drv
|
||||
else drv;
|
||||
|
||||
in inputs: builtins.map (checkDrv) inputs;
|
||||
in attrName: inputs: map (checkDrv attrName) inputs;
|
||||
|
||||
isBootstrapInstallPackage = builtins.elem (attrs.pname or null) [
|
||||
"flit-core" "installer"
|
||||
];
|
||||
isBootstrapInstallPackage = isBootstrapInstallPackage' (attrs.pname or null);
|
||||
|
||||
isBootstrapPackage = isBootstrapInstallPackage || builtins.elem (attrs.pname or null) ([
|
||||
"build" "packaging" "pyproject-hooks" "wheel"
|
||||
] ++ lib.optionals (python.pythonOlder "3.11") [
|
||||
"tomli"
|
||||
]);
|
||||
isBootstrapPackage = isBootstrapInstallPackage || isBootstrapPackage' (attrs.pname or null);
|
||||
|
||||
isSetuptoolsDependency = builtins.elem (attrs.pname or null) [
|
||||
"setuptools" "wheel"
|
||||
];
|
||||
isSetuptoolsDependency = isSetuptoolsDependency' (attrs.pname or null);
|
||||
|
||||
passthru =
|
||||
attrs.passthru or { }
|
||||
// {
|
||||
updateScript = let
|
||||
filename = builtins.head (lib.splitString ":" self.meta.position);
|
||||
filename = head (splitString ":" self.meta.position);
|
||||
in attrs.passthru.updateScript or [ update-python-libraries filename ];
|
||||
}
|
||||
// lib.optionalAttrs (dependencies != []) {
|
||||
// optionalAttrs (dependencies != []) {
|
||||
inherit dependencies;
|
||||
}
|
||||
// lib.optionalAttrs (optional-dependencies != {}) {
|
||||
// optionalAttrs (optional-dependencies != {}) {
|
||||
inherit optional-dependencies;
|
||||
}
|
||||
// lib.optionalAttrs (build-system != []) {
|
||||
// optionalAttrs (build-system != []) {
|
||||
inherit build-system;
|
||||
};
|
||||
|
||||
# Keep extra attributes from `attrs`, e.g., `patchPhase', etc.
|
||||
self = toPythonModule (stdenv.mkDerivation ((builtins.removeAttrs attrs [
|
||||
"disabled" "checkPhase" "checkInputs" "nativeCheckInputs" "doCheck" "doInstallCheck" "dontWrapPythonPrograms" "catchConflicts" "pyproject" "format"
|
||||
"disabledTestPaths" "outputs" "stdenv"
|
||||
"dependencies" "optional-dependencies" "build-system"
|
||||
]) // {
|
||||
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
|
||||
] ++ lib.optionals (catchConflicts && !isBootstrapPackage && !isSetuptoolsDependency) [
|
||||
] ++ 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
|
||||
|
@ -240,13 +252,13 @@ let
|
|||
# because the hook that checks for conflicts uses setuptools.
|
||||
#
|
||||
pythonCatchConflictsHook
|
||||
] ++ lib.optionals removeBinBytecode [
|
||||
] ++ optionals removeBinBytecode [
|
||||
pythonRemoveBinBytecodeHook
|
||||
] ++ lib.optionals (lib.hasSuffix "zip" (attrs.src.name or "")) [
|
||||
] ++ optionals (hasSuffix "zip" (attrs.src.name or "")) [
|
||||
unzip
|
||||
] ++ lib.optionals (format' == "setuptools") [
|
||||
] ++ optionals (format' == "setuptools") [
|
||||
setuptoolsBuildHook
|
||||
] ++ lib.optionals (format' == "pyproject") [(
|
||||
] ++ optionals (format' == "pyproject") [(
|
||||
if isBootstrapPackage then
|
||||
pypaBuildHook.override {
|
||||
inherit (python.pythonOnBuildForHost.pkgs.bootstrap) build;
|
||||
|
@ -261,24 +273,24 @@ let
|
|||
}
|
||||
else
|
||||
pythonRuntimeDepsCheckHook
|
||||
)] ++ lib.optionals (format' == "wheel") [
|
||||
)] ++ optionals (format' == "wheel") [
|
||||
wheelUnpackHook
|
||||
] ++ lib.optionals (format' == "egg") [
|
||||
] ++ optionals (format' == "egg") [
|
||||
eggUnpackHook eggBuildHook eggInstallHook
|
||||
] ++ lib.optionals (format' != "other") [(
|
||||
] ++ optionals (format' != "other") [(
|
||||
if isBootstrapInstallPackage then
|
||||
pypaInstallHook.override {
|
||||
inherit (python.pythonOnBuildForHost.pkgs.bootstrap) installer;
|
||||
}
|
||||
else
|
||||
pypaInstallHook
|
||||
)] ++ lib.optionals (stdenv.buildPlatform == stdenv.hostPlatform) [
|
||||
)] ++ optionals (stdenv.buildPlatform == stdenv.hostPlatform) [
|
||||
# This is a test, however, it should be ran independent of the checkPhase and checkInputs
|
||||
pythonImportsCheckHook
|
||||
] ++ lib.optionals (python.pythonAtLeast "3.3") [
|
||||
] ++ optionals (python.pythonAtLeast "3.3") [
|
||||
# Optionally enforce PEP420 for python3
|
||||
pythonNamespacesHook
|
||||
] ++ lib.optionals withDistOutput [
|
||||
] ++ optionals withDistOutput [
|
||||
pythonOutputDistHook
|
||||
] ++ nativeBuildInputs ++ build-system;
|
||||
|
||||
|
@ -299,7 +311,7 @@ let
|
|||
doCheck = false;
|
||||
doInstallCheck = attrs.doCheck or true;
|
||||
nativeInstallCheckInputs = [
|
||||
] ++ lib.optionals (format' == "setuptools") [
|
||||
] ++ optionals (format' == "setuptools") [
|
||||
# Longer-term we should get rid of this and require
|
||||
# users of this function to set the `installCheckPhase` or
|
||||
# pass in a hook that sets it.
|
||||
|
@ -307,14 +319,14 @@ let
|
|||
] ++ nativeCheckInputs;
|
||||
installCheckInputs = checkInputs;
|
||||
|
||||
postFixup = lib.optionalString (!dontWrapPythonPrograms) ''
|
||||
postFixup = 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 ];
|
||||
disallowedReferences = optionals (python.stdenv.hostPlatform != python.stdenv.buildPlatform) [ python.pythonOnBuildForHost ];
|
||||
|
||||
outputs = outputs ++ lib.optional withDistOutput "dist";
|
||||
outputs = outputs ++ optional withDistOutput "dist";
|
||||
|
||||
inherit passthru;
|
||||
|
||||
|
@ -323,15 +335,15 @@ let
|
|||
platforms = python.meta.platforms;
|
||||
isBuildPythonPackage = python.meta.platforms;
|
||||
} // meta;
|
||||
} // lib.optionalAttrs (attrs?checkPhase) {
|
||||
} // 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;
|
||||
} // optionalAttrs (disabledTestPaths != []) {
|
||||
disabledTestPaths = escapeShellArgs disabledTestPaths;
|
||||
}));
|
||||
|
||||
in lib.extendDerivation
|
||||
in extendDerivation
|
||||
(disabled -> throw "${name} not supported for interpreter ${python.executable}")
|
||||
passthru
|
||||
self
|
||||
|
|
Loading…
Reference in a new issue