From 4acf604723aa48a0c63b2f9f0581274de7385412 Mon Sep 17 00:00:00 2001 From: adisbladis Date: Sun, 29 Dec 2019 12:51:22 +0000 Subject: [PATCH] Add support for local path dependencies --- default.nix | 36 ++++++++++++++++++++---------- lib.nix | 14 ++++++++++++ mk-poetry-dep.nix | 25 ++++++++++++++++----- pyproject-without-path.py | 18 +++++++++++++++ tests/override-support/default.nix | 4 +++- tests/path-deps/default.nix | 5 +++-- tests/path-deps/pyproject.toml | 2 +- 7 files changed, 82 insertions(+), 22 deletions(-) create mode 100644 pyproject-without-path.py diff --git a/default.nix b/default.nix index 87c40d4..f5cf78b 100644 --- a/default.nix +++ b/default.nix @@ -25,9 +25,11 @@ let # mkPoetryPython = { poetrylock + , poetryPkg , overrides ? defaultPoetryOverrides , meta ? {} , python ? pkgs.python3 + , pwd ? null }@attrs: let lockData = readTOML poetrylock; lockFiles = lib.getAttrFromPath [ "metadata" "files" ] lockData; @@ -60,8 +62,10 @@ let name = pkgMeta.name; value = self.mkPoetryDep ( pkgMeta // { + inherit pwd; source = getAttrDefault "source" pkgMeta null; files = lockFiles.${name}; + pythonPackages = self; } ); } @@ -76,6 +80,7 @@ let mkPoetryDep = self.callPackage ./mk-poetry-dep.nix { inherit pkgs lib python poetryLib; }; + poetry = poetryPkg; } ) # Null out any filtered packages, we don't want python.pkgs from nixpkgs @@ -111,12 +116,14 @@ let { poetrylock , overrides ? defaultPoetryOverrides , meta ? {} + , pwd ? null , python ? pkgs.python3 }: let + poetryPkg = poetry.override { inherit python; }; py = mkPoetryPython ( { - inherit poetrylock overrides meta python; + inherit poetryPkg poetrylock overrides meta python pwd; } ); in @@ -133,13 +140,14 @@ let , overrides ? defaultPoetryOverrides , meta ? {} , python ? pkgs.python3 + , pwd ? null , ... }@attrs: let poetryPkg = poetry.override { inherit python; }; py = ( mkPoetryPython { - inherit poetrylock overrides meta python; + inherit poetryPkg poetrylock overrides meta python pwd; } ).python; @@ -157,16 +165,11 @@ let getInputs = attr: getAttrDefault attr attrs []; mkInput = attr: extraInputs: getInputs attr ++ extraInputs; - knownBuildSystems = { - "intreehooks:loader" = [ py.pkgs.intreehooks ]; - "poetry.masonry.api" = [ poetryPkg ]; - "" = []; + buildSystemPkgs = poetryLib.getBuildSystemPkgs { + inherit pyProject; + pythonPackages = py.pkgs; }; - getBuildSystemPkgs = let - buildSystem = lib.getAttrFromPath [ "build-system" "build-backend" ] pyProject; - in - knownBuildSystems.${buildSystem} or (throw "unsupported build system ${buildSystem}"); in py.pkgs.buildPythonApplication ( passedAttrs // { @@ -175,7 +178,8 @@ let format = "pyproject"; - buildInputs = mkInput "buildInputs" getBuildSystemPkgs; + nativeBuildInputs = [ pkgs.yj ]; + buildInputs = mkInput "buildInputs" buildSystemPkgs; propagatedBuildInputs = mkInput "propagatedBuildInputs" (getDeps "dependencies") ++ ([ py.pkgs.setuptools ]); checkInputs = mkInput "checkInputs" (getDeps "dev-dependencies"); @@ -183,6 +187,14 @@ let python = py; }; + postPatch = (getAttrDefault "postPatch" passedAttrs "") + '' + # Tell poetry not to resolve the path dependencies. Any version is + # fine ! + yj -tj < pyproject.toml | python ${./pyproject-without-path.py} > pyproject.json + yj -jt < pyproject.json > pyproject.toml + rm pyproject.json + ''; + meta = meta // { inherit (pyProject.tool.poetry) description; licenses = [ pyProject.tool.poetry.license ]; @@ -195,6 +207,6 @@ let in { - inherit mkPoetryPython mkPoetryEnv mkPoetryApplication defaultPoetryOverrides cli; + inherit mkPoetryEnv mkPoetryApplication defaultPoetryOverrides cli; mkPoetryPackage = attrs: builtins.trace "mkPoetryPackage is deprecated. Use mkPoetryApplication instead." (mkPoetryApplication attrs); } diff --git a/lib.nix b/lib.nix index 3ff47b5..4c69eb5 100644 --- a/lib.nix +++ b/lib.nix @@ -56,6 +56,19 @@ let } ); + getBuildSystemPkgs = + { pythonPackages + , pyProject + }: let + knownBuildSystems = { + "intreehooks:loader" = [ pythonPackages.intreehooks ]; + "poetry.masonry.api" = [ pythonPackages.poetry ]; + "" = []; + }; + buildSystem = lib.getAttrFromPath [ "build-system" "build-backend" ] pyProject; + in + knownBuildSystems.${buildSystem} or (throw "unsupported build system ${buildSystem}"); + in { inherit @@ -63,5 +76,6 @@ in getManyLinuxDeps isCompatible readTOML + getBuildSystemPkgs ; } diff --git a/mk-poetry-dep.nix b/mk-poetry-dep.nix index f55bdc4..3631cbd 100644 --- a/mk-poetry-dep.nix +++ b/mk-poetry-dep.nix @@ -11,7 +11,9 @@ , files , source , dependencies ? {} +, pythonPackages , python-versions +, pwd , supportedExtensions ? lib.importJSON ./extensions.json , ... }: let @@ -31,7 +33,18 @@ in builtins.filter (f: matchesVersion f.file && hasSupportedExtension f.file) files; - isGit = source != null && source.type == "git"; + 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; @@ -54,10 +67,10 @@ buildPythonPackage { doCheck = false; # We never get development deps dontStrip = true; - format = if isGit then "setuptools" else fileInfo.format; + format = if isLocal then "pyproject" else if isGit then "setuptools" else fileInfo.format; - nativeBuildInputs = if (!isGit && (getManyLinuxDeps fileInfo.name).str != null) then [ autoPatchelfHook ] else []; - buildInputs = if !isGit then (getManyLinuxDeps fileInfo.name).pkg else []; + nativeBuildInputs = if (!isSource && (getManyLinuxDeps fileInfo.name).str != null) then [ autoPatchelfHook ] else []; + buildInputs = if !isSource then (getManyLinuxDeps fileInfo.name).pkg else []; propagatedBuildInputs = let @@ -65,7 +78,7 @@ buildPythonPackage { # but dependencies try to access Django deps = builtins.map (d: lib.toLower d) (builtins.attrNames dependencies); in - builtins.map (n: pythonPackages.${n}) deps; + (builtins.map (n: pythonPackages.${n}) deps) ++ (if isLocal then buildSystemPkgs else []); meta = { broken = ! isCompatible python.version python-versions; @@ -80,7 +93,7 @@ buildPythonPackage { inherit (source) url; rev = source.reference; } - ) else fetchFromPypi { + ) else if isLocal then (localDepPath) else fetchFromPypi { pname = name; inherit (fileInfo) file hash kind; }; diff --git a/pyproject-without-path.py b/pyproject-without-path.py new file mode 100644 index 0000000..bb61e4a --- /dev/null +++ b/pyproject-without-path.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python +# Patch out path dependencies from a pyproject.json file + +import json +import sys + +data = json.load(sys.stdin) + +for dep in data['tool']['poetry']['dependencies'].values(): + if isinstance(dep, dict): + try: + del dep['path']; + except KeyError: + pass + else: + dep['version'] = '*' + +json.dump(data, sys.stdout, indent=4) diff --git a/tests/override-support/default.nix b/tests/override-support/default.nix index d6da8f8..2057be7 100644 --- a/tests/override-support/default.nix +++ b/tests/override-support/default.nix @@ -1,9 +1,11 @@ { lib, python3, poetry2nix, runCommand }: let - p = poetry2nix.mkPoetryPython { + p = poetry2nix.mkPoetryApplication { python = python3; + src = ./.; poetrylock = ./poetry.lock; + pyproject = ./pyproject.toml; overrides = poetry2nix.defaultPoetryOverrides ++ [ ( self: super: { diff --git a/tests/path-deps/default.nix b/tests/path-deps/default.nix index fee396e..9a73a07 100644 --- a/tests/path-deps/default.nix +++ b/tests/path-deps/default.nix @@ -1,8 +1,9 @@ { lib, poetry2nix, python3 }: -poetry2nix.mkPoetryPackage { +poetry2nix.mkPoetryApplication { python = python3; pyproject = ./pyproject.toml; - poetryLock = ./poetry.lock; + poetrylock = ./poetry.lock; src = lib.cleanSource ./.; + pwd = ./.; } diff --git a/tests/path-deps/pyproject.toml b/tests/path-deps/pyproject.toml index 7fc9f23..55c9c02 100644 --- a/tests/path-deps/pyproject.toml +++ b/tests/path-deps/pyproject.toml @@ -1,5 +1,5 @@ [tool.poetry] -name = "local-deps" +name = "path-deps" version = "0.1.0" description = "poetry2nix test" authors = ["Your Name "]