poetry2nix/mk-poetry-dep.nix

232 lines
7.9 KiB
Nix
Raw Normal View History

{ autoPatchelfHook
, lib
, python
, buildPythonPackage
, poetryLib
, pep508Env
, pyproject-nix
}:
{ name
, version
, pos ? __curPos
, extras ? [ ]
, 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 (python) stdenv;
inherit (pyproject-nix.pypa) normalizePackageName;
inherit (poetryLib) isCompatible getManyLinuxDeps fetchFromLegacy fetchFromPypi;
inherit (import ./pep425.nix {
inherit lib poetryLib python stdenv;
}) selectWheel
;
fileCandidates =
let
2023-10-23 12:23:59 -04:00
supportedRegex = "^.*(" + builtins.concatStringsSep "|" supportedExtensions + ")";
2021-09-17 17:01:43 +10:00
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}";
isLocked = lib.length fileCandidates > 0;
isSource = source != null;
isGit = isSource && source.type == "git";
2020-11-05 16:47:38 +00:00
isUrl = isSource && source.type == "url";
2023-01-17 21:28:51 +08:00
isWheelUrl = isSource && source.type == "url" && lib.strings.hasSuffix ".whl" source.url;
2021-07-10 13:38:34 +02:00
isDirectory = isSource && source.type == "directory";
isFile = isSource && source.type == "file";
isLegacy = isSource && source.type == "legacy";
localDepPath = toPath source.url;
buildSystemPkgs =
let
pyProjectPath = localDepPath + "/pyproject.toml";
pyProject = poetryLib.readTOML pyProjectPath;
in
2020-10-01 19:08:57 +02:00
if builtins.pathExists pyProjectPath then
poetryLib.getBuildSystemPkgs
{
inherit pythonPackages pyProject;
} else [ ];
pname = normalizePackageName name;
preferWheel' = preferWheel && pname != "wheel";
fileInfo =
let
isBdist = f: lib.strings.hasSuffix "whl" f.file;
isSdist = f: ! isBdist f && ! isEgg f;
isEgg = f: lib.strings.hasSuffix ".egg" f.file;
binaryDist = selectWheel fileCandidates;
sourceDist = builtins.filter isSdist fileCandidates;
eggs = builtins.filter isEgg fileCandidates;
# the `wheel` package cannot be built from a wheel, since that requires the wheel package
# this causes a circular dependency so we special-case ignore its `preferWheel` attribute value
entries = (if preferWheel' then binaryDist ++ sourceDist else sourceDist ++ binaryDist) ++ eggs;
2023-10-23 12:23:59 -04:00
lockFileEntry =
if lib.length entries > 0 then builtins.head entries
else throw "Missing suitable source/wheel file entry for ${name}"
2023-10-23 12:23:59 -04: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);
};
2023-01-17 21:28:51 +08:00
format = if isWheelUrl then "wheel" else if isDirectory || isGit || isUrl then "pyproject" else fileInfo.format;
hooks = python.pkgs.callPackage ./hooks { };
in
buildPythonPackage {
inherit pname version;
# Circumvent output separation (https://github.com/NixOS/nixpkgs/pull/190487)
format = if format == "pyproject" then "poetry2nix" else 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";
2020-01-17 18:06:09 +00:00
nativeBuildInputs = [
hooks.poetry2nixFixupHook
]
++ lib.optional (!pythonPackages.isPy27) hooks.poetry2nixPythonRequiresPatchHook
++ lib.optional (isLocked && (getManyLinuxDeps fileInfo.name).str != null) autoPatchelfHook
2022-10-07 23:09:59 +13:00
++ lib.optionals (format == "wheel") [
2023-10-23 12:23:59 -04:00
pythonPackages.wheelUnpackHook
pythonPackages.pypaInstallHook
2022-10-07 23:09:59 +13:00
]
2021-11-07 09:50:59 -05:00
++ lib.optionals (format == "pyproject") [
hooks.removePathDependenciesHook
hooks.removeGitDependenciesHook
2023-10-24 05:28:44 -04:00
hooks.pipBuildHook
2021-11-07 09:50:59 -05:00
];
2023-10-24 05:09:34 -04:00
buildInputs = lib.optional isLocked (getManyLinuxDeps fileInfo.name).pkg
2023-10-23 12:23:59 -04:00
++ lib.optional isDirectory buildSystemPkgs;
propagatedBuildInputs =
let
compat = isCompatible (poetryLib.getPythonVersion python);
2020-05-19 21:06:02 +01:00
deps = lib.filterAttrs
2023-10-23 12:23:59 -04:00
(_: v: v)
(
lib.mapAttrs
(
2023-10-23 12:23:59 -04:00
_: v:
let
constraints = v.python or "";
pep508Markers = v.markers or "";
in
compat constraints && (if pep508Markers == "" then true else
(pyproject-nix.pep508.evalMarkers
(pep508Env // {
extra = {
# All extras are always enabled
type = "extra";
value = lib.attrNames extras;
};
})
(pyproject-nix.pep508.parseMarkers pep508Markers)))
2020-05-19 21:06:02 +01:00
)
dependencies
);
depAttrs = lib.attrNames deps;
in
builtins.map (n: pythonPackages.${normalizePackageName n}) depAttrs;
inherit pos;
meta = {
broken = ! isCompatible (poetryLib.getPythonVersion python) python-versions;
license = [ ];
inherit (python.meta) platforms;
};
passthru = {
inherit args;
preferWheel = preferWheel';
};
# 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 =
2020-10-01 19:08:57 +02:00
if isGit then
(
builtins.fetchGit ({
2020-10-01 19:08:57 +02:00
inherit (source) url;
rev = source.resolved_reference or source.reference;
ref = sourceSpec.branch or (if sourceSpec ? tag then "refs/tags/${sourceSpec.tag}" else "HEAD");
} // (
2023-07-25 07:44:43 -04:00
lib.optionalAttrs
(((sourceSpec ? rev) || (sourceSpec ? branch) || (source ? resolved_reference) || (source ? reference))
&& (lib.versionAtLeast builtins.nixVersion "2.4"))
{
allRefs = true;
}) // (
lib.optionalAttrs (lib.versionAtLeast builtins.nixVersion "2.4") {
submodules = true;
})
)
2020-11-05 16:47:38 +00:00
)
2023-01-17 21:28:51 +08:00
else if isWheelUrl then
builtins.fetchurl
{
inherit (source) url;
sha256 = fileInfo.hash;
}
2020-11-05 16:47:38 +00:00
else if isUrl then
builtins.fetchTarball
{
inherit (source) url;
2023-01-17 20:05:23 +08:00
sha256 = fileInfo.hash;
2020-11-05 16:47:38 +00:00
}
2021-07-10 13:38:34 +02:00
else if isDirectory then
2020-11-05 16:47:38 +00:00
(poetryLib.cleanPythonSources { src = localDepPath; })
2021-07-10 13:38:34 +02:00
else if isFile then
localDepPath
else if isLegacy then
fetchFromLegacy
{
pname = name;
inherit python;
inherit (fileInfo) file hash;
inherit (source) url;
}
2020-11-05 16:47:38 +00:00
else
fetchFromPypi {
pname = name;
inherit (fileInfo) file hash kind;
inherit version;
2020-11-05 16:47:38 +00:00
};
}
2020-10-01 19:08:57 +02:00
)
{ }