poetry2nix: 1.6.0 -> 1.6.1

This commit is contained in:
adisbladis 2020-03-27 14:49:31 +00:00
parent c669d2991b
commit 7401afc428
No known key found for this signature in database
GPG Key ID: 110BFAD44C6249B7
9 changed files with 527 additions and 511 deletions

View File

@ -2,10 +2,8 @@
, lib ? pkgs.lib , lib ? pkgs.lib
, version , version
}: }:
let let
inherit (pkgs) python3; inherit (pkgs) python3;
in in
pkgs.stdenv.mkDerivation { pkgs.stdenv.mkDerivation {
pname = "poetry2nix"; pname = "poetry2nix";

View File

@ -7,7 +7,7 @@ let
inherit (poetryLib) isCompatible readTOML; inherit (poetryLib) isCompatible readTOML;
# Poetry2nix version # Poetry2nix version
version = "1.6.0"; version = "1.6.1";
/* The default list of poetry2nix override overlays */ /* The default list of poetry2nix override overlays */
defaultPoetryOverrides = (import ./overrides.nix { inherit pkgs lib; }); defaultPoetryOverrides = (import ./overrides.nix { inherit pkgs lib; });
@ -34,91 +34,94 @@ let
, overrides ? [ defaultPoetryOverrides ] , overrides ? [ defaultPoetryOverrides ]
, python ? pkgs.python3 , python ? pkgs.python3
, pwd ? projectDir , pwd ? projectDir
}@attrs: let }@attrs:
poetryPkg = poetry.override { inherit python; }; let
poetryPkg = poetry.override { inherit python; };
pyProject = readTOML pyproject; pyProject = readTOML pyproject;
poetryLock = readTOML poetrylock; poetryLock = readTOML poetrylock;
lockFiles = lib.getAttrFromPath [ "metadata" "files" ] poetryLock; lockFiles = lib.getAttrFromPath [ "metadata" "files" ] poetryLock;
specialAttrs = [ specialAttrs = [
"overrides" "overrides"
"poetrylock" "poetrylock"
"pwd" "projectDir"
]; "pwd"
passedAttrs = builtins.removeAttrs attrs specialAttrs; ];
passedAttrs = builtins.removeAttrs attrs specialAttrs;
evalPep508 = mkEvalPep508 python; evalPep508 = mkEvalPep508 python;
# Filter packages by their PEP508 markers & pyproject interpreter version # Filter packages by their PEP508 markers & pyproject interpreter version
partitions = let partitions = let
supportsPythonVersion = pkgMeta: if pkgMeta ? marker then (evalPep508 pkgMeta.marker) else true; supportsPythonVersion = pkgMeta: if pkgMeta ? marker then (evalPep508 pkgMeta.marker) else true;
in
lib.partition supportsPythonVersion poetryLock.package;
compatible = partitions.right;
incompatible = partitions.wrong;
# Create an overriden version of pythonPackages
#
# We need to avoid mixing multiple versions of pythonPackages in the same
# closure as python can only ever have one version of a dependency
baseOverlay = self: super:
let
getDep = depName: self.${depName};
lockPkgs = builtins.listToAttrs (
builtins.map (
pkgMeta: rec {
name = pkgMeta.name;
value = self.mkPoetryDep (
pkgMeta // {
inherit pwd;
source = pkgMeta.source or null;
files = lockFiles.${name};
pythonPackages = self;
}
);
}
) compatible
);
in in
lockPkgs; lib.partition supportsPythonVersion poetryLock.package;
overlays = builtins.map getFunctorFn (
[
(
self: super: let
hooks = self.callPackage ./hooks {};
in
{
mkPoetryDep = self.callPackage ./mk-poetry-dep.nix {
inherit pkgs lib python poetryLib;
};
poetry = poetryPkg;
# The canonical name is setuptools-scm
setuptools-scm = super.setuptools_scm;
inherit (hooks) removePathDependenciesHook poetry2nixFixupHook; compatible = partitions.right;
} incompatible = partitions.wrong;
)
# Null out any filtered packages, we don't want python.pkgs from nixpkgs
(self: super: builtins.listToAttrs (builtins.map (x: { name = x.name; value = null; }) incompatible))
# Create poetry2nix layer
baseOverlay
] ++ # User provided overrides
overrides
);
packageOverrides = lib.foldr lib.composeExtensions (self: super: {}) overlays; # Create an overriden version of pythonPackages
#
# We need to avoid mixing multiple versions of pythonPackages in the same
# closure as python can only ever have one version of a dependency
baseOverlay = self: super:
let
getDep = depName: self.${depName};
py = python.override { inherit packageOverrides; self = py; }; lockPkgs = builtins.listToAttrs (
in builtins.map (
{ pkgMeta: rec {
python = py; name = pkgMeta.name;
poetryPackages = map (pkg: py.pkgs.${pkg.name}) compatible; value = self.mkPoetryDep (
poetryLock = poetryLock; pkgMeta // {
inherit pyProject; inherit pwd;
}; source = pkgMeta.source or null;
files = lockFiles.${name};
pythonPackages = self;
}
);
}
) compatible
);
in
lockPkgs;
overlays = builtins.map getFunctorFn (
[
(
self: super:
let
hooks = self.callPackage ./hooks {};
in
{
mkPoetryDep = self.callPackage ./mk-poetry-dep.nix {
inherit pkgs lib python poetryLib;
};
poetry = poetryPkg;
# The canonical name is setuptools-scm
setuptools-scm = super.setuptools_scm;
inherit (hooks) removePathDependenciesHook poetry2nixFixupHook;
}
)
# Null out any filtered packages, we don't want python.pkgs from nixpkgs
(self: super: builtins.listToAttrs (builtins.map (x: { name = x.name; value = null; }) incompatible))
# Create poetry2nix layer
baseOverlay
] ++ # User provided overrides
overrides
);
packageOverrides = lib.foldr lib.composeExtensions (self: super: {}) overlays;
py = python.override { inherit packageOverrides; self = py; };
in
{
python = py;
poetryPackages = map (pkg: py.pkgs.${pkg.name}) compatible;
poetryLock = poetryLock;
inherit pyProject;
};
/* Returns a package with a python interpreter and all packages specified in the poetry.lock lock file. /* Returns a package with a python interpreter and all packages specified in the poetry.lock lock file.
@ -153,76 +156,78 @@ let
, python ? pkgs.python3 , python ? pkgs.python3
, pwd ? projectDir , pwd ? projectDir
, ... , ...
}@attrs: let }@attrs:
poetryPython = mkPoetryPackages { let
inherit pyproject poetrylock overrides python pwd; poetryPython = mkPoetryPackages {
}; inherit pyproject poetrylock overrides python pwd;
py = poetryPython.python; };
py = poetryPython.python;
inherit (poetryPython) pyProject; inherit (poetryPython) pyProject;
specialAttrs = [ specialAttrs = [
"overrides" "overrides"
"poetrylock" "poetrylock"
"pwd" "projectDir"
"pyproject" "pwd"
]; "pyproject"
passedAttrs = builtins.removeAttrs attrs specialAttrs; ];
passedAttrs = builtins.removeAttrs attrs specialAttrs;
# Get dependencies and filter out depending on interpreter version # Get dependencies and filter out depending on interpreter version
getDeps = depAttr: let getDeps = depAttr:
compat = isCompatible py.pythonVersion; let
deps = pyProject.tool.poetry.${depAttr} or {}; compat = isCompatible py.pythonVersion;
depAttrs = builtins.map (d: lib.toLower d) (builtins.attrNames deps); deps = pyProject.tool.poetry.${depAttr} or {};
in depAttrs = builtins.map (d: lib.toLower d) (builtins.attrNames deps);
builtins.map (
dep: let
pkg = py.pkgs."${dep}";
constraints = deps.${dep}.python or "";
isCompat = compat constraints;
in in
if isCompat then pkg else null builtins.map (
) depAttrs; dep:
let
pkg = py.pkgs."${dep}";
constraints = deps.${dep}.python or "";
isCompat = compat constraints;
in
if isCompat then pkg else null
) depAttrs;
getInputs = attr: attrs.${attr} or []; getInputs = attr: attrs.${attr} or [];
mkInput = attr: extraInputs: getInputs attr ++ extraInputs; mkInput = attr: extraInputs: getInputs attr ++ extraInputs;
buildSystemPkgs = poetryLib.getBuildSystemPkgs { buildSystemPkgs = poetryLib.getBuildSystemPkgs {
inherit pyProject; inherit pyProject;
pythonPackages = py.pkgs; pythonPackages = py.pkgs;
}; };
in
py.pkgs.buildPythonApplication (
passedAttrs // {
pname = pyProject.tool.poetry.name;
version = pyProject.tool.poetry.version;
in inherit src;
py.pkgs.buildPythonApplication (
passedAttrs // {
pname = pyProject.tool.poetry.name;
version = pyProject.tool.poetry.version;
inherit src; format = "pyproject";
format = "pyproject"; buildInputs = mkInput "buildInputs" buildSystemPkgs;
propagatedBuildInputs = mkInput "propagatedBuildInputs" (getDeps "dependencies") ++ ([ py.pkgs.setuptools ]);
nativeBuildInputs = mkInput "nativeBuildInputs" [ pkgs.yj py.pkgs.removePathDependenciesHook ];
checkInputs = mkInput "checkInputs" (getDeps "dev-dependencies");
buildInputs = mkInput "buildInputs" buildSystemPkgs; passthru = {
propagatedBuildInputs = mkInput "propagatedBuildInputs" (getDeps "dependencies") ++ ([ py.pkgs.setuptools ]); python = py;
nativeBuildInputs = mkInput "nativeBuildInputs" [ pkgs.yj py.pkgs.removePathDependenciesHook ]; };
checkInputs = mkInput "checkInputs" (getDeps "dev-dependencies");
passthru = { meta = meta // {
python = py; inherit (pyProject.tool.poetry) description homepage;
}; inherit (py.meta) platforms;
license = getLicenseBySpdxId (pyProject.tool.poetry.license or "unknown");
};
meta = meta // { }
inherit (pyProject.tool.poetry) description homepage; );
inherit (py.meta) platforms;
license = getLicenseBySpdxId (pyProject.tool.poetry.license or "unknown");
};
}
);
/* Poetry2nix CLI used to supplement SHA-256 hashes for git dependencies */ /* Poetry2nix CLI used to supplement SHA-256 hashes for git dependencies */
cli = import ./cli.nix { inherit pkgs lib version; }; cli = import ./cli.nix { inherit pkgs lib version; };
in in
{ {
inherit mkPoetryEnv mkPoetryApplication mkPoetryPackages cli version; inherit mkPoetryEnv mkPoetryApplication mkPoetryPackages cli version;
@ -236,11 +241,12 @@ in
*/ */
defaultPoetryOverrides = { defaultPoetryOverrides = {
__functor = defaultPoetryOverrides; __functor = defaultPoetryOverrides;
overrideOverlay = fn: self: super: let overrideOverlay = fn: self: super:
defaultSet = defaultPoetryOverrides self super; let
customSet = fn self super; defaultSet = defaultPoetryOverrides self super;
in customSet = fn self super;
defaultSet // customSet; in
defaultSet // customSet;
}; };
/* /*

View File

@ -3,7 +3,6 @@
, makeSetupHook , makeSetupHook
, yj , yj
}: }:
let let
pythonInterpreter = python.pythonForBuild.interpreter; pythonInterpreter = python.pythonForBuild.interpreter;
in in

View File

@ -9,29 +9,30 @@ let
); );
# Compare a semver expression with a version # Compare a semver expression with a version
isCompatible = version: let isCompatible = version:
operators = { let
"||" = cond1: cond2: cond1 || cond2; operators = {
"," = cond1: cond2: cond1 && cond2; # , means && "||" = cond1: cond2: cond1 || cond2;
"&&" = cond1: cond2: cond1 && cond2; "," = cond1: cond2: cond1 && cond2; # , means &&
}; "&&" = cond1: cond2: cond1 && cond2;
splitRe = "(" + (builtins.concatStringsSep "|" (builtins.map (x: lib.replaceStrings [ "|" ] [ "\\|" ] x) (lib.attrNames operators))) + ")"; };
in splitRe = "(" + (builtins.concatStringsSep "|" (builtins.map (x: lib.replaceStrings [ "|" ] [ "\\|" ] x) (lib.attrNames operators))) + ")";
expr: in
let expr:
tokens = builtins.filter (x: x != "") (builtins.split splitRe expr); let
combine = acc: v: tokens = builtins.filter (x: x != "") (builtins.split splitRe expr);
let combine = acc: v:
isOperator = builtins.typeOf v == "list"; let
operator = if isOperator then (builtins.elemAt v 0) else acc.operator; isOperator = builtins.typeOf v == "list";
in operator = if isOperator then (builtins.elemAt v 0) else acc.operator;
if isOperator then (acc // { inherit operator; }) else { in
inherit operator; if isOperator then (acc // { inherit operator; }) else {
state = operators."${operator}" acc.state (satisfiesSemver version v); inherit operator;
}; state = operators."${operator}" acc.state (satisfiesSemver version v);
initial = { operator = "&&"; state = true; }; };
in initial = { operator = "&&"; state = true; };
if expr == "" then true else (builtins.foldl' combine initial tokens).state; in
if expr == "" then true else (builtins.foldl' combine initial tokens).state;
fromTOML = builtins.fromTOML or fromTOML = builtins.fromTOML or
( (
@ -88,23 +89,25 @@ let
getBuildSystemPkgs = getBuildSystemPkgs =
{ pythonPackages { pythonPackages
, pyProject , pyProject
}: let }:
buildSystem = lib.getAttrFromPath [ "build-system" "build-backend" ] pyProject; let
drvAttr = builtins.elemAt (builtins.split "\\.|:" buildSystem) 0; buildSystem = lib.getAttrFromPath [ "build-system" "build-backend" ] pyProject;
in drvAttr = builtins.elemAt (builtins.split "\\.|:" buildSystem) 0;
if buildSystem == "" then [] else ( in
[ pythonPackages.${drvAttr} or (throw "unsupported build system ${buildSystem}") ] if buildSystem == "" then [] else (
); [ pythonPackages.${drvAttr} or (throw "unsupported build system ${buildSystem}") ]
);
# Find gitignore files recursively in parent directory stopping with .git # Find gitignore files recursively in parent directory stopping with .git
findGitIgnores = path: let findGitIgnores = path:
parent = path + "/.."; let
gitIgnore = path + "/.gitignore"; parent = path + "/..";
isGitRoot = builtins.pathExists (path + "/.git"); gitIgnore = path + "/.gitignore";
hasGitIgnore = builtins.pathExists gitIgnore; isGitRoot = builtins.pathExists (path + "/.git");
gitIgnores = if hasGitIgnore then [ gitIgnore ] else []; hasGitIgnore = builtins.pathExists gitIgnore;
in gitIgnores = if hasGitIgnore then [ gitIgnore ] else [];
lib.optionals (builtins.toString path != "/" && ! isGitRoot) (findGitIgnores parent) ++ gitIgnores; in
lib.optionals (builtins.toString path != "/" && ! isGitRoot) (findGitIgnores parent) ++ gitIgnores;
/* /*
Provides a source filtering mechanism that: Provides a source filtering mechanism that:
@ -113,21 +116,21 @@ let
- Filters pycache/pyc files - Filters pycache/pyc files
- Uses cleanSourceFilter to filter out .git/.hg, .o/.so, editor backup files & nix result symlinks - Uses cleanSourceFilter to filter out .git/.hg, .o/.so, editor backup files & nix result symlinks
*/ */
cleanPythonSources = { src }: let cleanPythonSources = { src }:
gitIgnores = findGitIgnores src; let
pycacheFilter = name: type: gitIgnores = findGitIgnores src;
(type == "directory" && ! lib.strings.hasInfix "__pycache__" name) pycacheFilter = name: type:
|| (type == "regular" && ! lib.strings.hasSuffix ".pyc" name) (type == "directory" && ! lib.strings.hasInfix "__pycache__" name)
; || (type == "regular" && ! lib.strings.hasSuffix ".pyc" name)
in ;
lib.cleanSourceWith { in
filter = lib.cleanSourceFilter; lib.cleanSourceWith {
src = lib.cleanSourceWith { filter = lib.cleanSourceFilter;
filter = pkgs.nix-gitignore.gitignoreFilterPure pycacheFilter gitIgnores src; src = lib.cleanSourceWith {
inherit src; filter = pkgs.nix-gitignore.gitignoreFilterPure pycacheFilter gitIgnores src;
inherit src;
};
}; };
};
in in
{ {
inherit inherit

View File

@ -22,9 +22,7 @@ pythonPackages.callPackage (
{ preferWheel ? false { preferWheel ? false
, ... , ...
}@args: }@args:
let let
inherit (poetryLib) isCompatible getManyLinuxDeps fetchFromPypi; inherit (poetryLib) isCompatible getManyLinuxDeps fetchFromPypi;
inherit (import ./pep425.nix { inherit (import ./pep425.nix {
@ -68,7 +66,6 @@ pythonPackages.callPackage (
lockFileEntry = builtins.head entries; lockFileEntry = builtins.head entries;
_isEgg = isEgg lockFileEntry; _isEgg = isEgg lockFileEntry;
in in
rec { rec {
inherit (lockFileEntry) file hash; inherit (lockFileEntry) file hash;
@ -92,7 +89,6 @@ pythonPackages.callPackage (
baseBuildInputs = lib.optional (! lib.elem name skipSetupToolsSCM) pythonPackages.setuptools-scm; baseBuildInputs = lib.optional (! lib.elem name skipSetupToolsSCM) pythonPackages.setuptools-scm;
format = if isLocal then "pyproject" else if isGit then "setuptools" else fileInfo.format; format = if isLocal then "pyproject" else if isGit then "setuptools" else fileInfo.format;
in in
buildPythonPackage { buildPythonPackage {
@ -123,10 +119,11 @@ pythonPackages.callPackage (
compat = isCompatible python.pythonVersion; compat = isCompatible python.pythonVersion;
deps = lib.filterAttrs (n: v: v) ( deps = lib.filterAttrs (n: v: v) (
lib.mapAttrs ( lib.mapAttrs (
n: v: let n: v:
constraints = v.python or ""; let
in constraints = v.python or "";
compat constraints in
compat constraints
) dependencies ) dependencies
); );
depAttrs = lib.attrNames deps; depAttrs = lib.attrNames deps;

View File

@ -195,39 +195,39 @@ self: super:
); );
matplotlib = super.matplotlib.overrideAttrs ( matplotlib = super.matplotlib.overrideAttrs (
old: let old:
enableGhostscript = old.passthru.enableGhostscript or false; let
enableGtk3 = old.passthru.enableTk or false; enableGhostscript = old.passthru.enableGhostscript or false;
enableQt = old.passthru.enableQt or false; enableGtk3 = old.passthru.enableTk or false;
enableTk = old.passthru.enableTk or false; enableQt = old.passthru.enableQt or false;
enableTk = old.passthru.enableTk or false;
inherit (pkgs.darwin.apple_sdk.frameworks) Cocoa; inherit (pkgs.darwin.apple_sdk.frameworks) Cocoa;
in
{
NIX_CFLAGS_COMPILE = stdenv.lib.optionalString stdenv.isDarwin "-I${pkgs.libcxx}/include/c++/v1";
in XDG_RUNTIME_DIR = "/tmp";
{
NIX_CFLAGS_COMPILE = stdenv.lib.optionalString stdenv.isDarwin "-I${pkgs.libcxx}/include/c++/v1";
XDG_RUNTIME_DIR = "/tmp"; buildInputs = old.buildInputs
++ lib.optional enableGhostscript pkgs.ghostscript
++ lib.optional stdenv.isDarwin [ Cocoa ];
buildInputs = old.buildInputs nativeBuildInputs = old.nativeBuildInputs ++ [
++ lib.optional enableGhostscript pkgs.ghostscript pkgs.pkgconfig
++ lib.optional stdenv.isDarwin [ Cocoa ]; ];
nativeBuildInputs = old.nativeBuildInputs ++ [ propagatedBuildInputs = old.propagatedBuildInputs ++ [
pkgs.pkgconfig pkgs.libpng
]; pkgs.freetype
]
++ stdenv.lib.optionals enableGtk3 [ pkgs.cairo self.pycairo pkgs.gtk3 pkgs.gobject-introspection self.pygobject3 ]
++ stdenv.lib.optionals enableTk [ pkgs.tcl pkgs.tk self.tkinter pkgs.libX11 ]
++ stdenv.lib.optionals enableQt [ self.pyqt5 ]
;
propagatedBuildInputs = old.propagatedBuildInputs ++ [ inherit (super.matplotlib) patches;
pkgs.libpng }
pkgs.freetype
]
++ stdenv.lib.optionals enableGtk3 [ pkgs.cairo self.pycairo pkgs.gtk3 pkgs.gobject-introspection self.pygobject3 ]
++ stdenv.lib.optionals enableTk [ pkgs.tcl pkgs.tk self.tkinter pkgs.libX11 ]
++ stdenv.lib.optionals enableQt [ self.pyqt5 ]
;
inherit (super.matplotlib) patches;
}
); );
# Calls Cargo at build time for source builds and is really tricky to package # Calls Cargo at build time for source builds and is really tricky to package
@ -266,36 +266,37 @@ self: super:
); );
numpy = super.numpy.overrideAttrs ( numpy = super.numpy.overrideAttrs (
old: let old:
blas = old.passthru.args.blas or pkgs.openblasCompat; let
blasImplementation = lib.nameFromURL blas.name "-"; blas = old.passthru.args.blas or pkgs.openblasCompat;
cfg = pkgs.writeTextFile { blasImplementation = lib.nameFromURL blas.name "-";
name = "site.cfg"; cfg = pkgs.writeTextFile {
text = ( name = "site.cfg";
lib.generators.toINI {} { text = (
${blasImplementation} = { lib.generators.toINI {} {
include_dirs = "${blas}/include"; ${blasImplementation} = {
library_dirs = "${blas}/lib"; include_dirs = "${blas}/include";
} // lib.optionalAttrs (blasImplementation == "mkl") { library_dirs = "${blas}/lib";
mkl_libs = "mkl_rt"; } // lib.optionalAttrs (blasImplementation == "mkl") {
lapack_libs = ""; mkl_libs = "mkl_rt";
}; lapack_libs = "";
} };
); }
}; );
in
{
nativeBuildInputs = old.nativeBuildInputs ++ [ pkgs.gfortran ];
buildInputs = old.buildInputs ++ [ blas self.cython ];
enableParallelBuilding = true;
preBuild = ''
ln -s ${cfg} site.cfg
'';
passthru = old.passthru // {
blas = blas;
inherit blasImplementation cfg;
}; };
} in
{
nativeBuildInputs = old.nativeBuildInputs ++ [ pkgs.gfortran ];
buildInputs = old.buildInputs ++ [ blas self.cython ];
enableParallelBuilding = true;
preBuild = ''
ln -s ${cfg} site.cfg
'';
passthru = old.passthru // {
blas = blas;
inherit blasImplementation cfg;
};
}
); );
openexr = super.openexr.overrideAttrs ( openexr = super.openexr.overrideAttrs (
@ -306,16 +307,17 @@ self: super:
); );
peewee = super.peewee.overridePythonAttrs ( peewee = super.peewee.overridePythonAttrs (
old: let old:
withPostgres = old.passthru.withPostgres or false; let
withMysql = old.passthru.withMysql or false; withPostgres = old.passthru.withPostgres or false;
in withMysql = old.passthru.withMysql or false;
{ in
buildInputs = old.buildInputs ++ [ self.cython pkgs.sqlite ]; {
propagatedBuildInputs = old.propagatedBuildInputs buildInputs = old.buildInputs ++ [ self.cython pkgs.sqlite ];
++ lib.optional withPostgres self.psycopg2 propagatedBuildInputs = old.propagatedBuildInputs
++ lib.optional withMysql self.mysql-connector; ++ lib.optional withPostgres self.psycopg2
} ++ lib.optional withMysql self.mysql-connector;
}
); );
pillow = super.pillow.overrideAttrs ( pillow = super.pillow.overrideAttrs (
@ -667,16 +669,24 @@ self: super:
); );
zipp = zipp =
if lib.versionAtLeast super.zipp.version "2.0.0" then ( (
super.zipp.overridePythonAttrs ( if lib.versionAtLeast super.zipp.version "2.0.0" then (
old: { super.zipp.overridePythonAttrs (
prePatch = '' old: {
substituteInPlace setup.py --replace \ prePatch = ''
'setuptools.setup()' \ substituteInPlace setup.py --replace \
'setuptools.setup(version="${super.zipp.version}")' 'setuptools.setup()' \
''; 'setuptools.setup(version="${super.zipp.version}")'
} '';
) }
) else super.zipp; )
) else super.zipp
).overridePythonAttrs (
old: {
propagatedBuildInputs = old.propagatedBuildInputs ++ [
self.toml
];
}
);
} }

View File

@ -1,5 +1,4 @@
{ lib, stdenv, python, isLinux ? stdenv.isLinux }: { lib, stdenv, python, isLinux ? stdenv.isLinux }:
let let
inherit (lib.strings) hasSuffix hasInfix splitString removeSuffix; inherit (lib.strings) hasSuffix hasInfix splitString removeSuffix;
@ -94,12 +93,10 @@ let
if isLinux if isLinux
then chooseLinux files then chooseLinux files
else chooseOSX files; else chooseOSX files;
in in
if (builtins.length filtered == 0) if (builtins.length filtered == 0)
then [] then []
else choose (filtered); else choose (filtered);
in in
{ {
inherit selectWheel toWheelAttrs isPyVersionCompatible; inherit selectWheel toWheelAttrs isPyVersionCompatible;

View File

@ -1,5 +1,4 @@
{ lib, stdenv, poetryLib }: python: { lib, stdenv, poetryLib }: python:
let let
inherit (poetryLib) ireplace; inherit (poetryLib) ireplace;
@ -37,195 +36,199 @@ let
); );
# Make a tree out of expression groups (parens) # Make a tree out of expression groups (parens)
findSubExpressions = expr: let findSubExpressions = expr:
acc = builtins.foldl' findSubExpressionsFun { let
exprs = []; acc = builtins.foldl' findSubExpressionsFun {
expr = expr; exprs = [];
pos = 0; expr = expr;
openP = 0; pos = 0;
exprPos = 0; openP = 0;
startPos = 0; exprPos = 0;
} (lib.stringToCharacters expr); startPos = 0;
tailExpr = (substr acc.exprPos acc.pos expr); } (lib.stringToCharacters expr);
tailExprs = if tailExpr != "" then [ tailExpr ] else []; tailExpr = (substr acc.exprPos acc.pos expr);
in tailExprs = if tailExpr != "" then [ tailExpr ] else [];
acc.exprs ++ tailExprs; in
acc.exprs ++ tailExprs;
parseExpressions = exprs: let parseExpressions = exprs:
splitCond = ( let
s: builtins.map splitCond = (
(x: stripStr (if builtins.typeOf x == "list" then (builtins.elemAt x 0) else x)) s: builtins.map
(builtins.split " (and|or) " (s + " ")) (x: stripStr (if builtins.typeOf x == "list" then (builtins.elemAt x 0) else x))
); (builtins.split " (and|or) " (s + " "))
);
mapfn = expr: ( mapfn = expr: (
if (builtins.match "^ ?$" expr != null) then null # Filter empty if (builtins.match "^ ?$" expr != null) then null # Filter empty
else if (builtins.elem expr [ "and" "or" ]) then { else if (builtins.elem expr [ "and" "or" ]) then {
type = "bool"; type = "bool";
value = expr; value = expr;
} }
else { else {
type = "expr"; type = "expr";
value = expr; value = expr;
} }
); );
parse = expr: builtins.filter (x: x != null) (builtins.map mapfn (splitCond expr)); parse = expr: builtins.filter (x: x != null) (builtins.map mapfn (splitCond expr));
in
in builtins.foldl' (
builtins.foldl' ( acc: v: acc ++ (
acc: v: acc ++ ( if builtins.typeOf v == "string" then parse v else [ (parseExpressions v) ]
if builtins.typeOf v == "string" then parse v else [ (parseExpressions v) ] )
) ) [] exprs;
) [] exprs;
# Transform individual expressions to structured expressions # Transform individual expressions to structured expressions
# This function also performs variable substitution, replacing environment markers with their explicit values # This function also performs variable substitution, replacing environment markers with their explicit values
transformExpressions = exprs: let transformExpressions = exprs:
variables = { let
os_name = ( variables = {
if python.pname == "jython" then "java" os_name = (
else "posix" if python.pname == "jython" then "java"
); else "posix"
sys_platform = (
if stdenv.isLinux then "linux"
else if stdenv.isDarwin then "darwin"
else throw "Unsupported platform"
);
platform_machine = stdenv.platform.kernelArch;
platform_python_implementation = let
impl = python.passthru.implementation;
in
(
if impl == "cpython" then "CPython"
else if impl == "pypy" then "PyPy"
else throw "Unsupported implementation ${impl}"
); );
platform_release = ""; # Field not reproducible sys_platform = (
platform_system = ( if stdenv.isLinux then "linux"
if stdenv.isLinux then "Linux" else if stdenv.isDarwin then "darwin"
else if stdenv.isDarwin then "Darwin" else throw "Unsupported platform"
else throw "Unsupported platform" );
); platform_machine = stdenv.platform.kernelArch;
platform_version = ""; # Field not reproducible platform_python_implementation = let
python_version = python.passthru.pythonVersion; impl = python.passthru.implementation;
python_full_version = python.version;
implementation_name = python.implementation;
implementation_version = python.version;
extra = "";
};
substituteVar = value: if builtins.hasAttr value variables then (builtins.toJSON variables."${value}") else value;
processVar = value: builtins.foldl' (acc: v: v acc) value [
stripStr
substituteVar
];
in
if builtins.typeOf exprs == "set" then (
if exprs.type == "expr" then (
let
mVal = ''[a-zA-Z0-9\'"_\. ]+'';
mOp = "in|[!=<>]+";
e = stripStr exprs.value;
m = builtins.map stripStr (builtins.match ''^(${mVal}) *(${mOp}) *(${mVal})$'' e);
in in
{ (
type = "expr"; if impl == "cpython" then "CPython"
value = { else if impl == "pypy" then "PyPy"
op = builtins.elemAt m 1; else throw "Unsupported implementation ${impl}"
values = [ );
(processVar (builtins.elemAt m 0)) platform_release = ""; # Field not reproducible
(processVar (builtins.elemAt m 2)) platform_system = (
]; if stdenv.isLinux then "Linux"
}; else if stdenv.isDarwin then "Darwin"
} else throw "Unsupported platform"
) else exprs );
) else builtins.map transformExpressions exprs; platform_version = ""; # Field not reproducible
python_version = python.passthru.pythonVersion;
python_full_version = python.version;
implementation_name = python.implementation;
implementation_version = python.version;
extra = "";
};
substituteVar = value: if builtins.hasAttr value variables then (builtins.toJSON variables."${value}") else value;
processVar = value: builtins.foldl' (acc: v: v acc) value [
stripStr
substituteVar
];
in
if builtins.typeOf exprs == "set" then (
if exprs.type == "expr" then (
let
mVal = ''[a-zA-Z0-9\'"_\. ]+'';
mOp = "in|[!=<>]+";
e = stripStr exprs.value;
m = builtins.map stripStr (builtins.match ''^(${mVal}) *(${mOp}) *(${mVal})$'' e);
in
{
type = "expr";
value = {
op = builtins.elemAt m 1;
values = [
(processVar (builtins.elemAt m 0))
(processVar (builtins.elemAt m 2))
];
};
}
) else exprs
) else builtins.map transformExpressions exprs;
# Recursively eval all expressions # Recursively eval all expressions
evalExpressions = exprs: let evalExpressions = exprs:
unmarshal = v: ( let
# TODO: Handle single quoted values unmarshal = v: (
if v == "True" then true # TODO: Handle single quoted values
else if v == "False" then false if v == "True" then true
else builtins.fromJSON v else if v == "False" then false
); else builtins.fromJSON v
hasElem = needle: haystack: builtins.elem needle (builtins.filter (x: builtins.typeOf x == "string") (builtins.split " " haystack)); );
op = { hasElem = needle: haystack: builtins.elem needle (builtins.filter (x: builtins.typeOf x == "string") (builtins.split " " haystack));
"<=" = x: y: (unmarshal x) <= (unmarshal y); op = {
"<" = x: y: (unmarshal x) < (unmarshal y); "<=" = x: y: (unmarshal x) <= (unmarshal y);
"!=" = x: y: x != y; "<" = x: y: (unmarshal x) < (unmarshal y);
"==" = x: y: x == y; "!=" = x: y: x != y;
">=" = x: y: (unmarshal x) >= (unmarshal y); "==" = x: y: x == y;
">" = x: y: (unmarshal x) > (unmarshal y); ">=" = x: y: (unmarshal x) >= (unmarshal y);
"~=" = v: c: let ">" = x: y: (unmarshal x) > (unmarshal y);
parts = builtins.splitVersion c; "~=" = v: c:
pruned = lib.take ((builtins.length parts) - 1) parts; let
upper = builtins.toString ( parts = builtins.splitVersion c;
(lib.toInt (builtins.elemAt pruned (builtins.length pruned - 1))) + 1 pruned = lib.take ((builtins.length parts) - 1) parts;
); upper = builtins.toString (
upperConstraint = builtins.concatStringsSep "." (ireplace (builtins.length pruned - 1) upper pruned); (lib.toInt (builtins.elemAt pruned (builtins.length pruned - 1))) + 1
in );
op.">=" v c && op."<" v upperConstraint; upperConstraint = builtins.concatStringsSep "." (ireplace (builtins.length pruned - 1) upper pruned);
"===" = x: y: x == y; in
"in" = x: y: let op.">=" v c && op."<" v upperConstraint;
values = builtins.filter (x: builtins.typeOf x == "string") (builtins.split " " (unmarshal y)); "===" = x: y: x == y;
in "in" = x: y:
builtins.elem (unmarshal x) values; let
}; values = builtins.filter (x: builtins.typeOf x == "string") (builtins.split " " (unmarshal y));
in in
if builtins.typeOf exprs == "set" then ( builtins.elem (unmarshal x) values;
if exprs.type == "expr" then ( };
let in
expr = exprs; if builtins.typeOf exprs == "set" then (
result = (op."${expr.value.op}") (builtins.elemAt expr.value.values 0) (builtins.elemAt expr.value.values 1); if exprs.type == "expr" then (
in let
{ expr = exprs;
type = "value"; result = (op."${expr.value.op}") (builtins.elemAt expr.value.values 0) (builtins.elemAt expr.value.values 1);
value = result; in
} {
) else exprs type = "value";
) else builtins.map evalExpressions exprs; value = result;
}
) else exprs
) else builtins.map evalExpressions exprs;
# Now that we have performed an eval all that's left to do is to concat the graph into a single bool # Now that we have performed an eval all that's left to do is to concat the graph into a single bool
reduceExpressions = exprs: let reduceExpressions = exprs:
cond = { let
"and" = x: y: x && y; cond = {
"or" = x: y: x || y; "and" = x: y: x && y;
}; "or" = x: y: x || y;
reduceExpressionsFun = acc: v: ( };
if builtins.typeOf v == "set" then ( reduceExpressionsFun = acc: v: (
if v.type == "value" then ( if builtins.typeOf v == "set" then (
acc // { if v.type == "value" then (
value = cond."${acc.cond}" acc.value v.value; acc // {
} value = cond."${acc.cond}" acc.value v.value;
) else if v.type == "bool" then ( }
acc // { ) else if v.type == "bool" then (
cond = v.value; acc // {
} cond = v.value;
}
) else throw "Unsupported type"
) else if builtins.typeOf v == "list" then (
let
ret = builtins.foldl' reduceExpressionsFun {
value = true;
cond = "and";
} v;
in
acc // {
value = cond."${acc.cond}" acc.value ret.value;
}
) else throw "Unsupported type" ) else throw "Unsupported type"
) else if builtins.typeOf v == "list" then ( );
let in
ret = builtins.foldl' reduceExpressionsFun { (
value = true; builtins.foldl' reduceExpressionsFun {
cond = "and"; value = true;
} v; cond = "and";
in } exprs
acc // { ).value;
value = cond."${acc.cond}" acc.value ret.value;
}
) else throw "Unsupported type"
);
in
(
builtins.foldl' reduceExpressionsFun {
value = true;
cond = "and";
} exprs
).value;
in in
e: builtins.foldl' (acc: v: v acc) e [ e: builtins.foldl' (acc: v: v acc) e [
findSubExpressions findSubExpressions

View File

@ -1,26 +1,27 @@
{ lib, ireplace }: { lib, ireplace }:
let let
inherit (builtins) elemAt match; inherit (builtins) elemAt match;
operators = let operators = let
matchWildCard = s: match "([^\*])(\.[\*])" s; matchWildCard = s: match "([^\*])(\.[\*])" s;
mkComparison = ret: version: v: builtins.compareVersions version v == ret; mkComparison = ret: version: v: builtins.compareVersions version v == ret;
mkIdxComparison = idx: version: v: let mkIdxComparison = idx: version: v:
ver = builtins.splitVersion v; let
minor = builtins.toString (lib.toInt (elemAt ver idx) + 1); ver = builtins.splitVersion v;
upper = builtins.concatStringsSep "." (ireplace idx minor ver); minor = builtins.toString (lib.toInt (elemAt ver idx) + 1);
in upper = builtins.concatStringsSep "." (ireplace idx minor ver);
operators.">=" version v && operators."<" version upper; in
dropWildcardPrecision = f: version: constraint: let operators.">=" version v && operators."<" version upper;
m = matchWildCard constraint; dropWildcardPrecision = f: version: constraint:
hasWildcard = m != null; let
c = if hasWildcard then (elemAt m 0) else constraint; m = matchWildCard constraint;
v = hasWildcard = m != null;
if hasWildcard then (builtins.substring 0 (builtins.stringLength c) version) c = if hasWildcard then (elemAt m 0) else constraint;
else version; v =
in if hasWildcard then (builtins.substring 0 (builtins.stringLength c) version)
f v c; else version;
in
f v c;
in in
{ {
# Prefix operators # Prefix operators
@ -33,16 +34,17 @@ let
# Semver specific operators # Semver specific operators
"~" = mkIdxComparison 1; "~" = mkIdxComparison 1;
"^" = mkIdxComparison 0; "^" = mkIdxComparison 0;
"~=" = v: c: let "~=" = v: c:
# Prune constraint let
parts = builtins.splitVersion c; # Prune constraint
pruned = lib.take ((builtins.length parts) - 1) parts; parts = builtins.splitVersion c;
upper = builtins.toString ( pruned = lib.take ((builtins.length parts) - 1) parts;
(lib.toInt (builtins.elemAt pruned (builtins.length pruned - 1))) + 1 upper = builtins.toString (
); (lib.toInt (builtins.elemAt pruned (builtins.length pruned - 1))) + 1
upperConstraint = builtins.concatStringsSep "." (ireplace (builtins.length pruned - 1) upper pruned); );
in upperConstraint = builtins.concatStringsSep "." (ireplace (builtins.length pruned - 1) upper pruned);
operators.">=" v c && operators."<" v upperConstraint; in
operators.">=" v c && operators."<" v upperConstraint;
# Infix operators # Infix operators
"-" = version: v: operators.">=" version v.vl && operators."<=" version v.vu; "-" = version: v: operators.">=" version v.vl && operators."<=" version v.vu;
# Arbitrary equality clause, just run simple comparison # Arbitrary equality clause, just run simple comparison
@ -55,33 +57,34 @@ let
version = "([0-9\.\*x]+)"; version = "([0-9\.\*x]+)";
}; };
parseConstraint = constraint: let parseConstraint = constraint:
constraintStr = builtins.replaceStrings [ " " ] [ "" ] constraint; let
# The common prefix operators constraintStr = builtins.replaceStrings [ " " ] [ "" ] constraint;
mPre = match "${re.operators} *${re.version}" constraintStr; # The common prefix operators
# There is also an infix operator to match ranges mPre = match "${re.operators} *${re.version}" constraintStr;
mIn = match "${re.version} *(-) *${re.version}" constraintStr; # There is also an infix operator to match ranges
in mIn = match "${re.version} *(-) *${re.version}" constraintStr;
( in
if mPre != null then { (
op = elemAt mPre 0; if mPre != null then {
v = elemAt mPre 1; op = elemAt mPre 0;
} v = elemAt mPre 1;
# Infix operators are range matches }
else if mIn != null then { # Infix operators are range matches
op = elemAt mIn 1; else if mIn != null then {
v = { op = elemAt mIn 1;
vl = (elemAt mIn 0); v = {
vu = (elemAt mIn 2); vl = (elemAt mIn 0);
}; vu = (elemAt mIn 2);
} };
else throw "Constraint \"${constraintStr}\" could not be parsed" }
); else throw "Constraint \"${constraintStr}\" could not be parsed"
);
satisfiesSemver = version: constraint: let
inherit (parseConstraint constraint) op v;
in
if constraint == "*" then true else operators."${op}" version v;
satisfiesSemver = version: constraint:
let
inherit (parseConstraint constraint) op v;
in
if constraint == "*" then true else operators."${op}" version v;
in in
{ inherit satisfiesSemver; } { inherit satisfiesSemver; }