pipx icon indicating copy to clipboard operation
pipx copied to clipboard

add get-pipx script

Open cs01 opened this issue 3 years ago • 5 comments

  • [x] I have added an entry to docs/changelog.md

Currently, pipx is commonly installed with pip install pipx --user, which installs into the user's site packages, rather than a virtual environment. This is a little ironic since the whole point of pipx is to not install everything into a single global environment. pipx makes an exception for itself here, but it's a little hypocritical. I would like to improve on this.

This PR adds a new installer script that installs pipx with itself: it creates a temporary dir, creates a venv in there, installs pipx to the temp venv, then installs pipx with pipx, then deletes the temporary venv..

Summary of changes

  • Add get-pipx.py script to allow for isolated pipx installations (following an approach similar to https://github.com/mattsb42-meta/pipx-in-pipx)
  • Add unit test
  • Update README install instructions
  • Update installation.md install page
  • Add @uranusjr's scoop as an installation method for windows
  • Add a required package to the list of packages required by unit tests

Test plan

Tested by running

> curl https://raw.githubusercontent.com/pypa/pipx/cs01/add-get-pipx-script/get-pipx.py | python3.10
Welcome to the pipx installer!

This will download and globally install pipx for you.
It does this by installing pipx to a temporary location, then uses the
temporarily-installed pipx to install pipx system-wide.

pipx will be installed to:

  /home/csmith/.local/bin

This can be modified with the PIPX_BIN_DIR environment variable.

Virtual environments for installed packages will be created at:

  /home/csmith/.local/pipx/venvs

This can be modified with the PIPX_HOME environment variable.

You can uninstall anytime with pipx uninstall pipx

The following options have been specified:

  modify PATH variable in shell: yes
  python: /usr/bin/python3.10
  pipx package specification: pipx

Waiting 10 seconds before continuing (pass --nowait to run immediately)...

  installed package pipx 1.1.0, installed using Python 3.10.0
  These apps are now globally available
    - pipx
Note: '/home/csmith/.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 (i.e. ~/.bashrc).
done! 
Success! Added /home/csmith/.local/bin to the PATH environment variable.

Consider adding shell completions for pipx. Run 'pipx completions' for instructions.

Otherwise pipx is ready to go! 

Try running 'pipx list' or 'pipx install'

fixes #338 fyi @mattsb42-meta

cs01 avatar Jun 10 '22 06:06 cs01

Generally looks good but the there seems to be some issues in documentation formatting.

uranusjr avatar Jun 27 '22 04:06 uranusjr

I am a little conflicted on adding this script. Another alternative I'm considering is building a pex and allowing users to just download and run it. It makes this script unnecessary. Thoughts?

cs01 avatar Jun 27 '22 04:06 cs01

Hmm, distributing a pex sounds nice, but do we need to do something to specify the default interpreter pipx uses if we do that?

uranusjr avatar Jun 27 '22 04:06 uranusjr

Hmm, distributing a pex sounds nice, but do we need to do something to specify the default interpreter pipx uses if we do that?

Kind of, the pex can be told to use a shell script to find the right python interpreter from a list. Whichever one ends up matching is the one that pipx uses, which is also the python executable associated with a pipx-installed app unless the --python flag is passed to pipx (or pipx.pex)

The --sh-boot option, described in the help text as follows:

  --sh-boot, --no-sh-boot
                        Create a modified ZIPAPP that uses `/bin/sh` to boot. If you know the machines that the PEX will be distributed to have POSIX compliant `/bin/sh`
                        (almost all do, see: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/sh.html); then this is probably the way you want your PEX to boot.
                        Instead of launching via a Python shebang, the PEX will launch via a `#!/bin/sh` shebang that executes a small script embedded in the head of the PEX
                        ZIPAPP that performs initial interpreter selection and re-execution of the underlying PEX in a way that is often more robust than a Python shebang and
                        always faster on 2nd and subsequent runs since the sh script has a constant overhead of O(1ms) whereas the Python overhead to perform the same
                        interpreter selection and re-execution is O(100ms). (default: False)

So if I do

> pipx run pex . --console-script pipx --output-file /tmp/pipx.pex --validate-entry-point --interpreter-constraint="CPython>=3.7" --sh-boot

we get

> head -n 100 /tmp/pipx.pex 
#!/bin/sh
# N.B.: This script should stick to syntax defined for POSIX `sh` and avoid non-builtins.
# See: https://pubs.opengroup.org/onlinepubs/9699919799/idx/shell.html
set -eu

VENV=""

# N.B.: This ensures tilde-expansion of the DEFAULT_PEX_ROOT value.
DEFAULT_PEX_ROOT="$(echo /home/csmith/.pex)"

DEFAULT_PYTHON="None"
DEFAULT_PYTHON_ARGS="None"

PEX_ROOT="${PEX_ROOT:-${DEFAULT_PEX_ROOT}}"
INSTALLED_PEX="${PEX_ROOT}/unzipped_pexes/65320b04ede11d9cb47acfd635e5ef1d9933dd4c"

if [ -n "${VENV}" -a -x "${INSTALLED_PEX}" ]; then
    # We're a --venv execution mode PEX installed under the PEX_ROOT and the venv
    # interpreter to use is embedded in the shebang of our venv pex script; so just
    # execute that script directly.
    export PEX="$0"
    exec "${INSTALLED_PEX}" "$@"
fi

find_python() {
    for python in \
"python3.9" \
"python3.10" \
"python3.7" \
"python3.8" \
"python3.11" \
"python3.6" \
"python3.5" \
"python2.7" \
"pypy3.11" \
"pypy3.10" \
"pypy3.9" \
"pypy3.8" \
"pypy3.7" \
"pypy3.6" \
"pypy3.5" \
"pypy2.7" \
"python3" \
"python2" \
"pypy3" \
"pypy2" \
"python" \
"pypy" \

I'm trying to figure out how to tell it to specify minimum versions (i.e. not use python2.7 in that list). The --interpreter-constraint isn't working...

Would this approach work for windows too? I'm guessing not since windows doesn't have a posix shell.

cs01 avatar Jun 27 '22 04:06 cs01

The --interpreter-constraint isn't working...

I guess --interpreter-constraint actually works?

Output of pipx.pex when there is no Python 3.7+ interpreter:

Examined the following working interpreters:
1.) /home/gitpod/.pyenv/versions/3.6.0/bin/python3.6 CPython==3.6.0
2.)                               /usr/bin/python2.7 CPython==2.7.18

