2019-12-11 13:31:22 +01:00
|
|
|
{ pkgs ? import <nixpkgs> {}
|
|
|
|
, lib ? pkgs.lib
|
|
|
|
, poetry ? null
|
2019-12-13 16:56:51 +01:00
|
|
|
, poetryLib ? import ./lib.nix { inherit lib pkgs; }
|
2019-06-17 16:27:16 +01:00
|
|
|
}:
|
2019-12-10 10:21:22 +01:00
|
|
|
|
2019-06-17 16:27:16 +01:00
|
|
|
let
|
2019-12-13 16:56:51 +01:00
|
|
|
inherit (poetryLib) isCompatible readTOML;
|
2019-06-24 16:23:02 +01:00
|
|
|
|
2019-12-20 13:35:08 +00:00
|
|
|
defaultPoetryOverrides = [ (import ./overrides.nix { inherit pkgs; }) ];
|
2019-06-17 16:27:16 +01:00
|
|
|
|
2019-11-16 12:57:43 +00:00
|
|
|
mkEvalPep508 = import ./pep508.nix {
|
|
|
|
inherit lib;
|
|
|
|
stdenv = pkgs.stdenv;
|
|
|
|
};
|
|
|
|
|
2019-12-13 16:56:51 +01:00
|
|
|
getAttrDefault = attribute: set: default: (
|
|
|
|
if builtins.hasAttr attribute set
|
|
|
|
then builtins.getAttr attribute set
|
|
|
|
else default
|
|
|
|
);
|
2019-12-10 10:21:22 +01:00
|
|
|
|
2019-12-17 14:01:45 +01:00
|
|
|
#
|
|
|
|
# Returns an attrset { python, poetryPackages } for the given lockfile
|
|
|
|
#
|
2019-12-16 11:23:09 +01:00
|
|
|
mkPoetryPython =
|
2019-12-17 12:38:34 +01:00
|
|
|
{ poetrylock
|
2019-12-11 13:31:22 +01:00
|
|
|
, overrides ? defaultPoetryOverrides
|
|
|
|
, meta ? {}
|
|
|
|
, python ? pkgs.python3
|
|
|
|
}@attrs: let
|
2019-12-17 12:38:34 +01:00
|
|
|
lockData = readTOML poetrylock;
|
|
|
|
lockFiles = lib.getAttrFromPath [ "metadata" "files" ] lockData;
|
2019-12-11 13:31:22 +01:00
|
|
|
|
2019-12-16 11:23:09 +01:00
|
|
|
specialAttrs = [ "poetrylock" "overrides" ];
|
2019-12-11 13:31:22 +01:00
|
|
|
passedAttrs = builtins.removeAttrs attrs specialAttrs;
|
|
|
|
|
|
|
|
evalPep508 = mkEvalPep508 python;
|
|
|
|
|
2019-12-17 14:01:45 +01:00
|
|
|
# Filter packages by their PEP508 markers
|
|
|
|
partitions = let
|
|
|
|
supportsPythonVersion = pkgMeta: if pkgMeta ? marker then (evalPep508 pkgMeta.marker) else true;
|
|
|
|
in
|
|
|
|
lib.partition supportsPythonVersion lockData.package;
|
|
|
|
|
|
|
|
compatible = partitions.right;
|
|
|
|
incompatible = partitions.wrong;
|
2019-12-11 13:31:22 +01:00
|
|
|
|
|
|
|
# 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
|
2019-12-20 13:35:08 +00:00
|
|
|
baseOverlay = self: super:
|
2019-12-17 14:01:45 +01:00
|
|
|
let
|
2019-12-13 16:56:51 +01:00
|
|
|
getDep = depName: if builtins.hasAttr depName self then self."${depName}" else throw "foo";
|
2019-12-11 13:31:22 +01:00
|
|
|
|
2019-12-13 16:56:51 +01:00
|
|
|
lockPkgs = builtins.listToAttrs (
|
|
|
|
builtins.map (
|
|
|
|
pkgMeta: rec {
|
|
|
|
name = pkgMeta.name;
|
2019-12-27 19:16:55 +00:00
|
|
|
value = self.mkPoetryDep (
|
|
|
|
pkgMeta // {
|
|
|
|
source = getAttrDefault "source" pkgMeta null;
|
|
|
|
files = lockFiles.${name};
|
|
|
|
}
|
|
|
|
);
|
2019-12-13 16:56:51 +01:00
|
|
|
}
|
|
|
|
) compatible
|
2019-12-11 13:31:22 +01:00
|
|
|
);
|
|
|
|
in
|
2019-12-20 13:35:08 +00:00
|
|
|
lockPkgs;
|
|
|
|
|
|
|
|
overlays = [
|
|
|
|
(
|
|
|
|
self: super: {
|
2019-12-13 16:56:51 +01:00
|
|
|
mkPoetryDep = self.callPackage ./mk-poetry-dep.nix {
|
|
|
|
inherit pkgs lib python poetryLib;
|
|
|
|
};
|
2019-12-20 13:35:08 +00:00
|
|
|
}
|
|
|
|
)
|
|
|
|
# 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 = self: super: (
|
|
|
|
builtins.foldl'
|
|
|
|
(
|
|
|
|
acc: v: let
|
|
|
|
newSuper = acc // v self acc;
|
|
|
|
in
|
|
|
|
newSuper
|
|
|
|
)
|
|
|
|
super
|
|
|
|
overlays
|
|
|
|
);
|
2019-12-17 14:01:45 +01:00
|
|
|
|
|
|
|
py = python.override { inherit packageOverrides; self = py; };
|
2019-12-17 20:58:41 +01:00
|
|
|
in
|
|
|
|
{
|
2019-12-17 14:01:45 +01:00
|
|
|
python = py;
|
|
|
|
poetryPackages = map (pkg: py.pkgs.${pkg.name}) compatible;
|
2019-12-17 20:58:41 +01:00
|
|
|
};
|
2019-12-17 14:01:45 +01:00
|
|
|
|
|
|
|
#
|
|
|
|
# Creates a python environment with the python packages from the specified lockfile
|
|
|
|
#
|
|
|
|
mkPoetryEnv =
|
|
|
|
{ poetrylock
|
|
|
|
, overrides ? defaultPoetryOverrides
|
|
|
|
, meta ? {}
|
|
|
|
, python ? pkgs.python3
|
2019-12-17 20:58:41 +01:00
|
|
|
}:
|
|
|
|
let
|
|
|
|
py = mkPoetryPython (
|
|
|
|
{
|
|
|
|
inherit poetrylock overrides meta python;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
in
|
|
|
|
py.python.withPackages (_: py.poetryPackages);
|
2019-12-16 11:23:09 +01:00
|
|
|
|
2019-12-17 14:01:45 +01:00
|
|
|
|
|
|
|
#
|
|
|
|
# Creates a python application
|
|
|
|
#
|
2019-12-16 11:23:09 +01:00
|
|
|
mkPoetryApplication =
|
|
|
|
{ src
|
2019-12-17 12:38:34 +01:00
|
|
|
, pyproject
|
|
|
|
, poetrylock
|
2019-12-16 11:23:09 +01:00
|
|
|
, overrides ? defaultPoetryOverrides
|
|
|
|
, meta ? {}
|
|
|
|
, python ? pkgs.python3
|
|
|
|
, ...
|
|
|
|
}@attrs: let
|
|
|
|
poetryPkg = poetry.override { inherit python; };
|
|
|
|
|
2019-12-17 20:58:41 +01:00
|
|
|
py = (
|
|
|
|
mkPoetryPython {
|
2019-12-17 12:38:34 +01:00
|
|
|
inherit poetrylock overrides meta python;
|
2019-12-17 20:58:41 +01:00
|
|
|
}
|
|
|
|
).python;
|
2019-12-16 11:23:09 +01:00
|
|
|
|
|
|
|
pyProject = readTOML pyproject;
|
|
|
|
|
|
|
|
specialAttrs = [ "pyproject" "poetrylock" "overrides" ];
|
|
|
|
passedAttrs = builtins.removeAttrs attrs specialAttrs;
|
2019-12-11 13:31:22 +01:00
|
|
|
|
|
|
|
getDeps = depAttr: let
|
|
|
|
deps = getAttrDefault depAttr pyProject.tool.poetry {};
|
|
|
|
depAttrs = builtins.map (d: lib.toLower d) (builtins.attrNames deps);
|
|
|
|
in
|
2019-12-16 11:23:09 +01:00
|
|
|
builtins.map (dep: py.pkgs."${dep}") depAttrs;
|
2019-12-11 13:31:22 +01:00
|
|
|
|
|
|
|
getInputs = attr: getAttrDefault attr attrs [];
|
|
|
|
mkInput = attr: extraInputs: getInputs attr ++ extraInputs;
|
|
|
|
|
2019-12-11 14:13:13 +01:00
|
|
|
knownBuildSystems = {
|
|
|
|
"intreehooks:loader" = [ py.pkgs.intreehooks ];
|
|
|
|
"poetry.masonry.api" = [ poetryPkg ];
|
|
|
|
"" = [];
|
|
|
|
};
|
|
|
|
|
|
|
|
getBuildSystemPkgs = let
|
2019-12-13 16:56:51 +01:00
|
|
|
buildSystem = lib.getAttrFromPath [ "build-system" "build-backend" ] pyProject;
|
2019-12-11 14:13:13 +01:00
|
|
|
in
|
|
|
|
knownBuildSystems.${buildSystem} or (throw "unsupported build system ${buildSystem}");
|
2019-12-11 13:31:22 +01:00
|
|
|
in
|
2019-12-16 11:23:09 +01:00
|
|
|
py.pkgs.buildPythonApplication (
|
2019-12-11 13:31:22 +01:00
|
|
|
passedAttrs // {
|
|
|
|
pname = pyProject.tool.poetry.name;
|
|
|
|
version = pyProject.tool.poetry.version;
|
|
|
|
|
|
|
|
format = "pyproject";
|
|
|
|
|
2019-12-11 14:13:13 +01:00
|
|
|
buildInputs = mkInput "buildInputs" getBuildSystemPkgs;
|
2019-12-16 11:23:09 +01:00
|
|
|
propagatedBuildInputs = mkInput "propagatedBuildInputs" (getDeps "dependencies") ++ ([ py.pkgs.setuptools ]);
|
2019-12-11 13:31:22 +01:00
|
|
|
checkInputs = mkInput "checkInputs" (getDeps "dev-dependencies");
|
|
|
|
|
|
|
|
passthru = {
|
2019-12-10 10:21:22 +01:00
|
|
|
python = py;
|
2019-10-16 15:36:52 +01:00
|
|
|
};
|
|
|
|
|
2019-12-11 13:31:22 +01:00
|
|
|
meta = meta // {
|
|
|
|
inherit (pyProject.tool.poetry) description;
|
|
|
|
licenses = [ pyProject.tool.poetry.license ];
|
2019-11-21 10:48:43 +01:00
|
|
|
};
|
2019-11-18 23:39:20 +00:00
|
|
|
|
2019-12-11 13:31:22 +01:00
|
|
|
}
|
|
|
|
);
|
|
|
|
in
|
|
|
|
{
|
2019-12-17 14:01:45 +01:00
|
|
|
inherit mkPoetryPython mkPoetryEnv mkPoetryApplication defaultPoetryOverrides;
|
2019-12-16 11:23:09 +01:00
|
|
|
mkPoetryPackage = attrs: builtins.trace "mkPoetryPackage is deprecated. Use mkPoetryApplication instead." (mkPoetryApplication attrs);
|
2019-06-17 16:27:16 +01:00
|
|
|
}
|