Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
keewenaw
GitHub Repository: keewenaw/ethereum-wallet-cracker
Path: blob/main/test/lib/python3.9/site-packages/pip/_internal/commands/cache.py
4804 views
1
import os
2
import textwrap
3
from optparse import Values
4
from typing import Any, List
5
6
import pip._internal.utils.filesystem as filesystem
7
from pip._internal.cli.base_command import Command
8
from pip._internal.cli.status_codes import ERROR, SUCCESS
9
from pip._internal.exceptions import CommandError, PipError
10
from pip._internal.utils.logging import getLogger
11
12
logger = getLogger(__name__)
13
14
15
class CacheCommand(Command):
16
"""
17
Inspect and manage pip's wheel cache.
18
19
Subcommands:
20
21
- dir: Show the cache directory.
22
- info: Show information about the cache.
23
- list: List filenames of packages stored in the cache.
24
- remove: Remove one or more package from the cache.
25
- purge: Remove all items from the cache.
26
27
``<pattern>`` can be a glob expression or a package name.
28
"""
29
30
ignore_require_venv = True
31
usage = """
32
%prog dir
33
%prog info
34
%prog list [<pattern>] [--format=[human, abspath]]
35
%prog remove <pattern>
36
%prog purge
37
"""
38
39
def add_options(self) -> None:
40
41
self.cmd_opts.add_option(
42
"--format",
43
action="store",
44
dest="list_format",
45
default="human",
46
choices=("human", "abspath"),
47
help="Select the output format among: human (default) or abspath",
48
)
49
50
self.parser.insert_option_group(0, self.cmd_opts)
51
52
def run(self, options: Values, args: List[str]) -> int:
53
handlers = {
54
"dir": self.get_cache_dir,
55
"info": self.get_cache_info,
56
"list": self.list_cache_items,
57
"remove": self.remove_cache_items,
58
"purge": self.purge_cache,
59
}
60
61
if not options.cache_dir:
62
logger.error("pip cache commands can not function since cache is disabled.")
63
return ERROR
64
65
# Determine action
66
if not args or args[0] not in handlers:
67
logger.error(
68
"Need an action (%s) to perform.",
69
", ".join(sorted(handlers)),
70
)
71
return ERROR
72
73
action = args[0]
74
75
# Error handling happens here, not in the action-handlers.
76
try:
77
handlers[action](options, args[1:])
78
except PipError as e:
79
logger.error(e.args[0])
80
return ERROR
81
82
return SUCCESS
83
84
def get_cache_dir(self, options: Values, args: List[Any]) -> None:
85
if args:
86
raise CommandError("Too many arguments")
87
88
logger.info(options.cache_dir)
89
90
def get_cache_info(self, options: Values, args: List[Any]) -> None:
91
if args:
92
raise CommandError("Too many arguments")
93
94
num_http_files = len(self._find_http_files(options))
95
num_packages = len(self._find_wheels(options, "*"))
96
97
http_cache_location = self._cache_dir(options, "http")
98
wheels_cache_location = self._cache_dir(options, "wheels")
99
http_cache_size = filesystem.format_directory_size(http_cache_location)
100
wheels_cache_size = filesystem.format_directory_size(wheels_cache_location)
101
102
message = (
103
textwrap.dedent(
104
"""
105
Package index page cache location: {http_cache_location}
106
Package index page cache size: {http_cache_size}
107
Number of HTTP files: {num_http_files}
108
Wheels location: {wheels_cache_location}
109
Wheels size: {wheels_cache_size}
110
Number of wheels: {package_count}
111
"""
112
)
113
.format(
114
http_cache_location=http_cache_location,
115
http_cache_size=http_cache_size,
116
num_http_files=num_http_files,
117
wheels_cache_location=wheels_cache_location,
118
package_count=num_packages,
119
wheels_cache_size=wheels_cache_size,
120
)
121
.strip()
122
)
123
124
logger.info(message)
125
126
def list_cache_items(self, options: Values, args: List[Any]) -> None:
127
if len(args) > 1:
128
raise CommandError("Too many arguments")
129
130
if args:
131
pattern = args[0]
132
else:
133
pattern = "*"
134
135
files = self._find_wheels(options, pattern)
136
if options.list_format == "human":
137
self.format_for_human(files)
138
else:
139
self.format_for_abspath(files)
140
141
def format_for_human(self, files: List[str]) -> None:
142
if not files:
143
logger.info("Nothing cached.")
144
return
145
146
results = []
147
for filename in files:
148
wheel = os.path.basename(filename)
149
size = filesystem.format_file_size(filename)
150
results.append(f" - {wheel} ({size})")
151
logger.info("Cache contents:\n")
152
logger.info("\n".join(sorted(results)))
153
154
def format_for_abspath(self, files: List[str]) -> None:
155
if not files:
156
return
157
158
results = []
159
for filename in files:
160
results.append(filename)
161
162
logger.info("\n".join(sorted(results)))
163
164
def remove_cache_items(self, options: Values, args: List[Any]) -> None:
165
if len(args) > 1:
166
raise CommandError("Too many arguments")
167
168
if not args:
169
raise CommandError("Please provide a pattern")
170
171
files = self._find_wheels(options, args[0])
172
173
no_matching_msg = "No matching packages"
174
if args[0] == "*":
175
# Only fetch http files if no specific pattern given
176
files += self._find_http_files(options)
177
else:
178
# Add the pattern to the log message
179
no_matching_msg += ' for pattern "{}"'.format(args[0])
180
181
if not files:
182
logger.warning(no_matching_msg)
183
184
for filename in files:
185
os.unlink(filename)
186
logger.verbose("Removed %s", filename)
187
logger.info("Files removed: %s", len(files))
188
189
def purge_cache(self, options: Values, args: List[Any]) -> None:
190
if args:
191
raise CommandError("Too many arguments")
192
193
return self.remove_cache_items(options, ["*"])
194
195
def _cache_dir(self, options: Values, subdir: str) -> str:
196
return os.path.join(options.cache_dir, subdir)
197
198
def _find_http_files(self, options: Values) -> List[str]:
199
http_dir = self._cache_dir(options, "http")
200
return filesystem.find_files(http_dir, "*")
201
202
def _find_wheels(self, options: Values, pattern: str) -> List[str]:
203
wheel_dir = self._cache_dir(options, "wheels")
204
205
# The wheel filename format, as specified in PEP 427, is:
206
# {distribution}-{version}(-{build})?-{python}-{abi}-{platform}.whl
207
#
208
# Additionally, non-alphanumeric values in the distribution are
209
# normalized to underscores (_), meaning hyphens can never occur
210
# before `-{version}`.
211
#
212
# Given that information:
213
# - If the pattern we're given contains a hyphen (-), the user is
214
# providing at least the version. Thus, we can just append `*.whl`
215
# to match the rest of it.
216
# - If the pattern we're given doesn't contain a hyphen (-), the
217
# user is only providing the name. Thus, we append `-*.whl` to
218
# match the hyphen before the version, followed by anything else.
219
#
220
# PEP 427: https://www.python.org/dev/peps/pep-0427/
221
pattern = pattern + ("*.whl" if "-" in pattern else "-*.whl")
222
223
return filesystem.find_files(wheel_dir, pattern)
224
225