Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make pipx more automation friendly, like pip #1562

Open
gaby opened this issue Oct 12, 2024 · 7 comments
Open

Make pipx more automation friendly, like pip #1562

gaby opened this issue Oct 12, 2024 · 7 comments
Labels
enhancement New feature or request

Comments

@gaby
Copy link

gaby commented Oct 12, 2024

Describe the bug

I currently manage a fleet of hosts configured with Ansible, and we’ve recently encountered a new challenge with newer operating systems. We're now required (PEP 668) to install applications globally for multiple users, which is where pipx comes in, using the --global flag. Previously, we could set the version of a Python application as an Ansible variable, and pip would handle the installation smoothly when the version changed. However, after migrating to pipx, this behavior has changed. Pipx won’t allow version updates unless the --force flag is used, which isn't ideal.

If our playbooks run daily, using --force becomes inefficient since it reinstalls the entire application every time. Pipx should ideally support version updates by automatically upgrading the app instead of simply stating that it’s already installed.

The same happens with using pipx inject, there's no way to upgrade an injected app.

How to reproduce

Example of simple pipx install, and changing version:

root@3a7829e7364c:/# pipx --version
1.7.1
root@3a7829e7364c:/# pipx install --global ruff==0.6.8
  installed package ruff 0.6.8, installed using Python 3.12.7
  These apps are now globally available
    - ruff
done! ✨ 🌟 ✨
root@3a7829e7364c:/# pipx install --global ruff==0.6.9
'ruff' already seems to be installed. Not modifying existing installation in
'/opt/pipx/venvs/ruff'. Pass '--force' to force installation.
root@3a7829e7364c:/#

Example pipx inject with issue:

root@3a7829e7364c:/# pipx install --global uv --include-deps
  installed package uv 0.4.20, installed using Python 3.12.7
  These apps are now globally available
    - uv
    - uvx
done! ✨ 🌟 ✨
root@3a7829e7364c:/# pipx inject --global uv ruff==0.6.8 --include-apps --include-deps
  installed package ruff 0.6.8, installed using Python 3.12.7
  These apps are now globally available
    - ruff
    - uv
    - uvx
done! ✨ 🌟 ✨
  injected package ruff into venv uv
done! ✨ 🌟 ✨
root@3a7829e7364c:/# pipx inject --global uv ruff==0.6.9 --include-apps --include-deps
⚠️ ruff already seems to be injected in 'uv'. Not modifying existing installation in '/opt/pipx/venvs/uv'. Pass '--force' to force installation.
root@3a7829e7364c:/#

Now if i try using pipx upgrade, it doesn't support specifying a spec, and doesn't work at all:

root@3a7829e7364c:/# pipx upgrade --global uv ruff==0.6.9
uv is already at latest version 0.4.20 (location: /opt/pipx/venvs/uv)
Package is not installed. Expected to find /opt/pipx/venvs/ruff==0-6-9, but it does not exist.

Expected behavior

Example pip install with a new version, works out of the box.

root@3a7829e7364c:/# pip install ruff==0.6.8
Collecting ruff==0.6.8
  Using cached ruff-0.6.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.metadata (25 kB)
Using cached ruff-0.6.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (10.7 MB)
Installing collected packages: ruff
Successfully installed ruff-0.6.8
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager, possibly rendering your system unusable.It is recommended to                                                            use a virtual environment instead: https://pip.pypa.io/warnings/venv. Use the --root-user-action option if you know what you are doing and want to suppress this warning.
root@3a7829e7364c:/# pip install ruff==0.6.9
Collecting ruff==0.6.9
  Downloading ruff-0.6.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.metadata (25 kB)
