comparison lib/python3.8/site-packages/pip/_internal/commands/show.py @ 0:9e54283cc701 draft

"planemo upload commit d12c32a45bcd441307e632fca6d9af7d60289d44"
author guerler
date Mon, 27 Jul 2020 03:47:31 -0400
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:9e54283cc701
1 # The following comment should be removed at some point in the future.
2 # mypy: disallow-untyped-defs=False
3
4 from __future__ import absolute_import
5
6 import logging
7 import os
8 from email.parser import FeedParser
9
10 from pip._vendor import pkg_resources
11 from pip._vendor.packaging.utils import canonicalize_name
12
13 from pip._internal.cli.base_command import Command
14 from pip._internal.cli.status_codes import ERROR, SUCCESS
15 from pip._internal.utils.misc import write_output
16
17 logger = logging.getLogger(__name__)
18
19
20 class ShowCommand(Command):
21 """
22 Show information about one or more installed packages.
23
24 The output is in RFC-compliant mail header format.
25 """
26
27 usage = """
28 %prog [options] <package> ..."""
29 ignore_require_venv = True
30
31 def __init__(self, *args, **kw):
32 super(ShowCommand, self).__init__(*args, **kw)
33 self.cmd_opts.add_option(
34 '-f', '--files',
35 dest='files',
36 action='store_true',
37 default=False,
38 help='Show the full list of installed files for each package.')
39
40 self.parser.insert_option_group(0, self.cmd_opts)
41
42 def run(self, options, args):
43 if not args:
44 logger.warning('ERROR: Please provide a package name or names.')
45 return ERROR
46 query = args
47
48 results = search_packages_info(query)
49 if not print_results(
50 results, list_files=options.files, verbose=options.verbose):
51 return ERROR
52 return SUCCESS
53
54
55 def search_packages_info(query):
56 """
57 Gather details from installed distributions. Print distribution name,
58 version, location, and installed files. Installed files requires a
59 pip generated 'installed-files.txt' in the distributions '.egg-info'
60 directory.
61 """
62 installed = {}
63 for p in pkg_resources.working_set:
64 installed[canonicalize_name(p.project_name)] = p
65
66 query_names = [canonicalize_name(name) for name in query]
67 missing = sorted(
68 [name for name, pkg in zip(query, query_names) if pkg not in installed]
69 )
70 if missing:
71 logger.warning('Package(s) not found: %s', ', '.join(missing))
72
73 def get_requiring_packages(package_name):
74 canonical_name = canonicalize_name(package_name)
75 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()]
80 ]
81
82 for dist in [installed[pkg] for pkg in query_names if pkg in installed]:
83 package = {
84 'name': dist.project_name,
85 'version': dist.version,
86 'location': dist.location,
87 'requires': [dep.project_name for dep in dist.requires()],
88 'required_by': get_requiring_packages(dist.project_name)
89 }
90 file_list = None
91 metadata = None
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 = [l.split(',')[0] for l 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)
140 yield package
141
142
143 def print_results(distributions, list_files=False, verbose=False):
144 """
145 Print the informations from installed distributions found.
146 """
147 results_printed = False
148 for i, dist in enumerate(distributions):
149 results_printed = True
150 if i > 0:
151 write_output("---")
152
153 write_output("Name: %s", dist.get('name', ''))
154 write_output("Version: %s", dist.get('version', ''))
155 write_output("Summary: %s", dist.get('summary', ''))
156 write_output("Home-page: %s", dist.get('home-page', ''))
157 write_output("Author: %s", dist.get('author', ''))
158 write_output("Author-email: %s", dist.get('author-email', ''))
159 write_output("License: %s", dist.get('license', ''))
160 write_output("Location: %s", dist.get('location', ''))
161 write_output("Requires: %s", ', '.join(dist.get('requires', [])))
162 write_output("Required-by: %s", ', '.join(dist.get('required_by', [])))
163
164 if verbose:
165 write_output("Metadata-Version: %s",
166 dist.get('metadata-version', ''))
167 write_output("Installer: %s", dist.get('installer', ''))
168 write_output("Classifiers:")
169 for classifier in dist.get('classifiers', []):
170 write_output(" %s", classifier)
171 write_output("Entry-points:")
172 for entry in dist.get('entry_points', []):
173 write_output(" %s", entry.strip())
174 if list_files:
175 write_output("Files:")
176 for line in dist.get('files', []):
177 write_output(" %s", line.strip())
178 if "files" not in dist:
179 write_output("Cannot locate installed-files.txt")
180 return results_printed