pex 2.63.0__py2.py3-none-any.whl → 2.64.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/cli/commands/lock.py +15 -0
- pex/dist_metadata.py +36 -9
- pex/docs/html/_pagefind/fragment/{en_f2578bc.pf_fragment → en_3046a3a.pf_fragment} +0 -0
- pex/docs/html/_pagefind/fragment/en_3f5cca9.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_5f2da5c.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_7350892.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/{en_66c5113.pf_fragment → en_ac9b982.pf_fragment} +0 -0
- pex/docs/html/_pagefind/fragment/en_d158da6.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_e575d34.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_fca878d.pf_fragment +0 -0
- pex/docs/html/_pagefind/index/en_23c894e.pf_index +0 -0
- pex/docs/html/_pagefind/pagefind-entry.json +1 -1
- pex/docs/html/_pagefind/pagefind.en_86ab41ad5d.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/pip/tool.py +84 -11
- pex/pip/vcs.py +42 -25
- pex/resolve/lock_downloader.py +0 -1
- pex/resolve/locked_resolve.py +11 -11
- pex/resolve/locker.py +98 -18
- pex/resolve/lockfile/create.py +157 -27
- pex/resolve/lockfile/updater.py +11 -0
- pex/resolver.py +201 -4
- pex/version.py +1 -1
- {pex-2.63.0.dist-info → pex-2.64.0.dist-info}/METADATA +4 -4
- {pex-2.63.0.dist-info → pex-2.64.0.dist-info}/RECORD +38 -38
- pex/docs/html/_pagefind/fragment/en_6c6ecbd.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_6c77f9b.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_71b5a8a.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_8762fc9.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_a55bc27.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_c87eb0d.pf_fragment +0 -0
- pex/docs/html/_pagefind/index/en_b6cc89e.pf_index +0 -0
- pex/docs/html/_pagefind/pagefind.en_5515c79d6d.pf_meta +0 -0
- {pex-2.63.0.dist-info → pex-2.64.0.dist-info}/WHEEL +0 -0
- {pex-2.63.0.dist-info → pex-2.64.0.dist-info}/entry_points.txt +0 -0
- {pex-2.63.0.dist-info → pex-2.64.0.dist-info}/licenses/LICENSE +0 -0
- {pex-2.63.0.dist-info → pex-2.64.0.dist-info}/pylock/pylock.toml +0 -0
- {pex-2.63.0.dist-info → pex-2.64.0.dist-info}/top_level.txt +0 -0
pex/resolve/lockfile/create.py
CHANGED
|
@@ -23,7 +23,7 @@ from pex.pep_440 import Version
|
|
|
23
23
|
from pex.pep_503 import ProjectName
|
|
24
24
|
from pex.pip.download_observer import DownloadObserver
|
|
25
25
|
from pex.pip.tool import PackageIndexConfiguration
|
|
26
|
-
from pex.pip.version import PipVersionValue
|
|
26
|
+
from pex.pip.version import PipVersion, PipVersionValue
|
|
27
27
|
from pex.resolve import lock_resolver, locker, resolvers
|
|
28
28
|
from pex.resolve.configured_resolver import ConfiguredResolver
|
|
29
29
|
from pex.resolve.downloads import ArtifactDownloader
|
|
@@ -41,15 +41,23 @@ from pex.resolve.locked_resolve import (
|
|
|
41
41
|
from pex.resolve.locker import Locker
|
|
42
42
|
from pex.resolve.lockfile.download_manager import DownloadManager
|
|
43
43
|
from pex.resolve.lockfile.model import Lockfile
|
|
44
|
-
from pex.resolve.lockfile.targets import calculate_download_input
|
|
44
|
+
from pex.resolve.lockfile.targets import DownloadInput, calculate_download_input
|
|
45
45
|
from pex.resolve.package_repository import ReposConfiguration
|
|
46
46
|
from pex.resolve.pep_691.fingerprint_service import FingerprintService
|
|
47
47
|
from pex.resolve.requirement_configuration import RequirementConfiguration
|
|
48
48
|
from pex.resolve.resolved_requirement import Pin, ResolvedRequirement
|
|
49
49
|
from pex.resolve.resolver_configuration import BuildConfiguration, PipConfiguration, ResolverVersion
|
|
50
50
|
from pex.resolve.resolvers import Resolver
|
|
51
|
-
from pex.resolver import
|
|
51
|
+
from pex.resolver import (
|
|
52
|
+
BuildRequest,
|
|
53
|
+
Downloaded,
|
|
54
|
+
DownloadTarget,
|
|
55
|
+
Reports,
|
|
56
|
+
ResolveObserver,
|
|
57
|
+
WheelBuilder,
|
|
58
|
+
)
|
|
52
59
|
from pex.resolver import download_requests as pip_download_requests
|
|
60
|
+
from pex.resolver import reports as pip_reports
|
|
53
61
|
from pex.result import Error, try_
|
|
54
62
|
from pex.targets import Target, Targets
|
|
55
63
|
from pex.tracer import TRACER
|
|
@@ -277,6 +285,7 @@ class LockObserver(ResolveObserver):
|
|
|
277
285
|
wheel_builder = attr.ib() # type: WheelBuilder
|
|
278
286
|
package_index_configuration = attr.ib() # type: PackageIndexConfiguration
|
|
279
287
|
max_parallel_jobs = attr.ib(default=None) # type: Optional[int]
|
|
288
|
+
lock_is_via_pip_download = attr.ib(default=False) # type: bool
|
|
280
289
|
_analysis = attr.ib(factory=OrderedSet, eq=False) # type: OrderedSet[_LockAnalysis]
|
|
281
290
|
|
|
282
291
|
def observe_download(
|
|
@@ -299,6 +308,7 @@ class LockObserver(ResolveObserver):
|
|
|
299
308
|
),
|
|
300
309
|
max_parallel_jobs=self.max_parallel_jobs,
|
|
301
310
|
),
|
|
311
|
+
lock_is_via_pip_download=self.lock_is_via_pip_download,
|
|
302
312
|
)
|
|
303
313
|
patch_set = locker.patch(universal_target=download_target.universal_target)
|
|
304
314
|
observer = DownloadObserver(analyzer=analyzer, patch_set=patch_set)
|
|
@@ -454,7 +464,7 @@ class LockObserver(ResolveObserver):
|
|
|
454
464
|
return tuple(
|
|
455
465
|
LockedResolve.create(
|
|
456
466
|
resolved_requirements=resolved_requirements,
|
|
457
|
-
|
|
467
|
+
project_metadatas=dist_metadatas_by_download_target[download_target],
|
|
458
468
|
fingerprinter=ArtifactDownloader(
|
|
459
469
|
resolver=self.resolver,
|
|
460
470
|
universal_target=download_target.universal_target,
|
|
@@ -476,6 +486,126 @@ class LockObserver(ResolveObserver):
|
|
|
476
486
|
for download_target, resolved_requirements in resolved_requirements_by_download_target.items()
|
|
477
487
|
)
|
|
478
488
|
|
|
489
|
+
def lock_reports(self, reports):
|
|
490
|
+
# type: (Reports) -> Tuple[LockedResolve, ...]
|
|
491
|
+
|
|
492
|
+
project_metadatas_by_download_target = {
|
|
493
|
+
report.download_target: tuple(report.metadata.values()) for report in reports
|
|
494
|
+
}
|
|
495
|
+
resolved_requirements_by_download_target = (
|
|
496
|
+
OrderedDict()
|
|
497
|
+
) # type: OrderedDict[DownloadTarget, Tuple[ResolvedRequirement, ...]]
|
|
498
|
+
for analysis in self._analysis:
|
|
499
|
+
lock_result = analysis.analyzer.lock_result
|
|
500
|
+
resolved_requirements_by_download_target[
|
|
501
|
+
analysis.download_target
|
|
502
|
+
] = lock_result.resolved_requirements
|
|
503
|
+
|
|
504
|
+
universal_targets = tuple(
|
|
505
|
+
download_target.universal_target
|
|
506
|
+
for download_target in resolved_requirements_by_download_target
|
|
507
|
+
if download_target.universal_target
|
|
508
|
+
)
|
|
509
|
+
return tuple(
|
|
510
|
+
LockedResolve.create(
|
|
511
|
+
resolved_requirements=resolved_requirements,
|
|
512
|
+
project_metadatas=project_metadatas_by_download_target[download_target],
|
|
513
|
+
fingerprinter=ArtifactDownloader(
|
|
514
|
+
resolver=self.resolver,
|
|
515
|
+
universal_target=download_target.universal_target,
|
|
516
|
+
target=download_target.target,
|
|
517
|
+
package_index_configuration=self.package_index_configuration,
|
|
518
|
+
max_parallel_jobs=self.max_parallel_jobs,
|
|
519
|
+
),
|
|
520
|
+
platform_tag=(
|
|
521
|
+
None
|
|
522
|
+
if self.lock_style == LockStyle.UNIVERSAL
|
|
523
|
+
else download_target.target.platform.tag
|
|
524
|
+
),
|
|
525
|
+
marker=(
|
|
526
|
+
download_target.universal_target.marker()
|
|
527
|
+
if download_target.universal_target and len(universal_targets) > 1
|
|
528
|
+
else None
|
|
529
|
+
),
|
|
530
|
+
)
|
|
531
|
+
for download_target, resolved_requirements in resolved_requirements_by_download_target.items()
|
|
532
|
+
)
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
def _create_lock_pip_download(
|
|
536
|
+
download_input, # type: DownloadInput
|
|
537
|
+
pip_configuration, # type: PipConfiguration
|
|
538
|
+
network_configuration, # type: NetworkConfiguration
|
|
539
|
+
download_dir, # type: str
|
|
540
|
+
lock_observer, # type: LockObserver
|
|
541
|
+
configured_resolver, # type: ConfiguredResolver
|
|
542
|
+
dependency_configuration, # type: DependencyConfiguration
|
|
543
|
+
):
|
|
544
|
+
# type: (...) -> Union[Tuple[LockedResolve, ...], Error]
|
|
545
|
+
try:
|
|
546
|
+
downloaded = pip_download_requests(
|
|
547
|
+
requests=download_input.download_requests,
|
|
548
|
+
direct_requirements=download_input.direct_requirements,
|
|
549
|
+
allow_prereleases=pip_configuration.allow_prereleases,
|
|
550
|
+
transitive=pip_configuration.transitive,
|
|
551
|
+
repos_configuration=pip_configuration.repos_configuration,
|
|
552
|
+
resolver_version=pip_configuration.resolver_version,
|
|
553
|
+
network_configuration=network_configuration,
|
|
554
|
+
build_configuration=pip_configuration.build_configuration,
|
|
555
|
+
max_parallel_jobs=pip_configuration.max_jobs,
|
|
556
|
+
observer=lock_observer,
|
|
557
|
+
dest=download_dir,
|
|
558
|
+
pip_log=pip_configuration.log,
|
|
559
|
+
pip_version=pip_configuration.version,
|
|
560
|
+
resolver=configured_resolver,
|
|
561
|
+
use_pip_config=pip_configuration.use_pip_config,
|
|
562
|
+
extra_pip_requirements=pip_configuration.extra_requirements,
|
|
563
|
+
keyring_provider=pip_configuration.keyring_provider,
|
|
564
|
+
dependency_configuration=dependency_configuration,
|
|
565
|
+
)
|
|
566
|
+
except resolvers.ResolveError as e:
|
|
567
|
+
return Error(str(e))
|
|
568
|
+
|
|
569
|
+
with TRACER.timed("Creating lock from resolve"):
|
|
570
|
+
return lock_observer.lock(downloaded)
|
|
571
|
+
|
|
572
|
+
|
|
573
|
+
def _create_lock_pip_reports(
|
|
574
|
+
download_input, # type: DownloadInput
|
|
575
|
+
pip_configuration, # type: PipConfiguration
|
|
576
|
+
network_configuration, # type: NetworkConfiguration
|
|
577
|
+
lock_observer, # type: LockObserver
|
|
578
|
+
configured_resolver, # type: ConfiguredResolver
|
|
579
|
+
dependency_configuration, # type: DependencyConfiguration
|
|
580
|
+
):
|
|
581
|
+
# type: (...) -> Union[Tuple[LockedResolve, ...], Error]
|
|
582
|
+
|
|
583
|
+
try:
|
|
584
|
+
reports = pip_reports(
|
|
585
|
+
requests=download_input.download_requests,
|
|
586
|
+
direct_requirements=download_input.direct_requirements,
|
|
587
|
+
allow_prereleases=pip_configuration.allow_prereleases,
|
|
588
|
+
transitive=pip_configuration.transitive,
|
|
589
|
+
repos_configuration=pip_configuration.repos_configuration,
|
|
590
|
+
resolver_version=pip_configuration.resolver_version,
|
|
591
|
+
network_configuration=network_configuration,
|
|
592
|
+
build_configuration=pip_configuration.build_configuration,
|
|
593
|
+
max_parallel_jobs=pip_configuration.max_jobs,
|
|
594
|
+
observer=lock_observer,
|
|
595
|
+
pip_log=pip_configuration.log,
|
|
596
|
+
pip_version=pip_configuration.version,
|
|
597
|
+
resolver=configured_resolver,
|
|
598
|
+
use_pip_config=pip_configuration.use_pip_config,
|
|
599
|
+
extra_pip_requirements=pip_configuration.extra_requirements,
|
|
600
|
+
keyring_provider=pip_configuration.keyring_provider,
|
|
601
|
+
dependency_configuration=dependency_configuration,
|
|
602
|
+
)
|
|
603
|
+
except resolvers.ResolveError as e:
|
|
604
|
+
return Error(str(e))
|
|
605
|
+
|
|
606
|
+
with TRACER.timed("Creating lock from resolve"):
|
|
607
|
+
return lock_observer.lock_reports(reports)
|
|
608
|
+
|
|
479
609
|
|
|
480
610
|
def create(
|
|
481
611
|
lock_configuration, # type: LockConfiguration
|
|
@@ -483,6 +613,7 @@ def create(
|
|
|
483
613
|
targets, # type: Targets
|
|
484
614
|
pip_configuration, # type: PipConfiguration
|
|
485
615
|
dependency_configuration=DependencyConfiguration(), # type: DependencyConfiguration
|
|
616
|
+
avoid_downloads=False, # type: bool
|
|
486
617
|
):
|
|
487
618
|
# type: (...) -> Union[Lockfile, Error]
|
|
488
619
|
"""Create a lock file for the given resolve configurations."""
|
|
@@ -510,6 +641,9 @@ def create(
|
|
|
510
641
|
)
|
|
511
642
|
|
|
512
643
|
configured_resolver = ConfiguredResolver(pip_configuration=pip_configuration)
|
|
644
|
+
lock_is_via_pip_download = (
|
|
645
|
+
pip_configuration.version is PipVersion.VENDORED or not avoid_downloads
|
|
646
|
+
)
|
|
513
647
|
lock_observer = LockObserver(
|
|
514
648
|
root_requirements=parsed_requirements,
|
|
515
649
|
lock_style=lock_configuration.style,
|
|
@@ -522,6 +656,7 @@ def create(
|
|
|
522
656
|
),
|
|
523
657
|
package_index_configuration=package_index_configuration,
|
|
524
658
|
max_parallel_jobs=pip_configuration.max_jobs,
|
|
659
|
+
lock_is_via_pip_download=lock_is_via_pip_download,
|
|
525
660
|
)
|
|
526
661
|
|
|
527
662
|
download_dir = safe_mkdtemp()
|
|
@@ -533,32 +668,27 @@ def create(
|
|
|
533
668
|
repos_configuration=pip_configuration.repos_configuration,
|
|
534
669
|
universal_target=lock_configuration.universal_target,
|
|
535
670
|
)
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
transitive=pip_configuration.transitive,
|
|
542
|
-
repos_configuration=pip_configuration.repos_configuration,
|
|
543
|
-
resolver_version=pip_configuration.resolver_version,
|
|
671
|
+
|
|
672
|
+
locked_resolves = try_(
|
|
673
|
+
_create_lock_pip_download(
|
|
674
|
+
download_input=download_input,
|
|
675
|
+
pip_configuration=pip_configuration,
|
|
544
676
|
network_configuration=network_configuration,
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
dest=download_dir,
|
|
549
|
-
pip_log=pip_configuration.log,
|
|
550
|
-
pip_version=pip_configuration.version,
|
|
551
|
-
resolver=configured_resolver,
|
|
552
|
-
use_pip_config=pip_configuration.use_pip_config,
|
|
553
|
-
extra_pip_requirements=pip_configuration.extra_requirements,
|
|
554
|
-
keyring_provider=pip_configuration.keyring_provider,
|
|
677
|
+
download_dir=download_dir,
|
|
678
|
+
lock_observer=lock_observer,
|
|
679
|
+
configured_resolver=configured_resolver,
|
|
555
680
|
dependency_configuration=dependency_configuration,
|
|
556
681
|
)
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
682
|
+
if lock_is_via_pip_download
|
|
683
|
+
else _create_lock_pip_reports(
|
|
684
|
+
download_input=download_input,
|
|
685
|
+
pip_configuration=pip_configuration,
|
|
686
|
+
network_configuration=network_configuration,
|
|
687
|
+
lock_observer=lock_observer,
|
|
688
|
+
configured_resolver=configured_resolver,
|
|
689
|
+
dependency_configuration=dependency_configuration,
|
|
690
|
+
)
|
|
691
|
+
)
|
|
562
692
|
|
|
563
693
|
with TRACER.timed("Indexing downloads"):
|
|
564
694
|
create_lock_download_manager = CreateLockDownloadManager.create(
|
pex/resolve/lockfile/updater.py
CHANGED
|
@@ -252,6 +252,7 @@ class ResolveUpdater(object):
|
|
|
252
252
|
lock_configuration, # type: LockConfiguration
|
|
253
253
|
pip_configuration, # type: PipConfiguration
|
|
254
254
|
dependency_configuration, # type: DependencyConfiguration
|
|
255
|
+
avoid_downloads, # type: bool
|
|
255
256
|
):
|
|
256
257
|
# type: (...) -> Union[ResolveUpdater, Error]
|
|
257
258
|
|
|
@@ -310,6 +311,7 @@ class ResolveUpdater(object):
|
|
|
310
311
|
lock_configuration=lock_configuration,
|
|
311
312
|
pip_configuration=pip_configuration,
|
|
312
313
|
dependency_configuration=dependency_configuration,
|
|
314
|
+
avoid_downloads=avoid_downloads,
|
|
313
315
|
)
|
|
314
316
|
|
|
315
317
|
@classmethod
|
|
@@ -322,6 +324,7 @@ class ResolveUpdater(object):
|
|
|
322
324
|
lock_configuration, # type: LockConfiguration
|
|
323
325
|
pip_configuration, # type: PipConfiguration
|
|
324
326
|
dependency_configuration, # type: DependencyConfiguration
|
|
327
|
+
avoid_downloads, # type: bool
|
|
325
328
|
):
|
|
326
329
|
# type: (...) -> ResolveUpdater
|
|
327
330
|
|
|
@@ -362,6 +365,7 @@ class ResolveUpdater(object):
|
|
|
362
365
|
lock_configuration=lock_configuration,
|
|
363
366
|
pip_configuration=pip_configuration,
|
|
364
367
|
dependency_configuration=dependency_configuration,
|
|
368
|
+
avoid_downloads=avoid_downloads,
|
|
365
369
|
)
|
|
366
370
|
|
|
367
371
|
requirement_configuration = attr.ib() # type: RequirementConfiguration
|
|
@@ -377,6 +381,7 @@ class ResolveUpdater(object):
|
|
|
377
381
|
update_requirements_by_project_name = attr.ib(
|
|
378
382
|
factory=dict
|
|
379
383
|
) # type: Mapping[ProjectName, Requirement]
|
|
384
|
+
avoid_downloads = attr.ib(default=False)
|
|
380
385
|
|
|
381
386
|
def iter_updated_requirements(self):
|
|
382
387
|
# type: () -> Iterator[Requirement]
|
|
@@ -502,6 +507,7 @@ class ResolveUpdater(object):
|
|
|
502
507
|
targets=Targets.from_target(target),
|
|
503
508
|
pip_configuration=self.pip_configuration,
|
|
504
509
|
dependency_configuration=self.dependency_configuration,
|
|
510
|
+
avoid_downloads=self.avoid_downloads,
|
|
505
511
|
)
|
|
506
512
|
)
|
|
507
513
|
assert 1 == len(updated_lock_file.locked_resolves)
|
|
@@ -691,6 +697,7 @@ class LockUpdater(object):
|
|
|
691
697
|
use_pip_config, # type: bool
|
|
692
698
|
dependency_configuration, # type: DependencyConfiguration
|
|
693
699
|
pip_log, # type: Optional[PipLog]
|
|
700
|
+
avoid_downloads, # type: bool
|
|
694
701
|
):
|
|
695
702
|
# type: (...) -> LockUpdater
|
|
696
703
|
|
|
@@ -711,12 +718,14 @@ class LockUpdater(object):
|
|
|
711
718
|
lock_configuration=lock_file.configuration,
|
|
712
719
|
pip_configuration=pip_configuration,
|
|
713
720
|
dependency_configuration=dependency_configuration,
|
|
721
|
+
avoid_downloads=avoid_downloads,
|
|
714
722
|
)
|
|
715
723
|
|
|
716
724
|
lock_file = attr.ib() # type: Lockfile
|
|
717
725
|
lock_configuration = attr.ib() # type: LockConfiguration
|
|
718
726
|
pip_configuration = attr.ib() # type: PipConfiguration
|
|
719
727
|
dependency_configuration = attr.ib() # type: DependencyConfiguration
|
|
728
|
+
avoid_downloads = attr.ib() # type: bool
|
|
720
729
|
|
|
721
730
|
def sync(
|
|
722
731
|
self,
|
|
@@ -738,6 +747,7 @@ class LockUpdater(object):
|
|
|
738
747
|
lock_configuration=self.lock_configuration,
|
|
739
748
|
pip_configuration=self.pip_configuration,
|
|
740
749
|
dependency_configuration=self.dependency_configuration,
|
|
750
|
+
avoid_downloads=self.avoid_downloads,
|
|
741
751
|
)
|
|
742
752
|
)
|
|
743
753
|
return self._perform_update(
|
|
@@ -773,6 +783,7 @@ class LockUpdater(object):
|
|
|
773
783
|
lock_configuration=self.lock_configuration,
|
|
774
784
|
pip_configuration=self.pip_configuration,
|
|
775
785
|
dependency_configuration=self.dependency_configuration,
|
|
786
|
+
avoid_downloads=self.avoid_downloads,
|
|
776
787
|
)
|
|
777
788
|
return self._perform_update(
|
|
778
789
|
update_requests=update_requests,
|
pex/resolver.py
CHANGED
|
@@ -8,6 +8,7 @@ import functools
|
|
|
8
8
|
import glob
|
|
9
9
|
import hashlib
|
|
10
10
|
import itertools
|
|
11
|
+
import json
|
|
11
12
|
import os
|
|
12
13
|
import tarfile
|
|
13
14
|
import zipfile
|
|
@@ -30,6 +31,7 @@ from pex.dependency_configuration import DependencyConfiguration
|
|
|
30
31
|
from pex.dist_metadata import (
|
|
31
32
|
DistMetadata,
|
|
32
33
|
Distribution,
|
|
34
|
+
ProjectMetadata,
|
|
33
35
|
Requirement,
|
|
34
36
|
is_tar_sdist,
|
|
35
37
|
is_wheel,
|
|
@@ -43,6 +45,7 @@ from pex.network_configuration import NetworkConfiguration
|
|
|
43
45
|
from pex.orderedset import OrderedSet
|
|
44
46
|
from pex.pep_425 import CompatibilityTags
|
|
45
47
|
from pex.pep_427 import InstallableType, WheelError, install_wheel_chroot
|
|
48
|
+
from pex.pep_440 import Version
|
|
46
49
|
from pex.pep_503 import ProjectName
|
|
47
50
|
from pex.pip.download_observer import DownloadObserver
|
|
48
51
|
from pex.pip.installation import get_pip
|
|
@@ -63,6 +66,7 @@ from pex.resolve.resolvers import (
|
|
|
63
66
|
)
|
|
64
67
|
from pex.resolve.target_system import TargetSystem, UniversalTarget
|
|
65
68
|
from pex.targets import AbbreviatedPlatform, CompletePlatform, LocalInterpreter, Target, Targets
|
|
69
|
+
from pex.third_party.packaging.specifiers import SpecifierSet
|
|
66
70
|
from pex.third_party.packaging.tags import Tag
|
|
67
71
|
from pex.tracer import TRACER
|
|
68
72
|
from pex.typing import TYPE_CHECKING
|
|
@@ -239,7 +243,52 @@ class PipLogManager(object):
|
|
|
239
243
|
|
|
240
244
|
|
|
241
245
|
@attr.s(frozen=True)
|
|
242
|
-
class
|
|
246
|
+
class Report(object):
|
|
247
|
+
@classmethod
|
|
248
|
+
def parse(
|
|
249
|
+
cls,
|
|
250
|
+
download_target, # type: DownloadTarget
|
|
251
|
+
report, # type: str
|
|
252
|
+
):
|
|
253
|
+
# type: (...) -> Report
|
|
254
|
+
|
|
255
|
+
with open(report) as fp:
|
|
256
|
+
data = json.load(fp)
|
|
257
|
+
|
|
258
|
+
project_metadata = [] # type: List[ProjectMetadata]
|
|
259
|
+
for distribution in data["install"]:
|
|
260
|
+
metadata = distribution["metadata"]
|
|
261
|
+
project_metadata.append(
|
|
262
|
+
ProjectMetadata(
|
|
263
|
+
project_name=ProjectName(metadata["name"]),
|
|
264
|
+
version=Version(metadata["version"]),
|
|
265
|
+
requires_python=SpecifierSet(metadata.get("requires_python", "")),
|
|
266
|
+
requires_dists=tuple(
|
|
267
|
+
Requirement.parse(requirement)
|
|
268
|
+
for requirement in metadata.get("requires_dist", ())
|
|
269
|
+
),
|
|
270
|
+
)
|
|
271
|
+
)
|
|
272
|
+
return cls(
|
|
273
|
+
download_target=download_target,
|
|
274
|
+
metadata={metadata.project_name: metadata for metadata in project_metadata},
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
download_target = attr.ib() # type: DownloadTarget
|
|
278
|
+
metadata = attr.ib() # type: Mapping[ProjectName, ProjectMetadata]
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
@attr.s(frozen=True)
|
|
282
|
+
class Reports(object):
|
|
283
|
+
reports = attr.ib(default=()) # type: Tuple[Report, ...]
|
|
284
|
+
|
|
285
|
+
def __iter__(self):
|
|
286
|
+
# type: () -> Iterator[Report]
|
|
287
|
+
return iter(self.reports)
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
@attr.s(frozen=True)
|
|
291
|
+
class _PipSession(object):
|
|
243
292
|
requests = attr.ib(converter=_uniqued_download_requests) # type: Tuple[DownloadRequest, ...]
|
|
244
293
|
direct_requirements = attr.ib() # type: Iterable[ParsedRequirement]
|
|
245
294
|
allow_prereleases = attr.ib(default=False) # type: bool
|
|
@@ -266,8 +315,108 @@ class _DownloadSession(object):
|
|
|
266
315
|
pip_version=self.pip_version,
|
|
267
316
|
)
|
|
268
317
|
|
|
318
|
+
def generate_reports(self, max_parallel_jobs=None):
|
|
319
|
+
# type: (Optional[int]) -> Reports
|
|
320
|
+
|
|
321
|
+
if not self.requests or not any(request.has_requirements for request in self.requests):
|
|
322
|
+
# Nothing to report.
|
|
323
|
+
return Reports()
|
|
324
|
+
|
|
325
|
+
dest = safe_mkdtemp(
|
|
326
|
+
prefix="resolver_report.", dir=safe_mkdir(CacheDir.DOWNLOADS.path(".tmp"))
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
log_manager = PipLogManager.create(
|
|
330
|
+
self.pip_log,
|
|
331
|
+
download_targets=tuple(request.download_target for request in self.requests),
|
|
332
|
+
)
|
|
333
|
+
if self.pip_log and not self.pip_log.user_specified:
|
|
334
|
+
TRACER.log(
|
|
335
|
+
"Preserving `pip install --dry-run` log at {log_path}".format(
|
|
336
|
+
log_path=self.pip_log.path
|
|
337
|
+
),
|
|
338
|
+
V=ENV.PEX_VERBOSE,
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
spawn_report = functools.partial(
|
|
342
|
+
self._spawn_report, resolved_target_dir=dest, log_manager=log_manager
|
|
343
|
+
)
|
|
344
|
+
with TRACER.timed(
|
|
345
|
+
"Resolving for:\n {}".format(
|
|
346
|
+
"\n ".join(request.render_description() for request in self.requests)
|
|
347
|
+
)
|
|
348
|
+
):
|
|
349
|
+
try:
|
|
350
|
+
return Reports(
|
|
351
|
+
reports=tuple(
|
|
352
|
+
Report.parse(download_request.download_target, report)
|
|
353
|
+
for download_request, report in zip(
|
|
354
|
+
self.requests,
|
|
355
|
+
execute_parallel(
|
|
356
|
+
inputs=self.requests,
|
|
357
|
+
spawn_func=spawn_report,
|
|
358
|
+
error_handler=Raise[DownloadRequest, str](Unsatisfiable),
|
|
359
|
+
max_jobs=max_parallel_jobs,
|
|
360
|
+
),
|
|
361
|
+
)
|
|
362
|
+
)
|
|
363
|
+
)
|
|
364
|
+
finally:
|
|
365
|
+
log_manager.finalize_log()
|
|
366
|
+
|
|
367
|
+
def _spawn_report(
|
|
368
|
+
self,
|
|
369
|
+
request, # type: DownloadRequest
|
|
370
|
+
resolved_target_dir, # type: str
|
|
371
|
+
log_manager, # type: PipLogManager
|
|
372
|
+
):
|
|
373
|
+
# type: (...) -> SpawnedJob[str]
|
|
374
|
+
|
|
375
|
+
report_dir = safe_mkdir(
|
|
376
|
+
os.path.join(resolved_target_dir, request.download_target.id(complete=True))
|
|
377
|
+
)
|
|
378
|
+
report = os.path.join(report_dir, "pip-report.json")
|
|
379
|
+
download_target = request.download_target
|
|
380
|
+
observer = (
|
|
381
|
+
self.observer.observe_download(
|
|
382
|
+
download_target=download_target, download_dir=resolved_target_dir
|
|
383
|
+
)
|
|
384
|
+
if self.observer
|
|
385
|
+
else None
|
|
386
|
+
)
|
|
387
|
+
|
|
388
|
+
target = download_target.target
|
|
389
|
+
|
|
390
|
+
download_job = get_pip(
|
|
391
|
+
interpreter=target.get_interpreter(),
|
|
392
|
+
version=self.pip_version,
|
|
393
|
+
resolver=self.resolver,
|
|
394
|
+
extra_requirements=(
|
|
395
|
+
self.package_index_configuration.extra_pip_requirements
|
|
396
|
+
if self.package_index_configuration
|
|
397
|
+
else ()
|
|
398
|
+
),
|
|
399
|
+
).spawn_report(
|
|
400
|
+
report_path=report,
|
|
401
|
+
requirements=request.requirements,
|
|
402
|
+
requirement_files=request.requirement_files,
|
|
403
|
+
constraint_files=request.constraint_files,
|
|
404
|
+
allow_prereleases=self.allow_prereleases,
|
|
405
|
+
transitive=self.transitive,
|
|
406
|
+
target=target,
|
|
407
|
+
package_index_configuration=self.package_index_configuration,
|
|
408
|
+
build_configuration=self.build_configuration,
|
|
409
|
+
observer=observer,
|
|
410
|
+
dependency_configuration=self.dependency_configuration,
|
|
411
|
+
universal_target=download_target.universal_target,
|
|
412
|
+
log=log_manager.get_log(download_target),
|
|
413
|
+
)
|
|
414
|
+
|
|
415
|
+
return SpawnedJob.wait(job=download_job, result=report)
|
|
416
|
+
|
|
269
417
|
def download_distributions(self, dest=None, max_parallel_jobs=None):
|
|
270
418
|
# type: (...) -> List[DownloadResult]
|
|
419
|
+
|
|
271
420
|
if not self.requests or not any(request.has_requirements for request in self.requests):
|
|
272
421
|
# Nothing to resolve.
|
|
273
422
|
return []
|
|
@@ -1515,7 +1664,7 @@ def _download_internal(
|
|
|
1515
1664
|
):
|
|
1516
1665
|
# type: (...) -> Tuple[List[BuildRequest], List[DownloadResult]]
|
|
1517
1666
|
|
|
1518
|
-
|
|
1667
|
+
pip_session = _PipSession(
|
|
1519
1668
|
requests=requests,
|
|
1520
1669
|
direct_requirements=direct_requirements,
|
|
1521
1670
|
allow_prereleases=allow_prereleases,
|
|
@@ -1529,8 +1678,8 @@ def _download_internal(
|
|
|
1529
1678
|
dependency_configuration=dependency_configuration,
|
|
1530
1679
|
)
|
|
1531
1680
|
|
|
1532
|
-
local_projects = list(
|
|
1533
|
-
download_results =
|
|
1681
|
+
local_projects = list(pip_session.iter_local_projects())
|
|
1682
|
+
download_results = pip_session.download_distributions(
|
|
1534
1683
|
dest=dest, max_parallel_jobs=max_parallel_jobs
|
|
1535
1684
|
)
|
|
1536
1685
|
return local_projects, download_results
|
|
@@ -1780,3 +1929,51 @@ def download_requests(
|
|
|
1780
1929
|
)
|
|
1781
1930
|
|
|
1782
1931
|
return Downloaded(local_distributions=tuple(local_distributions))
|
|
1932
|
+
|
|
1933
|
+
|
|
1934
|
+
def reports(
|
|
1935
|
+
requests, # type: Tuple[DownloadRequest, ...]
|
|
1936
|
+
direct_requirements, # type: Tuple[ParsedRequirement, ...]
|
|
1937
|
+
allow_prereleases=False, # type: bool
|
|
1938
|
+
transitive=True, # type: bool
|
|
1939
|
+
repos_configuration=ReposConfiguration(), # type: ReposConfiguration
|
|
1940
|
+
resolver_version=None, # type: Optional[ResolverVersion.Value]
|
|
1941
|
+
network_configuration=None, # type: Optional[NetworkConfiguration]
|
|
1942
|
+
build_configuration=BuildConfiguration(), # type: BuildConfiguration
|
|
1943
|
+
max_parallel_jobs=None, # type: Optional[int]
|
|
1944
|
+
observer=None, # type: Optional[ResolveObserver]
|
|
1945
|
+
pip_log=None, # type: Optional[PipLog]
|
|
1946
|
+
pip_version=None, # type: Optional[PipVersionValue]
|
|
1947
|
+
resolver=None, # type: Optional[Resolver]
|
|
1948
|
+
use_pip_config=False, # type: bool
|
|
1949
|
+
extra_pip_requirements=(), # type: Tuple[Requirement, ...]
|
|
1950
|
+
keyring_provider=None, # type: Optional[str]
|
|
1951
|
+
dependency_configuration=DependencyConfiguration(), # type: DependencyConfiguration
|
|
1952
|
+
):
|
|
1953
|
+
# type: (...) -> Reports
|
|
1954
|
+
|
|
1955
|
+
package_index_configuration = PackageIndexConfiguration.create(
|
|
1956
|
+
pip_version=pip_version,
|
|
1957
|
+
resolver_version=resolver_version,
|
|
1958
|
+
repos_configuration=repos_configuration,
|
|
1959
|
+
network_configuration=network_configuration,
|
|
1960
|
+
use_pip_config=use_pip_config,
|
|
1961
|
+
extra_pip_requirements=extra_pip_requirements,
|
|
1962
|
+
keyring_provider=keyring_provider,
|
|
1963
|
+
)
|
|
1964
|
+
|
|
1965
|
+
pip_session = _PipSession(
|
|
1966
|
+
requests=requests,
|
|
1967
|
+
direct_requirements=direct_requirements,
|
|
1968
|
+
allow_prereleases=allow_prereleases,
|
|
1969
|
+
transitive=transitive,
|
|
1970
|
+
package_index_configuration=package_index_configuration,
|
|
1971
|
+
build_configuration=build_configuration,
|
|
1972
|
+
observer=observer,
|
|
1973
|
+
pip_log=pip_log,
|
|
1974
|
+
pip_version=pip_version,
|
|
1975
|
+
resolver=resolver,
|
|
1976
|
+
dependency_configuration=dependency_configuration,
|
|
1977
|
+
)
|
|
1978
|
+
|
|
1979
|
+
return pip_session.generate_reports(max_parallel_jobs=max_parallel_jobs)
|
pex/version.py
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pex
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.64.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.64.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.64.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.64.0
|
|
13
13
|
Keywords: package,executable,virtualenv,lock,freeze
|
|
14
14
|
Classifier: Development Status :: 5 - Production/Stable
|
|
15
15
|
Classifier: Intended Audience :: Developers
|