Skip to content

Commit

Permalink
Respect PATHEXT when looking for Win executable
Browse files Browse the repository at this point in the history
... as idiomatic in Windows programming.
  • Loading branch information
uranusjr committed Jun 3, 2018
1 parent f91f53b commit cdb6b17
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 15 deletions.
6 changes: 3 additions & 3 deletions pipenv/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,10 @@ def which(command, location=None, allow_global=False):
if not allow_global:
if os.name == 'nt':
p = find_windows_executable(
os.path.join(location, 'Scripts'), command
os.path.join(location, 'Scripts'), command,
)
else:
p = os.sep.join([location] + ['bin/{0}'.format(command)])
p = os.path.join(location, 'bin', command)
else:
if command == 'python':
p = sys.executable
Expand Down Expand Up @@ -1508,7 +1508,7 @@ def pip_install(


def pip_download(package_name):
cache_dir = Path(PIPENV_CACHE_DIR)
cache_dir = Path(PIPENV_CACHE_DIR)
pip_config = {
'PIP_CACHE_DIR': fs_str(cache_dir.as_posix()),
'PIP_WHEEL_DIR': fs_str(cache_dir.joinpath('wheels').as_posix()),
Expand Down
22 changes: 10 additions & 12 deletions pipenv/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -835,20 +835,18 @@ def get_windows_path(*args):
def find_windows_executable(bin_path, exe_name):
"""Given an executable name, search the given location for an executable"""
requested_path = get_windows_path(bin_path, exe_name)
if os.path.exists(requested_path):
if os.path.isfile(requested_path):
return requested_path

# Ensure we aren't adding two layers of file extensions
exe_name = os.path.splitext(exe_name)[0]
files = [
'{0}.{1}'.format(exe_name, ext) for ext in ['', 'py', 'exe', 'bat']
]
exec_paths = [get_windows_path(bin_path, f) for f in files]
exec_files = [
filename for filename in exec_paths if os.path.isfile(filename)
]
if exec_files:
return exec_files[0]
try:
pathext = os.environ['PATHEXT']
except KeyError:
pass
else:
for ext in pathext.split(os.pathsep):
path = get_windows_path(bin_path, exe_name + ext.strip().lower())
if os.path.isfile(path):
return path

return find_executable(exe_name)

Expand Down
30 changes: 30 additions & 0 deletions tests/unit/test_utils_windows_executable.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import os

import mock
import pytest

from pipenv import utils


# This module is run only on Windows.
pytestmark = pytest.mark.skipif(
os.name != 'nt',
reason="only relevant on windows",
)


@mock.patch('os.path.isfile')
@mock.patch('pipenv.utils.find_executable')
def test_find_windows_executable(mocked_find_executable, mocked_isfile):
mocked_isfile.return_value = False
mocked_find_executable.return_value = None
found = utils.find_windows_executable('fake/path', 'python')
assert found is None

assert mocked_isfile.call_count > 1

calls = [mock.call('fake/path/python')] + [
mock.call('fake/path/python{0}'.format(ext.lower()))
for ext in os.environ['PATHEXT'].split(';')
]
assert mocked_isfile.mock_calls == calls

0 comments on commit cdb6b17

Please sign in to comment.