Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hhhrrrttt222111
GitHub Repository: hhhrrrttt222111/Dorkify
Path: blob/master/venv/Lib/site-packages/pip/_internal/exceptions.py
811 views
1
"""Exceptions used throughout package"""
2
3
# The following comment should be removed at some point in the future.
4
# mypy: disallow-untyped-defs=False
5
6
from __future__ import absolute_import
7
8
from itertools import chain, groupby, repeat
9
10
from pip._vendor.six import iteritems
11
12
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
13
14
if MYPY_CHECK_RUNNING:
15
from typing import Optional
16
from pip._vendor.pkg_resources import Distribution
17
from pip._internal.req.req_install import InstallRequirement
18
19
20
class PipError(Exception):
21
"""Base pip exception"""
22
23
24
class ConfigurationError(PipError):
25
"""General exception in configuration"""
26
27
28
class InstallationError(PipError):
29
"""General exception during installation"""
30
31
32
class UninstallationError(PipError):
33
"""General exception during uninstallation"""
34
35
36
class NoneMetadataError(PipError):
37
"""
38
Raised when accessing "METADATA" or "PKG-INFO" metadata for a
39
pip._vendor.pkg_resources.Distribution object and
40
`dist.has_metadata('METADATA')` returns True but
41
`dist.get_metadata('METADATA')` returns None (and similarly for
42
"PKG-INFO").
43
"""
44
45
def __init__(self, dist, metadata_name):
46
# type: (Distribution, str) -> None
47
"""
48
:param dist: A Distribution object.
49
:param metadata_name: The name of the metadata being accessed
50
(can be "METADATA" or "PKG-INFO").
51
"""
52
self.dist = dist
53
self.metadata_name = metadata_name
54
55
def __str__(self):
56
# type: () -> str
57
# Use `dist` in the error message because its stringification
58
# includes more information, like the version and location.
59
return (
60
'None {} metadata found for distribution: {}'.format(
61
self.metadata_name, self.dist,
62
)
63
)
64
65
66
class DistributionNotFound(InstallationError):
67
"""Raised when a distribution cannot be found to satisfy a requirement"""
68
69
70
class RequirementsFileParseError(InstallationError):
71
"""Raised when a general error occurs parsing a requirements file line."""
72
73
74
class BestVersionAlreadyInstalled(PipError):
75
"""Raised when the most up-to-date version of a package is already
76
installed."""
77
78
79
class BadCommand(PipError):
80
"""Raised when virtualenv or a command is not found"""
81
82
83
class CommandError(PipError):
84
"""Raised when there is an error in command-line arguments"""
85
86
87
class PreviousBuildDirError(PipError):
88
"""Raised when there's a previous conflicting build directory"""
89
90
91
class InvalidWheelFilename(InstallationError):
92
"""Invalid wheel filename."""
93
94
95
class UnsupportedWheel(InstallationError):
96
"""Unsupported wheel."""
97
98
99
class HashErrors(InstallationError):
100
"""Multiple HashError instances rolled into one for reporting"""
101
102
def __init__(self):
103
self.errors = []
104
105
def append(self, error):
106
self.errors.append(error)
107
108
def __str__(self):
109
lines = []
110
self.errors.sort(key=lambda e: e.order)
111
for cls, errors_of_cls in groupby(self.errors, lambda e: e.__class__):
112
lines.append(cls.head)
113
lines.extend(e.body() for e in errors_of_cls)
114
if lines:
115
return '\n'.join(lines)
116
117
def __nonzero__(self):
118
return bool(self.errors)
119
120
def __bool__(self):
121
return self.__nonzero__()
122
123
124
class HashError(InstallationError):
125
"""
126
A failure to verify a package against known-good hashes
127
128
:cvar order: An int sorting hash exception classes by difficulty of
129
recovery (lower being harder), so the user doesn't bother fretting
130
about unpinned packages when he has deeper issues, like VCS
131
dependencies, to deal with. Also keeps error reports in a
132
deterministic order.
133
:cvar head: A section heading for display above potentially many
134
exceptions of this kind
135
:ivar req: The InstallRequirement that triggered this error. This is
136
pasted on after the exception is instantiated, because it's not
137
typically available earlier.
138
139
"""
140
req = None # type: Optional[InstallRequirement]
141
head = ''
142
143
def body(self):
144
"""Return a summary of me for display under the heading.
145
146
This default implementation simply prints a description of the
147
triggering requirement.
148
149
:param req: The InstallRequirement that provoked this error, with
150
its link already populated by the resolver's _populate_link().
151
152
"""
153
return ' {}'.format(self._requirement_name())
154
155
def __str__(self):
156
return '{}\n{}'.format(self.head, self.body())
157
158
def _requirement_name(self):
159
"""Return a description of the requirement that triggered me.
160
161
This default implementation returns long description of the req, with
162
line numbers
163
164
"""
165
return str(self.req) if self.req else 'unknown package'
166
167
168
class VcsHashUnsupported(HashError):
169
"""A hash was provided for a version-control-system-based requirement, but
170
we don't have a method for hashing those."""
171
172
order = 0
173
head = ("Can't verify hashes for these requirements because we don't "
174
"have a way to hash version control repositories:")
175
176
177
class DirectoryUrlHashUnsupported(HashError):
178
"""A hash was provided for a version-control-system-based requirement, but
179
we don't have a method for hashing those."""
180
181
order = 1
182
head = ("Can't verify hashes for these file:// requirements because they "
183
"point to directories:")
184
185
186
class HashMissing(HashError):
187
"""A hash was needed for a requirement but is absent."""
188
189
order = 2
190
head = ('Hashes are required in --require-hashes mode, but they are '
191
'missing from some requirements. Here is a list of those '
192
'requirements along with the hashes their downloaded archives '
193
'actually had. Add lines like these to your requirements files to '
194
'prevent tampering. (If you did not enable --require-hashes '
195
'manually, note that it turns on automatically when any package '
196
'has a hash.)')
197
198
def __init__(self, gotten_hash):
199
"""
200
:param gotten_hash: The hash of the (possibly malicious) archive we
201
just downloaded
202
"""
203
self.gotten_hash = gotten_hash
204
205
def body(self):
206
# Dodge circular import.
207
from pip._internal.utils.hashes import FAVORITE_HASH
208
209
package = None
210
if self.req:
211
# In the case of URL-based requirements, display the original URL
212
# seen in the requirements file rather than the package name,
213
# so the output can be directly copied into the requirements file.
214
package = (self.req.original_link if self.req.original_link
215
# In case someone feeds something downright stupid
216
# to InstallRequirement's constructor.
217
else getattr(self.req, 'req', None))
218
return ' {} --hash={}:{}'.format(package or 'unknown package',
219
FAVORITE_HASH,
220
self.gotten_hash)
221
222
223
class HashUnpinned(HashError):
224
"""A requirement had a hash specified but was not pinned to a specific
225
version."""
226
227
order = 3
228
head = ('In --require-hashes mode, all requirements must have their '
229
'versions pinned with ==. These do not:')
230
231
232
class HashMismatch(HashError):
233
"""
234
Distribution file hash values don't match.
235
236
:ivar package_name: The name of the package that triggered the hash
237
mismatch. Feel free to write to this after the exception is raise to
238
improve its error message.
239
240
"""
241
order = 4
242
head = ('THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS '
243
'FILE. If you have updated the package versions, please update '
244
'the hashes. Otherwise, examine the package contents carefully; '
245
'someone may have tampered with them.')
246
247
def __init__(self, allowed, gots):
248
"""
249
:param allowed: A dict of algorithm names pointing to lists of allowed
250
hex digests
251
:param gots: A dict of algorithm names pointing to hashes we
252
actually got from the files under suspicion
253
"""
254
self.allowed = allowed
255
self.gots = gots
256
257
def body(self):
258
return ' {}:\n{}'.format(self._requirement_name(),
259
self._hash_comparison())
260
261
def _hash_comparison(self):
262
"""
263
Return a comparison of actual and expected hash values.
264
265
Example::
266
267
Expected sha256 abcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcde
268
or 123451234512345123451234512345123451234512345
269
Got bcdefbcdefbcdefbcdefbcdefbcdefbcdefbcdefbcdef
270
271
"""
272
def hash_then_or(hash_name):
273
# For now, all the decent hashes have 6-char names, so we can get
274
# away with hard-coding space literals.
275
return chain([hash_name], repeat(' or'))
276
277
lines = []
278
for hash_name, expecteds in iteritems(self.allowed):
279
prefix = hash_then_or(hash_name)
280
lines.extend((' Expected {} {}'.format(next(prefix), e))
281
for e in expecteds)
282
lines.append(' Got {}\n'.format(
283
self.gots[hash_name].hexdigest()))
284
return '\n'.join(lines)
285
286
287
class UnsupportedPythonVersion(InstallationError):
288
"""Unsupported python version according to Requires-Python package
289
metadata."""
290
291
292
class ConfigurationFileCouldNotBeLoaded(ConfigurationError):
293
"""When there are errors while loading a configuration file
294
"""
295
296
def __init__(self, reason="could not be loaded", fname=None, error=None):
297
super(ConfigurationFileCouldNotBeLoaded, self).__init__(error)
298
self.reason = reason
299
self.fname = fname
300
self.error = error
301
302
def __str__(self):
303
if self.fname is not None:
304
message_part = " in {}.".format(self.fname)
305
else:
306
assert self.error is not None
307
message_part = ".\n{}\n".format(self.error.message)
308
return "Configuration file {}{}".format(self.reason, message_part)
309
310