Skip to content

Commit

Permalink
Use correct executable name for completion command (#4755)
Browse files Browse the repository at this point in the history
  • Loading branch information
di authored and pradyunsg committed Oct 12, 2017
1 parent 2243562 commit ff5b201
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 10 deletions.
2 changes: 2 additions & 0 deletions news/3997.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Shell completion scripts now use correct executable names (e.g., ``pip3``
instead of ``pip``)
17 changes: 11 additions & 6 deletions src/pip/_internal/commands/completion.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import textwrap

from pip._internal.basecommand import Command
from pip._internal.utils.misc import get_prog

BASE_COMPLETION = """
# pip %(shell)s completion start%(script)s# pip %(shell)s completion end
Expand All @@ -17,7 +18,7 @@
COMP_CWORD=$COMP_CWORD \\
PIP_AUTO_COMPLETE=1 $1 ) )
}
complete -o default -F _pip_completion pip
complete -o default -F _pip_completion %(prog)s
""",
'zsh': """
function _pip_completion {
Expand All @@ -28,17 +29,19 @@
COMP_CWORD=$(( cword-1 )) \\
PIP_AUTO_COMPLETE=1 $words[1] ) )
}
compctl -K _pip_completion pip
compctl -K _pip_completion %(prog)s
""",
'fish': """
function __fish_complete_pip
set -lx COMP_WORDS (commandline -o) ""
set -lx COMP_CWORD {cword}
set -lx COMP_CWORD ( \\
math (contains -i -- (commandline -t) $COMP_WORDS)-1 \\
)
set -lx PIP_AUTO_COMPLETE 1
string split \\ -- (eval $COMP_WORDS[1])
end
complete -fa "(__fish_complete_pip)" -c pip
""".format(cword="(math (contains -i -- (commandline -t) $COMP_WORDS)-1)")
complete -fa "(__fish_complete_pip)" -c %(prog)s
""",
}


Expand Down Expand Up @@ -80,7 +83,9 @@ def run(self, options, args):
shell_options = ['--' + shell for shell in sorted(shells)]
if options.shell in shells:
script = textwrap.dedent(
COMPLETION_SCRIPTS.get(options.shell, '')
COMPLETION_SCRIPTS.get(options.shell, '') % {
'prog': get_prog(),
}
)
print(BASE_COMPLETION % {'script': script, 'shell': options.shell})
else:
Expand Down
5 changes: 4 additions & 1 deletion src/pip/_internal/utils/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,11 @@ def ensure_dir(path):

def get_prog():
try:
if os.path.basename(sys.argv[0]) in ('__main__.py', '-c'):
prog = os.path.basename(sys.argv[0])
if prog in ('__main__.py', '-c'):
return "%s -m pip" % sys.executable
else:
return prog
except (AttributeError, TypeError, IndexError):
pass
return 'pip'
Expand Down
17 changes: 16 additions & 1 deletion tests/functional/test_completion.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import os
import sys

import pytest


def test_completion_for_bash(script):
Expand Down Expand Up @@ -44,7 +47,9 @@ def test_completion_for_fish(script):
fish_completion = """\
function __fish_complete_pip
set -lx COMP_WORDS (commandline -o) ""
set -lx COMP_CWORD (math (contains -i -- (commandline -t) $COMP_WORDS)-1)
set -lx COMP_CWORD ( \\
math (contains -i -- (commandline -t) $COMP_WORDS)-1 \\
)
set -lx PIP_AUTO_COMPLETE 1
string split \\ -- (eval $COMP_WORDS[1])
end
Expand Down Expand Up @@ -114,3 +119,13 @@ def test_completion_option_for_command(script):
res, env = setup_completion(script, 'pip search --', '2')
assert '--help' in res.stdout,\
"autocomplete function could not complete ``--``"


@pytest.mark.parametrize('flag', ['--bash', '--zsh', '--fish'])
def test_completion_uses_same_executable_name(script, flag):
expect_stderr = sys.version_info[:2] == (3, 3)
executable_name = 'pip{}'.format(sys.version_info[0])
result = script.run(
executable_name, 'completion', flag, expect_stderr=expect_stderr
)
assert executable_name in result.stdout
24 changes: 22 additions & 2 deletions tests/unit/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
from pip._internal.utils.glibc import check_glibc_version
from pip._internal.utils.hashes import Hashes, MissingHashes
from pip._internal.utils.misc import (
egg_link_path, ensure_dir, get_installed_distributions, normalize_path,
rmtree, untar_file, unzip_file
egg_link_path, ensure_dir, get_installed_distributions, get_prog,
normalize_path, rmtree, untar_file, unzip_file
)
from pip._internal.utils.packaging import check_dist_requires_python
from pip._internal.utils.temp_dir import TempDirectory
Expand Down Expand Up @@ -592,3 +592,23 @@ def test_check_requires(self, metadata, should_raise):
check_dist_requires_python(fake_dist)
else:
check_dist_requires_python(fake_dist)


class TestGetProg(object):

@pytest.mark.parametrize(
("argv", "executable", "expected"),
[
('/usr/bin/pip', '', 'pip'),
('-c', '/usr/bin/python', '/usr/bin/python -m pip'),
('__main__.py', '/usr/bin/python', '/usr/bin/python -m pip'),
('/usr/bin/pip3', '', 'pip3'),
]
)
def test_get_prog(self, monkeypatch, argv, executable, expected):
monkeypatch.setattr('pip._internal.utils.misc.sys.argv', [argv])
monkeypatch.setattr(
'pip._internal.utils.misc.sys.executable',
executable
)
assert get_prog() == expected

0 comments on commit ff5b201

Please sign in to comment.