pex 2.54.2__py2.py3-none-any.whl → 2.69.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/auth.py +1 -1
- pex/bin/pex.py +15 -2
- pex/build_backend/configuration.py +5 -5
- pex/build_backend/wrap.py +27 -23
- pex/build_system/pep_517.py +4 -1
- pex/cache/dirs.py +17 -12
- pex/cli/commands/lock.py +302 -165
- pex/cli/commands/pip/core.py +4 -12
- pex/cli/commands/pip/wheel.py +1 -1
- pex/cli/commands/run.py +13 -20
- pex/cli/commands/venv.py +85 -16
- pex/cli/pex.py +11 -4
- pex/common.py +57 -7
- pex/compatibility.py +1 -1
- pex/dependency_configuration.py +87 -15
- pex/dist_metadata.py +143 -25
- pex/docs/html/_pagefind/fragment/en_4250138.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_7125dad.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_785d562.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_8e94bb8.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_a0396bb.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_a8a3588.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_c07d988.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_d718411.pf_fragment +0 -0
- pex/docs/html/_pagefind/index/en_a2e3c5e.pf_index +0 -0
- pex/docs/html/_pagefind/pagefind-entry.json +1 -1
- pex/docs/html/_pagefind/pagefind.en_4ce1afa9e3.pf_meta +0 -0
- pex/docs/html/_static/documentation_options.js +1 -1
- pex/docs/html/_static/pygments.css +164 -146
- pex/docs/html/_static/styles/furo.css +1 -1
- pex/docs/html/_static/styles/furo.css.map +1 -1
- pex/docs/html/api/vars.html +25 -34
- pex/docs/html/buildingpex.html +25 -34
- pex/docs/html/genindex.html +24 -33
- pex/docs/html/index.html +25 -34
- pex/docs/html/recipes.html +25 -34
- pex/docs/html/scie.html +25 -34
- pex/docs/html/search.html +24 -33
- pex/docs/html/whatispex.html +25 -34
- pex/entry_points_txt.py +98 -0
- pex/environment.py +54 -33
- pex/finders.py +1 -1
- pex/hashing.py +71 -9
- pex/installed_wheel.py +141 -0
- pex/interpreter.py +41 -38
- pex/interpreter_constraints.py +25 -25
- pex/interpreter_implementation.py +40 -0
- pex/jobs.py +13 -6
- pex/pep_376.py +68 -384
- pex/pep_425.py +11 -2
- pex/pep_427.py +937 -205
- pex/pep_508.py +4 -5
- pex/pex_builder.py +5 -8
- pex/pex_info.py +14 -9
- pex/pip/dependencies/__init__.py +85 -13
- pex/pip/dependencies/requires.py +38 -3
- pex/pip/foreign_platform/__init__.py +4 -3
- pex/pip/installation.py +2 -2
- pex/pip/local_project.py +6 -14
- pex/pip/package_repositories/__init__.py +78 -0
- pex/pip/package_repositories/link_collector.py +96 -0
- pex/pip/tool.py +139 -33
- pex/pip/vcs.py +109 -43
- pex/pip/version.py +8 -1
- pex/requirements.py +121 -16
- pex/resolve/config.py +5 -1
- pex/resolve/configured_resolve.py +32 -10
- pex/resolve/configured_resolver.py +10 -39
- pex/resolve/downloads.py +4 -3
- pex/resolve/lock_downloader.py +16 -23
- pex/resolve/lock_resolver.py +41 -51
- pex/resolve/locked_resolve.py +89 -32
- pex/resolve/locker.py +145 -101
- pex/resolve/locker_patches.py +123 -197
- pex/resolve/lockfile/create.py +232 -87
- pex/resolve/lockfile/download_manager.py +5 -1
- pex/resolve/lockfile/json_codec.py +103 -28
- pex/resolve/lockfile/model.py +13 -35
- pex/resolve/lockfile/pep_751.py +117 -98
- pex/resolve/lockfile/requires_dist.py +17 -262
- pex/resolve/lockfile/subset.py +11 -0
- pex/resolve/lockfile/targets.py +445 -0
- pex/resolve/lockfile/updater.py +22 -10
- pex/resolve/package_repository.py +406 -0
- pex/resolve/pex_repository_resolver.py +1 -1
- pex/resolve/pre_resolved_resolver.py +19 -16
- pex/resolve/project.py +233 -47
- pex/resolve/requirement_configuration.py +28 -10
- pex/resolve/resolver_configuration.py +18 -32
- pex/resolve/resolver_options.py +234 -28
- pex/resolve/resolvers.py +3 -12
- pex/resolve/target_options.py +18 -2
- pex/resolve/target_system.py +908 -0
- pex/resolve/venv_resolver.py +670 -0
- pex/resolver.py +673 -209
- pex/scie/__init__.py +40 -1
- pex/scie/model.py +2 -0
- pex/scie/science.py +25 -3
- pex/sdist.py +219 -0
- pex/sh_boot.py +24 -21
- pex/sysconfig.py +5 -3
- pex/targets.py +31 -10
- pex/third_party/__init__.py +1 -1
- pex/tools/commands/repository.py +48 -25
- pex/vendor/__init__.py +4 -9
- pex/vendor/__main__.py +65 -41
- pex/vendor/_vendored/ansicolors/.layout.json +1 -1
- pex/vendor/_vendored/ansicolors/ansicolors-1.1.8.dist-info/RECORD +11 -0
- pex/vendor/_vendored/ansicolors/ansicolors-1.1.8.pex-info/original-whl-info.json +1 -0
- pex/vendor/_vendored/appdirs/.layout.json +1 -1
- pex/vendor/_vendored/appdirs/appdirs-1.4.4.dist-info/RECORD +7 -0
- pex/vendor/_vendored/appdirs/appdirs-1.4.4.pex-info/original-whl-info.json +1 -0
- pex/vendor/_vendored/attrs/.layout.json +1 -1
- pex/vendor/_vendored/attrs/attrs-21.5.0.dev0.dist-info/RECORD +37 -0
- pex/vendor/_vendored/attrs/attrs-21.5.0.dev0.pex-info/original-whl-info.json +1 -0
- pex/vendor/_vendored/packaging_20_9/.layout.json +1 -1
- pex/vendor/_vendored/packaging_20_9/packaging-20.9.dist-info/RECORD +20 -0
- pex/vendor/_vendored/packaging_20_9/packaging-20.9.pex-info/original-whl-info.json +1 -0
- pex/vendor/_vendored/packaging_20_9/pyparsing-2.4.7.dist-info/RECORD +7 -0
- pex/vendor/_vendored/packaging_20_9/pyparsing-2.4.7.pex-info/original-whl-info.json +1 -0
- pex/vendor/_vendored/packaging_21_3/.layout.json +1 -1
- pex/vendor/_vendored/packaging_21_3/packaging-21.3.dist-info/RECORD +20 -0
- pex/vendor/_vendored/packaging_21_3/packaging-21.3.pex-info/original-whl-info.json +1 -0
- pex/vendor/_vendored/packaging_21_3/pyparsing-3.0.7.dist-info/RECORD +18 -0
- pex/vendor/_vendored/packaging_21_3/pyparsing-3.0.7.pex-info/original-whl-info.json +1 -0
- pex/vendor/_vendored/packaging_24_0/.layout.json +1 -1
- pex/vendor/_vendored/packaging_24_0/packaging-24.0.dist-info/RECORD +22 -0
- pex/vendor/_vendored/packaging_24_0/packaging-24.0.pex-info/original-whl-info.json +1 -0
- pex/vendor/_vendored/packaging_25_0/.layout.json +1 -1
- pex/vendor/_vendored/packaging_25_0/packaging-25.0.dist-info/RECORD +24 -0
- pex/vendor/_vendored/packaging_25_0/packaging-25.0.pex-info/original-whl-info.json +1 -0
- pex/vendor/_vendored/pip/.layout.json +1 -1
- pex/vendor/_vendored/pip/pip/_vendor/certifi/cacert.pem +63 -1
- pex/vendor/_vendored/pip/pip-20.3.4.dist-info/RECORD +388 -0
- pex/vendor/_vendored/pip/pip-20.3.4.pex-info/original-whl-info.json +1 -0
- pex/vendor/_vendored/setuptools/.layout.json +1 -1
- pex/vendor/_vendored/setuptools/setuptools-44.0.0+3acb925dd708430aeaf197ea53ac8a752f7c1863.dist-info/RECORD +107 -0
- pex/vendor/_vendored/setuptools/setuptools-44.0.0+3acb925dd708430aeaf197ea53ac8a752f7c1863.pex-info/original-whl-info.json +1 -0
- pex/vendor/_vendored/toml/.layout.json +1 -1
- pex/vendor/_vendored/toml/toml-0.10.2.dist-info/RECORD +11 -0
- pex/vendor/_vendored/toml/toml-0.10.2.pex-info/original-whl-info.json +1 -0
- pex/vendor/_vendored/tomli/.layout.json +1 -1
- pex/vendor/_vendored/tomli/tomli-2.0.1.dist-info/RECORD +10 -0
- pex/vendor/_vendored/tomli/tomli-2.0.1.pex-info/original-whl-info.json +1 -0
- pex/venv/installer.py +46 -19
- pex/venv/venv_pex.py +6 -3
- pex/version.py +1 -1
- pex/wheel.py +188 -40
- pex/whl.py +67 -0
- pex/windows/__init__.py +14 -11
- {pex-2.54.2.dist-info → pex-2.69.0.dist-info}/METADATA +6 -5
- {pex-2.54.2.dist-info → pex-2.69.0.dist-info}/RECORD +157 -133
- {pex-2.54.2.dist-info → pex-2.69.0.dist-info}/entry_points.txt +1 -0
- {pex-2.54.2.dist-info → pex-2.69.0.dist-info}/pylock/pylock.toml +1 -1
- pex/docs/html/_pagefind/fragment/en_42c9d8c.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_45dd5a2.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_4ca74d2.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_77273d5.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_87a59c5.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_8dc89b5.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_9d1319b.pf_fragment +0 -0
- pex/docs/html/_pagefind/fragment/en_e55df9d.pf_fragment +0 -0
- pex/docs/html/_pagefind/index/en_1e98c6f.pf_index +0 -0
- pex/docs/html/_pagefind/pagefind.en_d1c488ecae.pf_meta +0 -0
- pex/vendor/_vendored/ansicolors/ansicolors-1.1.8.dist-info/INSTALLER +0 -1
- pex/vendor/_vendored/appdirs/appdirs-1.4.4.dist-info/INSTALLER +0 -1
- pex/vendor/_vendored/attrs/attrs-21.5.0.dev0.dist-info/INSTALLER +0 -1
- pex/vendor/_vendored/packaging_20_9/packaging-20.9.dist-info/INSTALLER +0 -1
- pex/vendor/_vendored/packaging_20_9/pyparsing-2.4.7.dist-info/INSTALLER +0 -1
- pex/vendor/_vendored/packaging_21_3/packaging-21.3.dist-info/INSTALLER +0 -1
- pex/vendor/_vendored/packaging_21_3/pyparsing-3.0.7.dist-info/INSTALLER +0 -1
- pex/vendor/_vendored/packaging_24_0/packaging-24.0.dist-info/INSTALLER +0 -1
- pex/vendor/_vendored/packaging_25_0/packaging-25.0.dist-info/INSTALLER +0 -1
- pex/vendor/_vendored/pip/pip-20.3.4.dist-info/INSTALLER +0 -1
- pex/vendor/_vendored/setuptools/setuptools-44.0.0+3acb925dd708430aeaf197ea53ac8a752f7c1863.dist-info/INSTALLER +0 -1
- pex/vendor/_vendored/toml/toml-0.10.2.dist-info/INSTALLER +0 -1
- pex/vendor/_vendored/tomli/tomli-2.0.1.dist-info/INSTALLER +0 -1
- {pex-2.54.2.dist-info → pex-2.69.0.dist-info}/WHEEL +0 -0
- {pex-2.54.2.dist-info → pex-2.69.0.dist-info}/licenses/LICENSE +0 -0
- {pex-2.54.2.dist-info → pex-2.69.0.dist-info}/top_level.txt +0 -0
pex/cli/commands/pip/core.py
CHANGED
|
@@ -133,11 +133,9 @@ def download_distributions(configuration):
|
|
|
133
133
|
requirements=requirement_configuration.requirements,
|
|
134
134
|
requirement_files=requirement_configuration.requirement_files,
|
|
135
135
|
constraint_files=requirement_configuration.constraint_files,
|
|
136
|
-
|
|
137
|
-
find_links=resolver_configuration.repos_configuration.find_links,
|
|
136
|
+
repos_configuration=resolver_configuration.repos_configuration,
|
|
138
137
|
resolver_version=pip_configuration.resolver_version,
|
|
139
138
|
network_configuration=resolver_configuration.network_configuration,
|
|
140
|
-
password_entries=pip_configuration.repos_configuration.password_entries,
|
|
141
139
|
build_configuration=pip_configuration.build_configuration,
|
|
142
140
|
transitive=pip_configuration.transitive,
|
|
143
141
|
max_parallel_jobs=pip_configuration.max_jobs,
|
|
@@ -162,11 +160,9 @@ def download_distributions(configuration):
|
|
|
162
160
|
extras=resolver_configuration.extras,
|
|
163
161
|
dependency_groups=resolver_configuration.dependency_groups,
|
|
164
162
|
constraint_files=requirement_configuration.constraint_files,
|
|
165
|
-
|
|
166
|
-
find_links=resolver_configuration.repos_configuration.find_links,
|
|
163
|
+
repos_configuration=resolver_configuration.repos_configuration,
|
|
167
164
|
resolver_version=pip_configuration.resolver_version,
|
|
168
165
|
network_configuration=resolver_configuration.network_configuration,
|
|
169
|
-
password_entries=pip_configuration.repos_configuration.password_entries,
|
|
170
166
|
build_configuration=pip_configuration.build_configuration,
|
|
171
167
|
transitive=pip_configuration.transitive,
|
|
172
168
|
max_parallel_jobs=pip_configuration.max_jobs,
|
|
@@ -188,11 +184,9 @@ def download_distributions(configuration):
|
|
|
188
184
|
constraint_files=requirement_configuration.constraint_files,
|
|
189
185
|
allow_prereleases=pip_configuration.allow_prereleases,
|
|
190
186
|
transitive=pip_configuration.transitive,
|
|
191
|
-
|
|
192
|
-
find_links=resolver_configuration.repos_configuration.find_links,
|
|
187
|
+
repos_configuration=resolver_configuration.repos_configuration,
|
|
193
188
|
resolver_version=pip_configuration.resolver_version,
|
|
194
189
|
network_configuration=resolver_configuration.network_configuration,
|
|
195
|
-
password_entries=pip_configuration.repos_configuration.password_entries,
|
|
196
190
|
build_configuration=pip_configuration.build_configuration,
|
|
197
191
|
max_parallel_jobs=pip_configuration.max_jobs,
|
|
198
192
|
pip_log=pip_configuration.log,
|
|
@@ -229,10 +223,8 @@ def build_wheels(
|
|
|
229
223
|
package_index_configuration=PackageIndexConfiguration.create(
|
|
230
224
|
pip_version=configuration.pip_configuration.version,
|
|
231
225
|
resolver_version=configuration.pip_configuration.resolver_version,
|
|
232
|
-
|
|
233
|
-
find_links=configuration.pip_configuration.repos_configuration.find_links,
|
|
226
|
+
repos_configuration=configuration.pip_configuration.repos_configuration,
|
|
234
227
|
network_configuration=configuration.pip_configuration.network_configuration,
|
|
235
|
-
password_entries=configuration.pip_configuration.repos_configuration.password_entries,
|
|
236
228
|
use_pip_config=configuration.pip_configuration.use_pip_config,
|
|
237
229
|
extra_pip_requirements=configuration.pip_configuration.extra_requirements,
|
|
238
230
|
keyring_provider=configuration.pip_configuration.keyring_provider,
|
pex/cli/commands/pip/wheel.py
CHANGED
pex/cli/commands/run.py
CHANGED
|
@@ -10,12 +10,11 @@ import os.path
|
|
|
10
10
|
import posixpath
|
|
11
11
|
import shutil
|
|
12
12
|
import sys
|
|
13
|
-
import tarfile
|
|
14
13
|
from argparse import _ActionsContainer
|
|
15
|
-
from contextlib import closing
|
|
16
14
|
|
|
17
15
|
from pex import dependency_configuration, interpreter
|
|
18
16
|
from pex import resolver as pip_resolver
|
|
17
|
+
from pex import sdist
|
|
19
18
|
from pex.artifact_url import ArtifactURL, Fingerprint
|
|
20
19
|
from pex.atomic_directory import atomic_directory
|
|
21
20
|
from pex.build_system import pep_517
|
|
@@ -616,11 +615,9 @@ class Run(CacheAwareMixin, BuildTimeCommand):
|
|
|
616
615
|
constraint_files=run_spec.all_requirements.constraint_files,
|
|
617
616
|
allow_prereleases=pip_configuration.allow_prereleases,
|
|
618
617
|
transitive=False,
|
|
619
|
-
|
|
620
|
-
find_links=pip_configuration.repos_configuration.find_links,
|
|
618
|
+
repos_configuration=pip_configuration.repos_configuration,
|
|
621
619
|
resolver_version=pip_configuration.resolver_version,
|
|
622
620
|
network_configuration=pip_configuration.network_configuration,
|
|
623
|
-
password_entries=pip_configuration.repos_configuration.password_entries,
|
|
624
621
|
build_configuration=pip_configuration.build_configuration,
|
|
625
622
|
max_parallel_jobs=pip_configuration.max_jobs,
|
|
626
623
|
pip_log=pip_configuration.log,
|
|
@@ -678,19 +675,19 @@ class Run(CacheAwareMixin, BuildTimeCommand):
|
|
|
678
675
|
return package, os.path.join(lock_dest_dir, lock_path)
|
|
679
676
|
elif is_sdist(distribution.path):
|
|
680
677
|
if is_tar_sdist(distribution.path):
|
|
681
|
-
|
|
682
|
-
tf.extractall(lock_dest_dir)
|
|
678
|
+
sdist_root = sdist.extract_tarball(distribution.path, dest_dir=lock_dest_dir)
|
|
683
679
|
else:
|
|
684
680
|
with open_zip(distribution.path) as zf:
|
|
685
681
|
zf.extractall(lock_dest_dir)
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
682
|
+
entries = glob.glob(os.path.join(lock_dest_dir, "*"))
|
|
683
|
+
if len(entries) != 1:
|
|
684
|
+
return Error(
|
|
685
|
+
"Expected {sdist} to have 1 entry, found {count}: {entries}".format(
|
|
686
|
+
sdist=distribution.path, count=len(entries), entries=entries
|
|
687
|
+
)
|
|
691
688
|
)
|
|
692
|
-
|
|
693
|
-
|
|
689
|
+
sdist_root = entries[0]
|
|
690
|
+
|
|
694
691
|
for lock_name in run_spec.locks:
|
|
695
692
|
lock_path = os.path.join(sdist_root, lock_name)
|
|
696
693
|
if os.path.exists(lock_path):
|
|
@@ -724,11 +721,9 @@ class Run(CacheAwareMixin, BuildTimeCommand):
|
|
|
724
721
|
requirements=run_spec.all_requirements.requirements,
|
|
725
722
|
requirement_files=run_spec.all_requirements.requirement_files,
|
|
726
723
|
constraint_files=run_spec.all_requirements.constraint_files,
|
|
727
|
-
|
|
728
|
-
find_links=pip_configuration.repos_configuration.find_links,
|
|
724
|
+
repos_configuration=pip_configuration.repos_configuration,
|
|
729
725
|
resolver_version=pip_configuration.resolver_version,
|
|
730
726
|
network_configuration=pip_configuration.network_configuration,
|
|
731
|
-
password_entries=pip_configuration.repos_configuration.password_entries,
|
|
732
727
|
build_configuration=pip_configuration.build_configuration,
|
|
733
728
|
transitive=pip_configuration.transitive,
|
|
734
729
|
max_parallel_jobs=pip_configuration.max_jobs,
|
|
@@ -746,11 +741,9 @@ class Run(CacheAwareMixin, BuildTimeCommand):
|
|
|
746
741
|
constraint_files=run_spec.all_requirements.constraint_files,
|
|
747
742
|
allow_prereleases=pip_configuration.allow_prereleases,
|
|
748
743
|
transitive=pip_configuration.transitive,
|
|
749
|
-
|
|
750
|
-
find_links=pip_configuration.repos_configuration.find_links,
|
|
744
|
+
repos_configuration=pip_configuration.repos_configuration,
|
|
751
745
|
resolver_version=pip_configuration.resolver_version,
|
|
752
746
|
network_configuration=pip_configuration.network_configuration,
|
|
753
|
-
password_entries=pip_configuration.repos_configuration.password_entries,
|
|
754
747
|
build_configuration=pip_configuration.build_configuration,
|
|
755
748
|
max_parallel_jobs=pip_configuration.max_jobs,
|
|
756
749
|
pip_log=pip_configuration.log,
|
pex/cli/commands/venv.py
CHANGED
|
@@ -8,14 +8,17 @@ import logging
|
|
|
8
8
|
import os.path
|
|
9
9
|
from argparse import ArgumentParser, _ActionsContainer
|
|
10
10
|
|
|
11
|
-
from pex import pex_warnings
|
|
11
|
+
from pex import dependency_configuration, pex_warnings
|
|
12
12
|
from pex.cli.command import BuildTimeCommand
|
|
13
13
|
from pex.commands.command import JsonMixin, OutputMixin
|
|
14
14
|
from pex.common import CopyMode, open_zip, pluralize
|
|
15
|
-
from pex.
|
|
15
|
+
from pex.dependency_configuration import DependencyConfiguration
|
|
16
|
+
from pex.dist_metadata import Distribution, Requirement
|
|
16
17
|
from pex.enum import Enum
|
|
17
18
|
from pex.executables import is_python_script, is_script
|
|
18
19
|
from pex.executor import Executor
|
|
20
|
+
from pex.fingerprinted_distribution import FingerprintedDistribution
|
|
21
|
+
from pex.orderedset import OrderedSet
|
|
19
22
|
from pex.pex import PEX
|
|
20
23
|
from pex.pex_info import PexInfo
|
|
21
24
|
from pex.resolve import configured_resolve, requirement_options, resolver_options, target_options
|
|
@@ -23,6 +26,7 @@ from pex.resolve.resolver_configuration import (
|
|
|
23
26
|
LockRepositoryConfiguration,
|
|
24
27
|
PexRepositoryConfiguration,
|
|
25
28
|
PipConfiguration,
|
|
29
|
+
PylockRepositoryConfiguration,
|
|
26
30
|
)
|
|
27
31
|
from pex.result import Error, Ok, Result, try_
|
|
28
32
|
from pex.targets import LocalInterpreter, Target, Targets
|
|
@@ -35,7 +39,7 @@ from pex.venv.installer_configuration import InstallerConfiguration
|
|
|
35
39
|
from pex.venv.virtualenv import Virtualenv
|
|
36
40
|
|
|
37
41
|
if TYPE_CHECKING:
|
|
38
|
-
from typing import Any, Dict, Iterable, Optional
|
|
42
|
+
from typing import Any, Dict, Iterable, Optional, Sequence
|
|
39
43
|
|
|
40
44
|
|
|
41
45
|
logger = logging.getLogger(__name__)
|
|
@@ -123,8 +127,10 @@ class Venv(OutputMixin, JsonMixin, BuildTimeCommand):
|
|
|
123
127
|
include_pex_lock=True,
|
|
124
128
|
include_pylock=True,
|
|
125
129
|
include_pre_resolved=True,
|
|
130
|
+
include_venv_repository=True,
|
|
126
131
|
)
|
|
127
132
|
requirement_options.register(parser)
|
|
133
|
+
dependency_configuration.register(parser)
|
|
128
134
|
|
|
129
135
|
@classmethod
|
|
130
136
|
def add_extra_arguments(
|
|
@@ -285,11 +291,13 @@ class Venv(OutputMixin, JsonMixin, BuildTimeCommand):
|
|
|
285
291
|
)
|
|
286
292
|
|
|
287
293
|
requirement_configuration = requirement_options.configure(self.options)
|
|
294
|
+
dependency_config = dependency_configuration.configure(self.options)
|
|
288
295
|
with TRACER.timed("Resolving distributions"):
|
|
289
296
|
resolved = configured_resolve.resolve(
|
|
290
297
|
targets=targets,
|
|
291
298
|
requirement_configuration=requirement_configuration,
|
|
292
299
|
resolver_configuration=resolver_configuration,
|
|
300
|
+
dependency_configuration=dependency_config,
|
|
293
301
|
)
|
|
294
302
|
|
|
295
303
|
pex = None # type: Optional[PEX]
|
|
@@ -298,6 +306,8 @@ class Venv(OutputMixin, JsonMixin, BuildTimeCommand):
|
|
|
298
306
|
pex = PEX(resolver_configuration.pex_repository, interpreter=target.get_interpreter())
|
|
299
307
|
elif isinstance(resolver_configuration, LockRepositoryConfiguration):
|
|
300
308
|
lock = resolver_configuration.lock_file_path
|
|
309
|
+
elif isinstance(resolver_configuration, PylockRepositoryConfiguration):
|
|
310
|
+
lock = resolver_configuration.lock_file_path
|
|
301
311
|
|
|
302
312
|
with TRACER.timed(
|
|
303
313
|
"Installing {count} {wheels} in {subject} at {dest_dir}".format(
|
|
@@ -308,10 +318,6 @@ class Venv(OutputMixin, JsonMixin, BuildTimeCommand):
|
|
|
308
318
|
)
|
|
309
319
|
):
|
|
310
320
|
hermetic_scripts = not update and installer_configuration.hermetic_scripts
|
|
311
|
-
distributions = tuple(
|
|
312
|
-
resolved_distribution.distribution
|
|
313
|
-
for resolved_distribution in resolved.distributions
|
|
314
|
-
)
|
|
315
321
|
provenance = (
|
|
316
322
|
Provenance.create(venv=venv)
|
|
317
323
|
if venv
|
|
@@ -322,27 +328,41 @@ class Venv(OutputMixin, JsonMixin, BuildTimeCommand):
|
|
|
322
328
|
pex=pex,
|
|
323
329
|
installer_configuration=installer_configuration,
|
|
324
330
|
provenance=provenance,
|
|
325
|
-
distributions=
|
|
331
|
+
distributions=tuple(
|
|
332
|
+
resolved_distribution.distribution
|
|
333
|
+
for resolved_distribution in resolved.distributions
|
|
334
|
+
),
|
|
326
335
|
dest_dir=dest_dir,
|
|
327
336
|
hermetic_scripts=hermetic_scripts,
|
|
328
337
|
venv=venv,
|
|
329
338
|
)
|
|
330
339
|
elif venv:
|
|
331
|
-
|
|
340
|
+
_install_from_resolve(
|
|
332
341
|
venv=venv,
|
|
333
|
-
distributions=distributions,
|
|
334
342
|
provenance=provenance,
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
343
|
+
installer_configuration=installer_configuration,
|
|
344
|
+
dependency_config=dependency_config,
|
|
345
|
+
requirements=tuple(
|
|
346
|
+
OrderedSet(
|
|
347
|
+
itertools.chain.from_iterable(
|
|
348
|
+
resolved_distribution.direct_requirements
|
|
349
|
+
for resolved_distribution in resolved.distributions
|
|
350
|
+
)
|
|
351
|
+
)
|
|
352
|
+
),
|
|
353
|
+
distributions=tuple(
|
|
354
|
+
resolved_distribution.fingerprinted_distribution
|
|
355
|
+
for resolved_distribution in resolved.distributions
|
|
339
356
|
),
|
|
340
357
|
hermetic_scripts=hermetic_scripts,
|
|
341
358
|
)
|
|
342
359
|
else:
|
|
343
360
|
installer.populate_flat_distributions(
|
|
344
361
|
dest_dir=dest_dir,
|
|
345
|
-
distributions=
|
|
362
|
+
distributions=tuple(
|
|
363
|
+
resolved_distribution.distribution
|
|
364
|
+
for resolved_distribution in resolved.distributions
|
|
365
|
+
),
|
|
346
366
|
provenance=provenance,
|
|
347
367
|
copy_mode=(
|
|
348
368
|
CopyMode.COPY
|
|
@@ -366,7 +386,10 @@ class Venv(OutputMixin, JsonMixin, BuildTimeCommand):
|
|
|
366
386
|
try_(
|
|
367
387
|
installer.ensure_pip_installed(
|
|
368
388
|
venv,
|
|
369
|
-
distributions=
|
|
389
|
+
distributions=tuple(
|
|
390
|
+
resolved_distribution.distribution
|
|
391
|
+
for resolved_distribution in resolved.distributions
|
|
392
|
+
),
|
|
370
393
|
scope=installer_configuration.scope,
|
|
371
394
|
collisions_ok=installer_configuration.collisions_ok,
|
|
372
395
|
source=source,
|
|
@@ -439,3 +462,49 @@ def _install_from_pex(
|
|
|
439
462
|
)
|
|
440
463
|
else:
|
|
441
464
|
installer.populate_flat_sources(dst=dest_dir, pex=pex, provenance=provenance)
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
def _install_from_resolve(
|
|
468
|
+
venv, # type: Virtualenv
|
|
469
|
+
provenance, # type: Provenance
|
|
470
|
+
installer_configuration, # type: InstallerConfiguration
|
|
471
|
+
dependency_config, # type: DependencyConfiguration
|
|
472
|
+
requirements, # type: Sequence[Requirement]
|
|
473
|
+
distributions, # type: Sequence[FingerprintedDistribution]
|
|
474
|
+
hermetic_scripts, # type: bool
|
|
475
|
+
):
|
|
476
|
+
# type: (...) -> None
|
|
477
|
+
|
|
478
|
+
activated_dists = tuple(dist.distribution for dist in distributions)
|
|
479
|
+
installer.populate_venv_distributions(
|
|
480
|
+
venv=venv,
|
|
481
|
+
distributions=activated_dists,
|
|
482
|
+
provenance=provenance,
|
|
483
|
+
copy_mode=(
|
|
484
|
+
CopyMode.COPY if installer_configuration.site_packages_copies else CopyMode.LINK
|
|
485
|
+
),
|
|
486
|
+
hermetic_scripts=hermetic_scripts,
|
|
487
|
+
)
|
|
488
|
+
|
|
489
|
+
pex_info = PexInfo.default()
|
|
490
|
+
pex_info.includes_tools = False
|
|
491
|
+
pex_info.venv = True
|
|
492
|
+
pex_info.venv_copies = installer_configuration.copies
|
|
493
|
+
pex_info.venv_site_packages_copies = installer_configuration.site_packages_copies
|
|
494
|
+
pex_info.venv_system_site_packages = installer_configuration.system_site_packages
|
|
495
|
+
pex_info.venv_hermetic_scripts = installer_configuration.hermetic_scripts
|
|
496
|
+
dependency_config.configure(pex_info)
|
|
497
|
+
for requirement in requirements:
|
|
498
|
+
pex_info.add_requirement(requirement)
|
|
499
|
+
for distribution in distributions:
|
|
500
|
+
pex_info.add_distribution(os.path.basename(distribution.location), distribution.fingerprint)
|
|
501
|
+
|
|
502
|
+
installer.install_pex_main(
|
|
503
|
+
target_dir=provenance.target_dir,
|
|
504
|
+
venv=venv,
|
|
505
|
+
pex_info=pex_info,
|
|
506
|
+
activated_dists=activated_dists,
|
|
507
|
+
shebang=provenance.calculate_shebang(hermetic_scripts=hermetic_scripts),
|
|
508
|
+
venv_python=provenance.target_python,
|
|
509
|
+
bin_path=installer_configuration.bin_path,
|
|
510
|
+
)
|
pex/cli/pex.py
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
from __future__ import absolute_import
|
|
5
5
|
|
|
6
|
+
import sys
|
|
6
7
|
from argparse import ArgumentError, ArgumentTypeError
|
|
7
8
|
|
|
8
9
|
from pex.cli import commands
|
|
@@ -12,7 +13,7 @@ from pex.result import catch
|
|
|
12
13
|
from pex.typing import TYPE_CHECKING
|
|
13
14
|
|
|
14
15
|
if TYPE_CHECKING:
|
|
15
|
-
from typing import Union
|
|
16
|
+
from typing import Optional, Union
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
class Pex3(Main[BuildTimeCommand]):
|
|
@@ -23,14 +24,20 @@ class Pex3(Main[BuildTimeCommand]):
|
|
|
23
24
|
"""
|
|
24
25
|
|
|
25
26
|
|
|
26
|
-
def main():
|
|
27
|
-
# type: () -> Union[int, str]
|
|
27
|
+
def main(subcommand=None):
|
|
28
|
+
# type: (Optional[str]) -> Union[int, str]
|
|
28
29
|
|
|
29
30
|
pex3 = Pex3(command_types=commands.all_commands())
|
|
30
31
|
try:
|
|
31
|
-
|
|
32
|
+
args = [subcommand] + sys.argv[1:] if subcommand else None
|
|
33
|
+
with pex3.parsed_command(args=args) as command:
|
|
32
34
|
result = catch(command.run)
|
|
33
35
|
result.maybe_display()
|
|
34
36
|
return result.exit_code
|
|
35
37
|
except (ArgumentError, ArgumentTypeError, GlobalConfigurationError) as e:
|
|
36
38
|
return str(e)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def run():
|
|
42
|
+
# type: () -> Union[int, str]
|
|
43
|
+
return main("run")
|
pex/common.py
CHANGED
|
@@ -204,6 +204,56 @@ _MKDTEMP_SINGLETON = MktempTeardownRegistry()
|
|
|
204
204
|
setattr(zipfile, "ZIP64_LIMIT", (1 << 32) - 1)
|
|
205
205
|
|
|
206
206
|
|
|
207
|
+
class _ZipFileTypeValue(Enum.Value):
|
|
208
|
+
def __init__(
|
|
209
|
+
self,
|
|
210
|
+
value, # type: str
|
|
211
|
+
deterministic_mode, # type: int
|
|
212
|
+
):
|
|
213
|
+
# type: (...) -> None
|
|
214
|
+
super(_ZipFileTypeValue, self).__init__(value)
|
|
215
|
+
self.deterministic_mode = deterministic_mode
|
|
216
|
+
|
|
217
|
+
@property
|
|
218
|
+
def deterministic_external_attr(self):
|
|
219
|
+
# type: () -> int
|
|
220
|
+
return self.deterministic_mode << 16
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
class ZipFileType(Enum["ZipFileType.Value"]):
|
|
224
|
+
@classmethod
|
|
225
|
+
def from_zip_info(cls, zip_info):
|
|
226
|
+
# type: (ZipInfo) -> ZipFileType.Value
|
|
227
|
+
|
|
228
|
+
if zip_info.filename.endswith("/"):
|
|
229
|
+
return ZipFileType.DIRECTORY
|
|
230
|
+
|
|
231
|
+
mode = zip_info.external_attr >> 16
|
|
232
|
+
if stat.S_IXUSR & mode:
|
|
233
|
+
return ZipFileType.EXECUTABLE
|
|
234
|
+
|
|
235
|
+
return ZipFileType.FILE
|
|
236
|
+
|
|
237
|
+
@classmethod
|
|
238
|
+
def from_path(cls, path):
|
|
239
|
+
# type: (Text) -> ZipFileType.Value
|
|
240
|
+
if os.path.isdir(path):
|
|
241
|
+
return ZipFileType.DIRECTORY
|
|
242
|
+
elif is_exe(path):
|
|
243
|
+
return ZipFileType.EXECUTABLE
|
|
244
|
+
return ZipFileType.FILE
|
|
245
|
+
|
|
246
|
+
class Value(_ZipFileTypeValue):
|
|
247
|
+
pass
|
|
248
|
+
|
|
249
|
+
DIRECTORY = Value("directory", 0o755)
|
|
250
|
+
EXECUTABLE = Value("executable", 0o755)
|
|
251
|
+
FILE = Value("file", 0o644)
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
ZipFileType.seal()
|
|
255
|
+
|
|
256
|
+
|
|
207
257
|
class ZipFileEx(ZipFile):
|
|
208
258
|
"""A ZipFile that works around several issues in the stdlib.
|
|
209
259
|
|
|
@@ -218,8 +268,8 @@ class ZipFileEx(ZipFile):
|
|
|
218
268
|
@classmethod
|
|
219
269
|
def zip_info_from_file(
|
|
220
270
|
cls,
|
|
221
|
-
filename, # type:
|
|
222
|
-
arcname=None, # type: Optional[
|
|
271
|
+
filename, # type: Text
|
|
272
|
+
arcname=None, # type: Optional[Text]
|
|
223
273
|
date_time=None, # type: Optional[time.struct_time]
|
|
224
274
|
file_mode=None, # type: Optional[int]
|
|
225
275
|
compress=True, # type: bool
|
|
@@ -259,8 +309,8 @@ class ZipFileEx(ZipFile):
|
|
|
259
309
|
|
|
260
310
|
def write_deterministic(
|
|
261
311
|
self,
|
|
262
|
-
filename, # type:
|
|
263
|
-
arcname=None, # type: Optional[
|
|
312
|
+
filename, # type: Text
|
|
313
|
+
arcname=None, # type: Optional[Text]
|
|
264
314
|
digest=None, # type: Optional[Digest]
|
|
265
315
|
deterministic=True, # type: bool
|
|
266
316
|
compress=True, # type: bool
|
|
@@ -270,7 +320,7 @@ class ZipFileEx(ZipFile):
|
|
|
270
320
|
filename,
|
|
271
321
|
arcname=arcname,
|
|
272
322
|
date_time=DETERMINISTIC_DATETIME.timetuple(),
|
|
273
|
-
file_mode=
|
|
323
|
+
file_mode=ZipFileType.from_path(filename).deterministic_mode,
|
|
274
324
|
digest=digest,
|
|
275
325
|
compress=compress,
|
|
276
326
|
)
|
|
@@ -278,8 +328,8 @@ class ZipFileEx(ZipFile):
|
|
|
278
328
|
|
|
279
329
|
def write_ex(
|
|
280
330
|
self,
|
|
281
|
-
filename, # type:
|
|
282
|
-
arcname=None, # type: Optional[
|
|
331
|
+
filename, # type: Text
|
|
332
|
+
arcname=None, # type: Optional[Text]
|
|
283
333
|
date_time=None, # type: Optional[time.struct_time]
|
|
284
334
|
file_mode=None, # type: Optional[int]
|
|
285
335
|
digest=None, # type: Optional[Digest]
|
pex/compatibility.py
CHANGED
pex/dependency_configuration.py
CHANGED
|
@@ -4,10 +4,11 @@
|
|
|
4
4
|
from __future__ import absolute_import
|
|
5
5
|
|
|
6
6
|
import itertools
|
|
7
|
+
import re
|
|
7
8
|
from argparse import Namespace, _ActionsContainer
|
|
8
9
|
from collections import defaultdict
|
|
9
10
|
|
|
10
|
-
from pex.dist_metadata import Distribution, Requirement
|
|
11
|
+
from pex.dist_metadata import Distribution, Requirement, RequirementParseError
|
|
11
12
|
from pex.orderedset import OrderedSet
|
|
12
13
|
from pex.pep_503 import ProjectName
|
|
13
14
|
from pex.pex_info import PexInfo
|
|
@@ -22,13 +23,69 @@ else:
|
|
|
22
23
|
from pex.third_party import attr
|
|
23
24
|
|
|
24
25
|
|
|
26
|
+
@attr.s(frozen=True)
|
|
27
|
+
class Override(object):
|
|
28
|
+
class InvalidError(ValueError):
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
@classmethod
|
|
32
|
+
def parse(cls, override):
|
|
33
|
+
# type: (str) -> Override
|
|
34
|
+
|
|
35
|
+
project_name = None # type: Optional[ProjectName]
|
|
36
|
+
raw_requirement = override
|
|
37
|
+
|
|
38
|
+
# See: https://peps.python.org/pep-0508/#names
|
|
39
|
+
project_name_re = r"[A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9]"
|
|
40
|
+
match = re.match(
|
|
41
|
+
r"^(?P<project>{project_name_re})\s*=\s*(?P<requirement>{project_name_re}.*)$".format(
|
|
42
|
+
project_name_re=project_name_re
|
|
43
|
+
),
|
|
44
|
+
override,
|
|
45
|
+
re.IGNORECASE,
|
|
46
|
+
)
|
|
47
|
+
if match:
|
|
48
|
+
raw_project_name = match.group("project")
|
|
49
|
+
raw_requirement = match.group("requirement")
|
|
50
|
+
try:
|
|
51
|
+
project_name = ProjectName(raw_project_name)
|
|
52
|
+
except ProjectName.InvalidError as e:
|
|
53
|
+
raise cls.InvalidError(
|
|
54
|
+
"Invalid project name {raw_project_name!r} in override {override!r}: "
|
|
55
|
+
"{err}".format(raw_project_name=raw_project_name, override=override, err=e)
|
|
56
|
+
)
|
|
57
|
+
try:
|
|
58
|
+
requirement = Requirement.parse(raw_requirement)
|
|
59
|
+
except RequirementParseError as e:
|
|
60
|
+
raise cls.InvalidError(
|
|
61
|
+
"Invalid override requirement {raw_requirement!r}: {err}".format(
|
|
62
|
+
raw_requirement=raw_requirement, err=e
|
|
63
|
+
)
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
return cls(project_name=project_name or requirement.project_name, requirement=requirement)
|
|
67
|
+
|
|
68
|
+
project_name = attr.ib() # type: ProjectName
|
|
69
|
+
requirement = attr.ib() # type: Requirement
|
|
70
|
+
|
|
71
|
+
def __str__(self):
|
|
72
|
+
# type: () -> str
|
|
73
|
+
|
|
74
|
+
if self.requirement.project_name == self.project_name:
|
|
75
|
+
return str(self.requirement)
|
|
76
|
+
|
|
77
|
+
return "{project_name}={requirement}".format(
|
|
78
|
+
project_name=self.project_name, requirement=self.requirement
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
|
|
25
82
|
@attr.s(frozen=True)
|
|
26
83
|
class DependencyConfiguration(object):
|
|
27
84
|
@classmethod
|
|
28
85
|
def create(
|
|
29
86
|
cls,
|
|
30
87
|
excluded=(), # type: Iterable[Union[str, Requirement]]
|
|
31
|
-
overridden=(), # type: Iterable[Union[str,
|
|
88
|
+
overridden=(), # type: Iterable[Union[str, Override]]
|
|
32
89
|
):
|
|
33
90
|
# type: (...) -> DependencyConfiguration
|
|
34
91
|
|
|
@@ -36,8 +93,8 @@ class DependencyConfiguration(object):
|
|
|
36
93
|
OrderedSet
|
|
37
94
|
) # type: DefaultDict[ProjectName, OrderedSet[Requirement]]
|
|
38
95
|
for o in overridden:
|
|
39
|
-
override = o if isinstance(o,
|
|
40
|
-
overridden_projects[override.project_name].add(override)
|
|
96
|
+
override = o if isinstance(o, Override) else Override.parse(o)
|
|
97
|
+
overridden_projects[override.project_name].add(override.requirement)
|
|
41
98
|
|
|
42
99
|
return cls(
|
|
43
100
|
excluded=tuple(
|
|
@@ -64,25 +121,32 @@ class DependencyConfiguration(object):
|
|
|
64
121
|
# type: (PexInfo) -> None
|
|
65
122
|
for excluded in self.excluded:
|
|
66
123
|
pex_info.add_exclude(excluded)
|
|
67
|
-
for
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
pex_info.add_override(override)
|
|
124
|
+
for project_name, overrides in self.overridden.items():
|
|
125
|
+
for override in sorted(overrides, key=lambda req: req.key):
|
|
126
|
+
pex_info.add_override(Override(project_name=project_name, requirement=override))
|
|
71
127
|
|
|
72
128
|
def excluded_by(self, item):
|
|
73
129
|
# type: (Union[Distribution, Requirement]) -> Tuple[Requirement, ...]
|
|
74
130
|
return tuple(req for req in self.excluded if item in req)
|
|
75
131
|
|
|
76
132
|
def all_overrides(self):
|
|
77
|
-
# type: () -> Tuple[
|
|
78
|
-
return tuple(
|
|
133
|
+
# type: () -> Tuple[Override, ...]
|
|
134
|
+
return tuple(
|
|
135
|
+
Override(project_name=project_name, requirement=requirement)
|
|
136
|
+
for project_name, requirements in self.overridden.items()
|
|
137
|
+
for requirement in requirements
|
|
138
|
+
)
|
|
79
139
|
|
|
80
140
|
def overrides_for(self, requirement):
|
|
81
141
|
# type: (Requirement) -> Tuple[Requirement, ...]
|
|
82
142
|
return self.overridden.get(requirement.project_name, ())
|
|
83
143
|
|
|
84
|
-
def overridden_by(
|
|
85
|
-
|
|
144
|
+
def overridden_by(
|
|
145
|
+
self,
|
|
146
|
+
requirement, # type: Requirement
|
|
147
|
+
target, # type: Target
|
|
148
|
+
):
|
|
149
|
+
# type: (...) -> Optional[Requirement]
|
|
86
150
|
overrides = self.overrides_for(requirement)
|
|
87
151
|
applicable_overrides = [
|
|
88
152
|
override for override in overrides if target.requirement_applies(override)
|
|
@@ -152,9 +216,17 @@ def register(parser):
|
|
|
152
216
|
type=str,
|
|
153
217
|
action="append",
|
|
154
218
|
help=(
|
|
155
|
-
"Specifies a transitive requirement to override when resolving.
|
|
156
|
-
"
|
|
157
|
-
"
|
|
219
|
+
"Specifies a transitive requirement to override when resolving. Overrides can either "
|
|
220
|
+
"modify an existing dependency on a project name by changing extras, version "
|
|
221
|
+
"constraints or markers or else they can completely swap out the dependency for a "
|
|
222
|
+
"dependency on another project altogether. For the former, simply supply the "
|
|
223
|
+
"requirement you wish. For example, specifying `--override cowsay==5.0` will override "
|
|
224
|
+
"any transitive dependency on cowsay that has any combination of extras, version "
|
|
225
|
+
"constraints or markers with the requirement `cowsay==5.0`. To completely replace "
|
|
226
|
+
"cowsay with another library altogether, you can specify an override like "
|
|
227
|
+
"`--override cowsay=my-cowsay>2`. This will replace any transitive dependency on "
|
|
228
|
+
"cowsay that has any combination of extras, version constraints or markers with the "
|
|
229
|
+
"requirement `my-cowsay>2`. This option can be used multiple times."
|
|
158
230
|
),
|
|
159
231
|
)
|
|
160
232
|
|