Skip to content

Commit

Permalink
Merge pull request #7891 from deveshks/ignore-uninstall-error-if-easy…
Browse files Browse the repository at this point in the history
…-install-missing

Don't fail uninstallation if easy-install.pth doesn't exist
  • Loading branch information
pradyunsg authored Mar 30, 2020
2 parents c388315 + 0d2954d commit 57cb941
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 5 deletions.
1 change: 1 addition & 0 deletions news/7856.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Uninstallation no longer fails on trying to remove non-existent files.
13 changes: 8 additions & 5 deletions src/pip/_internal/req/req_uninstall.py
Original file line number Diff line number Diff line change
Expand Up @@ -585,11 +585,6 @@ def from_dist(cls, dist):
class UninstallPthEntries(object):
def __init__(self, pth_file):
# type: (str) -> None
if not os.path.isfile(pth_file):
raise UninstallationError(
"Cannot remove entries from nonexistent file {}".format(
pth_file)
)
self.file = pth_file
self.entries = set() # type: Set[str]
self._saved_lines = None # type: Optional[List[bytes]]
Expand All @@ -613,6 +608,14 @@ def add(self, entry):
def remove(self):
# type: () -> None
logger.debug('Removing pth entries from %s:', self.file)

# If the file doesn't exist, log a warning and return
if not os.path.isfile(self.file):
logger.warning(
"Cannot remove entries from nonexistent file {}".format(
self.file)
)
return
with open(self.file, 'rb') as fh:
# windows uses '\r\n' with py3k, but uses '\n' with py2.x
lines = fh.readlines()
Expand Down
47 changes: 47 additions & 0 deletions tests/functional/test_uninstall.py
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,53 @@ def test_uninstall_editable_and_pip_install(script, data):
assert "FSPkg" not in {p["name"] for p in json.loads(list_result2.stdout)}


def test_uninstall_editable_and_pip_install_easy_install_remove(script, data):
"""Try uninstall after pip install -e after pip install
and removing easy-install.pth"""
# SETUPTOOLS_SYS_PATH_TECHNIQUE=raw removes the assumption that `-e`
# installs are always higher priority than regular installs.
# This becomes the default behavior in setuptools 25.
script.environ['SETUPTOOLS_SYS_PATH_TECHNIQUE'] = 'raw'

# Rename easy-install.pth to pip-test.pth
easy_install_pth = join(script.site_packages_path, 'easy-install.pth')
pip_test_pth = join(script.site_packages_path, 'pip-test.pth')
os.rename(easy_install_pth, pip_test_pth)

# Install FSPkg
pkg_path = data.packages.joinpath("FSPkg")
script.pip('install', '-e', '.',
expect_stderr=True, cwd=pkg_path)

# Rename easy-install.pth to pip-test-fspkg.pth
pip_test_fspkg_pth = join(script.site_packages_path, 'pip-test-fspkg.pth')
os.rename(easy_install_pth, pip_test_fspkg_pth)

# Confirm that FSPkg is installed
list_result = script.pip('list', '--format=json')
assert {"name": "FSPkg", "version": "0.1.dev0"} \
in json.loads(list_result.stdout)

# Remove pip-test-fspkg.pth
os.remove(pip_test_fspkg_pth)

# Uninstall will fail with given warning
uninstall = script.pip('uninstall', 'FSPkg', '-y')
assert "Cannot remove entries from nonexistent file" in uninstall.stderr

assert join(
script.site_packages, 'FSPkg.egg-link'
) in uninstall.files_deleted, list(uninstall.files_deleted.keys())

# Confirm that FSPkg is uninstalled
list_result = script.pip('list', '--format=json')
assert {"name": "FSPkg", "version": "0.1.dev0"} \
not in json.loads(list_result.stdout)

# Rename pip-test.pth back to easy-install.pth
os.rename(pip_test_pth, easy_install_pth)


def test_uninstall_ignores_missing_packages(script, data):
"""Uninstall of a non existent package prints a warning and exits cleanly
"""
Expand Down

0 comments on commit 57cb941

Please sign in to comment.