Skip to content

Commit 5acd20b

Browse files
committed
Create custom get_distribution function
1 parent 1521fd8 commit 5acd20b

File tree

6 files changed

+56
-21
lines changed

6 files changed

+56
-21
lines changed

src/pip/_internal/commands/search.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from pip._internal.network.xmlrpc import PipXmlrpcTransport
2323
from pip._internal.utils.compat import get_terminal_size
2424
from pip._internal.utils.logging import indent_log
25-
from pip._internal.utils.misc import write_output
25+
from pip._internal.utils.misc import get_distribution, write_output
2626

2727
logger = logging.getLogger(__name__)
2828

@@ -127,7 +127,7 @@ def print_results(hits, name_column_width=None, terminal_width=None):
127127
try:
128128
write_output(line)
129129
if name in installed_packages:
130-
dist = pkg_resources.get_distribution(name)
130+
dist = get_distribution(name)
131131
with indent_log():
132132
if dist.version == latest:
133133
write_output('INSTALLED: %s (latest)', dist.version)

src/pip/_internal/req/req_install.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
display_path,
4141
dist_in_site_packages,
4242
dist_in_usersite,
43+
get_distribution,
4344
get_installed_version,
4445
hide_url,
4546
redact_auth_from_url,
@@ -421,21 +422,23 @@ def check_if_exists(self, use_user_site):
421422
if self.req is None:
422423
return
423424

424-
# Canonicalize requirement name to use normalized
425-
# names while searching for already installed packages
426-
no_marker = Requirement(str(self.req))
427-
no_marker.marker = None
428-
no_marker.name = canonicalize_name(no_marker.name)
429425
# get_distribution() will resolve the entire list of requirements
430426
# anyway, and we've already determined that we need the requirement
431427
# in question, so strip the marker so that we don't try to
432428
# evaluate it.
429+
no_marker = Requirement(str(self.req))
430+
no_marker.marker = None
431+
432+
# pkg_resources uses the canonical name to look up packages, but
433+
# the name passed passed to get_distribution is not canonicalized
434+
# so we have to explicitly convert it to a canonical name
435+
no_marker.name = canonicalize_name(no_marker.name)
433436
try:
434437
self.satisfied_by = pkg_resources.get_distribution(str(no_marker))
435438
except pkg_resources.DistributionNotFound:
436439
return
437440
except pkg_resources.VersionConflict:
438-
existing_dist = pkg_resources.get_distribution(
441+
existing_dist = get_distribution(
439442
self.req.name
440443
)
441444
if use_user_site:
@@ -668,13 +671,11 @@ def uninstall(self, auto_confirm=False, verbose=False):
668671
669672
"""
670673
assert self.req
671-
try:
672-
dist = pkg_resources.get_distribution(self.req.name)
673-
except pkg_resources.DistributionNotFound:
674+
dist = get_distribution(self.req.name)
675+
if not dist:
674676
logger.warning("Skipping %s as it is not installed.", self.name)
675677
return None
676-
else:
677-
logger.info('Found existing installation: %s', dist)
678+
logger.info('Found existing installation: %s', dist)
678679

679680
uninstalled_pathset = UninstallPathSet.from_dist(dist)
680681
uninstalled_pathset.remove(auto_confirm, verbose)

src/pip/_internal/self_outdated_check.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import os.path
1111
import sys
1212

13-
from pip._vendor import pkg_resources
1413
from pip._vendor.packaging import version as packaging_version
1514
from pip._vendor.six import ensure_binary
1615

@@ -25,6 +24,7 @@
2524
)
2625
from pip._internal.utils.misc import (
2726
ensure_dir,
27+
get_distribution,
2828
get_installed_version,
2929
redact_auth_from_url,
3030
)
@@ -149,11 +149,10 @@ def was_installed_by_pip(pkg):
149149
This is used not to display the upgrade message when pip is in fact
150150
installed by system package manager, such as dnf on Fedora.
151151
"""
152-
try:
153-
dist = pkg_resources.get_distribution(pkg)
154-
return "pip" == get_installer(dist)
155-
except pkg_resources.DistributionNotFound:
152+
dist = get_distribution(pkg)
153+
if not dist:
156154
return False
155+
return "pip" == get_installer(dist)
157156

158157

159158
def pip_self_version_check(session, options):

src/pip/_internal/utils/misc.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from pip._vendor import pkg_resources
2121
# NOTE: retrying is not annotated in typeshed as on 2017-07-17, which is
2222
# why we ignore the type on this import.
23+
from pip._vendor.packaging.utils import canonicalize_name
2324
from pip._vendor.retrying import retry # type: ignore
2425
from pip._vendor.six import PY2, text_type
2526
from pip._vendor.six.moves import input, map, zip_longest
@@ -480,6 +481,40 @@ def user_test(d):
480481
]
481482

482483

484+
def search_distribution(req_name):
485+
486+
# Canonicalize the name before searching in the list of
487+
# installed distributions and also while creating the package
488+
# dictionary to get the Distribution object
489+
req_name = canonicalize_name(req_name)
490+
packages = get_installed_distributions(skip=())
491+
pkg_dict = {canonicalize_name(p.key): p for p in packages}
492+
return pkg_dict.get(req_name)
493+
494+
495+
def get_distribution(req_name):
496+
"""Given a requirement name, return the installed Distribution object"""
497+
498+
# Search the distribution by looking through the working set
499+
dist = search_distribution(req_name)
500+
501+
# If distribution could not be found, call working_set.require
502+
# to update the working set, and try to find the distribution
503+
# again This might happen for e.g. when you install a package
504+
# twice, once in editable mode and again in normal mode. Now
505+
# when you want to run uninstall twice the package gets removed
506+
# from the working set in the first uninstall which removes the
507+
# normal package, so we have to populate the working set so that
508+
# the packages gets picked up and is successfully uninstalled
509+
# the second time too.
510+
if not dist:
511+
try:
512+
pkg_resources.working_set.require(req_name)
513+
except pkg_resources.DistributionNotFound:
514+
return None
515+
return search_distribution(req_name)
516+
517+
483518
def egg_link_path(dist):
484519
# type: (Distribution) -> Optional[str]
485520
"""

tests/functional/test_search.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ def test_latest_prerelease_install_message(caplog, monkeypatch):
168168

169169
dist = pretend.stub(version="1.0.0")
170170
get_dist = pretend.call_recorder(lambda x: dist)
171-
monkeypatch.setattr("pip._vendor.pkg_resources.get_distribution", get_dist)
171+
monkeypatch.setattr("pip._internal.commands.search.get_distribution",
172+
get_dist)
172173
with caplog.at_level(logging.INFO):
173174
print_results(hits)
174175

tests/unit/test_self_check_outdated.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import pretend
88
import pytest
99
from mock import patch
10-
from pip._vendor import pkg_resources
1110

1211
from pip._internal import self_outdated_check
1312
from pip._internal.models.candidate import InstallationCandidate
@@ -172,7 +171,7 @@ def test_pip_self_version_check(monkeypatch, stored_time, installed_ver,
172171
pretend.call_recorder(lambda *a, **kw: None))
173172
monkeypatch.setattr(logger, 'debug',
174173
pretend.call_recorder(lambda s, exc_info=None: None))
175-
monkeypatch.setattr(pkg_resources, 'get_distribution',
174+
monkeypatch.setattr(self_outdated_check, 'get_distribution',
176175
lambda name: MockDistribution(installer))
177176

178177
fake_state = pretend.stub(

0 commit comments

Comments
 (0)