Ability to select a package installed with suffix as default installation
How would this feature be useful? Binaries from packages installed with a suffix currently also end with the same suffix. This makes it impossible to use them together with existing scripts and is cumbersome to use. These issues could be alleviated by installing the binaries without a suffix. To work around the name clashes, an additional command is added with which one can quickly switch between installed packages and their suffixes.
Describe the solution you'd like
I have started a proof of concept here: https://github.com/ctbur/pipx/compare/master...command-select
With pipx select you can choose which installed suffix is used as the default.
Example:
pipx install pre-commit==2.4 --suffix _2_4
pipx install pre-commit==2.5 --suffix _2_5
pipx select pre-commit_2_4
pre-commit --version # will show version 2.4
pipx select pre-commit_2_5
pre-commit --version # will show version 2.5
Please let me know if that is something that you would like to add to pipx, too. If so, I will expand on the proof of concept and add documentation, tests, autocomplete, a changelog entry and proper commit message.
How would this work if you also had pre-commit (no suffix) installed?
Maybe we should add the ability to “symlink” a prefixed app to the non-prefixed location to avoid this problem.
Obviously if you run this:
pipx install pre-commit
pipx install pre-commit==2.5 --suffix _2_5
pipx select pre-commit_2_5
Then the pre-commit install without suffix is no longer callable, until you run pipx select pre-commit. You can choose if you want to forbid pipx select in that case or just accept that a package's binaries may not be callable some times.
@uranusjr I am not sure I understand. Are you talking about symlinking the venv? Or what is the "non-prefixed location"?
The venv, and its associated executables. With that approach, you won’t be able to “shadow” the non-suffixed app with a suffixed. The non-suffixed would always be the default if it exists, and select can only work if you only have suffixed variants installed. This may be less convenient for you, but IMO would be leas surprising for users in general.
If I thought this through correctly your suggested solution should be equivalent from the user's perspective to just forbidding to run pipx select if a non-suffixed variant is installed.
In this case the last command would fail:
pipx install pre-commit
pipx install pre-commit==2.5 --suffix _2_5
pipx select pre-commit_2_5 # fails because we forbid it
In this case the binary symlinks would be overwritten, leading to the non-suffixed variant being the default:
pipx install pre-commit==2.5 --suffix _2_5
pipx select pre-commit_2_5
pipx install pre-commit # overwrites symlinks created by `pipx select`, might need `--force` as argument
[...] forbidding to run
pipx selectif a non-suffixed variant is installed.
I like this way of doing it. It's the only way I can think of that makes sense.
A way of thinking about this that helps me, is just a more limited version of a hypothetical alias command, that you can only alias a suffixed venv with its non-suffixed name.
If you consider an alias blocking a new venv and an existing venv blocking an alias then the user interface makes sense and works out as @ctbur gives examples of above.
What now I'm curious about is how we would keep track of the select. Somehow pipx would have to keep track with some sort of metadata. Perhaps this is what @uranusjr is alluding to, but it seems to me you'd have to make a placeholder venv directory (with the un-suffixed root name) that just contains some sort of metadata describing what has happened to the selected executables. It would also naturally show up as an existing venv if a user tried to install to the same name.
Oh I understand @uranusjr 's point now. Just symlinking the venv and then making executables with the proper names would do much of that "keeping track of select".
However doesn't Windows have trouble doing real symlinking? Would this be a problem on non-macOS, non-unix platforms?
Yes, Windows would be a problem. I put symlink in quotes because we likely should implement something that mimics the symlink functionality instead of using os.symlink directly. We could e.g. create a file in place of an actual venv that contains tracking metadata, or create a directory that contains just metadata as you said.
I suggested directory with data file inside mostly because I know that "directory exists and has something inside of it" is the test that all/most of the pipx codebase uses already to determine that a venv is pre-existing and we cannot install to it.
Of course there would need to be some special new code to handle a select-shell-venv when a user force-installs to that name using install -f or attempts to inject to it.
IMO, this seems a worthwhile benefit to functionality and not too much extra complexity as far as I can tell.
Before working on it more I would wait for #498 to land, it cleans up a bunch of code related to suffixes.
Thinking more on this, I'm a little worried it may get complicated, if you really do it right so that pipx keeps track of everything properly and guards against collisions of install vs. select venvs. I wouldn't be surprised if this code gets involved...
Thinking more on this, I'm a little worried it may get complicated, if you really do it right so that pipx keeps track of everything properly and guards against collisions of
installvs.selectvenvs. I wouldn't be surprised if this code gets involved...
On this ground I'll say out of scope for now.