poetry2nix/mk-poetry-dep.nix

161 lines
5 KiB
Nix
Raw Normal View History

{ autoPatchelfHook
, pkgs
, lib
, python
, buildPythonPackage
, pythonPackages
, poetryLib
}:
{ name
, version
, files
2019-12-27 19:16:55 +00:00
, source
, dependencies ? {}
, pythonPackages
, python-versions
, pwd
, sourceSpec
, supportedExtensions ? lib.importJSON ./extensions.json
, preferWheels ? false
, ...
}:
pythonPackages.callPackage (
{ preferWheel ? preferWheels
, ...
}@args:
let
inherit (poetryLib) isCompatible getManyLinuxDeps fetchFromPypi moduleName;
inherit (import ./pep425.nix {
inherit lib python;
inherit (pkgs) stdenv;
}) selectWheel
;
fileCandidates = let
supportedRegex = ("^.*?(" + builtins.concatStringsSep "|" supportedExtensions + ")");
matchesVersion = fname: builtins.match ("^.*" + builtins.replaceStrings [ "." ] [ "\\." ] version + ".*$") fname != null;
hasSupportedExtension = fname: builtins.match supportedRegex fname != null;
isCompatibleEgg = fname: ! lib.strings.hasSuffix ".egg" fname || lib.strings.hasSuffix "py${python.pythonVersion}.egg" fname;
in
builtins.filter (f: matchesVersion f.file && hasSupportedExtension f.file && isCompatibleEgg f.file) files;
toPath = s: pwd + "/${s}";
2019-12-27 19:16:55 +00:00
isSource = source != null;
isGit = isSource && source.type == "git";
isLocal = isSource && source.type == "directory";
2020-01-07 23:40:40 +00:00
localDepPath = toPath source.url;
pyProject = poetryLib.readTOML (localDepPath + "/pyproject.toml");
2020-01-07 23:40:40 +00:00
buildSystemPkgs = poetryLib.getBuildSystemPkgs {
inherit pythonPackages pyProject;
};
2020-01-07 23:40:40 +00:00
fileInfo = let
isBdist = f: lib.strings.hasSuffix "whl" f.file;
isSdist = f: ! isBdist f && ! isEgg f;
isEgg = f: lib.strings.hasSuffix ".egg" f.file;
2020-01-07 23:40:40 +00:00
binaryDist = selectWheel fileCandidates;
sourceDist = builtins.filter isSdist fileCandidates;
eggs = builtins.filter isEgg fileCandidates;
2020-01-12 20:00:17 +00:00
entries = (if preferWheel then binaryDist ++ sourceDist else sourceDist ++ binaryDist) ++ eggs;
lockFileEntry = builtins.head entries;
2020-01-07 23:40:40 +00:00
_isEgg = isEgg lockFileEntry;
in
rec {
inherit (lockFileEntry) file hash;
name = file;
format =
if _isEgg then "egg"
else if lib.strings.hasSuffix ".whl" name then "wheel"
else "pyproject";
kind =
if _isEgg then python.pythonVersion
else if format == "pyproject" then "source"
else (builtins.elemAt (lib.strings.splitString "-" name) 2);
};
# Prevent infinite recursion
skipSetupToolsSCM = [
"setuptools_scm"
"setuptools-scm"
2020-01-28 20:04:44 +00:00
"toml" # Toml is an extra for setuptools-scm
];
baseBuildInputs = lib.optional (! lib.elem name skipSetupToolsSCM) pythonPackages.setuptools-scm;
format = if isLocal then "pyproject" else if isGit then "pyproject" else fileInfo.format;
in
buildPythonPackage {
pname = moduleName name;
version = version;
2020-01-17 18:06:09 +00:00
inherit format;
doCheck = false; # We never get development deps
2020-01-17 18:06:09 +00:00
# Stripping pre-built wheels lead to `ELF load command address/offset not properly aligned`
dontStrip = format == "wheel";
nativeBuildInputs = [
pythonPackages.poetry2nixFixupHook
]
++ lib.optional (!isSource && (getManyLinuxDeps fileInfo.name).str != null) autoPatchelfHook
++ lib.optional (format == "pyproject") pythonPackages.removePathDependenciesHook
;
buildInputs = (
baseBuildInputs
++ lib.optional (!isSource) (getManyLinuxDeps fileInfo.name).pkg
++ lib.optional isLocal buildSystemPkgs
);
propagatedBuildInputs = let
compat = isCompatible (poetryLib.getPythonVersion python);
deps = lib.filterAttrs (n: v: v) (
lib.mapAttrs (
2020-03-14 23:13:51 +00:00
n: v:
let
constraints = v.python or "";
in
compat constraints
) dependencies
);
depAttrs = lib.attrNames deps;
in
builtins.map (n: pythonPackages.${moduleName n}) depAttrs;
meta = {
broken = ! isCompatible (poetryLib.getPythonVersion python) python-versions;
license = [];
inherit (python.meta) platforms;
};
passthru = {
inherit args;
};
# We need to retrieve kind from the interpreter and the filename of the package
# Interpreters should declare what wheel types they're compatible with (python type + ABI)
# Here we can then choose a file based on that info.
src = if isGit then (
builtins.fetchGit {
inherit (source) url;
rev = source.reference;
ref = sourceSpec.branch or sourceSpec.rev or sourceSpec.tag or "HEAD";
}
) else if isLocal then (poetryLib.cleanPythonSources { src = localDepPath; }) else fetchFromPypi {
pname = name;
inherit (fileInfo) file hash kind;
};
}
) {}