pex 2.61.0__py2.py3-none-any.whl → 2.62.0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pex might be problematic. Click here for more details.
- pex/cache/dirs.py +3 -8
- pex/cli/commands/pip/wheel.py +1 -1
- pex/docs/html/_pagefind/fragment/en_19d749c.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_358f3c1.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/{en_7f63cbe.pf_fragment → en_4a62b9a.pf_fragment} +0 -0
- pex/docs/html/_pagefind/fragment/{en_9ce19f0.pf_fragment → en_5c1928c.pf_fragment} +0 -0
- pex/docs/html/_pagefind/fragment/en_a6b0f05.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_a77f515.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_ed65506.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/{en_cd3f4ce.pf_fragment → en_f5aab8f.pf_fragment} +0 -0
- pex/docs/html/_pagefind/index/en_856ae3c.pf_index +0 -0
- pex/docs/html/_pagefind/pagefind-entry.json +1 -1
- pex/docs/html/_pagefind/pagefind.en_92d55346bf.pf_meta +0 -0
- pex/docs/html/_static/documentation_options.js +1 -1
- pex/docs/html/api/vars.html +5 -5
- pex/docs/html/buildingpex.html +5 -5
- pex/docs/html/genindex.html +5 -5
- pex/docs/html/index.html +5 -5
- pex/docs/html/recipes.html +5 -5
- pex/docs/html/scie.html +5 -5
- pex/docs/html/search.html +5 -5
- pex/docs/html/whatispex.html +5 -5
- pex/resolve/locker.py +6 -51
- pex/resolve/locker_patches.py +123 -209
- pex/resolve/lockfile/create.py +26 -12
- pex/resolve/lockfile/targets.py +292 -26
- pex/resolve/pre_resolved_resolver.py +21 -12
- pex/resolve/requirement_configuration.py +15 -8
- pex/resolve/target_system.py +512 -119
- pex/resolver.py +269 -118
- pex/venv/venv_pex.py +1 -1
- pex/version.py +1 -1
- {pex-2.61.0.dist-info → pex-2.62.0.dist-info}/METADATA +4 -4
- {pex-2.61.0.dist-info → pex-2.62.0.dist-info}/RECORD +39 -39
- pex/docs/html/_pagefind/fragment/en_5c93d32.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_6262b88.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_d1987a6.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_d7a44fe.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_f6e4117.pf_fragment +0 -0
- pex/docs/html/_pagefind/index/en_3ad4a26.pf_index +0 -0
- pex/docs/html/_pagefind/pagefind.en_50edc69c3c.pf_meta +0 -0
- {pex-2.61.0.dist-info → pex-2.62.0.dist-info}/WHEEL +0 -0
- {pex-2.61.0.dist-info → pex-2.62.0.dist-info}/entry_points.txt +0 -0
- {pex-2.61.0.dist-info → pex-2.62.0.dist-info}/licenses/LICENSE +0 -0
- {pex-2.61.0.dist-info → pex-2.62.0.dist-info}/pylock/pylock.toml +0 -0
- {pex-2.61.0.dist-info → pex-2.62.0.dist-info}/top_level.txt +0 -0
pex/resolver.py
CHANGED
|
@@ -46,6 +46,7 @@ from pex.pep_427 import InstallableType, WheelError, install_wheel_chroot
|
|
|
46
46
|
from pex.pep_503 import ProjectName
|
|
47
47
|
from pex.pip.download_observer import DownloadObserver
|
|
48
48
|
from pex.pip.installation import get_pip
|
|
49
|
+
from pex.pip.local_project import digest_local_project
|
|
49
50
|
from pex.pip.tool import PackageIndexConfiguration
|
|
50
51
|
from pex.pip.version import PipVersionValue
|
|
51
52
|
from pex.requirements import LocalProjectRequirement, URLRequirement
|
|
@@ -149,9 +150,9 @@ class DownloadTarget(object):
|
|
|
149
150
|
return self.target.id
|
|
150
151
|
|
|
151
152
|
|
|
152
|
-
def
|
|
153
|
-
# type: (Optional[Iterable[
|
|
154
|
-
return tuple(OrderedSet(
|
|
153
|
+
def _uniqued_download_requests(requests=None):
|
|
154
|
+
# type: (Optional[Iterable[DownloadRequest]]) -> Tuple[DownloadRequest, ...]
|
|
155
|
+
return tuple(OrderedSet(requests)) if requests is not None else ()
|
|
155
156
|
|
|
156
157
|
|
|
157
158
|
@attr.s(frozen=True)
|
|
@@ -238,12 +239,9 @@ class PipLogManager(object):
|
|
|
238
239
|
|
|
239
240
|
|
|
240
241
|
@attr.s(frozen=True)
|
|
241
|
-
class
|
|
242
|
-
|
|
242
|
+
class _DownloadSession(object):
|
|
243
|
+
requests = attr.ib(converter=_uniqued_download_requests) # type: Tuple[DownloadRequest, ...]
|
|
243
244
|
direct_requirements = attr.ib() # type: Iterable[ParsedRequirement]
|
|
244
|
-
requirements = attr.ib(default=None) # type: Optional[Iterable[str]]
|
|
245
|
-
requirement_files = attr.ib(default=None) # type: Optional[Iterable[str]]
|
|
246
|
-
constraint_files = attr.ib(default=None) # type: Optional[Iterable[str]]
|
|
247
245
|
allow_prereleases = attr.ib(default=False) # type: bool
|
|
248
246
|
transitive = attr.ib(default=True) # type: bool
|
|
249
247
|
package_index_configuration = attr.ib(default=None) # type: Optional[PackageIndexConfiguration]
|
|
@@ -260,14 +258,17 @@ class DownloadRequest(object):
|
|
|
260
258
|
# type: () -> Iterator[BuildRequest]
|
|
261
259
|
for requirement in self.direct_requirements:
|
|
262
260
|
if isinstance(requirement, LocalProjectRequirement):
|
|
263
|
-
for
|
|
264
|
-
yield BuildRequest.
|
|
265
|
-
target=
|
|
261
|
+
for request in self.requests:
|
|
262
|
+
yield BuildRequest.for_directory(
|
|
263
|
+
target=request.target,
|
|
264
|
+
source_path=requirement.path,
|
|
265
|
+
resolver=self.resolver,
|
|
266
|
+
pip_version=self.pip_version,
|
|
266
267
|
)
|
|
267
268
|
|
|
268
269
|
def download_distributions(self, dest=None, max_parallel_jobs=None):
|
|
269
270
|
# type: (...) -> List[DownloadResult]
|
|
270
|
-
if not self.
|
|
271
|
+
if not self.requests or not any(request.has_requirements for request in self.requests):
|
|
271
272
|
# Nothing to resolve.
|
|
272
273
|
return []
|
|
273
274
|
|
|
@@ -275,48 +276,32 @@ class DownloadRequest(object):
|
|
|
275
276
|
prefix="resolver_download.", dir=safe_mkdir(CacheDir.DOWNLOADS.path(".tmp"))
|
|
276
277
|
)
|
|
277
278
|
|
|
278
|
-
log_manager = PipLogManager.create(
|
|
279
|
+
log_manager = PipLogManager.create(
|
|
280
|
+
self.pip_log,
|
|
281
|
+
download_targets=tuple(request.download_target for request in self.requests),
|
|
282
|
+
)
|
|
279
283
|
if self.pip_log and not self.pip_log.user_specified:
|
|
280
284
|
TRACER.log(
|
|
281
285
|
"Preserving `pip download` log at {log_path}".format(log_path=self.pip_log.path),
|
|
282
286
|
V=ENV.PEX_VERBOSE,
|
|
283
287
|
)
|
|
284
288
|
|
|
285
|
-
requirement_config = RequirementConfiguration(
|
|
286
|
-
requirements=self.requirements,
|
|
287
|
-
requirement_files=self.requirement_files,
|
|
288
|
-
constraint_files=self.constraint_files,
|
|
289
|
-
)
|
|
290
|
-
network_configuration = (
|
|
291
|
-
self.package_index_configuration.network_configuration
|
|
292
|
-
if self.package_index_configuration
|
|
293
|
-
else None
|
|
294
|
-
)
|
|
295
|
-
subdirectory_by_filename = {} # type: Dict[str, str]
|
|
296
|
-
for parsed_requirement in requirement_config.parse_requirements(network_configuration):
|
|
297
|
-
if not isinstance(parsed_requirement, URLRequirement):
|
|
298
|
-
continue
|
|
299
|
-
subdirectory = parsed_requirement.subdirectory
|
|
300
|
-
if subdirectory:
|
|
301
|
-
subdirectory_by_filename[parsed_requirement.filename] = subdirectory
|
|
302
|
-
|
|
303
289
|
spawn_download = functools.partial(
|
|
304
290
|
self._spawn_download,
|
|
305
291
|
resolved_dists_dir=dest,
|
|
306
292
|
log_manager=log_manager,
|
|
307
|
-
subdirectory_by_filename=subdirectory_by_filename,
|
|
308
293
|
)
|
|
309
294
|
with TRACER.timed(
|
|
310
295
|
"Resolving for:\n {}".format(
|
|
311
|
-
"\n ".join(
|
|
296
|
+
"\n ".join(request.render_description() for request in self.requests)
|
|
312
297
|
)
|
|
313
298
|
):
|
|
314
299
|
try:
|
|
315
300
|
return list(
|
|
316
301
|
execute_parallel(
|
|
317
|
-
inputs=self.
|
|
302
|
+
inputs=self.requests,
|
|
318
303
|
spawn_func=spawn_download,
|
|
319
|
-
error_handler=Raise[
|
|
304
|
+
error_handler=Raise[DownloadRequest, DownloadResult](Unsatisfiable),
|
|
320
305
|
max_jobs=max_parallel_jobs,
|
|
321
306
|
)
|
|
322
307
|
)
|
|
@@ -325,13 +310,31 @@ class DownloadRequest(object):
|
|
|
325
310
|
|
|
326
311
|
def _spawn_download(
|
|
327
312
|
self,
|
|
328
|
-
|
|
313
|
+
request, # type: DownloadRequest
|
|
329
314
|
resolved_dists_dir, # type: str
|
|
330
315
|
log_manager, # type: PipLogManager
|
|
331
|
-
subdirectory_by_filename, # type: Mapping[str, str]
|
|
332
316
|
):
|
|
333
317
|
# type: (...) -> SpawnedJob[DownloadResult]
|
|
334
318
|
|
|
319
|
+
requirement_config = RequirementConfiguration(
|
|
320
|
+
requirements=request.requirements,
|
|
321
|
+
requirement_files=request.requirement_files,
|
|
322
|
+
constraint_files=request.constraint_files,
|
|
323
|
+
)
|
|
324
|
+
network_configuration = (
|
|
325
|
+
self.package_index_configuration.network_configuration
|
|
326
|
+
if self.package_index_configuration
|
|
327
|
+
else None
|
|
328
|
+
)
|
|
329
|
+
subdirectory_by_filename = {} # type: Dict[str, str]
|
|
330
|
+
for parsed_requirement in requirement_config.parse_requirements(network_configuration):
|
|
331
|
+
if not isinstance(parsed_requirement, URLRequirement):
|
|
332
|
+
continue
|
|
333
|
+
subdirectory = parsed_requirement.subdirectory
|
|
334
|
+
if subdirectory:
|
|
335
|
+
subdirectory_by_filename[parsed_requirement.filename] = subdirectory
|
|
336
|
+
|
|
337
|
+
download_target = request.download_target
|
|
335
338
|
download_dir = os.path.join(resolved_dists_dir, download_target.id(complete=True))
|
|
336
339
|
observer = (
|
|
337
340
|
self.observer.observe_download(
|
|
@@ -354,9 +357,9 @@ class DownloadRequest(object):
|
|
|
354
357
|
),
|
|
355
358
|
).spawn_download_distributions(
|
|
356
359
|
download_dir=download_dir,
|
|
357
|
-
requirements=
|
|
358
|
-
requirement_files=
|
|
359
|
-
constraint_files=
|
|
360
|
+
requirements=request.requirements,
|
|
361
|
+
requirement_files=request.requirement_files,
|
|
362
|
+
constraint_files=request.constraint_files,
|
|
360
363
|
allow_prereleases=self.allow_prereleases,
|
|
361
364
|
transitive=self.transitive,
|
|
362
365
|
target=target,
|
|
@@ -396,7 +399,14 @@ class DownloadResult(object):
|
|
|
396
399
|
subdirectory = self.subdirectory_by_filename.get(
|
|
397
400
|
os.path.basename(distribution_path)
|
|
398
401
|
)
|
|
399
|
-
|
|
402
|
+
production_assert(
|
|
403
|
+
os.path.isfile(distribution_path),
|
|
404
|
+
(
|
|
405
|
+
"Pip download results should always be files and never local project "
|
|
406
|
+
"directories."
|
|
407
|
+
),
|
|
408
|
+
)
|
|
409
|
+
yield BuildRequest.for_file(
|
|
400
410
|
target=self.download_target,
|
|
401
411
|
source_path=distribution_path,
|
|
402
412
|
subdirectory=subdirectory,
|
|
@@ -415,26 +425,46 @@ class IntegrityError(Exception):
|
|
|
415
425
|
pass
|
|
416
426
|
|
|
417
427
|
|
|
418
|
-
|
|
428
|
+
if TYPE_CHECKING:
|
|
429
|
+
from pex.hashing import Hasher
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
def _hasher():
|
|
433
|
+
# type: () -> Hasher
|
|
434
|
+
|
|
435
|
+
return hashlib.sha256()
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
def _fingerprint_file(path):
|
|
419
439
|
# type: (str) -> str
|
|
440
|
+
return CacheHelper.hash(path, digest=_hasher())
|
|
420
441
|
|
|
421
|
-
# We switched from sha1 to sha256 at the transition from using `pip install --target` to
|
|
422
|
-
# `pip install --prefix` to serve two purposes:
|
|
423
|
-
# 1. Insulate the new installation scheme from the old.
|
|
424
|
-
# 2. Move past sha1 which was shown to have practical collision attacks in 2019.
|
|
425
|
-
#
|
|
426
|
-
# The installation scheme switch was the primary purpose and switching hashes proved a pragmatic
|
|
427
|
-
# insulation. If the `pip install --prefix` re-arrangement scheme evolves, then some other
|
|
428
|
-
# option than switching hashing algorithms will be needed, like post-fixing a running version
|
|
429
|
-
# integer or just mixing one into the hashed content.
|
|
430
|
-
#
|
|
431
|
-
# See: https://github.com/pex-tool/pex/issues/1655 for a general overview of these cache
|
|
432
|
-
# structure concerns.
|
|
433
|
-
hasher = hashlib.sha256
|
|
434
442
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
return CacheHelper.
|
|
443
|
+
def _fingerprint_directory(path):
|
|
444
|
+
# type: (str) -> str
|
|
445
|
+
return CacheHelper.dir_hash(path, digest=_hasher())
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
def _fingerprint_local_project(
|
|
449
|
+
path, # type: str
|
|
450
|
+
target, # type: Target
|
|
451
|
+
resolver=None, # type: Optional[Resolver]
|
|
452
|
+
pip_version=None, # type: Optional[PipVersionValue]
|
|
453
|
+
):
|
|
454
|
+
if resolver:
|
|
455
|
+
build_system_resolver = resolver
|
|
456
|
+
else:
|
|
457
|
+
from pex.resolve.configured_resolver import ConfiguredResolver
|
|
458
|
+
|
|
459
|
+
build_system_resolver = ConfiguredResolver.default()
|
|
460
|
+
|
|
461
|
+
return digest_local_project(
|
|
462
|
+
directory=path,
|
|
463
|
+
digest=_hasher(),
|
|
464
|
+
target=target,
|
|
465
|
+
resolver=build_system_resolver,
|
|
466
|
+
pip_version=pip_version,
|
|
467
|
+
)
|
|
438
468
|
|
|
439
469
|
|
|
440
470
|
class BuildError(Exception):
|
|
@@ -449,14 +479,14 @@ def _as_download_target(target):
|
|
|
449
479
|
@attr.s(frozen=True)
|
|
450
480
|
class BuildRequest(object):
|
|
451
481
|
@classmethod
|
|
452
|
-
def
|
|
482
|
+
def for_file(
|
|
453
483
|
cls,
|
|
454
484
|
target, # type: Union[DownloadTarget, Target]
|
|
455
485
|
source_path, # type: str
|
|
456
486
|
subdirectory=None, # type: Optional[str]
|
|
457
487
|
):
|
|
458
488
|
# type: (...) -> BuildRequest
|
|
459
|
-
fingerprint =
|
|
489
|
+
fingerprint = _fingerprint_file(source_path)
|
|
460
490
|
return cls(
|
|
461
491
|
download_target=_as_download_target(target),
|
|
462
492
|
source_path=source_path,
|
|
@@ -464,6 +494,30 @@ class BuildRequest(object):
|
|
|
464
494
|
subdirectory=subdirectory,
|
|
465
495
|
)
|
|
466
496
|
|
|
497
|
+
@classmethod
|
|
498
|
+
def for_directory(
|
|
499
|
+
cls,
|
|
500
|
+
target, # type: Union[DownloadTarget, Target]
|
|
501
|
+
source_path, # type: str
|
|
502
|
+
subdirectory=None, # type: Optional[str]
|
|
503
|
+
resolver=None, # type: Optional[Resolver]
|
|
504
|
+
pip_version=None, # type: Optional[PipVersionValue]
|
|
505
|
+
):
|
|
506
|
+
# type: (...) -> BuildRequest
|
|
507
|
+
download_target = _as_download_target(target)
|
|
508
|
+
fingerprint = _fingerprint_local_project(
|
|
509
|
+
path=source_path,
|
|
510
|
+
target=download_target.target,
|
|
511
|
+
resolver=resolver,
|
|
512
|
+
pip_version=pip_version,
|
|
513
|
+
)
|
|
514
|
+
return cls(
|
|
515
|
+
download_target=download_target,
|
|
516
|
+
source_path=source_path,
|
|
517
|
+
fingerprint=fingerprint,
|
|
518
|
+
subdirectory=subdirectory,
|
|
519
|
+
)
|
|
520
|
+
|
|
467
521
|
download_target = attr.ib(converter=_as_download_target) # type: DownloadTarget
|
|
468
522
|
source_path = attr.ib() # type: str
|
|
469
523
|
fingerprint = attr.ib() # type: str
|
|
@@ -635,7 +689,7 @@ class InstallRequest(object):
|
|
|
635
689
|
was_built_locally=False, # type: bool
|
|
636
690
|
):
|
|
637
691
|
# type: (...) -> InstallRequest
|
|
638
|
-
fingerprint =
|
|
692
|
+
fingerprint = _fingerprint_file(wheel_path)
|
|
639
693
|
return cls(
|
|
640
694
|
download_target=_as_download_target(target),
|
|
641
695
|
wheel_path=wheel_path,
|
|
@@ -768,7 +822,7 @@ class InstallResult(object):
|
|
|
768
822
|
else:
|
|
769
823
|
cached_fingerprint = installed_wheel.fingerprint
|
|
770
824
|
|
|
771
|
-
wheel_dir_hash = cached_fingerprint or
|
|
825
|
+
wheel_dir_hash = cached_fingerprint or _fingerprint_directory(self.install_chroot)
|
|
772
826
|
runtime_key_dir = os.path.join(self._installation_root, wheel_dir_hash)
|
|
773
827
|
with atomic_directory(runtime_key_dir) as atomic_dir:
|
|
774
828
|
if not atomic_dir.is_finalized():
|
|
@@ -1086,8 +1140,17 @@ class BuildAndInstallRequest(object):
|
|
|
1086
1140
|
)
|
|
1087
1141
|
if is_wheel(dist_path):
|
|
1088
1142
|
to_install.add(InstallRequest.create(install_request.target, dist_path))
|
|
1143
|
+
elif os.path.isdir(dist_path):
|
|
1144
|
+
to_build.add(
|
|
1145
|
+
BuildRequest.for_directory(
|
|
1146
|
+
install_request.target,
|
|
1147
|
+
dist_path,
|
|
1148
|
+
resolver=self._resolver,
|
|
1149
|
+
pip_version=self._pip_version,
|
|
1150
|
+
)
|
|
1151
|
+
)
|
|
1089
1152
|
else:
|
|
1090
|
-
to_build.add(BuildRequest.
|
|
1153
|
+
to_build.add(BuildRequest.for_file(install_request.target, dist_path))
|
|
1091
1154
|
already_analyzed.add(metadata.project_name)
|
|
1092
1155
|
|
|
1093
1156
|
all_install_requests = OrderedSet(install_requests)
|
|
@@ -1251,7 +1314,7 @@ def _parse_reqs(
|
|
|
1251
1314
|
requirement_files=None, # type: Optional[Iterable[str]]
|
|
1252
1315
|
network_configuration=None, # type: Optional[NetworkConfiguration]
|
|
1253
1316
|
):
|
|
1254
|
-
# type: (...) ->
|
|
1317
|
+
# type: (...) -> Tuple[ParsedRequirement, ...]
|
|
1255
1318
|
requirement_configuration = RequirementConfiguration(
|
|
1256
1319
|
requirements=requirements, requirement_files=requirement_files
|
|
1257
1320
|
)
|
|
@@ -1318,6 +1381,23 @@ def resolve(
|
|
|
1318
1381
|
:raises ValueError: If `build=False` and `use_wheel=False`.
|
|
1319
1382
|
"""
|
|
1320
1383
|
|
|
1384
|
+
if not build_configuration.allow_wheels:
|
|
1385
|
+
foreign_targets = [
|
|
1386
|
+
target
|
|
1387
|
+
for target in targets.unique_targets()
|
|
1388
|
+
if not isinstance(target, LocalInterpreter)
|
|
1389
|
+
]
|
|
1390
|
+
if foreign_targets:
|
|
1391
|
+
raise ValueError(
|
|
1392
|
+
"Cannot ignore wheels (use_wheel=False) when resolving for foreign {platforms}: "
|
|
1393
|
+
"{foreign_platforms}".format(
|
|
1394
|
+
platforms=pluralize(foreign_targets, "platform"),
|
|
1395
|
+
foreign_platforms=", ".join(
|
|
1396
|
+
target.render_description() for target in foreign_targets
|
|
1397
|
+
),
|
|
1398
|
+
)
|
|
1399
|
+
)
|
|
1400
|
+
|
|
1321
1401
|
# A resolve happens in four stages broken into two phases:
|
|
1322
1402
|
# 1. Download phase: resolves sdists and wheels in a single operation per distribution target.
|
|
1323
1403
|
# 2. Install phase:
|
|
@@ -1359,29 +1439,19 @@ def resolve(
|
|
|
1359
1439
|
keyring_provider=keyring_provider,
|
|
1360
1440
|
)
|
|
1361
1441
|
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
target
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
"{foreign_platforms}".format(
|
|
1372
|
-
platforms=pluralize(foreign_targets, "platform"),
|
|
1373
|
-
foreign_platforms=", ".join(
|
|
1374
|
-
target.render_description() for target in foreign_targets
|
|
1375
|
-
),
|
|
1376
|
-
)
|
|
1377
|
-
)
|
|
1442
|
+
requests = tuple(
|
|
1443
|
+
DownloadRequest(
|
|
1444
|
+
download_target=DownloadTarget(target=target),
|
|
1445
|
+
requirements=requirements,
|
|
1446
|
+
requirement_files=requirement_files,
|
|
1447
|
+
constraint_files=constraint_files,
|
|
1448
|
+
)
|
|
1449
|
+
for target in targets.unique_targets()
|
|
1450
|
+
)
|
|
1378
1451
|
|
|
1379
1452
|
build_requests, download_results = _download_internal(
|
|
1380
|
-
|
|
1453
|
+
requests=requests,
|
|
1381
1454
|
direct_requirements=direct_requirements,
|
|
1382
|
-
requirements=requirements,
|
|
1383
|
-
requirement_files=requirement_files,
|
|
1384
|
-
constraint_files=constraint_files,
|
|
1385
1455
|
allow_prereleases=allow_prereleases,
|
|
1386
1456
|
transitive=transitive,
|
|
1387
1457
|
package_index_configuration=package_index_configuration,
|
|
@@ -1429,11 +1499,8 @@ def resolve(
|
|
|
1429
1499
|
|
|
1430
1500
|
|
|
1431
1501
|
def _download_internal(
|
|
1432
|
-
|
|
1502
|
+
requests, # type: Tuple[DownloadRequest, ...]
|
|
1433
1503
|
direct_requirements, # type: Iterable[ParsedRequirement]
|
|
1434
|
-
requirements=None, # type: Optional[Iterable[str]]
|
|
1435
|
-
requirement_files=None, # type: Optional[Iterable[str]]
|
|
1436
|
-
constraint_files=None, # type: Optional[Iterable[str]]
|
|
1437
1504
|
allow_prereleases=False, # type: bool
|
|
1438
1505
|
transitive=True, # type: bool
|
|
1439
1506
|
package_index_configuration=None, # type: Optional[PackageIndexConfiguration]
|
|
@@ -1445,27 +1512,12 @@ def _download_internal(
|
|
|
1445
1512
|
pip_version=None, # type: Optional[PipVersionValue]
|
|
1446
1513
|
resolver=None, # type: Optional[Resolver]
|
|
1447
1514
|
dependency_configuration=DependencyConfiguration(), # type: DependencyConfiguration
|
|
1448
|
-
universal_targets=(), # type: Iterable[UniversalTarget]
|
|
1449
1515
|
):
|
|
1450
1516
|
# type: (...) -> Tuple[List[BuildRequest], List[DownloadResult]]
|
|
1451
1517
|
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
production_assert(len(unique_targets) == 1)
|
|
1455
|
-
target = unique_targets.pop()
|
|
1456
|
-
download_targets = tuple(
|
|
1457
|
-
DownloadTarget(target, universal_target=universal_target)
|
|
1458
|
-
for universal_target in universal_targets
|
|
1459
|
-
)
|
|
1460
|
-
else:
|
|
1461
|
-
download_targets = tuple(DownloadTarget(target) for target in unique_targets)
|
|
1462
|
-
|
|
1463
|
-
download_request = DownloadRequest(
|
|
1464
|
-
download_targets=download_targets,
|
|
1518
|
+
download_session = _DownloadSession(
|
|
1519
|
+
requests=requests,
|
|
1465
1520
|
direct_requirements=direct_requirements,
|
|
1466
|
-
requirements=requirements,
|
|
1467
|
-
requirement_files=requirement_files,
|
|
1468
|
-
constraint_files=constraint_files,
|
|
1469
1521
|
allow_prereleases=allow_prereleases,
|
|
1470
1522
|
transitive=transitive,
|
|
1471
1523
|
package_index_configuration=package_index_configuration,
|
|
@@ -1477,8 +1529,8 @@ def _download_internal(
|
|
|
1477
1529
|
dependency_configuration=dependency_configuration,
|
|
1478
1530
|
)
|
|
1479
1531
|
|
|
1480
|
-
local_projects = list(
|
|
1481
|
-
download_results =
|
|
1532
|
+
local_projects = list(download_session.iter_local_projects())
|
|
1533
|
+
download_results = download_session.download_distributions(
|
|
1482
1534
|
dest=dest, max_parallel_jobs=max_parallel_jobs
|
|
1483
1535
|
)
|
|
1484
1536
|
return local_projects, download_results
|
|
@@ -1496,10 +1548,6 @@ class LocalDistribution(object):
|
|
|
1496
1548
|
# type: () -> Target
|
|
1497
1549
|
return self.download_target.target
|
|
1498
1550
|
|
|
1499
|
-
@fingerprint.default
|
|
1500
|
-
def _calculate_fingerprint(self):
|
|
1501
|
-
return fingerprint_path(self.path)
|
|
1502
|
-
|
|
1503
1551
|
@property
|
|
1504
1552
|
def is_wheel(self):
|
|
1505
1553
|
return is_wheel(self.path) and zipfile.is_zipfile(self.path)
|
|
@@ -1542,7 +1590,6 @@ def download(
|
|
|
1542
1590
|
extra_pip_requirements=(), # type: Tuple[Requirement, ...]
|
|
1543
1591
|
keyring_provider=None, # type: Optional[str]
|
|
1544
1592
|
dependency_configuration=DependencyConfiguration(), # type: DependencyConfiguration
|
|
1545
|
-
universal_targets=(), # type: Iterable[UniversalTarget]
|
|
1546
1593
|
):
|
|
1547
1594
|
# type: (...) -> Downloaded
|
|
1548
1595
|
"""Downloads all distributions needed to meet requirements for multiple distribution targets.
|
|
@@ -1572,7 +1619,114 @@ def download(
|
|
|
1572
1619
|
:raises ValueError: If a foreign platform was provided in `platforms`, and `use_wheel=False`.
|
|
1573
1620
|
:raises ValueError: If `build=False` and `use_wheel=False`.
|
|
1574
1621
|
"""
|
|
1575
|
-
|
|
1622
|
+
return download_requests(
|
|
1623
|
+
requests=tuple(
|
|
1624
|
+
DownloadRequest(
|
|
1625
|
+
download_target=DownloadTarget(target),
|
|
1626
|
+
requirements=requirements,
|
|
1627
|
+
requirement_files=requirement_files,
|
|
1628
|
+
constraint_files=constraint_files,
|
|
1629
|
+
)
|
|
1630
|
+
for target in targets.unique_targets()
|
|
1631
|
+
),
|
|
1632
|
+
direct_requirements=_parse_reqs(requirements, requirement_files, network_configuration),
|
|
1633
|
+
allow_prereleases=allow_prereleases,
|
|
1634
|
+
transitive=transitive,
|
|
1635
|
+
repos_configuration=repos_configuration,
|
|
1636
|
+
resolver_version=resolver_version,
|
|
1637
|
+
network_configuration=network_configuration,
|
|
1638
|
+
build_configuration=build_configuration,
|
|
1639
|
+
dest=dest,
|
|
1640
|
+
max_parallel_jobs=max_parallel_jobs,
|
|
1641
|
+
observer=observer,
|
|
1642
|
+
pip_log=pip_log,
|
|
1643
|
+
pip_version=pip_version,
|
|
1644
|
+
resolver=resolver,
|
|
1645
|
+
use_pip_config=use_pip_config,
|
|
1646
|
+
extra_pip_requirements=extra_pip_requirements,
|
|
1647
|
+
keyring_provider=keyring_provider,
|
|
1648
|
+
dependency_configuration=dependency_configuration,
|
|
1649
|
+
)
|
|
1650
|
+
|
|
1651
|
+
|
|
1652
|
+
def _as_str_tuple(items):
|
|
1653
|
+
# type: (Optional[Iterable[str]]) -> Tuple[str, ...]
|
|
1654
|
+
if not items:
|
|
1655
|
+
return ()
|
|
1656
|
+
return items if isinstance(items, tuple) else tuple(items)
|
|
1657
|
+
|
|
1658
|
+
|
|
1659
|
+
@attr.s(frozen=True)
|
|
1660
|
+
class DownloadRequest(object):
|
|
1661
|
+
@classmethod
|
|
1662
|
+
def create(
|
|
1663
|
+
cls,
|
|
1664
|
+
target, # type: Target
|
|
1665
|
+
universal_target=None, # type: Optional[UniversalTarget]
|
|
1666
|
+
requirement_configuration=RequirementConfiguration(), # type: RequirementConfiguration
|
|
1667
|
+
provenance=None, # type: Optional[str]
|
|
1668
|
+
):
|
|
1669
|
+
# type: (...) -> DownloadRequest
|
|
1670
|
+
return cls(
|
|
1671
|
+
download_target=DownloadTarget(target=target, universal_target=universal_target),
|
|
1672
|
+
requirements=requirement_configuration.requirements,
|
|
1673
|
+
requirement_files=requirement_configuration.requirement_files,
|
|
1674
|
+
constraint_files=requirement_configuration.constraint_files,
|
|
1675
|
+
provenance=provenance,
|
|
1676
|
+
)
|
|
1677
|
+
|
|
1678
|
+
download_target = attr.ib() # type: DownloadTarget
|
|
1679
|
+
requirements = attr.ib(default=(), converter=_as_str_tuple) # type: Tuple[str, ...]
|
|
1680
|
+
requirement_files = attr.ib(default=(), converter=_as_str_tuple) # type: Tuple[str, ...]
|
|
1681
|
+
constraint_files = attr.ib(default=(), converter=_as_str_tuple) # type: Tuple[str, ...]
|
|
1682
|
+
provenance = attr.ib(default=None) # type: Optional[str]
|
|
1683
|
+
|
|
1684
|
+
def render_description(self):
|
|
1685
|
+
# type: () -> str
|
|
1686
|
+
description = self.download_target.render_description()
|
|
1687
|
+
if not self.provenance:
|
|
1688
|
+
return description
|
|
1689
|
+
return "{description} from {provenance}".format(
|
|
1690
|
+
description=description, provenance=self.provenance
|
|
1691
|
+
)
|
|
1692
|
+
|
|
1693
|
+
@property
|
|
1694
|
+
def target(self):
|
|
1695
|
+
# type: () -> Target
|
|
1696
|
+
return self.download_target.target
|
|
1697
|
+
|
|
1698
|
+
@property
|
|
1699
|
+
def universal_target(self):
|
|
1700
|
+
# type: () -> Optional[UniversalTarget]
|
|
1701
|
+
return self.download_target.universal_target
|
|
1702
|
+
|
|
1703
|
+
@property
|
|
1704
|
+
def has_requirements(self):
|
|
1705
|
+
return bool(self.requirements) or bool(self.requirement_files)
|
|
1706
|
+
|
|
1707
|
+
|
|
1708
|
+
def download_requests(
|
|
1709
|
+
requests, # type: Tuple[DownloadRequest, ...]
|
|
1710
|
+
direct_requirements, # type: Tuple[ParsedRequirement, ...]
|
|
1711
|
+
allow_prereleases=False, # type: bool
|
|
1712
|
+
transitive=True, # type: bool
|
|
1713
|
+
repos_configuration=ReposConfiguration(), # type: ReposConfiguration
|
|
1714
|
+
resolver_version=None, # type: Optional[ResolverVersion.Value]
|
|
1715
|
+
network_configuration=None, # type: Optional[NetworkConfiguration]
|
|
1716
|
+
build_configuration=BuildConfiguration(), # type: BuildConfiguration
|
|
1717
|
+
dest=None, # type: Optional[str]
|
|
1718
|
+
max_parallel_jobs=None, # type: Optional[int]
|
|
1719
|
+
observer=None, # type: Optional[ResolveObserver]
|
|
1720
|
+
pip_log=None, # type: Optional[PipLog]
|
|
1721
|
+
pip_version=None, # type: Optional[PipVersionValue]
|
|
1722
|
+
resolver=None, # type: Optional[Resolver]
|
|
1723
|
+
use_pip_config=False, # type: bool
|
|
1724
|
+
extra_pip_requirements=(), # type: Tuple[Requirement, ...]
|
|
1725
|
+
keyring_provider=None, # type: Optional[str]
|
|
1726
|
+
dependency_configuration=DependencyConfiguration(), # type: DependencyConfiguration
|
|
1727
|
+
):
|
|
1728
|
+
# type: (...) -> Downloaded
|
|
1729
|
+
|
|
1576
1730
|
package_index_configuration = PackageIndexConfiguration.create(
|
|
1577
1731
|
pip_version=pip_version,
|
|
1578
1732
|
resolver_version=resolver_version,
|
|
@@ -1582,12 +1736,10 @@ def download(
|
|
|
1582
1736
|
extra_pip_requirements=extra_pip_requirements,
|
|
1583
1737
|
keyring_provider=keyring_provider,
|
|
1584
1738
|
)
|
|
1739
|
+
|
|
1585
1740
|
build_requests, download_results = _download_internal(
|
|
1586
|
-
|
|
1741
|
+
requests=requests,
|
|
1587
1742
|
direct_requirements=direct_requirements,
|
|
1588
|
-
requirements=requirements,
|
|
1589
|
-
requirement_files=requirement_files,
|
|
1590
|
-
constraint_files=constraint_files,
|
|
1591
1743
|
allow_prereleases=allow_prereleases,
|
|
1592
1744
|
transitive=transitive,
|
|
1593
1745
|
package_index_configuration=package_index_configuration,
|
|
@@ -1599,7 +1751,6 @@ def download(
|
|
|
1599
1751
|
pip_version=pip_version,
|
|
1600
1752
|
resolver=resolver,
|
|
1601
1753
|
dependency_configuration=dependency_configuration,
|
|
1602
|
-
universal_targets=universal_targets,
|
|
1603
1754
|
)
|
|
1604
1755
|
|
|
1605
1756
|
local_distributions = []
|
pex/venv/venv_pex.py
CHANGED
|
@@ -186,7 +186,7 @@ def boot(
|
|
|
186
186
|
"_PEX_PATCHED_TAGS_FILE",
|
|
187
187
|
# These are used by Pex's Pip venv to implement universal locks.
|
|
188
188
|
"_PEX_PYTHON_VERSIONS_FILE",
|
|
189
|
-
"
|
|
189
|
+
"_PEX_UNIVERSAL_TARGET_FILE",
|
|
190
190
|
# This is used to implement Pex --exclude and --override support.
|
|
191
191
|
"_PEX_DEP_CONFIG_FILE",
|
|
192
192
|
# This is used to implement --source support.
|
pex/version.py
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pex
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.62.0
|
|
4
4
|
Summary: The PEX packaging toolchain.
|
|
5
5
|
Home-page: https://github.com/pex-tool/pex
|
|
6
|
-
Download-URL: https://github.com/pex-tool/pex/releases/download/v2.
|
|
6
|
+
Download-URL: https://github.com/pex-tool/pex/releases/download/v2.62.0/pex
|
|
7
7
|
Author: The PEX developers
|
|
8
8
|
Author-email: developers@pex-tool.org
|
|
9
9
|
License-Expression: Apache-2.0
|
|
10
|
-
Project-URL: Changelog, https://github.com/pex-tool/pex/blob/v2.
|
|
10
|
+
Project-URL: Changelog, https://github.com/pex-tool/pex/blob/v2.62.0/CHANGES.md
|
|
11
11
|
Project-URL: Documentation, https://docs.pex-tool.org/
|
|
12
|
-
Project-URL: Source, https://github.com/pex-tool/pex/tree/v2.
|
|
12
|
+
Project-URL: Source, https://github.com/pex-tool/pex/tree/v2.62.0
|
|
13
13
|
Keywords: package,executable,virtualenv,lock,freeze
|
|
14
14
|
Classifier: Development Status :: 5 - Production/Stable
|
|
15
15
|
Classifier: Intended Audience :: Developers
|