2013-07-27 14:58:28 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
'''
|
|
|
|
:codeauthor: :email:`Pedro Algarvio (pedro@algarvio.me)`
|
2013-09-16 16:24:00 +00:00
|
|
|
:copyright: © 2013 by the SaltStack Team, see AUTHORS for more details
|
2013-07-27 14:58:28 +00:00
|
|
|
:license: Apache 2.0, see LICENSE for more details.
|
2013-09-16 16:24:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
tests.unit.states.pip_test
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
2013-07-27 14:58:28 +00:00
|
|
|
'''
|
|
|
|
|
|
|
|
# Import python libs
|
|
|
|
import warnings
|
|
|
|
|
|
|
|
# Import Salt Testing libs
|
|
|
|
from salttesting import skipIf, TestCase
|
|
|
|
from salttesting.helpers import ensure_in_syspath
|
2013-08-26 10:10:06 +00:00
|
|
|
from salttesting.mock import NO_MOCK, NO_MOCK_REASON, MagicMock, patch
|
2013-07-27 14:58:28 +00:00
|
|
|
ensure_in_syspath('../../')
|
|
|
|
|
|
|
|
# Import salt libs
|
|
|
|
import integration
|
2013-08-29 10:37:25 +00:00
|
|
|
from salt.states import pip_state
|
2013-07-27 15:02:59 +00:00
|
|
|
from salt.exceptions import CommandExecutionError
|
2013-07-27 14:58:28 +00:00
|
|
|
|
2013-08-29 10:37:25 +00:00
|
|
|
# Import 3rd-party libs
|
2013-12-31 14:22:35 +00:00
|
|
|
try:
|
|
|
|
import pip
|
|
|
|
HAS_PIP = True
|
|
|
|
except ImportError:
|
|
|
|
HAS_PIP = False
|
2013-08-29 10:37:25 +00:00
|
|
|
|
2013-11-02 18:59:06 +00:00
|
|
|
pip_state.__env__ = 'base'
|
2013-08-29 10:37:25 +00:00
|
|
|
pip_state.__opts__ = {'test': False}
|
|
|
|
pip_state.__salt__ = {'cmd.which_bin': lambda _: 'pip'}
|
2013-07-27 14:58:28 +00:00
|
|
|
|
|
|
|
|
2013-08-26 10:10:06 +00:00
|
|
|
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
2013-12-31 14:22:35 +00:00
|
|
|
@skipIf(not HAS_PIP,
|
|
|
|
'The \'pip\' library is not importable(installed system-wide)')
|
2013-07-27 14:58:28 +00:00
|
|
|
class PipStateTest(TestCase, integration.SaltReturnAssertsMixIn):
|
|
|
|
|
|
|
|
def test_installed_deprecated_runas(self):
|
|
|
|
# We *always* want *all* warnings thrown on this module
|
|
|
|
warnings.resetwarnings()
|
|
|
|
warnings.filterwarnings('always', '', DeprecationWarning, __name__)
|
|
|
|
|
|
|
|
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
|
|
|
pip_list = MagicMock(return_value=[])
|
|
|
|
pip_install = MagicMock(return_value={'retcode': 0})
|
2013-08-29 10:37:25 +00:00
|
|
|
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
|
|
|
|
'pip.list': pip_list,
|
|
|
|
'pip.install': pip_install}):
|
2013-07-27 14:58:28 +00:00
|
|
|
with warnings.catch_warnings(record=True) as w:
|
2013-08-29 10:37:25 +00:00
|
|
|
ret = pip_state.installed('pep8', runas='me!')
|
2013-07-27 14:58:28 +00:00
|
|
|
self.assertEqual(
|
|
|
|
'The \'runas\' argument to pip.installed is deprecated, '
|
2013-10-04 12:09:54 +00:00
|
|
|
'and will be removed in Salt Hydrogen (Unreleased). '
|
|
|
|
'Please use \'user\' instead.', str(w[-1].message)
|
2013-07-27 14:58:28 +00:00
|
|
|
)
|
|
|
|
self.assertSaltTrueReturn({'testsuite': ret})
|
|
|
|
# Is the state returning a warnings key with the deprecation
|
|
|
|
# message?
|
|
|
|
self.assertInSalStatetWarning(
|
|
|
|
'The \'runas\' argument to pip.installed is deprecated, '
|
2013-10-04 12:09:54 +00:00
|
|
|
'and will be removed in Salt Hydrogen (Unreleased). '
|
|
|
|
'Please use \'user\' instead.', {'testsuite': ret}
|
2013-07-27 14:58:28 +00:00
|
|
|
)
|
|
|
|
|
2013-07-27 15:02:59 +00:00
|
|
|
def test_installed_runas_and_user_raises_exception(self):
|
|
|
|
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
2013-08-29 10:37:25 +00:00
|
|
|
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock}):
|
2013-07-27 15:02:59 +00:00
|
|
|
self.assertRaises(
|
|
|
|
CommandExecutionError,
|
2013-08-29 10:37:25 +00:00
|
|
|
pip_state.installed,
|
2013-07-27 15:02:59 +00:00
|
|
|
'pep8',
|
|
|
|
user='Me!',
|
|
|
|
runas='Not Me!'
|
|
|
|
)
|
|
|
|
|
2013-07-27 14:58:28 +00:00
|
|
|
def test_removed_deprecated_runas(self):
|
|
|
|
# We *always* want *all* warnings thrown on this module
|
|
|
|
warnings.resetwarnings()
|
|
|
|
warnings.filterwarnings('always', '', DeprecationWarning, __name__)
|
|
|
|
|
|
|
|
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
|
|
|
pip_list = MagicMock(return_value=['pep8'])
|
|
|
|
pip_uninstall = MagicMock(return_value=True)
|
2013-08-29 10:37:25 +00:00
|
|
|
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
|
|
|
|
'pip.list': pip_list,
|
|
|
|
'pip.uninstall': pip_uninstall}):
|
2013-07-27 14:58:28 +00:00
|
|
|
with warnings.catch_warnings(record=True) as w:
|
2013-08-29 10:37:25 +00:00
|
|
|
ret = pip_state.removed('pep8', runas='me!')
|
2013-07-27 14:58:28 +00:00
|
|
|
self.assertEqual(
|
|
|
|
'The \'runas\' argument to pip.installed is deprecated, '
|
2013-10-04 12:09:54 +00:00
|
|
|
'and will be removed in Salt Hydrogen (Unreleased). '
|
|
|
|
'Please use \'user\' instead.', str(w[-1].message)
|
2013-07-27 14:58:28 +00:00
|
|
|
)
|
|
|
|
self.assertSaltTrueReturn({'testsuite': ret})
|
|
|
|
# Is the state returning a warnings key with the deprecation
|
|
|
|
# message?
|
|
|
|
self.assertInSalStatetWarning(
|
|
|
|
'The \'runas\' argument to pip.installed is deprecated, '
|
2013-10-04 12:09:54 +00:00
|
|
|
'and will be removed in Salt Hydrogen (Unreleased). '
|
|
|
|
'Please use \'user\' instead.', {'testsuite': ret}
|
2013-07-27 14:58:28 +00:00
|
|
|
)
|
|
|
|
|
2013-07-27 15:02:59 +00:00
|
|
|
def test_removed_runas_and_user_raises_exception(self):
|
|
|
|
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
2013-08-29 10:37:25 +00:00
|
|
|
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock}):
|
2013-07-27 15:02:59 +00:00
|
|
|
self.assertRaises(
|
|
|
|
CommandExecutionError,
|
2013-08-29 10:37:25 +00:00
|
|
|
pip_state.removed,
|
2013-07-27 15:02:59 +00:00
|
|
|
'pep8',
|
|
|
|
user='Me!',
|
|
|
|
runas='Not Me!'
|
|
|
|
)
|
2013-07-27 14:58:28 +00:00
|
|
|
|
2013-08-18 05:45:23 +00:00
|
|
|
def test_install_requirements_parsing(self):
|
2013-08-18 06:27:32 +00:00
|
|
|
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
|
|
|
pip_list = MagicMock(return_value={'pep8': '1.3.3'})
|
2013-08-29 10:37:25 +00:00
|
|
|
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
|
|
|
|
'pip.list': pip_list}):
|
|
|
|
with patch.dict(pip_state.__opts__, {'test': True}):
|
|
|
|
ret = pip_state.installed('pep8=1.3.2')
|
2013-08-18 06:27:32 +00:00
|
|
|
self.assertSaltFalseReturn({'test': ret})
|
|
|
|
self.assertInSaltComment(
|
|
|
|
'Invalid version specification in package pep8=1.3.2. '
|
|
|
|
'\'=\' is not supported, use \'==\' instead.',
|
|
|
|
{'test': ret}
|
|
|
|
)
|
|
|
|
|
2013-08-18 05:45:23 +00:00
|
|
|
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
|
|
|
pip_list = MagicMock(return_value={'pep8': '1.3.3'})
|
2013-08-29 10:37:25 +00:00
|
|
|
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
|
|
|
|
'pip.list': pip_list}):
|
|
|
|
with patch.dict(pip_state.__opts__, {'test': True}):
|
|
|
|
ret = pip_state.installed('pep8>=1.3.2')
|
2013-08-18 05:45:23 +00:00
|
|
|
self.assertSaltTrueReturn({'test': ret})
|
|
|
|
self.assertInSaltComment(
|
|
|
|
'Python package pep8>=1.3.2 already installed',
|
|
|
|
{'test': ret}
|
|
|
|
)
|
|
|
|
|
|
|
|
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
|
|
|
pip_list = MagicMock(return_value={'pep8': '1.3.3'})
|
2013-08-29 10:37:25 +00:00
|
|
|
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
|
|
|
|
'pip.list': pip_list}):
|
|
|
|
with patch.dict(pip_state.__opts__, {'test': True}):
|
|
|
|
ret = pip_state.installed('pep8<1.3.2')
|
2013-08-18 05:45:23 +00:00
|
|
|
self.assertSaltNoneReturn({'test': ret})
|
|
|
|
self.assertInSaltComment(
|
|
|
|
'Python package pep8<1.3.2 is set to be installed',
|
|
|
|
{'test': ret}
|
|
|
|
)
|
|
|
|
|
|
|
|
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
|
|
|
pip_list = MagicMock(return_value={'pep8': '1.3.2'})
|
2013-08-29 10:37:25 +00:00
|
|
|
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
|
|
|
|
'pip.list': pip_list}):
|
|
|
|
with patch.dict(pip_state.__opts__, {'test': True}):
|
|
|
|
ret = pip_state.installed('pep8>1.3.1,<1.3.3')
|
2013-08-18 05:45:23 +00:00
|
|
|
self.assertSaltTrueReturn({'test': ret})
|
|
|
|
self.assertInSaltComment(
|
|
|
|
'Python package pep8>1.3.1;<1.3.3 already installed',
|
|
|
|
{'test': ret}
|
|
|
|
)
|
|
|
|
|
|
|
|
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
|
|
|
pip_list = MagicMock(return_value={'pep8': '1.3.1'})
|
2013-08-29 10:37:25 +00:00
|
|
|
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
|
|
|
|
'pip.list': pip_list}):
|
|
|
|
with patch.dict(pip_state.__opts__, {'test': True}):
|
|
|
|
ret = pip_state.installed('pep8>1.3.1,<1.3.3')
|
2013-08-18 05:45:23 +00:00
|
|
|
self.assertSaltNoneReturn({'test': ret})
|
|
|
|
self.assertInSaltComment(
|
|
|
|
'Python package pep8>1.3.1;<1.3.3 is set to be installed',
|
|
|
|
{'test': ret}
|
|
|
|
)
|
|
|
|
|
2013-08-18 06:27:32 +00:00
|
|
|
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
|
|
|
pip_list = MagicMock(return_value={'pep8': '1.3.1'})
|
2013-08-29 10:37:25 +00:00
|
|
|
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
|
|
|
|
'pip.list': pip_list}):
|
|
|
|
with patch.dict(pip_state.__opts__, {'test': True}):
|
|
|
|
ret = pip_state.installed(
|
2013-08-18 06:27:32 +00:00
|
|
|
'git+https://github.com/saltstack/salt-testing.git#egg=SaltTesting>=0.5.1'
|
|
|
|
)
|
|
|
|
self.assertSaltNoneReturn({'test': ret})
|
|
|
|
self.assertInSaltComment(
|
|
|
|
'Python package git+https://github.com/saltstack/'
|
2013-08-26 08:54:26 +00:00
|
|
|
'salt-testing.git#egg=SaltTesting>=0.5.1 is set to be '
|
|
|
|
'installed',
|
|
|
|
{'test': ret}
|
|
|
|
)
|
|
|
|
|
|
|
|
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
|
|
|
pip_list = MagicMock(return_value={'pep8': '1.3.1'})
|
2013-08-29 10:37:25 +00:00
|
|
|
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
|
|
|
|
'pip.list': pip_list}):
|
|
|
|
with patch.dict(pip_state.__opts__, {'test': True}):
|
|
|
|
ret = pip_state.installed(
|
2013-08-26 08:54:26 +00:00
|
|
|
'git+https://github.com/saltstack/salt-testing.git#egg=SaltTesting'
|
|
|
|
)
|
|
|
|
self.assertSaltNoneReturn({'test': ret})
|
|
|
|
self.assertInSaltComment(
|
|
|
|
'Python package git+https://github.com/saltstack/'
|
2013-08-26 10:46:50 +00:00
|
|
|
'salt-testing.git#egg=SaltTesting is set to be '
|
2013-08-18 06:27:32 +00:00
|
|
|
'installed',
|
|
|
|
{'test': ret}
|
|
|
|
)
|
|
|
|
|
|
|
|
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
|
|
|
pip_list = MagicMock(return_value={'pep8': '1.3.1'})
|
2013-08-29 10:37:25 +00:00
|
|
|
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
|
|
|
|
'pip.list': pip_list}):
|
|
|
|
with patch.dict(pip_state.__opts__, {'test': True}):
|
|
|
|
ret = pip_state.installed(
|
2013-08-18 06:27:32 +00:00
|
|
|
'https://pypi.python.org/packages/source/S/SaltTesting/'
|
|
|
|
'SaltTesting-0.5.0.tar.gz'
|
|
|
|
'#md5=e6760af92b7165f8be53b5763e40bc24'
|
|
|
|
)
|
|
|
|
self.assertSaltNoneReturn({'test': ret})
|
|
|
|
self.assertInSaltComment(
|
|
|
|
'Python package https://pypi.python.org/packages/source/'
|
|
|
|
'S/SaltTesting/SaltTesting-0.5.0.tar.gz'
|
|
|
|
'#md5=e6760af92b7165f8be53b5763e40bc24 is set to be '
|
|
|
|
'installed',
|
|
|
|
{'test': ret}
|
|
|
|
)
|
2013-08-18 05:45:23 +00:00
|
|
|
|
2013-08-18 07:03:41 +00:00
|
|
|
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
|
|
|
pip_list = MagicMock(return_value={'SaltTesting': '0.5.0'})
|
|
|
|
pip_install = MagicMock(return_value={
|
|
|
|
'retcode': 0,
|
2013-11-27 12:59:56 +00:00
|
|
|
'stderr': '',
|
2013-08-18 07:03:41 +00:00
|
|
|
'stdout': 'Downloading/unpacking https://pypi.python.org/packages'
|
|
|
|
'/source/S/SaltTesting/SaltTesting-0.5.0.tar.gz\n '
|
|
|
|
'Downloading SaltTesting-0.5.0.tar.gz\n Running '
|
|
|
|
'setup.py egg_info for package from '
|
|
|
|
'https://pypi.python.org/packages/source/S/SaltTesting/'
|
|
|
|
'SaltTesting-0.5.0.tar.gz\n \nCleaning up...'
|
|
|
|
})
|
2013-08-29 10:37:25 +00:00
|
|
|
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
|
|
|
|
'pip.list': pip_list,
|
|
|
|
'pip.install': pip_install}):
|
|
|
|
ret = pip_state.installed(
|
2013-08-18 07:03:41 +00:00
|
|
|
'https://pypi.python.org/packages/source/S/SaltTesting/'
|
|
|
|
'SaltTesting-0.5.0.tar.gz'
|
|
|
|
'#md5=e6760af92b7165f8be53b5763e40bc24'
|
|
|
|
)
|
|
|
|
self.assertSaltTrueReturn({'test': ret})
|
|
|
|
self.assertInSaltComment(
|
2013-08-22 20:06:06 +00:00
|
|
|
'There was no error installing package '
|
|
|
|
'\'https://pypi.python.org/packages/source/S/SaltTesting/'
|
|
|
|
'SaltTesting-0.5.0.tar.gz#md5=e6760af92b7165f8be53b5763e40bc24\' '
|
|
|
|
'although it does not show when calling \'pip.freeze\'.',
|
2013-08-18 07:03:41 +00:00
|
|
|
{'test': ret}
|
|
|
|
)
|
|
|
|
self.assertInSaltReturn(
|
|
|
|
'Installed',
|
|
|
|
{'test': ret},
|
2013-08-22 20:06:06 +00:00
|
|
|
('changes', 'https://pypi.python.org/packages/source/S/'
|
|
|
|
'SaltTesting/SaltTesting-0.5.0.tar.gz'
|
|
|
|
'#md5=e6760af92b7165f8be53b5763e40bc24==???')
|
2013-08-18 07:03:41 +00:00
|
|
|
)
|
|
|
|
|
2013-08-26 10:46:50 +00:00
|
|
|
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
|
|
|
pip_list = MagicMock(return_value={'pep8': '1.3.1'})
|
|
|
|
pip_install = MagicMock(return_value={
|
|
|
|
'retcode': 0,
|
2013-11-27 12:59:56 +00:00
|
|
|
'stderr': '',
|
2013-08-26 10:46:50 +00:00
|
|
|
'stdout': 'Cloned!'
|
|
|
|
})
|
2013-08-29 10:37:25 +00:00
|
|
|
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
|
|
|
|
'pip.list': pip_list,
|
|
|
|
'pip.install': pip_install}):
|
|
|
|
with patch.dict(pip_state.__opts__, {'test': False}):
|
|
|
|
ret = pip_state.installed(
|
2013-08-26 10:46:50 +00:00
|
|
|
'git+https://github.com/saltstack/salt-testing.git#egg=SaltTesting'
|
|
|
|
)
|
|
|
|
self.assertSaltTrueReturn({'test': ret})
|
|
|
|
self.assertInSaltComment(
|
|
|
|
'Package was successfully installed',
|
|
|
|
{'test': ret}
|
|
|
|
)
|
|
|
|
|
2013-11-14 13:23:09 +00:00
|
|
|
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
|
|
|
pip_list = MagicMock(return_value={'pep8': '1.3.1'})
|
2013-11-27 12:59:56 +00:00
|
|
|
pip_install = MagicMock(return_value={'retcode': 0})
|
2013-11-14 13:23:09 +00:00
|
|
|
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
|
|
|
|
'pip.list': pip_list,
|
|
|
|
'pip.install': pip_install}):
|
|
|
|
with patch.dict(pip_state.__opts__, {'test': False}):
|
|
|
|
ret = pip_state.installed(
|
|
|
|
'arbitrary ID that should be ignored due to requirements specified',
|
|
|
|
requirements='/tmp/non-existing-requirements.txt'
|
|
|
|
)
|
|
|
|
self.assertSaltTrueReturn({'test': ret})
|
|
|
|
|
2013-09-09 19:53:52 +00:00
|
|
|
# Test VCS installations using git+git://
|
|
|
|
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
|
|
|
pip_list = MagicMock(return_value={'pep8': '1.3.1'})
|
|
|
|
pip_install = MagicMock(return_value={
|
|
|
|
'retcode': 0,
|
2013-11-27 12:59:56 +00:00
|
|
|
'stderr': '',
|
2013-09-09 19:53:52 +00:00
|
|
|
'stdout': 'Cloned!'
|
|
|
|
})
|
|
|
|
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
|
|
|
|
'pip.list': pip_list,
|
|
|
|
'pip.install': pip_install}):
|
|
|
|
with patch.dict(pip_state.__opts__, {'test': False}):
|
|
|
|
ret = pip_state.installed(
|
|
|
|
'git+git://github.com/saltstack/salt-testing.git#egg=SaltTesting'
|
|
|
|
)
|
|
|
|
self.assertSaltTrueReturn({'test': ret})
|
|
|
|
self.assertInSaltComment(
|
|
|
|
'Package was successfully installed',
|
|
|
|
{'test': ret}
|
|
|
|
)
|
|
|
|
|
2013-08-29 10:37:25 +00:00
|
|
|
# Test VCS installations with version info like >= 0.1
|
|
|
|
try:
|
|
|
|
orignal_pip_version = pip.__version__
|
|
|
|
pip.__version__ = MagicMock(
|
|
|
|
side_effect=AttributeError(
|
|
|
|
'Faked missing __version__ attribute'
|
|
|
|
)
|
|
|
|
)
|
|
|
|
except AttributeError:
|
|
|
|
# The pip version being used is already < 1.2
|
|
|
|
pass
|
|
|
|
|
|
|
|
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
|
|
|
pip_list = MagicMock(return_value={'pep8': '1.3.1'})
|
|
|
|
pip_install = MagicMock(return_value={
|
|
|
|
'retcode': 0,
|
2013-11-27 12:59:56 +00:00
|
|
|
'stderr': '',
|
2013-08-29 10:37:25 +00:00
|
|
|
'stdout': 'Cloned!'
|
|
|
|
})
|
|
|
|
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
|
|
|
|
'pip.list': pip_list,
|
|
|
|
'pip.install': pip_install}):
|
|
|
|
with patch.dict(pip_state.__opts__, {'test': False}):
|
|
|
|
ret = pip_state.installed(
|
|
|
|
'git+https://github.com/saltstack/salt-testing.git#egg=SaltTesting>=0.5.0'
|
|
|
|
)
|
|
|
|
self.assertSaltTrueReturn({'test': ret})
|
|
|
|
self.assertInSaltComment(
|
|
|
|
'Package was successfully installed',
|
|
|
|
{'test': ret}
|
|
|
|
)
|
|
|
|
|
|
|
|
# Reset the version attribute if existing
|
|
|
|
if hasattr(pip, '__version__'):
|
|
|
|
pip.__version__ = orignal_pip_version
|
|
|
|
|
2013-07-27 14:58:28 +00:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
from integration import run_tests
|
|
|
|
run_tests(PipStateTest, needs_daemon=False)
|