Skip to content

Commit df04434

Browse files
committed
Remove pkg_resources usages from 'pip show'
1 parent 3b8c83d commit df04434

File tree

2 files changed

+59
-65
lines changed

2 files changed

+59
-65
lines changed

src/pip/_internal/commands/show.py

Lines changed: 57 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1+
import csv
12
import logging
23
import os
3-
from email.parser import FeedParser
44
from optparse import Values
5-
from typing import Dict, Iterator, List
5+
from typing import Dict, Iterator, List, Optional
66

7-
from pip._vendor import pkg_resources
87
from pip._vendor.packaging.utils import canonicalize_name
98

109
from pip._internal.cli.base_command import Command
1110
from pip._internal.cli.status_codes import ERROR, SUCCESS
11+
from pip._internal.metadata import BaseDistribution, get_default_environment
1212
from pip._internal.utils.misc import write_output
1313

1414
logger = logging.getLogger(__name__)
@@ -58,85 +58,77 @@ def search_packages_info(query):
5858
pip generated 'installed-files.txt' in the distributions '.egg-info'
5959
directory.
6060
"""
61-
installed = {}
62-
for p in pkg_resources.working_set:
63-
installed[canonicalize_name(p.project_name)] = p
61+
env = get_default_environment()
6462

63+
installed = {
64+
dist.canonical_name: dist
65+
for dist in env.iter_distributions()
66+
}
6567
query_names = [canonicalize_name(name) for name in query]
6668
missing = sorted(
6769
[name for name, pkg in zip(query, query_names) if pkg not in installed]
6870
)
6971
if missing:
7072
logger.warning('Package(s) not found: %s', ', '.join(missing))
7173

72-
def get_requiring_packages(package_name):
74+
def get_requiring_packages(canonical_name):
7375
# type: (str) -> List[str]
74-
canonical_name = canonicalize_name(package_name)
7576
return [
76-
pkg.project_name for pkg in pkg_resources.working_set
77-
if canonical_name in
78-
[canonicalize_name(required.name) for required in
79-
pkg.requires()]
77+
dist.canonical_name
78+
for dist in env.iter_distributions()
79+
if canonical_name in {
80+
canonicalize_name(d.name) for d in dist.iter_dependencies()
81+
}
8082
]
8183

82-
for dist in [installed[pkg] for pkg in query_names if pkg in installed]:
84+
def _files_from_record(dist: BaseDistribution) -> Optional[Iterator[str]]:
85+
try:
86+
text = dist.read_text('RECORD')
87+
except FileNotFoundError:
88+
return None
89+
return (row[0] for row in csv.reader(text.splitlines()))
90+
91+
def _files_from_installed_files(dist: BaseDistribution) -> Optional[Iterator[str]]:
92+
try:
93+
text = dist.read_text('installed-files.txt')
94+
except FileNotFoundError:
95+
return None
96+
return (p for p in text.splitlines(keepends=False) if p)
97+
98+
for query_name in query_names:
99+
try:
100+
dist = installed[query_name]
101+
except KeyError:
102+
continue
83103
package = {
84104
'name': dist.project_name,
85105
'version': dist.version,
86106
'location': dist.location,
87-
'requires': [dep.project_name for dep in dist.requires()],
88-
'required_by': get_requiring_packages(dist.project_name)
107+
'requires': [req.nameroject_name for req in dist.iter_dependencies()],
108+
'required_by': get_requiring_packages(dist.canonical_name),
109+
'installer': dist.installer,
110+
'metadata-version': dist.metadata_version,
111+
'classifiers': dist.metadata.get_all('Classifiers'),
89112
}
90-
file_list = None
91-
metadata = ''
92-
if isinstance(dist, pkg_resources.DistInfoDistribution):
93-
# RECORDs should be part of .dist-info metadatas
94-
if dist.has_metadata('RECORD'):
95-
lines = dist.get_metadata_lines('RECORD')
96-
paths = [line.split(',')[0] for line in lines]
97-
paths = [os.path.join(dist.location, p) for p in paths]
98-
file_list = [os.path.relpath(p, dist.location) for p in paths]
99-
100-
if dist.has_metadata('METADATA'):
101-
metadata = dist.get_metadata('METADATA')
102-
else:
103-
# Otherwise use pip's log for .egg-info's
104-
if dist.has_metadata('installed-files.txt'):
105-
paths = dist.get_metadata_lines('installed-files.txt')
106-
paths = [os.path.join(dist.egg_info, p) for p in paths]
107-
file_list = [os.path.relpath(p, dist.location) for p in paths]
108-
109-
if dist.has_metadata('PKG-INFO'):
110-
metadata = dist.get_metadata('PKG-INFO')
111-
112-
if dist.has_metadata('entry_points.txt'):
113-
entry_points = dist.get_metadata_lines('entry_points.txt')
114-
package['entry_points'] = entry_points
115-
116-
if dist.has_metadata('INSTALLER'):
117-
for line in dist.get_metadata_lines('INSTALLER'):
118-
if line.strip():
119-
package['installer'] = line.strip()
120-
break
121-
122-
# @todo: Should pkg_resources.Distribution have a
123-
# `get_pkg_info` method?
124-
feed_parser = FeedParser()
125-
feed_parser.feed(metadata)
126-
pkg_info_dict = feed_parser.close()
127-
for key in ('metadata-version', 'summary',
128-
'home-page', 'author', 'author-email', 'license'):
129-
package[key] = pkg_info_dict.get(key)
130-
131-
# It looks like FeedParser cannot deal with repeated headers
132-
classifiers = []
133-
for line in metadata.splitlines():
134-
if line.startswith('Classifier: '):
135-
classifiers.append(line[len('Classifier: '):])
136-
package['classifiers'] = classifiers
137-
138-
if file_list:
139-
package['files'] = sorted(file_list)
113+
114+
for key in ('Summary', 'Home-page', 'Author', 'Author-email', 'License'):
115+
package[key] = dist.metadata[key]
116+
117+
try:
118+
entry_points_text = dist.read_text('entry_points.txt')
119+
package['entry_points'] = entry_points_text.splitlines(keepends=False)
120+
except FileNotFoundError:
121+
pass
122+
if dist.installer:
123+
package['installer'] = dist.installer
124+
125+
files = (
126+
_files_from_record(dist) or
127+
_files_from_installed_files(dist.read_text('installed-files.txt'))
128+
)
129+
if files:
130+
package['files'] = sorted(os.path.relpath(p, dist.location) for p in files)
131+
140132
yield package
141133

142134

src/pip/_internal/metadata/pkg_resources.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ def in_usersite(self) -> bool:
6868
return misc.dist_in_usersite(self._dist)
6969

7070
def read_text(self, name: str) -> str:
71+
if not self._dist.has_metadata(name):
72+
raise FileNotFoundError(name)
7173
return self._dist.get_metadata(name)
7274

7375
def iter_entry_points(self) -> Iterable[BaseEntryPoint]:

0 commit comments

Comments
 (0)