pypa / pipx

Install and Run Python Applications in Isolated Environments
https://pipx.pypa.io
MIT License
9.49k stars 393 forks source link

HIGH: pipx install --global order broken in 1.6.0 #1443

Open wdoekes opened 4 weeks ago

wdoekes commented 4 weeks ago

Describe the bug

Doing pipx install --global behaves differently from pipx --global install. The latter command does not do global but local.

How to reproduce

root@05515ef1bff7:/# pipx --global install dutree
  installed package dutree 1.8, installed using Python 3.9.2
  These apps are now globally available
    - dutree
⚠️  Note: '/root/.local/bin' is not on your PATH environment variable. These apps will not be globally accessible until your PATH is updated. Run `pipx ensurepath` to automatically
    add it, or manually modify your PATH in your shell's config file (e.g. ~/.bashrc).
done! ✨ 🌟 ✨
root@05515ef1bff7:/# which dutree
root@05515ef1bff7:/# ls /root/.local/bin
dutree

^- not global

root@05515ef1bff7:/# pipx uninstall dutree
uninstalled dutree! ✨ 🌟 ✨
root@05515ef1bff7:/# pipx install --global dutree
  installed package dutree 1.8, installed using Python 3.9.2
  These apps are now globally available
    - dutree
done! ✨ 🌟 ✨
root@05515ef1bff7:/# which dutree
/usr/local/bin/dutree

^- yes, global

root@05515ef1bff7:/# pipx --version
1.6.0

Expected behavior

Both install --global and --global install should install in the same place: /usr/local/bin.

Cause?

Likely the code from #1397 has something to do with this.

1.5 works fine:

root@05515ef1bff7:/# pipx uninstall --global dutree
uninstalled dutree! ✨ 🌟 ✨
root@05515ef1bff7:/# pip3 install pipx==1.5.0
Collecting pipx==1.5.0
  Downloading pipx-1.5.0-py3-none-any.whl (72 kB)
     |████████████████████████████████| 72 kB 653 kB/s 
...
Successfully installed pipx-1.5.0
root@05515ef1bff7:/# pipx --global install dutree
  installed package dutree 1.8, installed using Python 3.9.2
  These apps are now globally available
    - dutree
done! ✨ 🌟 ✨
root@05515ef1bff7:/# which dutree
/usr/local/bin/dutree

In 1.5 it complains when doing things "the new way":

root@05515ef1bff7:/# pipx install --global dutree
usage: pipx [-h] [--quiet] [--verbose] [--global] [--version]
            {install,uninject,inject,upgrade,upgrade-all,uninstall,uninstall-all,reinstall,reinstall-all,list,interpreter,run,runpip,ensurepath,environment,completions} ...
pipx: error: unrecognized arguments: --global

So, the only order has been --global install and something in 1.6.0 severely broke it.

dukecat0 commented 4 weeks ago

Seems related to #1282.

wdoekes commented 4 weeks ago

There is this code:

    parser = argparse.ArgumentParser(
        prog=prog_name(),
        formatter_class=LineWrapRawTextHelpFormatter,
        description=PIPX_DESCRIPTION,
        parents=[shared_parser],
    )

It enables/allows --global etc. before the install command. But it's a separate parser and values are not available at parser.parse_args() because they are overwritten by the second usage of shared_parser.

Easiest workaround is to disallow the shared_parser values. At least then the breakage is obvious:

    parser = argparse.ArgumentParser(
        prog=prog_name(),
        formatter_class=LineWrapRawTextHelpFormatter,
        description=PIPX_DESCRIPTION,
        #REMOVEME# `parents=[shared_parser],
    )

An alternative might be to rename the dest (from global_is_global to is_global) before using it as second shared_parser and then checking a combination of global_is_global and is_global. But that feels hackish.

michelzanini commented 3 weeks ago

This is a major bug to me. It breaks backwards compatibility.