diff --git a/salt/modules/pip.py b/salt/modules/pip.py index ffdb73aefa36..0a0773a8f4d4 100644 --- a/salt/modules/pip.py +++ b/salt/modules/pip.py @@ -88,6 +88,7 @@ import sys import tempfile + # Import Salt libs import salt.utils.data import salt.utils.files @@ -99,6 +100,7 @@ import salt.utils.versions from salt.ext import six from salt.exceptions import CommandExecutionError, CommandNotFoundError +import salt.utils.platform # This needs to be named logger so we don't shadow it in pip.install logger = logging.getLogger(__name__) # pylint: disable=C0103 @@ -122,6 +124,19 @@ def __virtual__(): return 'pip' +def _pip_bin_env(cwd, bin_env): + """ + Binary builds need to have the 'cwd' set when using pip on Windows. This will + set cwd if pip is being used in 'bin_env', 'cwd' is None and salt is on windows. + """ + + if salt.utils.platform.is_windows(): + if bin_env is not None and cwd is None and 'pip' in os.path.basename(bin_env): + cwd = os.path.dirname(bin_env) + + return cwd + + def _clear_context(bin_env=None): ''' Remove the cached pip version @@ -652,6 +667,8 @@ def install(pkgs=None, # pylint: disable=R0912,R0913,R0914 editable=git+https://github.com/worldcompany/djangoembed.git#egg=djangoembed upgrade=True no_deps=True ''' + + cwd = _pip_bin_env(cwd, bin_env) cmd = _get_pip_bin(bin_env) cmd.append('install') @@ -666,7 +683,7 @@ def install(pkgs=None, # pylint: disable=R0912,R0913,R0914 if error: return error - cur_version = version(bin_env) + cur_version = version(bin_env, cwd) if use_wheel: min_version = '1.4' @@ -1037,6 +1054,8 @@ def uninstall(pkgs=None, salt '*' pip.uninstall bin_env=/path/to/virtualenv salt '*' pip.uninstall bin_env=/path/to/pip_bin ''' + + cwd = _pip_bin_env(cwd, bin_env) cmd = _get_pip_bin(bin_env) cmd.extend(['uninstall', '-y']) @@ -1148,12 +1167,14 @@ def freeze(bin_env=None, salt '*' pip.freeze bin_env=/home/code/path/to/virtualenv ''' + + cwd = _pip_bin_env(cwd, bin_env) cmd = _get_pip_bin(bin_env) cmd.append('freeze') # Include pip, setuptools, distribute, wheel min_version = '8.0.3' - cur_version = version(bin_env) + cur_version = version(bin_env, cwd) if salt.utils.versions.compare(ver1=cur_version, oper='<', ver2=min_version): logger.warning( 'The version of pip installed is %s, which is older than %s. ' @@ -1202,10 +1223,12 @@ def list_(prefix=None, salt '*' pip.list salt ''' + + cwd = _pip_bin_env(cwd, bin_env) packages = {} if prefix is None or 'pip'.startswith(prefix): - packages['pip'] = version(bin_env) + packages['pip'] = version(bin_env, cwd) for line in freeze(bin_env=bin_env, user=user, @@ -1249,7 +1272,7 @@ def list_(prefix=None, return packages -def version(bin_env=None): +def version(bin_env=None, cwd=None): ''' .. versionadded:: 0.17.0 @@ -1264,6 +1287,8 @@ def version(bin_env=None): salt '*' pip.version ''' + + cwd = _pip_bin_env(cwd, bin_env) contextkey = 'pip.version' if bin_env is not None: contextkey = '{0}.{1}'.format(contextkey, bin_env) @@ -1274,7 +1299,7 @@ def version(bin_env=None): cmd = _get_pip_bin(bin_env)[:] cmd.append('--version') - ret = __salt__['cmd.run_all'](cmd, python_shell=False) + ret = __salt__['cmd.run_all'](cmd, cwd=cwd, python_shell=False) if ret['retcode']: raise CommandNotFoundError('Could not find a `pip` binary') @@ -1299,10 +1324,12 @@ def list_upgrades(bin_env=None, salt '*' pip.list_upgrades ''' + + cwd = _pip_bin_env(cwd, bin_env) cmd = _get_pip_bin(bin_env) cmd.extend(['list', '--outdated']) - pip_version = version(bin_env) + pip_version = version(bin_env, cwd) # Pip started supporting the ability to output json starting with 9.0.0 min_version = '9.0' if salt.utils.versions.compare(ver1=pip_version, @@ -1388,6 +1415,8 @@ def is_installed(pkgname=None, salt '*' pip.is_installed salt ''' + + cwd = _pip_bin_env(cwd, bin_env) for line in freeze(bin_env=bin_env, user=user, cwd=cwd): if line.startswith('-f') or line.startswith('#'): # ignore -f line as it contains --find-links directory @@ -1431,6 +1460,8 @@ def upgrade_available(pkg, salt '*' pip.upgrade_available ''' + + cwd = _pip_bin_env(cwd, bin_env) return pkg in list_upgrades(bin_env=bin_env, user=user, cwd=cwd) @@ -1459,6 +1490,8 @@ def upgrade(bin_env=None, salt '*' pip.upgrade ''' + + cwd = _pip_bin_env(cwd, bin_env) ret = {'changes': {}, 'result': True, 'comment': '', @@ -1544,6 +1577,7 @@ def list_all_versions(pkg, salt '*' pip.list_all_versions ''' + cwd = _pip_bin_env(cwd, bin_env) cmd = _get_pip_bin(bin_env) cmd.extend(['install', '{0}==versions'.format(pkg)]) diff --git a/tests/unit/modules/test_pip.py b/tests/unit/modules/test_pip.py index b2677295d119..d04885ae51e8 100644 --- a/tests/unit/modules/test_pip.py +++ b/tests/unit/modules/test_pip.py @@ -14,12 +14,29 @@ import salt.utils.platform import salt.modules.pip as pip from salt.exceptions import CommandExecutionError +import salt.utils.platform class PipTestCase(TestCase, LoaderModuleMockMixin): def setup_loader_modules(self): return {pip: {'__salt__': {'cmd.which_bin': lambda _: 'pip'}}} + def test__pip_bin_env(self): + ret = pip._pip_bin_env(None, 'C:/Users/ch44d/Documents/salt/tests/pip.exe') + if salt.utils.platform.is_windows(): + self.assertEqual(ret, 'C:/Users/ch44d/Documents/salt/tests') + else: + self.assertEqual(ret, None) + + def test__pip_bin_env_no_change(self): + cwd = 'C:/Users/ch44d/Desktop' + ret = pip._pip_bin_env(cwd, 'C:/Users/ch44d/Documents/salt/tests/pip.exe') + self.assertEqual(ret, cwd) + + def test__pip_bin_env_no_bin_env(self): + ret = pip._pip_bin_env(None, None) + self.assertEqual(None, None) + def test_fix4361(self): mock = MagicMock(return_value={'retcode': 0, 'stdout': ''}) with patch.dict(pip.__salt__, {'cmd.run_all': mock}):