Pipx: register-python-argcomplete not available when pipx is installed via homebrew

Created on 10 Jan 2020  路  13Comments  路  Source: pipxproject/pipx

Describe the bug
pipx completions cannot be enabled when pipx is installed via homebrew because the command register-python-argcomplete is not available.

How to reproduce

$ brew install pipx
$ eval "$(register-python-argcomplete pipx)"
-bash: register-python-argcomplete: command not found

Expected behavior
eval "$(register-python-argcomplete pipx)" completes without errors and pipx autocomplete works.

Most helpful comment

@itsayellow you can thank @chenrui333 who鈥檚 been maintaining it!

And yes there is a homebrew location for completions. I鈥檒l look into it and make a PR.

All 13 comments

@AlJohri can this dependency be added to brew? Also a few new versions of pipx were published, not sure if they made it into homebrew.

Also a few new versions of pipx were published, not sure if they made it into homebrew.

Actually I'm impressed with @AlJohri, we've had a flurry of releases and he's kept up with every single one of them, just waiting on the most recent 0.15.1.2 (thanks @AlJohri)

There are a bunch of homebrew tools that have optional shell completions, so maybe there's a homebrew formula idiom for this?

@itsayellow you can thank @chenrui333 who鈥檚 been maintaining it!

And yes there is a homebrew location for completions. I鈥檒l look into it and make a PR.

Thank you @chenrui333 馃槂

And yes there is a homebrew location for completions. I鈥檒l look into it and make a PR.

Wouldn't the fix just be to add the argcomplete package as part of the pipx homebrew bundle, similar to userpath?

If you look at the docs here: https://docs.brew.sh/Shell-Completion

It shows that homebrew installs bash completions to $HOMEBREW_PREFIX/etc/bash_completion.d/ and zsh completions to $HOMEBREW_PREFIX/share/zsh/site-functions/.

This way, if a user has set up sourcing the completions in their profile, it will automatically pick up the completion of each newly installed tool. I'll take a look at this again tomorrow as to how this should be implemented in the homebrew formula.

Here's an example of how this is done in homebrew from hub:

bash_completion.install "etc/hub.bash_completion.sh"
zsh_completion.install "etc/hub.zsh_completion" => "_hub"
fish_completion.install "etc/hub.fish_completion" => "hub.fish"

Source: https://github.com/Homebrew/homebrew-core/blob/master/Formula/hub.rb#L23

So it seems homebrew requires static completion files? Here's a github issue from argcomplete talking about generating such files: https://github.com/kislyuk/argcomplete/issues/85

I also wouldn't want to add register-python-argcomplete to the PATH in homebrew since this is not a pipx specific utility. We ran into a similar issue when you wanted to use userpath as a top level tool.

I'll do some more research next chance I get- if anyone has any insights here, please chime in.

Edit a simple solution, of course is to just wrap the completion within the pipx CLI: eval "$(pipx completions)" and then I would just add argcomplete as a regular dependency and it doesn't need to be in the PATH.

But ideally if there was a way to create a static completion file the end user doesn't have to run anything at all.

Would it be good enough to add register-python-completion as a build-time dependency (I forget the terminology for that), and simply output the result to a static file during installation? Or is pipx鈥檚 argparse usage too dynamic for that to work?

Edit a simple solution, of course is to just wrap the completion within the pipx CLI: eval "$(pipx completions)" and then I would just add argcomplete as a regular dependency and it doesn't need to be in the PATH.
But ideally if there was a way to create a static completion file the end user doesn't have to run anything at all.
Would it be good enough to add register-python-completion as a build-time dependency (I forget the terminology for that), and simply output the result to a static file during installation? Or is pipx鈥檚 argparse usage too dynamic for that to work?

Yes this can be done. The bash completion, for example, is fairly small:

>> register-python-argcomplete pipx

# Run something, muting output or redirecting it to the debug stream
# depending on the value of _ARC_DEBUG.
__python_argcomplete_run() {
    if [[ -z "$_ARC_DEBUG" ]]; then
        "$@" 8>&1 9>&2 1>/dev/null 2>&1
    else
        "$@" 8>&1 9>&2 1>&9 2>&1
    fi
}

