mirror of
https://github.com/vale981/poetry2nix
synced 2025-03-05 09:11:39 -05:00

Currently Poetry does not have a notion of build-time dependencies (setup-requires) in it's lock file. When installing a dependency built with Poetry this has to be added via an override which is really bad UX. This change always adds Poetry as an interim solution until we have resolved this in upstream Poetry.
158 lines
5.2 KiB
Nix
158 lines
5.2 KiB
Nix
{ autoPatchelfHook
|
|
, pkgs
|
|
, lib
|
|
, python
|
|
, buildPythonPackage
|
|
, pythonPackages
|
|
, poetryLib
|
|
}:
|
|
{ name
|
|
, version
|
|
, files
|
|
, source
|
|
, dependencies ? { }
|
|
, pythonPackages
|
|
, python-versions
|
|
, pwd
|
|
, sourceSpec
|
|
, supportedExtensions ? lib.importJSON ./extensions.json
|
|
, preferWheels ? false
|
|
, __isBootstrap ? false # Hack: Always add Poetry as a build input unless bootstrapping
|
|
, ...
|
|
}:
|
|
|
|
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}";
|
|
isSource = source != null;
|
|
isGit = isSource && source.type == "git";
|
|
isLocal = isSource && source.type == "directory";
|
|
localDepPath = toPath source.url;
|
|
pyProject = poetryLib.readTOML (localDepPath + "/pyproject.toml");
|
|
buildSystemPkgs = poetryLib.getBuildSystemPkgs {
|
|
inherit pythonPackages pyProject;
|
|
};
|
|
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;
|
|
entries = (if preferWheel then binaryDist ++ sourceDist else sourceDist ++ binaryDist) ++ eggs;
|
|
lockFileEntry = builtins.head entries;
|
|
_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"
|
|
"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;
|
|
|
|
inherit format;
|
|
|
|
doCheck = false; # We never get development deps
|
|
|
|
# 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
|
|
++ lib.optional (!__isBootstrap) [ pythonPackages.poetry ]
|
|
);
|
|
|
|
propagatedBuildInputs =
|
|
let
|
|
compat = isCompatible (poetryLib.getPythonVersion python);
|
|
deps = lib.filterAttrs
|
|
(n: v: v)
|
|
(
|
|
lib.mapAttrs
|
|
(
|
|
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;
|
|
};
|
|
}
|
|
) { }
|