NixOS / nixpkgs

Nix Packages collection & NixOS
MIT License
18.04k stars 14.09k forks source link

pipx: virtual environment symlink points to nix store path instead of nix profile path #171429

Open seasonedfish opened 2 years ago

seasonedfish commented 2 years ago

Describe the bug

If you install pipx through Nix and use pipx to install packages, pipx's virtual environment symlink points to the Nix store path instead of the Nix profile path.

[fisher@workshop ~]$ cd .local/pipx/shared/bin
[fisher@workshop bin]$ readlink python3.8
/nix/store/4s37sy0bql8wj1n3iwi0ircj96ydh25g-python3-3.8.13/bin/python3.8

The result is that whenever the user upgrades Python and collects garbage using Nix, the symlink will be invalid.

Steps To Reproduce

Steps to reproduce the behavior:

  1. Install pipx using Nix
  2. Install packages using pipx
  3. Upgrade Python using Nix, collect garbage
  4. Try to run packages installed using pipx

Expected behavior

The virtual environment symlink should point to the Nix profile path. Using venv by itself yields the correct behavior:

[fisher@workshop /tmp]$ python3 -m venv .venv
[fisher@workshop /tmp]$ cd .venv/bin
[fisher@workshop bin]$ readlink python3
/Users/fisher/.nix-profile/bin/python3

Additional context

If I may speculate, this seems to be a Nix packaging issue. On creating a venv, pipx uses the DEFAULT_PYTHON variable, which is set to the output of sys.executable.

Running sys.executable from a REPL gives me the correct result.

[fisher@workshop bin]$ python3
Python 3.8.13 (default, Apr 15 2022, 15:21:31)
[Clang 11.1.0 ] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.executable
'/Users/fisher/.nix-profile/bin/python3'

Notify maintainers

@yshym

Metadata

Please run nix-shell -p nix-info --run "nix-info -m" and paste the result.

[user@system:~]$ nix-shell -p nix-info --run "nix-info -m"
 - system: `"x86_64-darwin"`
 - host os: `Darwin 20.6.0, macOS 10.16`
 - multi-user?: `no`
 - sandbox: `no`
 - version: `nix-env (Nix) 2.3.16`
 - channels(fisher): `"home-manager, nixpkgs-22.05pre373991.b283b64580d"`
 - nixpkgs: `/Users/fisher/.nix-defexpr/channels/nixpkgs`
spott commented 1 year ago

I'm getting a different result than you are:

which python3.10                                                                                                                                                                          ~
/Users/spott/.nix-profile/bin/python
λ › python3.10                                                                                                                                                                                ~
Python 3.10.12 (main, Aug 24 2023, 05:19:11) [Clang 11.1.0 ] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys; sys.executable
'/nix/store/my12ln4rzvqiinyi2f3cyyvsvs29s7aq-python3-3.10.12-env/bin/python3.10'

I get the same result with python3, and python.

The env variable PIPX_DEFAULT_PYTHON can change the python interpreter that is used. I'm not sure if there is a way to set that for the python package when it is installed.

spott commented 1 year ago

It looks like PIPX_DEFAULT_PYTHON can be set by adding makeWrapperArgs = ["--set PIPX_DEFAULT_PYTHON ${nix_profile_path_for_python}"] to the buildPythonPackage function.

Unfortunately, there is the issue that this kind of breaks purity for the pipx package if you depend on a profile path within a derivation. Is there a way to prevent the GC from cleaning up the locations?