(See https://github.com/pantsbuild/pex/issues/1027 for a list of known breaks and workarounds.)

No working interpreter compatible with the requested constraints was found:

  Version matches CPython>=3.7

dukecat0 avatar Jul 23 '22 16:07 dukecat0

The interpreter check seems to work for me as well. When I make a requirement and then remove the path to my latest interpreters from my shell, it correctly tells me that I have a python but not the right one.

But I can't find the mechanism (!!) The only thing I can think of is that the info is obscured somewhere below the shell script in the zipped data.

This is the command I used, referring directly to our entrypoint location, not sure if there are any benefits one way or another:

pex pipx -o pipx.pex -m pipx.main:cli --interpreter-constraint="CPython>=3.7" --sh-boot

I really like the idea of generating what looks like a "pipx binary" for POSIX folks to easily put in a system PATH location. I've always been dissatisfied with our install process on linux especially (i.e. without homebrew to install).

itsayellow avatar Nov 24 '22 06:11 itsayellow

One slight annoyance is that now we generate a ~/.pex directory inside of the user's home directory when pipx.pex is run. 🙁

itsayellow avatar Nov 24 '22 07:11 itsayellow

Seems stalled, closing until more contribution when we can reopen.

gaborbernat avatar Nov 30 '23 19:11 gaborbernat