salt/tests/unit/modules/test_pip.py
rallytime 786076ac03
Merge branch '2017.7' into '2018.3'
Conflicts:
  - pkg/windows/modules/get-settings.psm1
  - salt/modules/cmdmod.py
  - salt/modules/pip.py
  - salt/modules/win_lgpo.py
  - salt/states/pip_state.py
  - tests/integration/states/test_pip.py
  - tests/support/helpers.py
  - tests/unit/modules/test_pip.py
  - tests/whitelist.txt
2018-05-07 13:17:01 -04:00

1317 lines
50 KiB
Python

# -*- coding: utf-8 -*-
# Import python libs
from __future__ import absolute_import
import os
import sys
# Import Salt Testing libs
from tests.support.mixins import LoaderModuleMockMixin
from tests.support.unit import skipIf, TestCase
from tests.support.mock import NO_MOCK, NO_MOCK_REASON, MagicMock, patch
# Import salt libs
import salt.utils.platform
import salt.modules.pip as pip
from salt.exceptions import CommandExecutionError
@skipIf(NO_MOCK, NO_MOCK_REASON)
class PipTestCase(TestCase, LoaderModuleMockMixin):
def setup_loader_modules(self):
return {pip: {'__salt__': {'cmd.which_bin': lambda _: 'pip'}}}
def test_fix4361(self):
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(requirements='requirements.txt')
expected_cmd = [sys.executable, '-m', 'pip', 'install', '--requirement', 'requirements.txt']
mock.assert_called_with(
expected_cmd,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
def test_install_editable_without_egg_fails(self):
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
self.assertRaises(
CommandExecutionError,
pip.install,
editable='git+https://github.com/saltstack/salt-testing.git'
)
def test_install_multiple_editable(self):
editables = [
'git+https://github.com/jek/blinker.git#egg=Blinker',
'git+https://github.com/saltstack/salt-testing.git#egg=SaltTesting'
]
expected = [sys.executable, '-m', 'pip', 'install']
for item in editables:
expected.extend(['--editable', item])
# Passing editables as a list
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(editable=editables)
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
# Passing editables as a comma separated list
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(editable=','.join(editables))
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
def test_install_multiple_pkgs_and_editables(self):
pkgs = ['pep8', 'salt']
editables = [
'git+https://github.com/jek/blinker.git#egg=Blinker',
'git+https://github.com/saltstack/salt-testing.git#egg=SaltTesting'
]
expected = [sys.executable, '-m', 'pip', 'install']
expected.extend(pkgs)
for item in editables:
expected.extend(['--editable', item])
# Passing editables as a list
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkgs=pkgs, editable=editables)
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
# Passing editables as a comma separated list
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkgs=','.join(pkgs), editable=','.join(editables))
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
# As single string (just use the first element from pkgs and editables)
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkgs=pkgs[0], editable=editables[0])
expected = [sys.executable, '-m', 'pip', 'install', pkgs[0], '--editable', editables[0]]
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
def test_issue5940_install_multiple_pip_mirrors(self):
'''
test multiple pip mirrors. This test only works with pip < 7.0.0
'''
with patch.object(pip, 'version', MagicMock(return_value='1.4')):
mirrors = [
'http://g.pypi.python.org',
'http://c.pypi.python.org',
'http://pypi.crate.io'
]
expected = [sys.executable, '-m', 'pip', 'install', '--use-mirrors']
for item in mirrors:
expected.extend(['--mirrors', item])
expected.append('pep8')
# Passing mirrors as a list
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkgs=['pep8'], mirrors=mirrors)
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
# Passing mirrors as a comma separated list
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkgs=['pep8'], mirrors=','.join(mirrors))
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
expected = [sys.executable, '-m', 'pip', 'install', '--use-mirrors', '--mirrors', mirrors[0], 'pep8']
# As single string (just use the first element from mirrors)
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkgs=['pep8'], mirrors=mirrors[0])
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
def test_install_with_multiple_find_links(self):
find_links = [
'http://g.pypi.python.org',
'http://c.pypi.python.org',
'http://pypi.crate.io'
]
pkg = 'pep8'
expected = [sys.executable, '-m', 'pip', 'install']
for item in find_links:
expected.extend(['--find-links', item])
expected.append(pkg)
# Passing mirrors as a list
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, find_links=find_links)
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
# Passing mirrors as a comma separated list
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, find_links=','.join(find_links))
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
# Valid protos work?
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, find_links=find_links)
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
expected = [sys.executable, '-m', 'pip', 'install', '--find-links', find_links[0], pkg]
# As single string (just use the first element from find_links)
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, find_links=find_links[0])
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
# Invalid proto raises exception
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
self.assertRaises(
CommandExecutionError,
pip.install,
'\'' + pkg + '\'',
find_links='sftp://pypi.crate.io'
)
def test_install_no_index_with_index_url_or_extra_index_url_raises(self):
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
self.assertRaises(
CommandExecutionError,
pip.install, no_index=True, index_url='http://foo.tld'
)
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
self.assertRaises(
CommandExecutionError,
pip.install, no_index=True, extra_index_url='http://foo.tld'
)
def test_install_failed_cached_requirements(self):
with patch('salt.modules.pip._get_cached_requirements') as get_cached_requirements:
get_cached_requirements.return_value = False
ret = pip.install(requirements='salt://my_test_reqs')
self.assertEqual(False, ret['result'])
self.assertIn('my_test_reqs', ret['comment'])
def test_install_cached_requirements_used(self):
with patch('salt.modules.pip._get_cached_requirements') as get_cached_requirements:
get_cached_requirements.return_value = 'my_cached_reqs'
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(requirements='salt://requirements.txt')
expected = [sys.executable, '-m', 'pip', 'install', '--requirement', 'my_cached_reqs']
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
def test_install_venv(self):
with patch('os.path') as mock_path:
def join(*args):
return os.path.normpath(os.sep.join(args))
mock_path.is_file.return_value = True
mock_path.isdir.return_value = True
mock_path.join = join
if salt.utils.is_windows():
venv_path = 'C:\\test_env'
bin_path = os.path.join(venv_path, 'python.exe')
else:
venv_path = '/test_env'
bin_path = os.path.join(venv_path, 'python')
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
pip_bin = MagicMock(return_value=[bin_path, '-m', 'pip'])
with patch.dict(pip.__salt__, {'cmd.run_all': mock}), \
patch.object(pip, '_get_pip_bin', pip_bin):
pip.install('mock', bin_env=venv_path)
mock.assert_called_with(
[bin_path, '-m', 'pip', 'install', 'mock'],
env={'VIRTUAL_ENV': venv_path},
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
def test_install_log_argument_in_resulting_command(self):
with patch('os.access') as mock_path:
pkg = 'pep8'
log_path = '/tmp/pip-install.log'
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, log=log_path)
expected = [sys.executable, '-m', 'pip', 'install', '--log', log_path, pkg]
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
def test_non_writeable_log(self):
with patch('os.path') as mock_path:
# Let's fake a non-writable log file
pkg = 'pep8'
log_path = '/tmp/pip-install.log'
mock_path.exists.side_effect = IOError('Fooo!')
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
self.assertRaises(
IOError,
pip.install,
pkg,
log=log_path
)
def test_install_timeout_argument_in_resulting_command(self):
# Passing an int
pkg = 'pep8'
expected = [sys.executable, '-m', 'pip', 'install', '--timeout']
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, timeout=10)
mock.assert_called_with(
expected + [10, pkg],
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
# Passing an int as a string
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, timeout='10')
mock.assert_called_with(
expected + ['10', pkg],
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
# Passing a non-int to timeout
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
self.assertRaises(
ValueError,
pip.install,
pkg,
timeout='a'
)
def test_install_index_url_argument_in_resulting_command(self):
pkg = 'pep8'
index_url = 'http://foo.tld'
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, index_url=index_url)
expected = [sys.executable, '-m', 'pip', 'install', '--index-url', index_url, pkg]
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
def test_install_extra_index_url_argument_in_resulting_command(self):
pkg = 'pep8'
extra_index_url = 'http://foo.tld'
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, extra_index_url=extra_index_url)
expected = [sys.executable, '-m', 'pip', 'install', '--extra-index-url', extra_index_url, pkg]
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
def test_install_no_index_argument_in_resulting_command(self):
pkg = 'pep8'
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, no_index=True)
expected = [sys.executable, '-m', 'pip', 'install', '--no-index', pkg]
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
def test_install_build_argument_in_resulting_command(self):
pkg = 'pep8'
build = '/tmp/foo'
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, build=build)
expected = [sys.executable, '-m', 'pip', 'install', '--build', build, pkg]
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
def test_install_target_argument_in_resulting_command(self):
pkg = 'pep8'
target = '/tmp/foo'
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, target=target)
expected = [sys.executable, '-m', 'pip', 'install', '--target', target, pkg]
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
def test_install_download_argument_in_resulting_command(self):
pkg = 'pep8'
download = '/tmp/foo'
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, download=download)
expected = [sys.executable, '-m', 'pip', 'install', '--download', download, pkg]
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
def test_install_no_download_argument_in_resulting_command(self):
pkg = 'pep8'
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, no_download=True)
expected = [sys.executable, '-m', 'pip', 'install', '--no-download', pkg]
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
def test_install_download_cache_dir_arguments_in_resulting_command(self):
pkg = 'pep8'
cache_dir_arg_mapping = {
'1.5.6': '--download-cache',
'6.0': '--cache-dir',
}
download_cache = '/tmp/foo'
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
for pip_version, cmd_arg in cache_dir_arg_mapping.items():
with patch('salt.modules.pip.version',
MagicMock(return_value=pip_version)):
# test `download_cache` kwarg
pip.install(pkg, download_cache='/tmp/foo')
expected = [sys.executable, '-m', 'pip', 'install', cmd_arg, download_cache, pkg]
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
# test `cache_dir` kwarg
pip.install(pkg, cache_dir='/tmp/foo')
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
def test_install_source_argument_in_resulting_command(self):
pkg = 'pep8'
source = '/tmp/foo'
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, source=source)
expected = [sys.executable, '-m', 'pip', 'install', '--source', source, pkg]
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
def test_install_exists_action_argument_in_resulting_command(self):
pkg = 'pep8'
for action in ('s', 'i', 'w', 'b'):
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, exists_action=action)
expected = [sys.executable, '-m', 'pip', 'install', '--exists-action', action, pkg]
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
# Test for invalid action
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
self.assertRaises(
CommandExecutionError,
pip.install,
pkg,
exists_action='d'
)
def test_install_install_options_argument_in_resulting_command(self):
install_options = [
'--exec-prefix=/foo/bar',
'--install-scripts=/foo/bar/bin'
]
pkg = 'pep8'
expected = [sys.executable, '-m', 'pip', 'install']
for item in install_options:
expected.extend(['--install-option', item])
expected.append(pkg)
# Passing options as a list
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, install_options=install_options)
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
# Passing mirrors as a comma separated list
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, install_options=','.join(install_options))
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
# Passing mirrors as a single string entry
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, install_options=install_options[0])
expected = [sys.executable, '-m', 'pip', 'install', '--install-option', install_options[0], pkg]
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
def test_install_global_options_argument_in_resulting_command(self):
global_options = [
'--quiet',
'--no-user-cfg'
]
pkg = 'pep8'
expected = [sys.executable, '-m', 'pip', 'install']
for item in global_options:
expected.extend(['--global-option', item])
expected.append(pkg)
# Passing options as a list
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, global_options=global_options)
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
# Passing mirrors as a comma separated list
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, global_options=','.join(global_options))
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
# Passing mirrors as a single string entry
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, global_options=global_options[0])
expected = [sys.executable, '-m', 'pip', 'install', '--global-option', global_options[0], pkg]
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
def test_install_upgrade_argument_in_resulting_command(self):
pkg = 'pep8'
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, upgrade=True)
expected = [sys.executable, '-m', 'pip', 'install', '--upgrade', pkg]
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
def test_install_force_reinstall_argument_in_resulting_command(self):
pkg = 'pep8'
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, force_reinstall=True)
expected = [sys.executable, '-m', 'pip', 'install', '--force-reinstall', pkg]
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
def test_install_ignore_installed_argument_in_resulting_command(self):
pkg = 'pep8'
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, ignore_installed=True)
expected = [sys.executable, '-m', 'pip', 'install', '--ignore-installed', pkg]
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
def test_install_no_deps_argument_in_resulting_command(self):
pkg = 'pep8'
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, no_deps=True)
expected = [sys.executable, '-m', 'pip', 'install', '--no-deps', pkg]
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
def test_install_no_install_argument_in_resulting_command(self):
pkg = 'pep8'
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, no_install=True)
expected = [sys.executable, '-m', 'pip', 'install', '--no-install', pkg]
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
def test_install_proxy_argument_in_resulting_command(self):
pkg = 'pep8'
proxy = 'salt-user:salt-passwd@salt-proxy:3128'
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(pkg, proxy=proxy)
expected = [sys.executable, '-m', 'pip', 'install', '--proxy', proxy, pkg]
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
def test_install_multiple_requirements_arguments_in_resulting_command(self):
with patch('salt.modules.pip._get_cached_requirements') as get_cached_requirements:
cached_reqs = [
'my_cached_reqs-1', 'my_cached_reqs-2'
]
get_cached_requirements.side_effect = cached_reqs
requirements = [
'salt://requirements-1.txt', 'salt://requirements-2.txt'
]
expected = [sys.executable, '-m', 'pip', 'install']
for item in cached_reqs:
expected.extend(['--requirement', item])
# Passing option as a list
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(requirements=requirements)
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
# Passing option as a comma separated list
get_cached_requirements.side_effect = cached_reqs
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(requirements=','.join(requirements))
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
# Passing option as a single string entry
get_cached_requirements.side_effect = [cached_reqs[0]]
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.install(requirements=requirements[0])
expected = [sys.executable, '-m', 'pip', 'install', '--requirement', cached_reqs[0]]
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
def test_uninstall_multiple_requirements_arguments_in_resulting_command(self):
with patch('salt.modules.pip._get_cached_requirements') as get_cached_requirements:
cached_reqs = [
'my_cached_reqs-1', 'my_cached_reqs-2'
]
get_cached_requirements.side_effect = cached_reqs
requirements = [
'salt://requirements-1.txt', 'salt://requirements-2.txt'
]
expected = [sys.executable, '-m', 'pip', 'uninstall', '-y']
for item in cached_reqs:
expected.extend(['--requirement', item])
# Passing option as a list
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.uninstall(requirements=requirements)
mock.assert_called_with(
expected,
cwd=None,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
# Passing option as a comma separated list
get_cached_requirements.side_effect = cached_reqs
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.uninstall(requirements=','.join(requirements))
mock.assert_called_with(
expected,
cwd=None,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
# Passing option as a single string entry
get_cached_requirements.side_effect = [cached_reqs[0]]
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.uninstall(requirements=requirements[0])
expected = [sys.executable, '-m', 'pip', 'uninstall', '-y', '--requirement', cached_reqs[0]]
mock.assert_called_with(
expected,
cwd=None,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
def test_uninstall_proxy_argument_in_resulting_command(self):
pkg = 'pep8'
proxy = 'salt-user:salt-passwd@salt-proxy:3128'
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.uninstall(pkg, proxy=proxy)
expected = [sys.executable, '-m', 'pip', 'uninstall', '-y', '--proxy', proxy, pkg]
mock.assert_called_with(
expected,
saltenv='base',
cwd=None,
runas=None,
use_vt=False,
python_shell=False,
)
def test_uninstall_log_argument_in_resulting_command(self):
pkg = 'pep8'
log_path = '/tmp/pip-install.log'
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.uninstall(pkg, log=log_path)
expected = [sys.executable, '-m', 'pip', 'uninstall', '-y', '--log', log_path, pkg]
mock.assert_called_with(
expected,
saltenv='base',
cwd=None,
runas=None,
use_vt=False,
python_shell=False,
)
# Let's fake a non-writable log file
with patch('os.path') as mock_path:
mock_path.exists.side_effect = IOError('Fooo!')
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
self.assertRaises(
IOError,
pip.uninstall,
pkg,
log=log_path
)
def test_uninstall_timeout_argument_in_resulting_command(self):
pkg = 'pep8'
expected = [sys.executable, '-m', 'pip', 'uninstall', '-y', '--timeout']
# Passing an int
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.uninstall(pkg, timeout=10)
mock.assert_called_with(
expected + [10, pkg],
cwd=None,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
# Passing an int as a string
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
pip.uninstall(pkg, timeout='10')
mock.assert_called_with(
expected + ['10', pkg],
cwd=None,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
# Passing a non-int to timeout
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
self.assertRaises(
ValueError,
pip.uninstall,
pkg,
timeout='a'
)
def test_freeze_command(self):
expected = [sys.executable, '-m', 'pip', 'freeze']
eggs = [
'M2Crypto==0.21.1',
'-e git+git@github.com:s0undt3ch/salt-testing.git@9ed81aa2f918d59d3706e56b18f0782d1ea43bf8#egg=SaltTesting-dev',
'bbfreeze==1.1.0',
'bbfreeze-loader==1.1.0',
'pycrypto==2.6'
]
mock = MagicMock(
return_value={
'retcode': 0,
'stdout': '\n'.join(eggs)
}
)
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
with patch('salt.modules.pip.version',
MagicMock(return_value='6.1.1')):
ret = pip.freeze()
mock.assert_called_with(
expected,
cwd=None,
runas=None,
use_vt=False,
python_shell=False,
)
self.assertEqual(ret, eggs)
mock = MagicMock(
return_value={
'retcode': 0,
'stdout': '\n'.join(eggs)
}
)
# Passing env_vars passes them to underlying command?
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
with patch('salt.modules.pip.version',
MagicMock(return_value='6.1.1')):
ret = pip.freeze(env_vars={"foo": "bar"})
mock.assert_called_with(
expected,
cwd=None,
runas=None,
use_vt=False,
python_shell=False,
env={"foo": "bar"}
)
self.assertEqual(ret, eggs)
# Non zero returncode raises exception?
mock = MagicMock(return_value={'retcode': 1, 'stderr': 'CABOOOOMMM!'})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
with patch('salt.modules.pip.version',
MagicMock(return_value='6.1.1')):
self.assertRaises(
CommandExecutionError,
pip.freeze,
)
def test_freeze_command_with_all(self):
eggs = [
'M2Crypto==0.21.1',
'-e git+git@github.com:s0undt3ch/salt-testing.git@9ed81aa2f918d59d3706e56b18f0782d1ea43bf8#egg=SaltTesting-dev',
'bbfreeze==1.1.0',
'bbfreeze-loader==1.1.0',
'pip==0.9.1',
'pycrypto==2.6',
'setuptools==20.10.1'
]
mock = MagicMock(
return_value={
'retcode': 0,
'stdout': '\n'.join(eggs)
}
)
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
with patch('salt.modules.pip.version',
MagicMock(return_value='9.0.1')):
ret = pip.freeze()
expected = [sys.executable, '-m', 'pip', 'freeze', '--all']
mock.assert_called_with(
expected,
cwd=None,
runas=None,
use_vt=False,
python_shell=False,
)
self.assertEqual(ret, eggs)
# Non zero returncode raises exception?
mock = MagicMock(return_value={'retcode': 1, 'stderr': 'CABOOOOMMM!'})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
with patch('salt.modules.pip.version',
MagicMock(return_value='9.0.1')):
self.assertRaises(
CommandExecutionError,
pip.freeze,
)
def test_list_command(self):
eggs = [
'M2Crypto==0.21.1',
'-e git+git@github.com:s0undt3ch/salt-testing.git@9ed81aa2f918d59d3706e56b18f0782d1ea43bf8#egg=SaltTesting-dev',
'bbfreeze==1.1.0',
'bbfreeze-loader==1.1.0',
'pycrypto==2.6'
]
mock_version = '6.1.1'
mock = MagicMock(return_value={'retcode': 0, 'stdout': '\n'.join(eggs)})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
with patch('salt.modules.pip.version',
MagicMock(return_value=mock_version)):
ret = pip.list_()
expected = [sys.executable, '-m', 'pip', 'freeze']
mock.assert_called_with(
expected,
cwd=None,
runas=None,
python_shell=False,
use_vt=False,
)
self.assertEqual(
ret, {
'SaltTesting-dev': 'git+git@github.com:s0undt3ch/salt-testing.git@9ed81aa2f918d59d3706e56b18f0782d1ea43bf8',
'M2Crypto': '0.21.1',
'bbfreeze-loader': '1.1.0',
'bbfreeze': '1.1.0',
'pip': mock_version,
'pycrypto': '2.6'
}
)
# Non zero returncode raises exception?
mock = MagicMock(return_value={'retcode': 1, 'stderr': 'CABOOOOMMM!'})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
with patch('salt.modules.pip.version',
MagicMock(return_value='6.1.1')):
self.assertRaises(
CommandExecutionError,
pip.list_,
)
def test_list_command_with_all(self):
eggs = [
'M2Crypto==0.21.1',
'-e git+git@github.com:s0undt3ch/salt-testing.git@9ed81aa2f918d59d3706e56b18f0782d1ea43bf8#egg=SaltTesting-dev',
'bbfreeze==1.1.0',
'bbfreeze-loader==1.1.0',
'pip==9.0.1',
'pycrypto==2.6',
'setuptools==20.10.1'
]
# N.B.: this is deliberately different from the "output" of pip freeze.
# This is to demonstrate that the version reported comes from freeze
# instead of from the pip.version function.
mock_version = '9.0.0'
mock = MagicMock(return_value={'retcode': 0, 'stdout': '\n'.join(eggs)})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
with patch('salt.modules.pip.version',
MagicMock(return_value=mock_version)):
ret = pip.list_()
expected = [sys.executable, '-m', 'pip', 'freeze', '--all']
mock.assert_called_with(
expected,
cwd=None,
runas=None,
python_shell=False,
use_vt=False,
)
self.assertEqual(
ret, {
'SaltTesting-dev': 'git+git@github.com:s0undt3ch/salt-testing.git@9ed81aa2f918d59d3706e56b18f0782d1ea43bf8',
'M2Crypto': '0.21.1',
'bbfreeze-loader': '1.1.0',
'bbfreeze': '1.1.0',
'pip': '9.0.1',
'pycrypto': '2.6',
'setuptools': '20.10.1'
}
)
# Non zero returncode raises exception?
mock = MagicMock(return_value={'retcode': 1, 'stderr': 'CABOOOOMMM!'})
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
with patch('salt.modules.pip.version',
MagicMock(return_value='6.1.1')):
self.assertRaises(
CommandExecutionError,
pip.list_,
)
def test_list_command_with_prefix(self):
eggs = [
'M2Crypto==0.21.1',
'-e git+git@github.com:s0undt3ch/salt-testing.git@9ed81aa2f918d59d3706e56b18f0782d1ea43bf8#egg=SaltTesting-dev',
'bbfreeze==1.1.0',
'bbfreeze-loader==1.1.0',
'pycrypto==2.6'
]
mock = MagicMock(
return_value={
'retcode': 0,
'stdout': '\n'.join(eggs)
}
)
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
with patch('salt.modules.pip.version',
MagicMock(return_value='6.1.1')):
ret = pip.list_(prefix='bb')
expected = [sys.executable, '-m', 'pip', 'freeze']
mock.assert_called_with(
expected,
cwd=None,
runas=None,
python_shell=False,
use_vt=False,
)
self.assertEqual(
ret, {
'bbfreeze-loader': '1.1.0',
'bbfreeze': '1.1.0',
}
)
def test_list_upgrades_legacy(self):
eggs = [
'apache-libcloud (1.1.0) - Latest: 2.2.1 [wheel]',
'appdirs (1.4.1) - Latest: 1.4.3 [wheel]',
'awscli (1.11.63) - Latest: 1.12.1 [sdist]'
]
mock = MagicMock(
return_value={
'retcode': 0,
'stdout': '\n'.join(eggs)
}
)
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
with patch('salt.modules.pip.version',
MagicMock(return_value='6.1.1')):
ret = pip.list_upgrades()
mock.assert_called_with(
['pip', 'list', '--outdated'],
cwd=None,
runas=None,
)
self.assertEqual(
ret, {
'apache-libcloud': '2.2.1 [wheel]',
'appdirs': '1.4.3 [wheel]',
'awscli': '1.12.1 [sdist]'
}
)
def test_list_upgrades_gt9(self):
eggs = '''[{"latest_filetype": "wheel", "version": "1.1.0", "name": "apache-libcloud", "latest_version": "2.2.1"},
{"latest_filetype": "wheel", "version": "1.4.1", "name": "appdirs", "latest_version": "1.4.3"},
{"latest_filetype": "sdist", "version": "1.11.63", "name": "awscli", "latest_version": "1.12.1"}
]'''
mock = MagicMock(
return_value={
'retcode': 0,
'stdout': '{0}'.format(eggs)
}
)
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
with patch('salt.modules.pip.version',
MagicMock(return_value='9.1.1')):
ret = pip.list_upgrades()
mock.assert_called_with(
['pip', 'list', '--outdated', '--format=json'],
cwd=None,
runas=None,
)
self.assertEqual(
ret, {
'apache-libcloud': '2.2.1',
'appdirs': '1.4.3',
'awscli': '1.12.1'
}
)
def test_is_installed_true(self):
eggs = [
'M2Crypto==0.21.1',
'-e git+git@github.com:s0undt3ch/salt-testing.git@9ed81aa2f918d59d3706e56b18f0782d1ea43bf8#egg=SaltTesting-dev',
'bbfreeze==1.1.0',
'bbfreeze-loader==1.1.0',
'pycrypto==2.6'
]
mock = MagicMock(
return_value={
'retcode': 0,
'stdout': '\n'.join(eggs)
}
)
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
with patch('salt.modules.pip.version',
MagicMock(return_value='6.1.1')):
ret = pip.is_installed(pkgname='bbfreeze')
mock.assert_called_with(
['pip', 'freeze'],
cwd=None,
runas=None,
python_shell=False,
use_vt=False,
)
self.assertTrue(ret)
def test_is_installed_false(self):
eggs = [
'M2Crypto==0.21.1',
'-e git+git@github.com:s0undt3ch/salt-testing.git@9ed81aa2f918d59d3706e56b18f0782d1ea43bf8#egg=SaltTesting-dev',
'bbfreeze==1.1.0',
'bbfreeze-loader==1.1.0',
'pycrypto==2.6'
]
mock = MagicMock(
return_value={
'retcode': 0,
'stdout': '\n'.join(eggs)
}
)
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
with patch('salt.modules.pip.version',
MagicMock(return_value='6.1.1')):
ret = pip.is_installed(pkgname='notexist')
mock.assert_called_with(
['pip', 'freeze'],
cwd=None,
runas=None,
python_shell=False,
use_vt=False,
)
self.assertFalse(ret)
def test_install_pre_argument_in_resulting_command(self):
pkg = 'pep8'
# Lower than 1.4 versions don't end-up with `--pre` in the resulting
# output
mock = MagicMock(side_effect=[
{'retcode': 0, 'stdout': 'pip 1.2.0 /path/to/site-packages/pip'},
{'retcode': 0, 'stdout': ''}
])
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
with patch('salt.modules.pip.version',
MagicMock(return_value='1.3')):
pip.install(pkg, pre_releases=True)
expected = [sys.executable, '-m', 'pip', 'install', pkg]
mock.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)
mock_run = MagicMock(return_value='pip 1.4.1 /path/to/site-packages/pip')
mock_run_all = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(pip.__salt__, {'cmd.run_stdout': mock_run,
'cmd.run_all': mock_run_all}):
with patch('salt.modules.pip._get_pip_bin',
MagicMock(return_value=['pip'])):
pip.install(pkg, pre_releases=True)
expected = ['pip', 'install', '--pre', pkg]
mock_run_all.assert_called_with(
expected,
saltenv='base',
runas=None,
use_vt=False,
python_shell=False,
)