selectWheel: init

This commit is contained in:
DavHau 2023-10-22 00:25:32 +01:00 committed by mergify[bot]
parent 0c6910060f
commit 19fce43579
2 changed files with 159 additions and 1 deletions

View File

@ -0,0 +1,147 @@
# MIT Licensed by @adisbladis
# this is vendored from poetry2nix atm, because it uses pyprojects pep599 instead of poetryLib,
# to get going while testing the design.
# FIXME: just port selectWheel to pyproject.nix
# https://github.com/nix-community/poetry2nix/blame/master/pep425.nix
{
lib,
stdenv,
pep599,
python,
isLinux ? stdenv.isLinux,
}: let
inherit (lib.strings) escapeRegex hasPrefix hasSuffix hasInfix splitString removeSuffix;
targetMachine = pep599.manyLinuxTargetMachines.${stdenv.targetPlatform.parsed.cpu.name} or null;
pythonVer = let
ver = builtins.splitVersion python.version;
major = builtins.elemAt ver 0;
minor = builtins.elemAt ver 1;
tags = ["cp" "py"];
in {inherit major minor tags;};
# Builds with and without pymalloc (m) are ABI compatible since python 3.8 (bpo-36707)
abiTag =
"cp${pythonVer.major}${pythonVer.minor}"
+ lib.optionalString (builtins.compareVersions python.version "3.8" < 0) "m";
#
# Parses wheel file returning an attribute set
#
toWheelAttrs = str: let
entries' = splitString "-" str;
el = builtins.length entries';
entryAt = builtins.elemAt entries';
# Hack: Remove version "suffixes" like 2.11.4-1
entries =
if el == 6
then [
(entryAt 0) # name
(entryAt 1) # version
# build tag is skipped
(entryAt (el - 3)) # python version
(entryAt (el - 2)) # abi
(entryAt (el - 1)) # platform
]
else entries';
p = removeSuffix ".whl" (builtins.elemAt entries 4);
in {
pkgName = builtins.elemAt entries 0;
pkgVer = builtins.elemAt entries 1;
pyVer = builtins.elemAt entries 2;
abi = builtins.elemAt entries 3;
platform = p;
};
#
# Builds list of acceptable osx wheel files
#
# <versions> accepted versions in descending order of preference
# <candidates> list of wheel files to select from
findBestMatches = versions: candidates: let
v = lib.lists.head versions;
vs = lib.lists.tail versions;
in
if (builtins.length versions == 0)
then []
else (builtins.filter (file: hasInfix v file) candidates) ++ (findBestMatches vs candidates);
# x = "cpXX" | "py2" | "py3" | "py2.py3"
isPyVersionCompatible = pyver @ {
major,
minor,
tags,
}: x: let
isCompat = m:
builtins.elem m.tag tags
&& m.major == major
&& builtins.compareVersions minor m.minor >= 0;
parseMarker = v: let
tag = builtins.substring 0 2 v;
major = builtins.substring 2 1 v;
end = builtins.substring 3 3 v;
minor =
if builtins.stringLength end > 0
then end
else "0";
in {inherit major minor tag;};
markers = splitString "." x;
in
lib.lists.any isCompat (map parseMarker markers);
#
# Selects the best matching wheel file from a list of files
#
selectWheel = files: let
filesWithoutSources = builtins.filter (file: hasSuffix ".whl" file) files;
isPyAbiCompatible = pyabi: x:
x
== "none"
|| hasPrefix pyabi x
|| hasPrefix x pyabi
|| (
# The CPython stable ABI is abi3 as in the shared library suffix.
python.passthru.implementation
== "cpython"
&& builtins.elemAt (lib.splitString "." python.version) 0 == "3"
&& x == "abi3"
);
withPython = ver: abi: x: (isPyVersionCompatible ver x.pyVer) && (isPyAbiCompatible abi x.abi);
withPlatform =
if isLinux
then
if targetMachine != null
then
# See PEP 600 for details.
(
p:
builtins.match "any|(linux|manylinux(1|2010|2014))_${escapeRegex targetMachine}|manylinux_[0-9]+_[0-9]+_${escapeRegex targetMachine}" p != null
)
else (p: p == "any")
else if stdenv.isDarwin
then
if stdenv.targetPlatform.isAarch64
then (p: p == "any" || (hasInfix "macosx" p && lib.lists.any (e: hasSuffix e p) ["arm64" "aarch64"]))
else (p: p == "any" || (hasInfix "macosx" p && hasSuffix "x86_64" p))
else (p: p == "any");
withPlatforms = x: lib.lists.any withPlatform (splitString "." x.platform);
filterWheel = file: let
f = toWheelAttrs file;
in
(withPython pythonVer abiTag f) && (withPlatforms f);
filtered = builtins.filter filterWheel filesWithoutSources;
choose = files: let
osxMatches = ["12_0" "11_0" "10_15" "10_14" "10_12" "10_11" "10_10" "10_9" "10_8" "10_7" "any"];
linuxMatches = ["manylinux1_" "manylinux2010_" "manylinux2014_" "manylinux_" "linux_" "any"];
chooseLinux = x: lib.head (findBestMatches linuxMatches x);
chooseOSX = x: lib.head (findBestMatches osxMatches x);
in
if isLinux
then chooseLinux files
else chooseOSX files;
in
if (builtins.length filtered == 0)
then null
else choose filtered;
in
selectWheel

View File

@ -10,9 +10,16 @@
libpyproject = import (dream2nix.inputs.pyproject-nix + "/lib") {inherit lib;}; libpyproject = import (dream2nix.inputs.pyproject-nix + "/lib") {inherit lib;};
selectWheel = import ../../../lib/internal/python/selectWheel.nix {
inherit lib;
pep599 = libpyproject.pep599;
python = config.deps.python3;
stdenv = config.deps.stdenv;
};
lock_data = lib.importTOML config.pdm.lockfile; lock_data = lib.importTOML config.pdm.lockfile;
environ = libpyproject.pep508.mkEnviron config.deps.python3; environ = libpyproject.pep508.mkEnviron config.deps.python3;
selector = libpdm.preferWheelSelector; selector = config.pdm.sourceSelector;
pyproject = libpdm.loadPdmPyProject (lib.importTOML config.pdm.pyproject); pyproject = libpdm.loadPdmPyProject (lib.importTOML config.pdm.pyproject);
@ -33,16 +40,20 @@ in {
../core/deps ../core/deps
./interface.nix ./interface.nix
]; ];
pdm.sourceSelector = lib.mkDefault selectWheel;
deps = {nixpkgs, ...}: { deps = {nixpkgs, ...}: {
inherit inherit
(nixpkgs) (nixpkgs)
curl curl
jq jq
stdenvNoCC stdenvNoCC
python3
stdenv
; ;
}; };
commonModule = { commonModule = {
options.sourceSelector = import ./sourceSelectorOption.nix {inherit lib;}; options.sourceSelector = import ./sourceSelectorOption.nix {inherit lib;};
# TODO: per dependency selector isn't yet respected
config.sourceSelector = lib.mkOptionDefault config.pdm.sourceSelector; config.sourceSelector = lib.mkOptionDefault config.pdm.sourceSelector;
}; };
groups = let groups = let