Downloading ruff-0.6.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (10.8 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 10.8/10.8 MB 23.6 MB/s eta 0:00:00
Installing collected packages: ruff
  Attempting uninstall: ruff
    Found existing installation: ruff 0.6.8
    Uninstalling ruff-0.6.8:
      Successfully uninstalled ruff-0.6.8
Successfully installed ruff-0.6.9
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager, possibly rendering your system unusable.It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv. Use the --root-user-action option if you know what you are doing and want to suppress this warning.
root@3a7829e7364c:/#

We have spent multiple days trying to figure out how to migrate our automated setup from pip to pipx. It shouldn't be this hard.

tldr

  • Updating installed applications is not user friendly.
  • Updating injected applications is not user friendly.
  • pipx is not consistent across commands in terms of spec. Some commands take a version, some don't.
  • pipx upgrade doesn't support specifying package version.
  • pipx is a nightmare to use with any automation tool that will update versions.

Potential Solutions

  • Adding a --upgrade param to pipx install that will use the spec to auto-upgrade the package. Similar to what pip --upgrade <spec> does.
  • Add support for <spec> to pipx upgrade.
  • Add support for upgrading injected apps via pipx inject --upgrade, similar to point 1 on this list of Potential Solutions
@dukecat0
Copy link
Member

Thanks for the feedback, I agree that some parts of the application can be improved to be more user-friendly.

Here are some of the alternative solutions that I would recommend:

Adding a --upgrade param to pipx install that will use the spec to auto-upgrade the package. Similar to what pip --upgrade does.

pipx upgrade --install <spec>

Add support for upgrading injected apps via pipx inject --upgrade, similar to point 1 on this list of Potential Solutions

pipx upgrade --include-injected <package>

@dukecat0 dukecat0 added the enhancement New feature or request label Oct 16, 2024
@gaby
Copy link
Author

gaby commented Oct 16, 2024

Thanks for the feedback, I agree that some parts of the application can be improved to be more user-friendly.

Here are some of the alternative solutions that I would recommend:

Adding a --upgrade param to pipx install that will use the spec to auto-upgrade the package. Similar to what pip --upgrade does.

pipx upgrade --install <spec>

Add support for upgrading injected apps via pipx inject --upgrade, similar to point 1 on this list of Potential Solutions

pipx upgrade --include-injected <package>

@dukecat0 Your first suggestion does solve one problem. The 2nd suggestion doesnt allow using <spec> which a deal breaker.

My team manages/installs several python applications/packages for a fleet of hosts. We keep a tight boat by controlling which versions are installed via ansible group variables. The playbooks run automatically on each host every day to maintain a consistent fleet of hosts.

Being able to specify versions allows us to revert a deployment in case an application has a bug on their release.

Given my example, I would like to be able to upgrade ruff to a specific version while its injected into uv.

@gaby
Copy link
Author

gaby commented Oct 16, 2024

Another issue I noticed is that pipx list doesnt show versions of injected packages. There's actually 0 way of finding this information.

This one is a known issue since 2023, #997

@powercoconola
Copy link

powercoconola commented Oct 17, 2024

pipx is a nightmare to use with any automation tool that will update versions.

I am curious about this. I tried installing and/or upgrading my packages with threading in a custom python script so it can take less time, but I wasn't successful. I think this is due to the shared directory but I am not sure. I ran into odd issues.
What sort of automation tools are you using?

@gaby
Copy link
Author

gaby commented Oct 17, 2024

pipx is a nightmare to use with any automation tool that will update versions.

I am curious about this. I tried installing and/or upgrading my packages with threading in a custom python script so it can take less time, but I wasn't successful. I think this is due to the shared directory but I am not sure. I ran into odd issues. What sort of automation tools are you using?

Ansible, which has a "pipx" module.

https://docs.ansible.com/ansible/latest/collections/community/general/pipx_module.html

@gaby
Copy link
Author

gaby commented Oct 17, 2024

For example this won't work with plain pipx and/or ansible:

---
- name: Install tox
  community.general.pipx:
    name: tox==1.0.0

Then running the same thing with ==2.0.0, it just fails. With pip it works by properly upgrading the package.

@gaby
Copy link
Author

gaby commented Oct 17, 2024

Another issue that makes pipx not friendly is the fact it doesnt use System Certificates like pip does. This causes locally issued certs to not be trusted even though the System and Pip trust them.

This has been extensively documented here #961

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants