diff --git a/explanations/python-unsupported-platforms.md b/explanations/python-unsupported-platforms.md new file mode 100644 index 0000000..e775a8c --- /dev/null +++ b/explanations/python-unsupported-platforms.md @@ -0,0 +1 @@ +The python builder automatically sets `meta.platforms` to that of the interpreter, so the only reason to set it is to further limit the supported platforms to a subset of those supported by the python interpreter. diff --git a/lib/default.nix b/lib/default.nix index 3bb7d02..dc09489 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -107,6 +107,7 @@ rec { lib.genAttrs pythonPackageSetNames (pythonName: prev.${pythonName}.override (oldOverrides: { packageOverrides = lib.composeExtensions (oldOverrides.packageOverrides or idOverlay) (final: prev: { + buildPythonApplication = wrapFunctionWithChecks prev.buildPythonApplication check; buildPythonPackage = wrapFunctionWithChecks prev.buildPythonPackage check; }); }) diff --git a/overlays/python-inconsistent-interpreters.nix b/overlays/python-inconsistent-interpreters.nix index ecec91d..4722f05 100644 --- a/overlays/python-inconsistent-interpreters.nix +++ b/overlays/python-inconsistent-interpreters.nix @@ -9,7 +9,7 @@ let checkInputs = drvArgs.checkInputs or []; runtimeInputs = checkInputs ++ propagatedBuildInputs; inputPythonInterpreters = map (p: p.pythonModule) (builtins.filter (p: p ? pythonModule) runtimeInputs); - allPythonInterpreters = lib.unique (inputPythonInterpreters ++ [ drv.pythonModule ]); + allPythonInterpreters = lib.unique (inputPythonInterpreters ++ lib.optionals (drv ? pythonModule) [ drv.pythonModule ]); in lib.singleton { name = "python-inconsistent-interpreters"; @@ -17,13 +17,20 @@ let msg = let allPythonNames = map (p: p.name) allPythonInterpreters; - sources = [ - "buildPythonPackage" + sources = if drv ? pythonModule + then [ "buildPythonPackage" ] ++ lib.optionals (builtins.any (p: p.pythonModule or drv.pythonModule != drv.pythonModule) propagatedBuildInputs) [ "propagatedBuildInputs" ] ++ lib.optionals (builtins.any (p: p.pythonModule or drv.pythonModule != drv.pythonModule) checkInputs) [ "checkInputs" + ] + else [ "buildPythonApplication" + ] ++ lib.optionals (builtins.length (lib.unique(map (p: p.pythonModule) propagatedBuildInputs)) >= 2) [ + "propagatedBuildInputs" + ] ++ lib.optionals (builtins.length (lib.unique(map (p: p.pythonModule) checkInputs)) >= 2) [ + "checkInputs" ]; + in '' Between ${lib.concatStringsSep " and " sources}, this derivation seems to be simultaneously trying to use packages from multiple different Python package sets. diff --git a/overlays/python-unsupported-platforms.nix b/overlays/python-unsupported-platforms.nix new file mode 100644 index 0000000..04b1cc9 --- /dev/null +++ b/overlays/python-unsupported-platforms.nix @@ -0,0 +1,30 @@ +final: prev: +let + inherit (prev) lib; + inherit (import ../lib { inherit lib; }) checkBuildPythonPackageFor; + + checkDerivation = drvArgs: drv: + let + # We can access python with the `pythonModule` attribute of `buildPythonPackage` + # derivations, but it is not so simple with `buildPythonApplication`. Here we rely on the + # performance hack in nixpkgs/pkgs/development/interpreters/python/mk-python-derivation.nix + # which injects python into propagatedBuildInputs. + python = lib.lists.last (builtins.filter (p: p ? pythonVersion) drv.propagatedBuildInputs); + drvPlatforms = drvArgs.meta.platforms or [ ]; + unsupportedPlatforms = lib.lists.subtractLists python.meta.platforms drvPlatforms; + in lib.singleton { + name = "python-unsupported-platforms"; + cond = (unsupportedPlatforms != [ ]) || (lib.lists.naturalSort drvPlatforms == lib.lists.naturalSort python.meta.platforms); + msg = if unsupportedPlatforms != [ ] then '' + The following meta.platforms are not supported by the ${python} interpreter: + [ ${builtins.toString unsupportedPlatforms} ] + '' else '' + The meta.platforms attribute is set to the same value by default. + ''; + locations = [ + (builtins.unsafeGetAttrPos "platforms" python.meta) + (builtins.unsafeGetAttrPos "platforms" drvArgs.meta) + ]; + }; +in + checkBuildPythonPackageFor checkDerivation final prev diff --git a/run-tests.py b/run-tests.py index 8ec15d5..6a7d674 100755 --- a/run-tests.py +++ b/run-tests.py @@ -277,6 +277,19 @@ def __iter__(self): ], ) + yield make_test_rule( + 'python-unsupported-platforms', + [ + 'platforms-all', + "build-python-application-platforms-all", + ], + [ + 'platforms-linux', + 'unspecified', + "build-python-application-platforms-linux", + ] + ) + yield make_test_rule( "python-include-tests", [ @@ -291,9 +304,11 @@ def __iter__(self): [ "mixed-1", "mixed-2", + "build-python-application-mixed", ], [ "normal", + "build-python-application-normal", ], ) diff --git a/tests/default.nix b/tests/default.nix index 80c2003..5e60083 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -25,6 +25,7 @@ python-imports-check-typo = pkgs.recurseIntoAttrs (pkgs.python3.pkgs.callPackage ./python-imports-check-typo { }); python-include-tests = pkgs.recurseIntoAttrs (pkgs.python3.pkgs.callPackage ./python-include-tests { }); python-inconsistent-interpreters = pkgs.recurseIntoAttrs (pkgs.python3.pkgs.callPackage ./python-inconsistent-interpreters { }); + python-unsupported-platforms = pkgs.recurseIntoAttrs (pkgs.python3.pkgs.callPackage ./python-unsupported-platforms { }); stale-substitute = pkgs.recurseIntoAttrs (pkgs.callPackage ./stale-substitute { }); unclear-gpl = pkgs.recurseIntoAttrs (pkgs.callPackage ./unclear-gpl { }); unnecessary-parallel-building = pkgs.recurseIntoAttrs (pkgs.callPackage ./unnecessary-parallel-building { }); diff --git a/tests/python-inconsistent-interpreters/build-python-application-mixed.nix b/tests/python-inconsistent-interpreters/build-python-application-mixed.nix new file mode 100644 index 0000000..28d02a4 --- /dev/null +++ b/tests/python-inconsistent-interpreters/build-python-application-mixed.nix @@ -0,0 +1,13 @@ +{ buildPythonApplication +, python37Packages +, python39Packages +}: + +buildPythonApplication rec { + name = "package"; + + propagatedBuildInputs = [ + python37Packages.numpy + python39Packages.scipy + ]; +} diff --git a/tests/python-inconsistent-interpreters/build-python-application-normal.nix b/tests/python-inconsistent-interpreters/build-python-application-normal.nix new file mode 100644 index 0000000..885ce66 --- /dev/null +++ b/tests/python-inconsistent-interpreters/build-python-application-normal.nix @@ -0,0 +1,13 @@ +{ buildPythonApplication +, numpy +, scipy +}: + +buildPythonApplication rec { + name = "package"; + + propagatedBuildInputs = [ + numpy + scipy + ]; +} diff --git a/tests/python-inconsistent-interpreters/default.nix b/tests/python-inconsistent-interpreters/default.nix index 5badab5..07ac5e8 100644 --- a/tests/python-inconsistent-interpreters/default.nix +++ b/tests/python-inconsistent-interpreters/default.nix @@ -5,7 +5,9 @@ # positive cases mixed-1 = callPackage ./mixed-1.nix { }; mixed-2 = callPackage ./mixed-2.nix { }; + build-python-application-mixed = callPackage ./build-python-application-mixed.nix { }; # negative cases normal = callPackage ./normal.nix { }; + build-python-application-normal = callPackage ./build-python-application-normal.nix { }; } diff --git a/tests/python-unsupported-platforms/build-python-application-platforms-all.nix b/tests/python-unsupported-platforms/build-python-application-platforms-all.nix new file mode 100644 index 0000000..ce80506 --- /dev/null +++ b/tests/python-unsupported-platforms/build-python-application-platforms-all.nix @@ -0,0 +1,12 @@ +{ lib +, buildPythonApplication +}: + +buildPythonApplication rec { + pname = "package"; + version = "0.1.0"; + + meta = with lib; { + platforms = platforms.all; + }; +} diff --git a/tests/python-unsupported-platforms/build-python-application-platforms-linux.nix b/tests/python-unsupported-platforms/build-python-application-platforms-linux.nix new file mode 100644 index 0000000..0df9bc1 --- /dev/null +++ b/tests/python-unsupported-platforms/build-python-application-platforms-linux.nix @@ -0,0 +1,12 @@ +{ lib +, buildPythonApplication +}: + +buildPythonApplication rec { + pname = "package"; + version = "0.1.0"; + + meta = with lib; { + platforms = platforms.linux; + }; +} diff --git a/tests/python-unsupported-platforms/default.nix b/tests/python-unsupported-platforms/default.nix new file mode 100644 index 0000000..803a10c --- /dev/null +++ b/tests/python-unsupported-platforms/default.nix @@ -0,0 +1,13 @@ +{ callPackage +}: + +{ + # positive cases + platforms-all = callPackage ./platforms-all.nix { }; + build-python-application-platforms-all = callPackage ./build-python-application-platforms-all.nix { }; + + # negative cases + platforms-linux = callPackage ./platforms-linux.nix { }; + unspecified = callPackage ./unspecified.nix { }; + build-python-application-platforms-linux = callPackage ./build-python-application-platforms-linux.nix { }; +} diff --git a/tests/python-unsupported-platforms/platforms-all.nix b/tests/python-unsupported-platforms/platforms-all.nix new file mode 100644 index 0000000..49ed31a --- /dev/null +++ b/tests/python-unsupported-platforms/platforms-all.nix @@ -0,0 +1,12 @@ +{ lib +, buildPythonPackage +}: + +buildPythonPackage rec { + pname = "package"; + version = "0.1.0"; + + meta = with lib; { + platforms = platforms.all; + }; +} diff --git a/tests/python-unsupported-platforms/platforms-linux.nix b/tests/python-unsupported-platforms/platforms-linux.nix new file mode 100644 index 0000000..666d113 --- /dev/null +++ b/tests/python-unsupported-platforms/platforms-linux.nix @@ -0,0 +1,12 @@ +{ lib +, buildPythonPackage +}: + +buildPythonPackage rec { + pname = "package"; + version = "0.1.0"; + + meta = with lib; { + platforms = platforms.linux; + }; +} diff --git a/tests/python-unsupported-platforms/unspecified.nix b/tests/python-unsupported-platforms/unspecified.nix new file mode 100644 index 0000000..df58e82 --- /dev/null +++ b/tests/python-unsupported-platforms/unspecified.nix @@ -0,0 +1,7 @@ +{ buildPythonPackage +}: + +buildPythonPackage rec { + pname = "package"; + version = "0.1.0"; +}