diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/git_submodule_helpers.py | 13 | ||||
-rwxr-xr-x | tests/packages/HackedEggInfo/setup.py | 17 | ||||
-rw-r--r-- | tests/packages/README.txt | 3 | ||||
-rw-r--r-- | tests/packages/child-0.1.tar.gz | bin | 0 -> 498 bytes | |||
-rw-r--r-- | tests/packages/parent-0.1.tar.gz | bin | 0 -> 483 bytes | |||
-rw-r--r-- | tests/test_basic.py | 10 | ||||
-rw-r--r-- | tests/test_cleanup.py | 23 | ||||
-rw-r--r-- | tests/test_hashes.py | 194 | ||||
-rw-r--r-- | tests/test_index.py | 29 | ||||
-rw-r--r-- | tests/test_pip.py | 26 | ||||
-rw-r--r-- | tests/test_requirements.py | 17 | ||||
-rw-r--r-- | tests/test_test.py | 21 | ||||
-rw-r--r-- | tests/test_unicode.py | 4 | ||||
-rw-r--r-- | tests/test_uninstall.py | 57 | ||||
-rw-r--r-- | tests/test_upgrade.py | 4 | ||||
-rw-r--r-- | tests/test_user_site.py | 95 | ||||
-rw-r--r-- | tests/test_util.py | 140 | ||||
-rw-r--r-- | tests/test_vcs_git.py | 5 |
18 files changed, 619 insertions, 39 deletions
diff --git a/tests/git_submodule_helpers.py b/tests/git_submodule_helpers.py index ef08b2636..ecb789b10 100644 --- a/tests/git_submodule_helpers.py +++ b/tests/git_submodule_helpers.py @@ -44,19 +44,22 @@ def _create_test_package_with_submodule(env): packages=find_packages(), ) '''), version_pkg_path) - env.run('git', 'init', cwd=version_pkg_path) - env.run('git', 'add', '.', cwd=version_pkg_path) + env.run('git', 'init', cwd=version_pkg_path, expect_error=True) + env.run('git', 'add', '.', cwd=version_pkg_path, expect_error=True) env.run('git', 'commit', '-q', '--author', 'Pip <python-virtualenv@googlegroups.com>', - '-am', 'initial version', cwd=version_pkg_path) + '-am', 'initial version', cwd=version_pkg_path, + expect_error=True) submodule_path = _create_test_package_submodule(env) - env.run('git', 'submodule', 'add', submodule_path, 'testpkg/static', cwd=version_pkg_path) + env.run('git', 'submodule', 'add', submodule_path, 'testpkg/static', cwd=version_pkg_path, + expect_error=True) env.run('git', 'commit', '-q', '--author', 'Pip <python-virtualenv@googlegroups.com>', - '-am', 'initial version w submodule', cwd=version_pkg_path) + '-am', 'initial version w submodule', cwd=version_pkg_path, + expect_error=True) return version_pkg_path, submodule_path diff --git a/tests/packages/HackedEggInfo/setup.py b/tests/packages/HackedEggInfo/setup.py new file mode 100755 index 000000000..c34b57c4b --- /dev/null +++ b/tests/packages/HackedEggInfo/setup.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- + +from setuptools import setup +from setuptools.command import egg_info as orig_egg_info + +class egg_info (orig_egg_info.egg_info): + def run(self): + orig_egg_info.egg_info.run(self) + + +setup( + name = "hackedegginfo", + version = '0.0.0', + cmdclass = {'egg_info':egg_info }, + zip_safe = False, +) + diff --git a/tests/packages/README.txt b/tests/packages/README.txt index b6ecde635..069b32c14 100644 --- a/tests/packages/README.txt +++ b/tests/packages/README.txt @@ -4,3 +4,6 @@ Version 0.2broken has a setup.py crafted to fail on install (and only on install). If any earlier step would fail (i.e. egg-info-generation), the already-installed version would never be uninstalled, so uninstall-rollback would not come into play. + +The parent-0.1.tar.gz and child-0.1.tar.gz packages are used by +test_uninstall:test_uninstall_overlapping_package. diff --git a/tests/packages/child-0.1.tar.gz b/tests/packages/child-0.1.tar.gz Binary files differnew file mode 100644 index 000000000..2fb34ca5d --- /dev/null +++ b/tests/packages/child-0.1.tar.gz diff --git a/tests/packages/parent-0.1.tar.gz b/tests/packages/parent-0.1.tar.gz Binary files differnew file mode 100644 index 000000000..130e756f4 --- /dev/null +++ b/tests/packages/parent-0.1.tar.gz diff --git a/tests/test_basic.py b/tests/test_basic.py index c27e28fd1..a49824abf 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -376,6 +376,16 @@ def test_install_with_pax_header(): run_pip('install', 'paxpkg.tar.bz2', cwd=run_from) +def test_install_with_hacked_egg_info(): + """ + test installing a package which defines its own egg_info class + """ + reset_env() + run_from = abspath(join(here, 'packages', 'HackedEggInfo')) + result = run_pip('install', '.', cwd=run_from) + assert 'Successfully installed hackedegginfo\n' in result.stdout + + def test_install_using_install_option_and_editable(): """ Test installing a tool using -e and --install-option diff --git a/tests/test_cleanup.py b/tests/test_cleanup.py index 15a050833..c57db91ee 100644 --- a/tests/test_cleanup.py +++ b/tests/test_cleanup.py @@ -17,6 +17,7 @@ def test_cleanup_after_install_from_pypi(): src = env.scratch_path/"src" assert not exists(build), "build/ dir still exists: %s" % build assert not exists(src), "unexpected src/ dir exists: %s" % src + env.assert_no_temp() def test_cleanup_after_install_editable_from_hg(): @@ -34,6 +35,7 @@ def test_cleanup_after_install_editable_from_hg(): src = env.venv_path/'src' assert not exists(build), "build/ dir still exists: %s" % build assert exists(src), "expected src/ dir doesn't exist: %s" % src + env.assert_no_temp() def test_cleanup_after_install_from_local_directory(): @@ -48,6 +50,7 @@ def test_cleanup_after_install_from_local_directory(): src = env.venv_path/'src' assert not exists(build), "unexpected build/ dir exists: %s" % build assert not exists(src), "unexpected src/ dir exist: %s" % src + env.assert_no_temp() def test_cleanup_after_create_bundle(): @@ -79,6 +82,7 @@ def test_cleanup_after_create_bundle(): src_bundle = env.scratch_path/"src-bundle" assert not exists(build_bundle), "build-bundle/ dir still exists: %s" % build_bundle assert not exists(src_bundle), "src-bundle/ dir still exists: %s" % src_bundle + env.assert_no_temp() # Make sure previously created src/ from editable still exists assert exists(src), "expected src dir doesn't exist: %s" % src @@ -96,6 +100,25 @@ def test_no_install_and_download_should_not_leave_build_dir(): assert not os.path.exists(env.venv_path/'/build'), "build/ dir should be deleted" +def test_cleanup_req_satisifed_no_name(): + """ + Test cleanup when req is already satisfied, and req has no 'name' + """ + #this test confirms Issue #420 is fixed + #reqs with no 'name' that were already satisfied were leaving behind tmp build dirs + #2 examples of reqs that would do this + # 1) https://bitbucket.org/ianb/initools/get/tip.zip + # 2) parent-0.1.tar.gz + + dist = abspath(join(here, 'packages', 'parent-0.1.tar.gz')) + env = reset_env() + result = run_pip('install', dist) + result = run_pip('install', dist) + build = env.venv_path/'build' + assert not exists(build), "unexpected build/ dir exists: %s" % build + env.assert_no_temp() + + def test_download_should_not_delete_existing_build_dir(): """ It should not delete build/ if existing before run the command diff --git a/tests/test_hashes.py b/tests/test_hashes.py new file mode 100644 index 000000000..79c4f1649 --- /dev/null +++ b/tests/test_hashes.py @@ -0,0 +1,194 @@ +import os + +from nose.tools import assert_raises + +from pip.download import _get_hash_from_file, _check_hash +from pip.exceptions import InstallationError +from pip.index import Link + + +def test_get_hash_from_file_md5(): + file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz") + file_link = Link("http://testserver/gmpy-1.15.tar.gz#md5=d41d8cd98f00b204e9800998ecf8427e") + + download_hash = _get_hash_from_file(file_path, file_link) + + assert download_hash.digest_size == 16 + assert download_hash.hexdigest() == "d41d8cd98f00b204e9800998ecf8427e" + + +def test_get_hash_from_file_sha1(): + file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz") + file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha1=da39a3ee5e6b4b0d3255bfef95601890afd80709") + + download_hash = _get_hash_from_file(file_path, file_link) + + assert download_hash.digest_size == 20 + assert download_hash.hexdigest() == "da39a3ee5e6b4b0d3255bfef95601890afd80709" + + +def test_get_hash_from_file_sha224(): + file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz") + file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha224=d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f") + + download_hash = _get_hash_from_file(file_path, file_link) + + assert download_hash.digest_size == 28 + assert download_hash.hexdigest() == "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f" + + +def test_get_hash_from_file_sha384(): + file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz") + file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha384=38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b") + + download_hash = _get_hash_from_file(file_path, file_link) + + assert download_hash.digest_size == 48 + assert download_hash.hexdigest() == "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b" + + +def test_get_hash_from_file_sha256(): + file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz") + file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855") + + download_hash = _get_hash_from_file(file_path, file_link) + + assert download_hash.digest_size == 32 + assert download_hash.hexdigest() == "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + + +def test_get_hash_from_file_sha512(): + file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz") + file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha512=cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e") + + download_hash = _get_hash_from_file(file_path, file_link) + + assert download_hash.digest_size == 64 + assert download_hash.hexdigest() == "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e" + + +def test_get_hash_from_file_unknown(): + file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz") + file_link = Link("http://testserver/gmpy-1.15.tar.gz#unknown_hash=d41d8cd98f00b204e9800998ecf8427e") + + download_hash = _get_hash_from_file(file_path, file_link) + + assert download_hash is None + + +def test_check_hash_md5_valid(): + file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz") + file_link = Link("http://testserver/gmpy-1.15.tar.gz#md5=d41d8cd98f00b204e9800998ecf8427e") + + download_hash = _get_hash_from_file(file_path, file_link) + + _check_hash(download_hash, file_link) + + +def test_check_hash_md5_invalid(): + file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz") + file_link = Link("http://testserver/gmpy-1.15.tar.gz#md5=deadbeef") + + download_hash = _get_hash_from_file(file_path, file_link) + + assert_raises(InstallationError, _check_hash, download_hash, file_link) + + +def test_check_hash_sha1_valid(): + file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz") + file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha1=da39a3ee5e6b4b0d3255bfef95601890afd80709") + + download_hash = _get_hash_from_file(file_path, file_link) + + _check_hash(download_hash, file_link) + + +def test_check_hash_sha1_invalid(): + file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz") + file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha1=deadbeef") + + download_hash = _get_hash_from_file(file_path, file_link) + + assert_raises(InstallationError, _check_hash, download_hash, file_link) + + +def test_check_hash_sha224_valid(): + file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz") + file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha224=d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f'") + + download_hash = _get_hash_from_file(file_path, file_link) + + _check_hash(download_hash, file_link) + + +def test_check_hash_sha224_invalid(): + file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz") + file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha224=deadbeef") + + download_hash = _get_hash_from_file(file_path, file_link) + + assert_raises(InstallationError, _check_hash, download_hash, file_link) + + +def test_check_hash_sha384_valid(): + file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz") + file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha384=38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b") + + download_hash = _get_hash_from_file(file_path, file_link) + + _check_hash(download_hash, file_link) + + +def test_check_hash_sha384_invalid(): + file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz") + file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha384=deadbeef") + + download_hash = _get_hash_from_file(file_path, file_link) + + assert_raises(InstallationError, _check_hash, download_hash, file_link) + + +def test_check_hash_sha256_valid(): + file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz") + file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855") + + download_hash = _get_hash_from_file(file_path, file_link) + + _check_hash(download_hash, file_link) + + +def test_check_hash_sha256_invalid(): + file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz") + file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha256=deadbeef") + + download_hash = _get_hash_from_file(file_path, file_link) + + assert_raises(InstallationError, _check_hash, download_hash, file_link) + + +def test_check_hash_sha512_valid(): + file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz") + file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha512=cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e") + + download_hash = _get_hash_from_file(file_path, file_link) + + _check_hash(download_hash, file_link) + + +def test_check_hash_sha512_invalid(): + file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz") + file_link = Link("http://testserver/gmpy-1.15.tar.gz#sha512=deadbeef") + + download_hash = _get_hash_from_file(file_path, file_link) + + assert_raises(InstallationError, _check_hash, download_hash, file_link) + + +def test_check_hasher_mismsatch(): + file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "packages", "gmpy-1.15.tar.gz") + file_link = Link("http://testserver/gmpy-1.15.tar.gz#md5=d41d8cd98f00b204e9800998ecf8427e") + other_link = Link("http://testserver/gmpy-1.15.tar.gz#sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855") + + download_hash = _get_hash_from_file(file_path, file_link) + + assert_raises(InstallationError, _check_hash, download_hash, other_link) diff --git a/tests/test_index.py b/tests/test_index.py index 6f9d216dc..c537172aa 100644 --- a/tests/test_index.py +++ b/tests/test_index.py @@ -1,4 +1,6 @@ -from pip.index import package_to_requirement, HTMLPage +from pip.index import package_to_requirement, HTMLPage, get_mirrors, DEFAULT_MIRROR_HOSTNAME +from string import ascii_lowercase +from mock import patch def test_package_name_should_be_converted_to_requirement(): @@ -26,3 +28,28 @@ def test_html_page_should_be_able_to_scrap_rel_links(): assert len(links) == 1 assert links[0].url == 'http://supervisord.org/' +@patch('socket.gethostbyname_ex') +def test_get_mirrors(mock_gethostbyname_ex): + # Test when the expected result comes back + # from socket.gethostbyname_ex + mock_gethostbyname_ex.return_value = ('g.pypi.python.org', [DEFAULT_MIRROR_HOSTNAME], ['129.21.171.98']) + mirrors = get_mirrors() + # Expect [a-g].pypi.python.org, since last mirror + # is returned as g.pypi.python.org + assert len(mirrors) == 7 + for c in "abcdefg": + assert c + ".pypi.python.org" in mirrors + +@patch('socket.gethostbyname_ex') +def test_get_mirrors_no_cname(mock_gethostbyname_ex): + # Test when the UNexpected result comes back + # from socket.gethostbyname_ex + # (seeing this in Japan and was resulting in 216k + # invalid mirrors and a hot CPU) + mock_gethostbyname_ex.return_value = (DEFAULT_MIRROR_HOSTNAME, [DEFAULT_MIRROR_HOSTNAME], ['129.21.171.98']) + mirrors = get_mirrors() + # Falls back to [a-z].pypi.python.org + assert len(mirrors) == 26 + for c in ascii_lowercase: + assert c + ".pypi.python.org" in mirrors + diff --git a/tests/test_pip.py b/tests/test_pip.py index 10f075b98..8612232cf 100644 --- a/tests/test_pip.py +++ b/tests/test_pip.py @@ -314,12 +314,18 @@ class TestPipEnvironment(TestFileEnvironment): assert self.venv_path == virtualenv_paths[0] # sanity check for id, path in zip(('venv', 'lib', 'include', 'bin'), virtualenv_paths): + #fix for virtualenv issue #306 + if hasattr(sys, "pypy_version_info") and id == 'lib': + path = os.path.join(self.venv_path, 'lib-python', pyversion) setattr(self, id+'_path', Path(path)) setattr(self, id, relpath(self.root_path, path)) assert self.venv == TestPipEnvironment.venv # sanity check - self.site_packages = self.lib/'site-packages' + if hasattr(sys, "pypy_version_info"): + self.site_packages = self.venv/'site-packages' + else: + self.site_packages = self.lib/'site-packages' self.user_base_path = self.venv_path/'user' self.user_site_path = self.venv_path/'user'/site_packages_suffix @@ -362,6 +368,10 @@ class TestPipEnvironment(TestFileEnvironment): if sitecustomize: self._add_to_sitecustomize(sitecustomize) + # Ensure that $TMPDIR exists (because we use start_clear=False, it's not created for us) + if self.temp_path and not os.path.exists(self.temp_path): + os.makedirs(self.temp_path) + def _ignore_file(self, fn): if fn.endswith('__pycache__') or fn.endswith(".pyc"): result = True @@ -444,12 +454,18 @@ class FastTestPipEnvironment(TestPipEnvironment): virtualenv_paths = virtualenv.path_locations(self.venv_path) for id, path in zip(('venv', 'lib', 'include', 'bin'), virtualenv_paths): + #fix for virtualenv issue #306 + if hasattr(sys, "pypy_version_info") and id == 'lib': + path = os.path.join(self.venv_path, 'lib-python', pyversion) setattr(self, id+'_path', Path(path)) setattr(self, id, relpath(self.root_path, path)) assert self.venv == TestPipEnvironment.venv # sanity check - self.site_packages = self.lib/'site-packages' + if hasattr(sys, "pypy_version_info"): + self.site_packages = self.venv/'site-packages' + else: + self.site_packages = self.lib/'site-packages' self.user_base_path = self.venv_path/'user' self.user_site_path = self.venv_path/'user'/'lib'/self.lib.name/'site-packages' @@ -510,6 +526,10 @@ class FastTestPipEnvironment(TestPipEnvironment): assert self.root_path.exists + # Ensure that $TMPDIR exists (because we use start_clear=False, it's not created for us) + if self.temp_path and not os.path.exists(self.temp_path): + os.makedirs(self.temp_path) + def __del__(self): pass # shutil.rmtree(str(self.root_path), ignore_errors=True) @@ -663,5 +683,5 @@ def _change_test_package_version(env, version_pkg_path): if __name__ == '__main__': - sys.stderr.write("Run pip's tests using nosetests. Requires virtualenv, ScriptTest, and nose.\n") + sys.stderr.write("Run pip's tests using nosetests. Requires virtualenv, ScriptTest, mock, and nose.\n") sys.exit(1) diff --git a/tests/test_requirements.py b/tests/test_requirements.py index 6fd8c67a5..64a88e378 100644 --- a/tests/test_requirements.py +++ b/tests/test_requirements.py @@ -121,19 +121,22 @@ def test_requirements_data_structure_implements__contains__(): assert 'pip' in requirements assert 'nose' not in requirements +@patch('os.path.normcase') @patch('pip.req.os.getcwd') @patch('pip.req.os.path.exists') @patch('pip.req.os.path.isdir') -def test_parse_editable_local(isdir_mock, exists_mock, getcwd_mock): +def test_parse_editable_local(isdir_mock, exists_mock, getcwd_mock, normcase_mock): exists_mock.return_value = isdir_mock.return_value = True - getcwd_mock.return_value = "/some/path" + # mocks needed to support path operations on windows tests + normcase_mock.return_value = getcwd_mock.return_value = "/some/path" assert_equal( parse_editable('.', 'git'), (None, 'file:///some/path', None) ) + normcase_mock.return_value = "/some/path/foo" assert_equal( parse_editable('foo', 'git'), - (None, 'file://' + os.path.join("/some/path", 'foo'), None) + (None, 'file:///some/path/foo', None) ) def test_parse_editable_default_vcs(): @@ -154,19 +157,21 @@ def test_parse_editable_vcs_extras(): ('foo[extras]', 'svn+https://foo#egg=foo[extras]', None) ) +@patch('os.path.normcase') @patch('pip.req.os.getcwd') @patch('pip.req.os.path.exists') @patch('pip.req.os.path.isdir') -def test_parse_editable_local_extras(isdir_mock, exists_mock, getcwd_mock): +def test_parse_editable_local_extras(isdir_mock, exists_mock, getcwd_mock, normcase_mock): exists_mock.return_value = isdir_mock.return_value = True - getcwd_mock.return_value = "/some/path" + normcase_mock.return_value = getcwd_mock.return_value = "/some/path" assert_equal( parse_editable('.[extras]', 'git'), (None, 'file://' + "/some/path", ('extras',)) ) + normcase_mock.return_value = "/some/path/foo" assert_equal( parse_editable('foo[bar,baz]', 'git'), - (None, 'file://' + os.path.join("/some/path", 'foo'), ('bar', 'baz')) + (None, 'file:///some/path/foo', ('bar', 'baz')) ) def test_install_local_editable_with_extras(): diff --git a/tests/test_test.py b/tests/test_test.py index a52939575..498652d95 100644 --- a/tests/test_test.py +++ b/tests/test_test.py @@ -66,3 +66,24 @@ def test_sitecustomize_not_growing_in_fast_environment(): size2 = os.stat(sc2).st_size assert size1==size2, "size before, %d != size after, %d" %(size1, size2) + +def test_tmp_dir_exists_in_env(): + """ + Test that $TMPDIR == env.temp_path and path exists, and env.assert_no_temp() passes + """ + #need these tests to ensure the assert_no_temp feature of scripttest is working + env = reset_env(use_distribute=True) + env.assert_no_temp() #this fails if env.tmp_path doesn't exist + assert env.environ['TMPDIR'] == env.temp_path + assert isdir(env.temp_path) + + +def test_tmp_dir_exists_in_fast_env(): + """ + Test that $TMPDIR == env.temp_path and path exists and env.assert_no_temp() passes (in fast env) + """ + #need these tests to ensure the assert_no_temp feature of scripttest is working + env = reset_env() + env.assert_no_temp() #this fails if env.tmp_path doesn't exist + assert env.environ['TMPDIR'] == env.temp_path + assert isdir(env.temp_path) diff --git a/tests/test_unicode.py b/tests/test_unicode.py index d9196e750..eb926494e 100644 --- a/tests/test_unicode.py +++ b/tests/test_unicode.py @@ -20,6 +20,6 @@ def test_install_package_that_emits_unicode(): env = reset_env() to_install = os.path.abspath(os.path.join(here, 'packages', 'BrokenEmitsUTF8')) - result = run_pip('install', to_install, expect_error=True) - assert '__main__.FakeError: this package designed to fail on install' in result.stdout + result = run_pip('install', to_install, expect_error=True, expect_temp=True, quiet=True) + assert 'FakeError: this package designed to fail on install' in result.stdout assert 'UnicodeDecodeError' not in result.stdout diff --git a/tests/test_uninstall.py b/tests/test_uninstall.py index 21b111710..28339a615 100644 --- a/tests/test_uninstall.py +++ b/tests/test_uninstall.py @@ -1,7 +1,9 @@ import textwrap import sys -from os.path import join, abspath +from os.path import join, abspath, normpath from tempfile import mkdtemp +from mock import Mock +from nose.tools import assert_raises from tests.test_pip import here, reset_env, run_pip, assert_all_changes, write_file, pyversion from tests.local_repos import local_repo, local_checkout @@ -16,6 +18,8 @@ def test_simple_uninstall(): env = reset_env() result = run_pip('install', 'INITools==0.2') assert join(env.site_packages, 'initools') in result.files_created, sorted(result.files_created.keys()) + #the import forces the generation of __pycache__ if the version of python supports it + env.run('python', '-c', "import initools") result2 = run_pip('uninstall', 'INITools', '-y') assert_all_changes(result, result2, [env.venv/'build', 'cache']) @@ -34,6 +38,19 @@ def test_uninstall_with_scripts(): assert_all_changes(result, result2, [env.venv/'build', 'cache']) +def test_uninstall_easy_install_after_import(): + """ + Uninstall an easy_installed package after it's been imported + + """ + env = reset_env() + result = env.run('easy_install', 'INITools==0.2', expect_stderr=True) + #the import forces the generation of __pycache__ if the version of python supports it + env.run('python', '-c', "import initools") + result2 = run_pip('uninstall', 'INITools', '-y') + assert_all_changes(result, result2, [env.venv/'build', 'cache']) + + def test_uninstall_namespace_package(): """ Uninstall a distribution with a namespace package without clobbering @@ -48,6 +65,33 @@ def test_uninstall_namespace_package(): assert join(env.site_packages, 'pd', 'find') in result2.files_deleted, sorted(result2.files_deleted.keys()) +def test_uninstall_overlapping_package(): + """ + Uninstalling a distribution that adds modules to a pre-existing package + should only remove those added modules, not the rest of the existing + package. + + See: GitHub issue #355 (pip uninstall removes things it didn't install) + """ + parent_pkg = abspath(join(here, 'packages', 'parent-0.1.tar.gz')) + child_pkg = abspath(join(here, 'packages', 'child-0.1.tar.gz')) + env = reset_env() + result1 = run_pip('install', parent_pkg, expect_error=False) + assert join(env.site_packages, 'parent') in result1.files_created, sorted(result1.files_created.keys()) + result2 = run_pip('install', child_pkg, expect_error=False) + assert join(env.site_packages, 'child') in result2.files_created, sorted(result2.files_created.keys()) + assert normpath(join(env.site_packages, 'parent/plugins/child_plugin.py')) in result2.files_created, sorted(result2.files_created.keys()) + #the import forces the generation of __pycache__ if the version of python supports it + env.run('python', '-c', "import parent.plugins.child_plugin, child") + result3 = run_pip('uninstall', '-y', 'child', expect_error=False) + assert join(env.site_packages, 'child') in result3.files_deleted, sorted(result3.files_created.keys()) + assert normpath(join(env.site_packages, 'parent/plugins/child_plugin.py')) in result3.files_deleted, sorted(result3.files_deleted.keys()) + assert join(env.site_packages, 'parent') not in result3.files_deleted, sorted(result3.files_deleted.keys()) + # Additional check: uninstalling 'child' should return things to the + # previous state, without unintended side effects. + assert_all_changes(result2, result3, []) + + def test_uninstall_console_scripts(): """ Test uninstalling a package with more files (console_script entry points, extra directories). @@ -155,3 +199,14 @@ def test_uninstall_as_egg(): result2 = run_pip('uninstall', 'FSPkg', '-y', expect_error=True) assert_all_changes(result, result2, [env.venv/'build', 'cache']) + +def test_uninstallpathset_no_paths(): + """ + Test UninstallPathSet raises installation error when there are no paths (uses mocking) + + """ + from pip.req import UninstallPathSet + from pip.exceptions import InstallationError + mock_dist = Mock(project_name='pkg') + uninstall_set = UninstallPathSet(mock_dist) + assert_raises(InstallationError, uninstall_set.remove) diff --git a/tests/test_upgrade.py b/tests/test_upgrade.py index 795e68f85..24449aec0 100644 --- a/tests/test_upgrade.py +++ b/tests/test_upgrade.py @@ -207,8 +207,8 @@ def test_upgrade_vcs_req_with_no_dists_found(): def test_upgrade_vcs_req_with_dist_found(): """It can upgrade a VCS requirement that has distributions on the index.""" reset_env() - req = "%s#egg=virtualenv" % local_checkout( - "git+git://github.com/pypa/virtualenv@c21fef2c2d53cf19f49bcc37f9c058a33fb50499") + # TODO(pnasrat) Using local_checkout fails on windows - oddness with the test path urls/git. + req = "%s#egg=virtualenv" % "git+git://github.com/pypa/virtualenv@c21fef2c2d53cf19f49bcc37f9c058a33fb50499" run_pip("install", req) result = run_pip("install", "-U", req) assert not "pypi.python.org" in result.stdout, result.stdout diff --git a/tests/test_user_site.py b/tests/test_user_site.py index 4e997692e..2d1eec924 100644 --- a/tests/test_user_site.py +++ b/tests/test_user_site.py @@ -6,7 +6,15 @@ import sys from os.path import abspath, join, curdir, isdir, isfile from nose import SkipTest from tests.local_repos import local_checkout -from tests.test_pip import here, reset_env, run_pip, pyversion +from tests.test_pip import here, reset_env, run_pip, pyversion, assert_all_changes + + +patch_dist_in_site_packages = """ + def dist_in_site_packages(dist): + return False + import pip + pip.util.dist_in_site_packages=dist_in_site_packages +""" def test_install_curdir_usersite_fails_in_old_python(): @@ -27,6 +35,10 @@ class Tests_UserSite: # --user only works on 2.6 or higher if sys.version_info < (2, 6): raise SkipTest() + # --user option is broken in pypy + if hasattr(sys, "pypy_version_info"): + raise SkipTest() + def test_reset_env_system_site_packages_usersite(self): """ @@ -58,9 +70,6 @@ class Tests_UserSite: """ Test installing current directory ('.') into usersite after installing distribute """ - # FIXME distutils --user option seems to be broken in pypy - if hasattr(sys, "pypy_version_info"): - raise SkipTest() env = reset_env(use_distribute=True, system_site_packages=True) result = run_pip('install', '--user', '-e', '%s#egg=initools-dev' % @@ -72,9 +81,6 @@ class Tests_UserSite: """ Test installing current directory ('.') into usersite """ - # FIXME distutils --user option seems to be broken in pypy - if hasattr(sys, "pypy_version_info"): - raise SkipTest() env = reset_env(use_distribute=True, system_site_packages=True) run_from = abspath(join(here, 'packages', 'FSPkg')) result = run_pip('install', '--user', curdir, cwd=run_from, expect_error=False) @@ -111,15 +117,21 @@ class Tests_UserSite: assert not isfile(initools_v3_file), initools_v3_file - def test_install_user_conflict_in_site(self): + def test_install_user_conflict_in_globalsite(self): """ - Test user install with conflict in site ignores site and installs to usersite + Test user install with conflict in global site ignores site and installs to usersite """ - #the test framework only supports testing using virtualenvs - #this test will use a --system_site_packages virtualenv to achieve the conflict scenario. + # the test framework only supports testing using virtualenvs + # the sys.path ordering for virtualenvs with --system-site-packages is this: virtualenv-site, user-site, global-site + # this test will use 2 modifications to simulate the user-site/global-site relationship + # 1) a monkey patch which will make it appear INITools==0.2 is not in in the virtualenv site + # if we don't patch this, pip will return an installation error: "Will not install to the usersite because it will lack sys.path precedence..." + # 2) adding usersite to PYTHONPATH, so usersite as sys.path precedence over the virtualenv site + + env = reset_env(system_site_packages=True, sitecustomize=patch_dist_in_site_packages) + env.environ["PYTHONPATH"] = env.root_path / env.user_site - env = reset_env(system_site_packages=True) result1 = run_pip('install', 'INITools==0.2') result2 = run_pip('install', '--user', 'INITools==0.1') @@ -141,14 +153,14 @@ class Tests_UserSite: Test user install with conflict in globalsite and usersite ignores global site and updates usersite. """ - #the test framework only supports testing using virtualenvs - #this test will use a --system_site_packages virtualenv to achieve the conflict scenario. - - env = reset_env(system_site_packages=True) + # the test framework only supports testing using virtualenvs. + # the sys.path ordering for virtualenvs with --system-site-packages is this: virtualenv-site, user-site, global-site. + # this test will use 2 modifications to simulate the user-site/global-site relationship + # 1) a monkey patch which will make it appear INITools==0.2 is not in in the virtualenv site + # if we don't patch this, pip will return an installation error: "Will not install to the usersite because it will lack sys.path precedence..." + # 2) adding usersite to PYTHONPATH, so usersite as sys.path precedence over the virtualenv site - # the sys.path ordering for virtualenvs with --system-site-packages is this: virtualenv site, usersite, global site - # given this ordering you *can't* use it to simulate the scenario for this test. - # this test will add the usersite to PYTHONPATH to simulate the desired ordering + env = reset_env(system_site_packages=True, sitecustomize=patch_dist_in_site_packages) env.environ["PYTHONPATH"] = env.root_path / env.user_site result1 = run_pip('install', 'INITools==0.2') @@ -166,3 +178,48 @@ class Tests_UserSite: initools_folder = env.root_path / env.site_packages / 'initools' assert isdir(egg_info_folder) assert isdir(initools_folder) + + + def test_install_user_in_global_virtualenv_with_conflict_fails(self): + """ + Test user install in --system-site-packages virtualenv with conflict in site fails. + """ + env = reset_env(system_site_packages=True) + result1 = run_pip('install', 'INITools==0.2') + result2 = run_pip('install', '--user', 'INITools==0.1', expect_error=True) + resultp = env.run('python', '-c', "import pkg_resources; print(pkg_resources.get_distribution('initools').location)") + dist_location = resultp.stdout.strip() + assert result2.stdout.startswith("Will not install to the user site because it will lack sys.path precedence to %s in %s" + %('INITools', dist_location)), result2.stdout + + + def test_uninstall_from_usersite(self): + """ + Test uninstall from usersite + """ + env = reset_env(system_site_packages=True) + result1 = run_pip('install', '--user', 'INITools==0.3') + result2 = run_pip('uninstall', '-y', 'INITools') + assert_all_changes(result1, result2, [env.venv/'build', 'cache']) + + + def test_uninstall_editable_from_usersite(self): + """ + Test uninstall editable local user install + """ + env = reset_env(use_distribute=True, system_site_packages=True) + + #install + to_install = abspath(join(here, 'packages', 'FSPkg')) + result1 = run_pip('install', '--user', '-e', to_install, expect_error=False) + egg_link = env.user_site/'FSPkg.egg-link' + assert egg_link in result1.files_created, str(result1.stdout) + + #uninstall + result2 = run_pip('uninstall', '-y', 'FSPkg') + assert not isfile(env.root_path / egg_link) + + assert_all_changes(result1, result2, + [env.venv/'build', 'cache', env.user_site/'easy-install.pth']) + + diff --git a/tests/test_util.py b/tests/test_util.py new file mode 100644 index 000000000..2907cc067 --- /dev/null +++ b/tests/test_util.py @@ -0,0 +1,140 @@ +""" +util tests + +""" +import os +import pkg_resources +from mock import Mock +from nose.tools import eq_ +from tests.path import Path +from pip.util import egg_link_path + + +class Tests_EgglinkPath: + "util.egg_link_path() tests" + + def setup(self): + + project = 'foo' + + self.mock_dist = Mock(project_name=project) + self.site_packages = 'SITE_PACKAGES' + self.user_site = 'USER_SITE' + self.user_site_egglink = os.path.join(self.user_site,'%s.egg-link' % project) + self.site_packages_egglink = os.path.join(self.site_packages,'%s.egg-link' % project) + + #patches + from pip import util + self.old_site_packages = util.site_packages + self.mock_site_packages = util.site_packages = 'SITE_PACKAGES' + self.old_running_under_virtualenv = util.running_under_virtualenv + self.mock_running_under_virtualenv = util.running_under_virtualenv = Mock() + self.old_virtualenv_no_global = util.virtualenv_no_global + self.mock_virtualenv_no_global = util.virtualenv_no_global = Mock() + self.old_user_site = util.user_site + self.mock_user_site = util.user_site = self.user_site + from os import path + self.old_isfile = path.isfile + self.mock_isfile = path.isfile = Mock() + + + def teardown(self): + from pip import util + util.site_packages = self.old_site_packages + util.running_under_virtualenv = self.old_running_under_virtualenv + util.virtualenv_no_global = self.old_virtualenv_no_global + util.user_site = self.old_user_site + from os import path + path.isfile = self.old_isfile + + + def eggLinkInUserSite(self,egglink): + return egglink==self.user_site_egglink + + def eggLinkInSitePackages(self,egglink): + return egglink==self.site_packages_egglink + + ######################### + ## egglink in usersite ## + ######################### + def test_egglink_in_usersite_notvenv(self): + self.mock_virtualenv_no_global.return_value = False + self.mock_running_under_virtualenv.return_value = False + self.mock_isfile.side_effect = self.eggLinkInUserSite + eq_(egg_link_path(self.mock_dist), self.user_site_egglink) + + def test_egglink_in_usersite_venv_noglobal(self): + self.mock_virtualenv_no_global.return_value = True + self.mock_running_under_virtualenv.return_value = True + self.mock_isfile.side_effect = self.eggLinkInUserSite + eq_(egg_link_path(self.mock_dist), None) + + def test_egglink_in_usersite_venv_global(self): + self.mock_virtualenv_no_global.return_value = False + self.mock_running_under_virtualenv.return_value = True + self.mock_isfile.side_effect = self.eggLinkInUserSite + eq_(egg_link_path(self.mock_dist), self.user_site_egglink) + + ######################### + ## egglink in sitepkgs ## + ######################### + def test_egglink_in_sitepkgs_notvenv(self): + self.mock_virtualenv_no_global.return_value = False + self.mock_running_under_virtualenv.return_value = False + self.mock_isfile.side_effect = self.eggLinkInSitePackages + eq_(egg_link_path(self.mock_dist), self.site_packages_egglink) + + def test_egglink_in_sitepkgs_venv_noglobal(self): + self.mock_virtualenv_no_global.return_value = True + self.mock_running_under_virtualenv.return_value = True + self.mock_isfile.side_effect = self.eggLinkInSitePackages + eq_(egg_link_path(self.mock_dist), self.site_packages_egglink) + + def test_egglink_in_sitepkgs_venv_global(self): + self.mock_virtualenv_no_global.return_value = False + self.mock_running_under_virtualenv.return_value = True + self.mock_isfile.side_effect = self.eggLinkInSitePackages + eq_(egg_link_path(self.mock_dist), self.site_packages_egglink) + + #################################### + ## egglink in usersite & sitepkgs ## + #################################### + def test_egglink_in_both_notvenv(self): + self.mock_virtualenv_no_global.return_value = False + self.mock_running_under_virtualenv.return_value = False + self.mock_isfile.return_value = True + eq_(egg_link_path(self.mock_dist), self.user_site_egglink) + + def test_egglink_in_both_venv_noglobal(self): + self.mock_virtualenv_no_global.return_value = True + self.mock_running_under_virtualenv.return_value = True + self.mock_isfile.return_value = True + eq_(egg_link_path(self.mock_dist), self.site_packages_egglink) + + def test_egglink_in_both_venv_global(self): + self.mock_virtualenv_no_global.return_value = False + self.mock_running_under_virtualenv.return_value = True + self.mock_isfile.return_value = True + eq_(egg_link_path(self.mock_dist), self.site_packages_egglink) + + ################ + ## no egglink ## + ################ + def test_noegglink_in_sitepkgs_notvenv(self): + self.mock_virtualenv_no_global.return_value = False + self.mock_running_under_virtualenv.return_value = False + self.mock_isfile.return_value = False + eq_(egg_link_path(self.mock_dist), None) + + def test_noegglink_in_sitepkgs_venv_noglobal(self): + self.mock_virtualenv_no_global.return_value = True + self.mock_running_under_virtualenv.return_value = True + self.mock_isfile.return_value = False + eq_(egg_link_path(self.mock_dist), None) + + def test_noegglink_in_sitepkgs_venv_global(self): + self.mock_virtualenv_no_global.return_value = False + self.mock_running_under_virtualenv.return_value = True + self.mock_isfile.return_value = False + eq_(egg_link_path(self.mock_dist), None) + diff --git a/tests/test_vcs_git.py b/tests/test_vcs_git.py index 206e80512..b27c12d8b 100644 --- a/tests/test_vcs_git.py +++ b/tests/test_vcs_git.py @@ -1,4 +1,6 @@ +import sys from mock import patch +from nose import SkipTest from pip.vcs.git import Git from tests.test_pip import (reset_env, run_pip, _create_test_package,) @@ -87,6 +89,9 @@ def test_check_submodule_addition(): Submodules are pulled in on install and updated on upgrade. """ + # TODO(pnasrat) fix all helpers to do right things with paths on windows. + if sys.platform == 'win32': + raise SkipTest() env = reset_env() module_path, submodule_path = _create_test_package_with_submodule(env) |