diff --git a/pkgs/development/interpreters/python/hooks/default.nix b/pkgs/development/interpreters/python/hooks/default.nix index b3c97de30317..d50e12dc7262 100644 --- a/pkgs/development/interpreters/python/hooks/default.nix +++ b/pkgs/development/interpreters/python/hooks/default.nix @@ -138,6 +138,7 @@ in propagatedBuildInputs = [ installer ]; substitutions = { inherit pythonInterpreter pythonSitePackages; + python = python.interpreter; }; } ./pypa-install-hook.sh ) diff --git a/pkgs/development/interpreters/python/hooks/pypa-install-hook.sh b/pkgs/development/interpreters/python/hooks/pypa-install-hook.sh index f6d60be35d21..54e6375bb861 100644 --- a/pkgs/development/interpreters/python/hooks/pypa-install-hook.sh +++ b/pkgs/development/interpreters/python/hooks/pypa-install-hook.sh @@ -8,7 +8,7 @@ pypaInstallPhase() { pushd dist >/dev/null for wheel in *.whl; do - @pythonInterpreter@ -m installer --prefix "$out" "$wheel" + @pythonInterpreter@ -m installer --prefix "$out" --executable "@python@" "$wheel" echo "Successfully installed $wheel" done diff --git a/pkgs/development/python-modules/installer/cross.patch b/pkgs/development/python-modules/installer/cross.patch new file mode 100644 index 000000000000..3e7f185f041d --- /dev/null +++ b/pkgs/development/python-modules/installer/cross.patch @@ -0,0 +1,67 @@ +diff --git a/src/installer/__main__.py b/src/installer/__main__.py +index 51014b9..45682d0 100644 +--- a/src/installer/__main__.py ++++ b/src/installer/__main__.py +@@ -30,6 +30,13 @@ def _get_main_parser() -> argparse.ArgumentParser: + type=str, + help="override prefix to install packages to", + ) ++ parser.add_argument( ++ "--executable", ++ metavar="path", ++ default=sys.executable, ++ type=str, ++ help="#! executable to install scripts with (default=sys.executable)", ++ ) + parser.add_argument( + "--compile-bytecode", + action="append", +@@ -86,7 +93,7 @@ def _main(cli_args: Sequence[str], program: Optional[str] = None) -> None: + with WheelFile.open(args.wheel) as source: + destination = SchemeDictionaryDestination( + scheme_dict=_get_scheme_dict(source.distribution, prefix=args.prefix), +- interpreter=sys.executable, ++ interpreter=args.executable, + script_kind=get_launcher_kind(), + bytecode_optimization_levels=bytecode_levels, + destdir=args.destdir, +@@ -94,5 +101,6 @@ def _main(cli_args: Sequence[str], program: Optional[str] = None) -> None: + installer.install(source, destination, {}) + + ++ + if __name__ == "__main__": # pragma: no cover + _main(sys.argv[1:], "python -m installer") +diff --git a/tests/test_main.py b/tests/test_main.py +index 391a13d..d7b4192 100644 +--- a/tests/test_main.py ++++ b/tests/test_main.py +@@ -53,6 +53,28 @@ def test_main_prefix(fancy_wheel, tmp_path): + } + + ++def test_main_executable(fancy_wheel, tmp_path): ++ destdir = tmp_path / "dest" ++ ++ main( ++ [ ++ str(fancy_wheel), ++ "-d", ++ str(destdir), ++ "--executable", ++ "/monty/python3.x", ++ ], ++ "python -m installer", ++ ) ++ ++ installed_scripts = destdir.rglob("bin/*") ++ ++ for f in installed_scripts: ++ with f.open("rb") as fp: ++ shebang = fp.readline() ++ assert shebang == b"#!/monty/python3.x\n" ++ ++ + def test_main_no_pyc(fancy_wheel, tmp_path): + destdir = tmp_path / "dest" + diff --git a/pkgs/development/python-modules/installer/default.nix b/pkgs/development/python-modules/installer/default.nix index 7170c110673e..377c3637d04a 100644 --- a/pkgs/development/python-modules/installer/default.nix +++ b/pkgs/development/python-modules/installer/default.nix @@ -21,11 +21,17 @@ buildPythonPackage rec { hash = "sha256-thHghU+1Alpay5r9Dc3v7ATRFfYKV8l9qR0nbGOOX/A="; }; - patches = lib.optionals (pythonAtLeast "3.13") [ - # Fix compatibility with Python 3.13 - # https://github.com/pypa/installer/pull/201 - ./python313-compat.patch - ]; + patches = + lib.optionals (pythonAtLeast "3.13") [ + # Fix compatibility with Python 3.13 + # https://github.com/pypa/installer/pull/201 + ./python313-compat.patch + ] + ++ [ + # Add -m flag to installer to correctly support cross + # https://github.com/pypa/installer/pull/258 + ./cross.patch + ]; nativeBuildInputs = [ flit-core ];