diff --git a/pkgs/development/interpreters/python/python-packages-base.nix b/pkgs/development/interpreters/python/python-packages-base.nix index e3a92bef52f35..97ec3f5076f20 100644 --- a/pkgs/development/interpreters/python/python-packages-base.nix +++ b/pkgs/development/interpreters/python/python-packages-base.nix @@ -14,27 +14,23 @@ let # Derivations built with `buildPythonPackage` can already be overridden with `override`, `overrideAttrs`, and `overrideDerivation`. # This function introduces `overridePythonAttrs` and it overrides the call to `buildPythonPackage`. + # + # Overridings specified through `overridePythonAttrs` will always be applied + # before those specified by `overrideAttrs`, even if invoked after them. makeOverridablePythonPackage = f: lib.mirrorFunctionArgs f ( origArgs: let - args = lib.fix ( - lib.extends (_: previousAttrs: { - passthru = (previousAttrs.passthru or { }) // { - overridePythonAttrs = newArgs: makeOverridablePythonPackage f (overrideWith newArgs); - }; - }) (_: origArgs) - ); - result = f args; - overrideWith = newArgs: args // (if pkgs.lib.isFunction newArgs then newArgs args else newArgs); + result = f origArgs; + overrideWith = newArgs: origArgs // lib.toFunction newArgs origArgs; in - if builtins.isAttrs result then + if lib.isAttrs result then result - else if builtins.isFunction result then - { + // { overridePythonAttrs = newArgs: makeOverridablePythonPackage f (overrideWith newArgs); - __functor = self: result; + overrideAttrs = + newArgs: makeOverridablePythonPackage (args: (f args).overrideAttrs newArgs) origArgs; } else result diff --git a/pkgs/test/overriding.nix b/pkgs/test/overriding.nix index 3daa01b6247de..a41400d0d6c1d 100644 --- a/pkgs/test/overriding.nix +++ b/pkgs/test/overriding.nix @@ -390,15 +390,73 @@ let tests-python = let - p = pkgs.python3Packages.xpybutil.overridePythonAttrs (_: { - dontWrapPythonPrograms = true; - }); + python-package-stub = pkgs.python3Packages.callPackage ( + { + buildPythonPackage, + emptyDirectory, + }: + buildPythonPackage { + pname = "python-package-stub"; + version = "0.1.0"; + pyproject = true; + src = emptyDirectory; + } + ) { }; + applyOverridePythonAttrs = + p: + p.overridePythonAttrs (previousAttrs: { + overridePythonAttrsFlag = previousAttrs.overridePythonAttrsFlag or 0 + 1; + }); + overrideAttrsFooBar = + drv: + drv.overrideAttrs ( + finalAttrs: previousAttrs: { + FOO = "a"; + BAR = finalAttrs.FOO; + } + ); in { overridePythonAttrs = { - expr = !lib.hasInfix "wrapPythonPrograms" p.postFixup; + expr = (applyOverridePythonAttrs python-package-stub).overridePythonAttrsFlag; + expected = 1; + }; + overridePythonAttrs-nested = { + expr = + (applyOverridePythonAttrs (applyOverridePythonAttrs python-package-stub)).overridePythonAttrsFlag; + expected = 2; + }; + overrideAttrs-overridePythonAttrs-test-overrideAttrs = { + expr = { + inherit (applyOverridePythonAttrs (overrideAttrsFooBar python-package-stub)) + FOO + BAR + ; + }; + expected = { + FOO = "a"; + BAR = "a"; + }; + }; + overrideAttrs-overridePythonAttrs-test-overridePythonAttrs = { + expr = + (applyOverridePythonAttrs (overrideAttrsFooBar python-package-stub)) ? overridePythonAttrsFlag; expected = true; }; + overrideAttrs-overridePythonAttrs-test-commutation = { + expr = overrideAttrsFooBar (applyOverridePythonAttrs python-package-stub); + expected = applyOverridePythonAttrs (overrideAttrsFooBar python-package-stub); + }; + chain-of-overrides = rec { + expr = lib.pipe python-package-stub [ + (p: p.overrideAttrs { inherit (expected) a; }) + (p: p.overridePythonAttrs { inherit (expected) b; }) + (p: p.overrideAttrs { inherit (expected) c; }) + (p: p.overridePythonAttrs { inherit (expected) d; }) + (builtins.intersectAttrs expected) + ]; + expected = lib.genAttrs [ "a" "b" "c" "d" ] lib.id; + }; }; in