mirror of
https://github.com/pypa/pip
synced 2023-12-13 21:30:23 +01:00
177 lines
5.5 KiB
Python
177 lines
5.5 KiB
Python
import os
|
|
|
|
import pytest
|
|
from mock import Mock
|
|
|
|
import pip._internal.req.req_uninstall
|
|
from pip._internal.req.req_uninstall import (
|
|
UninstallPathSet, compact, compress_for_output_listing,
|
|
compress_for_rename, uninstallation_paths,
|
|
)
|
|
from tests.lib import create_file
|
|
|
|
|
|
# Pretend all files are local, so UninstallPathSet accepts files in the tmpdir,
|
|
# outside the virtualenv
|
|
def mock_is_local(path):
|
|
return True
|
|
|
|
|
|
def test_uninstallation_paths():
|
|
class dist(object):
|
|
def get_metadata_lines(self, record):
|
|
return ['file.py,,',
|
|
'file.pyc,,',
|
|
'file.so,,',
|
|
'nopyc.py']
|
|
location = ''
|
|
|
|
d = dist()
|
|
|
|
paths = list(uninstallation_paths(d))
|
|
|
|
expected = ['file.py',
|
|
'file.pyc',
|
|
'file.pyo',
|
|
'file.so',
|
|
'nopyc.py',
|
|
'nopyc.pyc',
|
|
'nopyc.pyo']
|
|
|
|
assert paths == expected
|
|
|
|
# Avoid an easy 'unique generator' bug
|
|
paths2 = list(uninstallation_paths(d))
|
|
|
|
assert paths2 == paths
|
|
|
|
|
|
def test_compressed_listing(tmpdir):
|
|
def in_tmpdir(paths):
|
|
li = []
|
|
for path in paths:
|
|
li.append(
|
|
str(os.path.join(tmpdir, path.replace("/", os.path.sep)))
|
|
)
|
|
return li
|
|
|
|
sample = in_tmpdir([
|
|
"lib/mypkg.dist-info/METADATA",
|
|
"lib/mypkg.dist-info/PKG-INFO",
|
|
"lib/mypkg/would_be_removed.txt",
|
|
"lib/mypkg/would_be_skipped.skip.txt",
|
|
"lib/mypkg/__init__.py",
|
|
"lib/mypkg/my_awesome_code.py",
|
|
"lib/mypkg/__pycache__/my_awesome_code-magic.pyc",
|
|
"lib/mypkg/support/support_file.py",
|
|
"lib/mypkg/support/more_support.py",
|
|
"lib/mypkg/support/would_be_skipped.skip.py",
|
|
"lib/mypkg/support/__pycache__/support_file-magic.pyc",
|
|
"lib/random_other_place/file_without_a_dot_pyc",
|
|
"bin/mybin",
|
|
])
|
|
|
|
# Create the required files
|
|
for fname in sample:
|
|
create_file(fname, "random blub")
|
|
|
|
# Remove the files to be skipped from the paths
|
|
sample = [path for path in sample if ".skip." not in path]
|
|
|
|
expected_remove = in_tmpdir([
|
|
"bin/mybin",
|
|
"lib/mypkg.dist-info/*",
|
|
"lib/mypkg/*",
|
|
"lib/random_other_place/file_without_a_dot_pyc",
|
|
])
|
|
|
|
expected_skip = in_tmpdir([
|
|
"lib/mypkg/would_be_skipped.skip.txt",
|
|
"lib/mypkg/support/would_be_skipped.skip.py",
|
|
])
|
|
|
|
expected_rename = in_tmpdir([
|
|
"bin/",
|
|
"lib/mypkg.dist-info/",
|
|
"lib/mypkg/would_be_removed.txt",
|
|
"lib/mypkg/__init__.py",
|
|
"lib/mypkg/my_awesome_code.py",
|
|
"lib/mypkg/__pycache__/",
|
|
"lib/mypkg/support/support_file.py",
|
|
"lib/mypkg/support/more_support.py",
|
|
"lib/mypkg/support/__pycache__/",
|
|
"lib/random_other_place/",
|
|
])
|
|
|
|
will_remove, will_skip = compress_for_output_listing(sample)
|
|
will_rename = compress_for_rename(sample)
|
|
assert sorted(expected_skip) == sorted(compact(will_skip))
|
|
assert sorted(expected_remove) == sorted(compact(will_remove))
|
|
assert sorted(expected_rename) == sorted(compact(will_rename))
|
|
|
|
|
|
class TestUninstallPathSet(object):
|
|
def test_add(self, tmpdir, monkeypatch):
|
|
monkeypatch.setattr(pip._internal.req.req_uninstall, 'is_local',
|
|
mock_is_local)
|
|
# Fix case for windows tests
|
|
file_extant = os.path.normcase(os.path.join(tmpdir, 'foo'))
|
|
file_nonexistent = os.path.normcase(
|
|
os.path.join(tmpdir, 'nonexistent'))
|
|
with open(file_extant, 'w'):
|
|
pass
|
|
|
|
ups = UninstallPathSet(dist=Mock())
|
|
assert ups.paths == set()
|
|
ups.add(file_extant)
|
|
assert ups.paths == {file_extant}
|
|
|
|
ups.add(file_nonexistent)
|
|
assert ups.paths == {file_extant}
|
|
|
|
@pytest.mark.skipif("sys.platform == 'win32'")
|
|
def test_add_symlink(self, tmpdir, monkeypatch):
|
|
monkeypatch.setattr(pip._internal.req.req_uninstall, 'is_local',
|
|
mock_is_local)
|
|
f = os.path.join(tmpdir, 'foo')
|
|
with open(f, 'w'):
|
|
pass
|
|
foo_link = os.path.join(tmpdir, 'foo_link')
|
|
os.symlink(f, foo_link)
|
|
|
|
ups = UninstallPathSet(dist=Mock())
|
|
ups.add(foo_link)
|
|
assert ups.paths == {foo_link}
|
|
|
|
def test_compact_shorter_path(self, monkeypatch):
|
|
monkeypatch.setattr(pip._internal.req.req_uninstall, 'is_local',
|
|
lambda p: True)
|
|
monkeypatch.setattr('os.path.exists', lambda p: True)
|
|
# This deals with nt/posix path differences
|
|
short_path = os.path.normcase(os.path.abspath(
|
|
os.path.join(os.path.sep, 'path')))
|
|
ups = UninstallPathSet(dist=Mock())
|
|
ups.add(short_path)
|
|
ups.add(os.path.join(short_path, 'longer'))
|
|
assert compact(ups.paths) == {short_path}
|
|
|
|
@pytest.mark.skipif("sys.platform == 'win32'")
|
|
def test_detect_symlink_dirs(self, monkeypatch, tmpdir):
|
|
monkeypatch.setattr(pip._internal.req.req_uninstall, 'is_local',
|
|
lambda p: True)
|
|
|
|
# construct 2 paths:
|
|
# tmpdir/dir/file
|
|
# tmpdir/dirlink/file (where dirlink is a link to dir)
|
|
d = tmpdir.join('dir')
|
|
d.mkdir()
|
|
dlink = tmpdir.join('dirlink')
|
|
os.symlink(d, dlink)
|
|
d.join('file').touch()
|
|
path1 = str(d.join('file'))
|
|
path2 = str(dlink.join('file'))
|
|
|
|
ups = UninstallPathSet(dist=Mock())
|
|
ups.add(path1)
|
|
ups.add(path2)
|
|
assert ups.paths == {path1}
|