diff --git a/mk-poetry-dep.nix b/mk-poetry-dep.nix index 256e2d9..7ce7e67 100644 --- a/mk-poetry-dep.nix +++ b/mk-poetry-dep.nix @@ -16,102 +16,112 @@ , pwd , supportedExtensions ? lib.importJSON ./extensions.json , ... -}: let +}: - inherit (poetryLib) isCompatible getManyLinuxDeps fetchFromPypi; +pythonPackages.callPackage ( + { preferWheel ? false + }: - 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; - - lockFileEntry = builtins.head (sourceDist ++ binaryDist ++ eggs); - - _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 "setuptools"; - kind = - if _isEgg then python.pythonVersion - else if format == "setuptools" then "source" - else (builtins.elemAt (lib.strings.splitString "-" name) 2); - }; - - baseBuildInputs = lib.optional (name != "setuptools_scm" && name != "setuptools-scm") pythonPackages.setuptools_scm; - -in - -buildPythonPackage { - pname = name; - version = version; - - doCheck = false; # We never get development deps - dontStrip = true; - format = if isLocal then "pyproject" else if isGit then "setuptools" else fileInfo.format; - - nativeBuildInputs = if (!isSource && (getManyLinuxDeps fileInfo.name).str != null) then [ autoPatchelfHook ] else []; - buildInputs = baseBuildInputs ++ (if !isSource then (getManyLinuxDeps fileInfo.name).pkg else []); - - propagatedBuildInputs = let - # Some dependencies like django gets the attribute name django - # but dependencies try to access Django - deps = builtins.map (d: lib.toLower d) (builtins.attrNames dependencies); + + inherit (poetryLib) isCompatible getManyLinuxDeps fetchFromPypi; + + 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); + + 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 "setuptools"; + kind = + if _isEgg then python.pythonVersion + else if format == "setuptools" then "source" + else (builtins.elemAt (lib.strings.splitString "-" name) 2); + }; + + baseBuildInputs = lib.optional (name != "setuptools_scm" && name != "setuptools-scm") pythonPackages.setuptools_scm; + in - (builtins.map (n: pythonPackages.${n}) deps) ++ (if isLocal then buildSystemPkgs else []); - meta = { - broken = ! isCompatible python.version python-versions; - license = []; - }; + buildPythonPackage { + pname = name; + version = version; - # 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; - } - ) else if isLocal then (localDepPath) else fetchFromPypi { - pname = name; - inherit (fileInfo) file hash kind; - }; -} + doCheck = false; # We never get development deps + dontStrip = true; + format = if isLocal then "pyproject" else if isGit then "setuptools" else fileInfo.format; + + nativeBuildInputs = if (!isSource && (getManyLinuxDeps fileInfo.name).str != null) then [ autoPatchelfHook ] else []; + buildInputs = baseBuildInputs ++ (if !isSource then (getManyLinuxDeps fileInfo.name).pkg else []); + + propagatedBuildInputs = + let + # Some dependencies like django gets the attribute name django + # but dependencies try to access Django + deps = builtins.map (d: lib.toLower d) (builtins.attrNames dependencies); + in + (builtins.map (n: pythonPackages.${n}) deps) ++ (if isLocal then buildSystemPkgs else []); + + meta = { + broken = ! isCompatible python.version python-versions; + license = []; + }; + + # 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; + } + ) else if isLocal then (localDepPath) else fetchFromPypi { + pname = name; + inherit (fileInfo) file hash kind; + }; + } + +) {} diff --git a/overrides.nix b/overrides.nix index 207841f..849040c 100644 --- a/overrides.nix +++ b/overrides.nix @@ -154,6 +154,11 @@ in } ); + # Calls Cargo at build time for source builds and is really tricky to package + maturin = super.maturin.override { + preferWheel = true; + }; + mccabe = super.mccabe.overrideAttrs ( old: { postPatch = '' diff --git a/tests/default.nix b/tests/default.nix index a952914..5f63a01 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -21,6 +21,7 @@ in cli = poetry2nix; path-deps = pkgs.callPackage ./path-deps { inherit poetry2nix; }; operators = pkgs.callPackage ./operators { inherit poetry2nix; }; + preferWheel = pkgs.callPackage ./prefer-wheel { inherit poetry2nix; }; # Egg support not yet in channel, uncomment when channel progressed # eggs = pkgs.callPackage ./eggs { inherit poetry2nix; }; diff --git a/tests/prefer-wheel/default.nix b/tests/prefer-wheel/default.nix new file mode 100644 index 0000000..0809511 --- /dev/null +++ b/tests/prefer-wheel/default.nix @@ -0,0 +1,20 @@ +{ lib, poetry2nix, python3 }: + +poetry2nix.mkPoetryApplication { + python = python3; + pyproject = ./pyproject.toml; + poetrylock = ./poetry.lock; + src = lib.cleanSource ./.; + overrides = [ + poetry2nix.defaultPoetryOverrides + # This is also in overrides.nix but repeated for completeness + ( + self: super: { + maturin = super.maturin.override { + preferWheel = true; + }; + } + ) + + ]; +} diff --git a/tests/prefer-wheel/poetry.lock b/tests/prefer-wheel/poetry.lock new file mode 100644 index 0000000..605cd75 --- /dev/null +++ b/tests/prefer-wheel/poetry.lock @@ -0,0 +1,37 @@ +[[package]] +category = "main" +description = "Build and publish crates with pyo3, rust-cpython and cffi bindings as well as rust binaries as python packages" +name = "maturin" +optional = false +python-versions = ">=3.5" +version = "0.7.7" + +[package.dependencies] +toml = ">=0.10.0,<0.11.0" + +[[package]] +category = "main" +description = "Python Library for Tom's Obvious, Minimal Language" +name = "toml" +optional = false +python-versions = "*" +version = "0.10.0" + +[metadata] +content-hash = "7335d3fa093f70b77439e92fa00ba1c990d37e4515bc588fce2144580db8b504" +python-versions = "^3.7" + +[metadata.files] +maturin = [ + {file = "maturin-0.7.7-py2.py3-none-macosx_10_7_x86_64.whl", hash = "sha256:87a3d9a94f9c3b8d3ecc57017cdae2b3f1e0f6bfc851509f0b53c2486f312dcc"}, + {file = "maturin-0.7.7-py2.py3-none-manylinux1_i686.whl", hash = "sha256:7f7f04de2acf379b1ff8993747f11bfb60760c69caf8c43414212cf7cc4b07ef"}, + {file = "maturin-0.7.7-py2.py3-none-manylinux1_x86_64.whl", hash = "sha256:aa474d70630833349dac090306fd51a8af2df88080cea74ea4d831b40616ea41"}, + {file = "maturin-0.7.7-py2.py3-none-win32.whl", hash = "sha256:5e6390245a023cbdca39d9276035fdee4d892b44d3ab798ccf2c3443d87e3f98"}, + {file = "maturin-0.7.7-py2.py3-none-win_amd64.whl", hash = "sha256:4fd7fcf4e40e984274dc9caf80c08fa16a6c7c1f4ca1f694ba2ac3802b7340aa"}, + {file = "maturin-0.7.7.tar.gz", hash = "sha256:2533c648aa8fa19f7a9d4f62282b4adce2f9c07c49f512005f92911be767555e"}, +] +toml = [ + {file = "toml-0.10.0-py2.7.egg", hash = "sha256:f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3"}, + {file = "toml-0.10.0-py2.py3-none-any.whl", hash = "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e"}, + {file = "toml-0.10.0.tar.gz", hash = "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c"}, +] diff --git a/tests/prefer-wheel/pyproject.toml b/tests/prefer-wheel/pyproject.toml new file mode 100644 index 0000000..38fa20b --- /dev/null +++ b/tests/prefer-wheel/pyproject.toml @@ -0,0 +1,15 @@ +[tool.poetry] +name = "test_preferwheel" +version = "0.1.0" +description = "" +authors = ["adisbladis "] + +[tool.poetry.dependencies] +python = "^3.7" +maturin = "^0.7.7" + +[tool.poetry.dev-dependencies] + +[build-system] +requires = ["poetry>=0.12"] +build-backend = "poetry.masonry.api" diff --git a/tests/prefer-wheel/test_preferwheel.py b/tests/prefer-wheel/test_preferwheel.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/trivial/default.nix b/tests/trivial/default.nix index 7941317..bf33137 100644 --- a/tests/trivial/default.nix +++ b/tests/trivial/default.nix @@ -5,4 +5,17 @@ poetry2nix.mkPoetryApplication { pyproject = ./pyproject.toml; poetrylock = ./poetry.lock; src = lib.cleanSource ./.; + + overrides = [ + poetry2nix.defaultPoetryOverrides + ( + self: super: { + maturin = (builtins.trace (lib.functionArgs super.maturin.override) super.maturin.override) { + preferWheel = true; + }; + } + ) + + ]; + }