_python_argcomplete() {
    local IFS=$'\013'
    local SUPPRESS_SPACE=0
    if compopt +o nospace 2> /dev/null; then
        SUPPRESS_SPACE=1
    fi
    COMPREPLY=( $(IFS="$IFS" \
                  COMP_LINE="$COMP_LINE" \
                  COMP_POINT="$COMP_POINT" \
                  COMP_TYPE="$COMP_TYPE" \
                  _ARGCOMPLETE_COMP_WORDBREAKS="$COMP_WORDBREAKS" \
                  _ARGCOMPLETE=1 \
                  _ARGCOMPLETE_SUPPRESS_SPACE=$SUPPRESS_SPACE \
                  __python_argcomplete_run "$1") )
    if [[ $? != 0 ]]; then
        unset COMPREPLY
    elif [[ $SUPPRESS_SPACE == 1 ]] && [[ "$COMPREPLY" =~ [=/:]$ ]]; then
        compopt -o nospace
    fi
}
complete -o nospace -o default -o bashdefault -F _python_argcomplete pipx

Although pipx's autocompletions are dynamic (they vary based on folder contents, for example), the dynamic aspect of it comes from argcomplete itself in pipx's source code, not in the shell autocompletions.

The various shell completions could be committed to files in pipx's source tree and included in the package, then homebrew could use them as hub does. The only requirement is that argcomplete is bundled in the homebrew distribution, which it sounds like it is/can be.

I don't think the shell files would ever change unless argparse changed how it sets itself up (which is rare/unlikely); all the variability is contained within the pipx Python code itself.

Here are the completions for the various shells. The only one that requires a globally installed tool, and thus can't be used by homebrew, is tcsh which calls python-argcomplete-tcsh.

bash and zsh

>> register-python-argcomplete pipx

# Run something, muting output or redirecting it to the debug stream
# depending on the value of _ARC_DEBUG.
__python_argcomplete_run() {
    if [[ -z "$_ARC_DEBUG" ]]; then
        "$@" 8>&1 9>&2 1>/dev/null 2>&1
    else
        "$@" 8>&1 9>&2 1>&9 2>&1
    fi
}

_python_argcomplete() {
    local IFS=$'\013'
    local SUPPRESS_SPACE=0
    if compopt +o nospace 2> /dev/null; then
        SUPPRESS_SPACE=1
    fi
    COMPREPLY=( $(IFS="$IFS" \
                  COMP_LINE="$COMP_LINE" \
                  COMP_POINT="$COMP_POINT" \
                  COMP_TYPE="$COMP_TYPE" \
                  _ARGCOMPLETE_COMP_WORDBREAKS="$COMP_WORDBREAKS" \
                  _ARGCOMPLETE=1 \
                  _ARGCOMPLETE_SUPPRESS_SPACE=$SUPPRESS_SPACE \
                  __python_argcomplete_run "$1") )
    if [[ $? != 0 ]]; then
        unset COMPREPLY
    elif [[ $SUPPRESS_SPACE == 1 ]] && [[ "$COMPREPLY" =~ [=/:]$ ]]; then
        compopt -o nospace
    fi
}
complete -o nospace -o default -o bashdefault -F _python_argcomplete pipx

fish

>> register-python-argcomplete --shell fish pipx

function __fish_pipx_complete
    set -x _ARGCOMPLETE 1
    set -x _ARGCOMPLETE_IFS \n
    set -x _ARGCOMPLETE_SUPPRESS_SPACE 1
    set -x _ARGCOMPLETE_SHELL fish
    set -x COMP_LINE (commandline -p)
    set -x COMP_POINT (string length (commandline -cp))
    set -x COMP_TYPE
    if set -q _ARC_DEBUG
        pipx 8>&1 9>&2 1>/dev/null 2>&1
    else
        pipx 8>&1 9>&2 1>&9 2>&1
    end
end
complete -c pipx -f -a '(__fish_pipx_complete)'

tcsh

>> register-python-argcomplete --shell tcsh pipx
complete "pipx" 'p@*@`python-argcomplete-tcsh "pipx"`@' ;

This was temporarily fixed via https://github.com/Homebrew/homebrew-core/pull/48756.
Will add more permanent fix using the completion scripts above.

Did you run pipx ensurepath ?

Was this page helpful?
0 / 5 - 0 ratings