1
1
import logging
2
2
import sys
3
3
4
+ from pip ._vendor .contextlib2 import suppress
4
5
from pip ._vendor .packaging .specifiers import InvalidSpecifier , SpecifierSet
5
6
from pip ._vendor .packaging .utils import canonicalize_name
6
7
from pip ._vendor .packaging .version import Version
7
8
8
9
from pip ._internal .exceptions import HashError , MetadataInconsistent
10
+ from pip ._internal .network .lazy_wheel import dist_from_wheel_url
9
11
from pip ._internal .req .constructors import (
10
12
install_req_from_editable ,
11
13
install_req_from_line ,
12
14
)
13
15
from pip ._internal .req .req_install import InstallRequirement
16
+ from pip ._internal .utils .logging import indent_log
14
17
from pip ._internal .utils .misc import dist_is_editable , normalize_version_info
15
18
from pip ._internal .utils .packaging import get_requires_python
16
19
from pip ._internal .utils .typing import MYPY_CHECK_RUNNING
@@ -197,11 +200,21 @@ def _prepare_abstract_distribution(self):
197
200
# type: () -> AbstractDistribution
198
201
raise NotImplementedError ("Override in subclass" )
199
202
200
- def _prepare (self ):
203
+ def _check_metadata_consistency (self ):
201
204
# type: () -> None
202
- if self ._dist is not None :
203
- return
205
+ """Check for consistency of project name and version of dist."""
206
+ # TODO: (Longer term) Rather than abort, reject this candidate
207
+ # and backtrack. This would need resolvelib support.
208
+ dist = self ._dist # type: Distribution
209
+ name = canonicalize_name (dist .project_name )
210
+ if self ._name is not None and self ._name != name :
211
+ raise MetadataInconsistent (self ._ireq , "name" , dist .project_name )
212
+ version = dist .parsed_version
213
+ if self ._version is not None and self ._version != version :
214
+ raise MetadataInconsistent (self ._ireq , "version" , dist .version )
204
215
216
+ def _prepare (self ):
217
+ # type: () -> None
205
218
try :
206
219
abstract_dist = self ._prepare_abstract_distribution ()
207
220
except HashError as e :
@@ -210,24 +223,36 @@ def _prepare(self):
210
223
211
224
self ._dist = abstract_dist .get_pkg_resources_distribution ()
212
225
assert self ._dist is not None , "Distribution already installed"
226
+ self ._check_metadata_consistency ()
213
227
214
- # TODO: (Longer term) Rather than abort, reject this candidate
215
- # and backtrack. This would need resolvelib support.
216
- name = canonicalize_name (self ._dist .project_name )
217
- if self ._name is not None and self ._name != name :
218
- raise MetadataInconsistent (
219
- self ._ireq , "name" , self ._dist .project_name ,
220
- )
221
- version = self ._dist .parsed_version
222
- if self ._version is not None and self ._version != version :
223
- raise MetadataInconsistent (
224
- self ._ireq , "version" , self ._dist .version ,
225
- )
228
+ def _fetch_metadata (self ):
229
+ # type: () -> None
230
+ """Fetch metadata, using lazy wheel if possible."""
231
+ preparer = self ._factory .preparer
232
+ use_lazy_wheel = self ._factory .use_lazy_wheel
233
+ remote_wheel = self ._link .is_wheel and not self ._link .is_file
234
+ if use_lazy_wheel and remote_wheel and not preparer .require_hashes :
235
+ assert self ._name is not None
236
+ logger .info ('Collecting %s' , self ._ireq .req or self ._ireq )
237
+ # TODO: Rename to HTTPRangeRequestUnsupported (GH-8584)
238
+ # If RuntimeError is raised, fallback to self._prepare
239
+ with indent_log (), suppress (RuntimeError ):
240
+ logger .info (
241
+ 'Obtaining dependency information from %s %s' ,
242
+ self ._name , self ._version ,
243
+ )
244
+ url = self ._link .url .split ('#' , 1 )[0 ]
245
+ session = preparer .downloader ._session
246
+ self ._dist = dist_from_wheel_url (self ._name , url , session )
247
+ self ._check_metadata_consistency ()
248
+ if self ._dist is None :
249
+ self ._prepare ()
226
250
227
251
@property
228
252
def dist (self ):
229
253
# type: () -> Distribution
230
- self ._prepare ()
254
+ if self ._dist is None :
255
+ self ._fetch_metadata ()
231
256
return self ._dist
232
257
233
258
def _get_requires_python_specifier (self ):
0 commit comments