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/pip/tool.py
CHANGED
|
@@ -21,21 +21,21 @@ from pex.common import safe_mkdir, safe_mkdtemp
|
|
|
21
21
|
from pex.compatibility import get_stderr_bytes_buffer, shlex_quote, urlparse
|
|
22
22
|
from pex.dependency_configuration import DependencyConfiguration
|
|
23
23
|
from pex.dist_metadata import Requirement
|
|
24
|
+
from pex.fetcher import URLFetcher
|
|
24
25
|
from pex.interpreter import PythonInterpreter
|
|
25
26
|
from pex.jobs import Job
|
|
26
27
|
from pex.network_configuration import NetworkConfiguration
|
|
27
28
|
from pex.pep_427 import install_wheel_interpreter
|
|
28
|
-
from pex.
|
|
29
|
+
from pex.pep_508 import MarkerEnvironment
|
|
30
|
+
from pex.pip import dependencies, foreign_platform, package_repositories
|
|
29
31
|
from pex.pip.download_observer import DownloadObserver, PatchSet
|
|
30
32
|
from pex.pip.log_analyzer import ErrorAnalyzer, ErrorMessage, LogAnalyzer, LogScrapeJob
|
|
31
33
|
from pex.pip.tailer import Tailer
|
|
32
34
|
from pex.pip.version import PipVersion, PipVersionValue
|
|
33
35
|
from pex.platforms import PlatformSpec
|
|
34
|
-
from pex.resolve.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
ResolverVersion,
|
|
38
|
-
)
|
|
36
|
+
from pex.resolve.package_repository import ReposConfiguration
|
|
37
|
+
from pex.resolve.resolver_configuration import BuildConfiguration, ResolverVersion
|
|
38
|
+
from pex.resolve.target_system import UniversalTarget
|
|
39
39
|
from pex.targets import Target
|
|
40
40
|
from pex.tracer import TRACER
|
|
41
41
|
from pex.typing import TYPE_CHECKING
|
|
@@ -54,7 +54,9 @@ if TYPE_CHECKING:
|
|
|
54
54
|
Match,
|
|
55
55
|
Optional,
|
|
56
56
|
Sequence,
|
|
57
|
+
Text,
|
|
57
58
|
Tuple,
|
|
59
|
+
Union,
|
|
58
60
|
)
|
|
59
61
|
|
|
60
62
|
import attr # vendor:skip
|
|
@@ -64,8 +66,8 @@ else:
|
|
|
64
66
|
|
|
65
67
|
@attr.s(frozen=True)
|
|
66
68
|
class PipArgs(object):
|
|
67
|
-
indexes = attr.ib(default=None) # type: Optional[Sequence[
|
|
68
|
-
find_links = attr.ib(default=None) # type: Optional[Iterable[
|
|
69
|
+
indexes = attr.ib(default=None) # type: Optional[Sequence[Text]]
|
|
70
|
+
find_links = attr.ib(default=None) # type: Optional[Iterable[Text]]
|
|
69
71
|
network_configuration = attr.ib(default=None) # type: Optional[NetworkConfiguration]
|
|
70
72
|
|
|
71
73
|
def iter(self, version):
|
|
@@ -152,10 +154,8 @@ class PackageIndexConfiguration(object):
|
|
|
152
154
|
cls,
|
|
153
155
|
pip_version=None, # type: Optional[PipVersionValue]
|
|
154
156
|
resolver_version=None, # type: Optional[ResolverVersion.Value]
|
|
155
|
-
|
|
156
|
-
find_links=None, # type: Optional[Iterable[str]]
|
|
157
|
+
repos_configuration=ReposConfiguration(), # type: ReposConfiguration
|
|
157
158
|
network_configuration=None, # type: Optional[NetworkConfiguration]
|
|
158
|
-
password_entries=(), # type: Iterable[PasswordEntry]
|
|
159
159
|
use_pip_config=False, # type: bool
|
|
160
160
|
extra_pip_requirements=(), # type: Tuple[Requirement, ...]
|
|
161
161
|
keyring_provider=None, # type: Optional[str]
|
|
@@ -174,8 +174,8 @@ class PackageIndexConfiguration(object):
|
|
|
174
174
|
resolver_version=resolver_version,
|
|
175
175
|
network_configuration=network_configuration,
|
|
176
176
|
args=PipArgs(
|
|
177
|
-
indexes=indexes,
|
|
178
|
-
find_links=find_links,
|
|
177
|
+
indexes=repos_configuration.indexes,
|
|
178
|
+
find_links=repos_configuration.find_links,
|
|
179
179
|
network_configuration=network_configuration,
|
|
180
180
|
),
|
|
181
181
|
env=cls._calculate_env(
|
|
@@ -183,7 +183,7 @@ class PackageIndexConfiguration(object):
|
|
|
183
183
|
),
|
|
184
184
|
use_pip_config=use_pip_config,
|
|
185
185
|
extra_pip_requirements=extra_pip_requirements,
|
|
186
|
-
|
|
186
|
+
repos_configuration=repos_configuration,
|
|
187
187
|
keyring_provider=keyring_provider,
|
|
188
188
|
)
|
|
189
189
|
|
|
@@ -194,7 +194,7 @@ class PackageIndexConfiguration(object):
|
|
|
194
194
|
args, # type: PipArgs
|
|
195
195
|
env, # type: Iterable[Tuple[str, str]]
|
|
196
196
|
use_pip_config, # type: bool
|
|
197
|
-
|
|
197
|
+
repos_configuration=ReposConfiguration(), # type: ReposConfiguration
|
|
198
198
|
pip_version=None, # type: Optional[PipVersionValue]
|
|
199
199
|
extra_pip_requirements=(), # type: Tuple[Requirement, ...]
|
|
200
200
|
keyring_provider=None, # type: Optional[str]
|
|
@@ -205,11 +205,32 @@ class PackageIndexConfiguration(object):
|
|
|
205
205
|
self.args = args # type: PipArgs
|
|
206
206
|
self.env = dict(env) # type: Mapping[str, str]
|
|
207
207
|
self.use_pip_config = use_pip_config # type: bool
|
|
208
|
-
self.
|
|
208
|
+
self.repos_configuration = repos_configuration
|
|
209
209
|
self.pip_version = pip_version # type: Optional[PipVersionValue]
|
|
210
210
|
self.extra_pip_requirements = extra_pip_requirements # type: Tuple[Requirement, ...]
|
|
211
211
|
self.keyring_provider = keyring_provider # type: Optional[str]
|
|
212
212
|
|
|
213
|
+
@property
|
|
214
|
+
def password_entries(self):
|
|
215
|
+
# type: () -> Iterable[PasswordEntry]
|
|
216
|
+
return self.repos_configuration.password_entries
|
|
217
|
+
|
|
218
|
+
def patch(
|
|
219
|
+
self,
|
|
220
|
+
pip_version, # type: PipVersionValue
|
|
221
|
+
target, # type: Union[UniversalTarget, MarkerEnvironment]
|
|
222
|
+
requirement_files=None, # type: Optional[Iterable[str]]
|
|
223
|
+
):
|
|
224
|
+
# type: (...) -> Optional[DownloadObserver]
|
|
225
|
+
return package_repositories.patch(
|
|
226
|
+
repos_configuration=self.repos_configuration.with_contained_repos(
|
|
227
|
+
requirement_files,
|
|
228
|
+
fetcher=URLFetcher(network_configuration=self.network_configuration),
|
|
229
|
+
),
|
|
230
|
+
pip_version=pip_version,
|
|
231
|
+
target=target,
|
|
232
|
+
)
|
|
233
|
+
|
|
213
234
|
|
|
214
235
|
if TYPE_CHECKING:
|
|
215
236
|
from pex.pip.log_analyzer import ErrorAnalysis
|
|
@@ -455,7 +476,7 @@ class Pip(object):
|
|
|
455
476
|
|
|
456
477
|
command = pip_args + list(args)
|
|
457
478
|
|
|
458
|
-
# N.B.: Package index options in
|
|
479
|
+
# N.B.: Package index options in Pip always have the same option names, but they are
|
|
459
480
|
# registered as subcommand-specific, so we must append them here _after_ the pip subcommand
|
|
460
481
|
# specified in `args`.
|
|
461
482
|
if package_index_configuration:
|
|
@@ -470,9 +491,7 @@ class Pip(object):
|
|
|
470
491
|
# since Pip relies upon `shutil.move` which is only atomic when `os.rename` can be used.
|
|
471
492
|
# See https://github.com/pex-tool/pex/issues/1776 for an example of the issues non-atomic
|
|
472
493
|
# moves lead to in the `pip wheel` case.
|
|
473
|
-
|
|
474
|
-
safe_mkdir(pip_tmpdir)
|
|
475
|
-
extra_env.update(TMPDIR=pip_tmpdir)
|
|
494
|
+
extra_env.update(TMPDIR=safe_mkdtemp(dir=safe_mkdir(self.cache_dir), prefix=".tmp."))
|
|
476
495
|
|
|
477
496
|
with ENV.strip().patch(
|
|
478
497
|
PEX_ROOT=ENV.PEX_ROOT,
|
|
@@ -533,8 +552,7 @@ class Pip(object):
|
|
|
533
552
|
)
|
|
534
553
|
return Job(command=command, process=process, finalizer=finalizer, context="pip")
|
|
535
554
|
|
|
536
|
-
|
|
537
|
-
def _iter_build_configuration_options(build_configuration):
|
|
555
|
+
def _iter_build_configuration_options(self, build_configuration):
|
|
538
556
|
# type: (BuildConfiguration) -> Iterator[str]
|
|
539
557
|
|
|
540
558
|
# N.B.: BuildConfiguration maintains invariants that ensure --only-binary, --no-binary,
|
|
@@ -557,12 +575,54 @@ class Pip(object):
|
|
|
557
575
|
if build_configuration.prefer_older_binary:
|
|
558
576
|
yield "--prefer-binary"
|
|
559
577
|
|
|
560
|
-
|
|
578
|
+
# N.B.: In 25.3 `--use-pep517` became the default and only option.
|
|
579
|
+
if build_configuration.use_pep517 is not None and self.version < PipVersion.v25_3:
|
|
561
580
|
yield "--use-pep517" if build_configuration.use_pep517 else "--no-use-pep517"
|
|
562
581
|
|
|
563
582
|
if not build_configuration.build_isolation:
|
|
564
583
|
yield "--no-build-isolation"
|
|
565
584
|
|
|
585
|
+
def spawn_report(
|
|
586
|
+
self,
|
|
587
|
+
report_path, # type: str
|
|
588
|
+
requirements=None, # type: Optional[Iterable[str]]
|
|
589
|
+
requirement_files=None, # type: Optional[Iterable[str]]
|
|
590
|
+
constraint_files=None, # type: Optional[Iterable[str]]
|
|
591
|
+
allow_prereleases=False, # type: bool
|
|
592
|
+
transitive=True, # type: bool
|
|
593
|
+
target=None, # type: Optional[Target]
|
|
594
|
+
package_index_configuration=None, # type: Optional[PackageIndexConfiguration]
|
|
595
|
+
build_configuration=BuildConfiguration(), # type: BuildConfiguration
|
|
596
|
+
observer=None, # type: Optional[DownloadObserver]
|
|
597
|
+
dependency_configuration=DependencyConfiguration(), # type: DependencyConfiguration
|
|
598
|
+
universal_target=None, # type: Optional[UniversalTarget]
|
|
599
|
+
log=None, # type: Optional[str]
|
|
600
|
+
):
|
|
601
|
+
# type: (...) -> Job
|
|
602
|
+
report_cmd = [
|
|
603
|
+
"install",
|
|
604
|
+
"--no-clean",
|
|
605
|
+
"--dry-run",
|
|
606
|
+
"--ignore-installed",
|
|
607
|
+
"--report",
|
|
608
|
+
report_path,
|
|
609
|
+
]
|
|
610
|
+
return self._spawn_install_compatible_command(
|
|
611
|
+
cmd=report_cmd,
|
|
612
|
+
requirements=requirements,
|
|
613
|
+
requirement_files=requirement_files,
|
|
614
|
+
constraint_files=constraint_files,
|
|
615
|
+
allow_prereleases=allow_prereleases,
|
|
616
|
+
transitive=transitive,
|
|
617
|
+
target=target,
|
|
618
|
+
package_index_configuration=package_index_configuration,
|
|
619
|
+
build_configuration=build_configuration,
|
|
620
|
+
observer=observer,
|
|
621
|
+
dependency_configuration=dependency_configuration,
|
|
622
|
+
universal_target=universal_target,
|
|
623
|
+
log=log,
|
|
624
|
+
)
|
|
625
|
+
|
|
566
626
|
def spawn_download_distributions(
|
|
567
627
|
self,
|
|
568
628
|
download_dir, # type: str
|
|
@@ -576,35 +636,70 @@ class Pip(object):
|
|
|
576
636
|
build_configuration=BuildConfiguration(), # type: BuildConfiguration
|
|
577
637
|
observer=None, # type: Optional[DownloadObserver]
|
|
578
638
|
dependency_configuration=DependencyConfiguration(), # type: DependencyConfiguration
|
|
639
|
+
universal_target=None, # type: Optional[UniversalTarget]
|
|
579
640
|
log=None, # type: Optional[str]
|
|
580
641
|
):
|
|
581
642
|
# type: (...) -> Job
|
|
582
|
-
target = target or targets.current()
|
|
583
643
|
|
|
584
644
|
download_cmd = ["download", "--dest", download_dir]
|
|
645
|
+
return self._spawn_install_compatible_command(
|
|
646
|
+
cmd=download_cmd,
|
|
647
|
+
requirements=requirements,
|
|
648
|
+
requirement_files=requirement_files,
|
|
649
|
+
constraint_files=constraint_files,
|
|
650
|
+
allow_prereleases=allow_prereleases,
|
|
651
|
+
transitive=transitive,
|
|
652
|
+
target=target,
|
|
653
|
+
package_index_configuration=package_index_configuration,
|
|
654
|
+
build_configuration=build_configuration,
|
|
655
|
+
observer=observer,
|
|
656
|
+
dependency_configuration=dependency_configuration,
|
|
657
|
+
universal_target=universal_target,
|
|
658
|
+
log=log,
|
|
659
|
+
)
|
|
660
|
+
|
|
661
|
+
def _spawn_install_compatible_command(
|
|
662
|
+
self,
|
|
663
|
+
cmd, # type: List[str]
|
|
664
|
+
requirements=None, # type: Optional[Iterable[str]]
|
|
665
|
+
requirement_files=None, # type: Optional[Iterable[str]]
|
|
666
|
+
constraint_files=None, # type: Optional[Iterable[str]]
|
|
667
|
+
allow_prereleases=False, # type: bool
|
|
668
|
+
transitive=True, # type: bool
|
|
669
|
+
target=None, # type: Optional[Target]
|
|
670
|
+
package_index_configuration=None, # type: Optional[PackageIndexConfiguration]
|
|
671
|
+
build_configuration=BuildConfiguration(), # type: BuildConfiguration
|
|
672
|
+
observer=None, # type: Optional[DownloadObserver]
|
|
673
|
+
dependency_configuration=DependencyConfiguration(), # type: DependencyConfiguration
|
|
674
|
+
universal_target=None, # type: Optional[UniversalTarget]
|
|
675
|
+
log=None, # type: Optional[str]
|
|
676
|
+
):
|
|
677
|
+
# type: (...) -> Job
|
|
678
|
+
target = target or targets.current()
|
|
679
|
+
|
|
585
680
|
extra_env = {} # type: Dict[str, str]
|
|
586
681
|
pex_extra_sys_path = [] # type: List[str]
|
|
587
682
|
|
|
588
|
-
|
|
683
|
+
cmd.extend(self._iter_build_configuration_options(build_configuration))
|
|
589
684
|
if not build_configuration.build_isolation:
|
|
590
685
|
pex_extra_sys_path.extend(sys.path)
|
|
591
686
|
|
|
592
687
|
if allow_prereleases:
|
|
593
|
-
|
|
688
|
+
cmd.append("--pre")
|
|
594
689
|
|
|
595
690
|
if not transitive:
|
|
596
|
-
|
|
691
|
+
cmd.append("--no-deps")
|
|
597
692
|
|
|
598
693
|
if requirement_files:
|
|
599
694
|
for requirement_file in requirement_files:
|
|
600
|
-
|
|
695
|
+
cmd.extend(["--requirement", requirement_file])
|
|
601
696
|
|
|
602
697
|
if constraint_files:
|
|
603
698
|
for constraint_file in constraint_files:
|
|
604
|
-
|
|
699
|
+
cmd.extend(["--constraint", constraint_file])
|
|
605
700
|
|
|
606
701
|
if requirements:
|
|
607
|
-
|
|
702
|
+
cmd.extend(requirements)
|
|
608
703
|
|
|
609
704
|
foreign_platform_observer = foreign_platform.patch(target)
|
|
610
705
|
if (
|
|
@@ -623,7 +718,18 @@ class Pip(object):
|
|
|
623
718
|
for obs in (
|
|
624
719
|
foreign_platform_observer,
|
|
625
720
|
observer,
|
|
626
|
-
dependencies.patch(
|
|
721
|
+
dependencies.patch(
|
|
722
|
+
dependency_configuration, target=universal_target or target.marker_environment
|
|
723
|
+
),
|
|
724
|
+
(
|
|
725
|
+
package_index_configuration.patch(
|
|
726
|
+
pip_version=self.version,
|
|
727
|
+
target=universal_target or target.marker_environment,
|
|
728
|
+
requirement_files=requirement_files,
|
|
729
|
+
)
|
|
730
|
+
if package_index_configuration
|
|
731
|
+
else None
|
|
732
|
+
),
|
|
627
733
|
):
|
|
628
734
|
if obs:
|
|
629
735
|
if obs.analyzer:
|
|
@@ -689,7 +795,7 @@ class Pip(object):
|
|
|
689
795
|
tailer.stop()
|
|
690
796
|
|
|
691
797
|
command, process = self._spawn_pip_isolated(
|
|
692
|
-
|
|
798
|
+
cmd,
|
|
693
799
|
package_index_configuration=package_index_configuration,
|
|
694
800
|
interpreter=target.get_interpreter(),
|
|
695
801
|
log=log,
|
|
@@ -717,7 +823,7 @@ class Pip(object):
|
|
|
717
823
|
build_configuration=BuildConfiguration.create(allow_builds=False),
|
|
718
824
|
).wait()
|
|
719
825
|
for wheel in glob.glob(os.path.join(atomic_dir.work_dir, "*.whl")):
|
|
720
|
-
install_wheel_interpreter(
|
|
826
|
+
install_wheel_interpreter(wheel=wheel, interpreter=pip_interpreter)
|
|
721
827
|
|
|
722
828
|
def spawn_build_wheels(
|
|
723
829
|
self,
|
pex/pip/vcs.py
CHANGED
|
@@ -8,20 +8,37 @@ import re
|
|
|
8
8
|
|
|
9
9
|
from pex import hashing
|
|
10
10
|
from pex.artifact_url import VCS, Fingerprint
|
|
11
|
-
from pex.common import is_pyc_dir, is_pyc_file
|
|
11
|
+
from pex.common import is_pyc_dir, is_pyc_file
|
|
12
|
+
from pex.exceptions import reportable_unexpected_error_msg
|
|
12
13
|
from pex.hashing import Sha256
|
|
13
14
|
from pex.pep_440 import Version
|
|
14
15
|
from pex.pep_503 import ProjectName
|
|
15
16
|
from pex.result import Error, try_
|
|
16
|
-
from pex.tracer import TRACER
|
|
17
17
|
from pex.typing import TYPE_CHECKING
|
|
18
18
|
|
|
19
19
|
if TYPE_CHECKING:
|
|
20
|
-
|
|
20
|
+
# N.B.: The `re.Pattern` type is not available in all Python versions Pex supports.
|
|
21
|
+
from re import Pattern # type: ignore[attr-defined]
|
|
22
|
+
from typing import Callable, Optional, Text, Tuple, Union
|
|
21
23
|
|
|
22
24
|
from pex.hashing import HintedDigest
|
|
23
25
|
|
|
24
26
|
|
|
27
|
+
def _project_name_re(project_name):
|
|
28
|
+
# type: (ProjectName) -> str
|
|
29
|
+
return project_name.normalized.replace("-", "[-_.]+")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _built_source_dist_pattern(project_name):
|
|
33
|
+
# type: (ProjectName) -> Pattern
|
|
34
|
+
return re.compile(
|
|
35
|
+
r"(?P<project_name>{project_name_re})-(?P<version>.+)\.zip".format(
|
|
36
|
+
project_name_re=_project_name_re(project_name)
|
|
37
|
+
),
|
|
38
|
+
re.IGNORECASE,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
25
42
|
def _find_built_source_dist(
|
|
26
43
|
build_dir, # type: str
|
|
27
44
|
project_name, # type: ProjectName
|
|
@@ -33,12 +50,7 @@ def _find_built_source_dist(
|
|
|
33
50
|
# encoded in: `pip._internal.req.req_install.InstallRequirement.archive`.
|
|
34
51
|
|
|
35
52
|
listing = os.listdir(build_dir)
|
|
36
|
-
pattern =
|
|
37
|
-
r"{project_name}-(?P<version>.+)\.zip".format(
|
|
38
|
-
project_name=project_name.normalized.replace("-", "[-_.]+")
|
|
39
|
-
),
|
|
40
|
-
re.IGNORECASE,
|
|
41
|
-
)
|
|
53
|
+
pattern = _built_source_dist_pattern(project_name)
|
|
42
54
|
for name in listing:
|
|
43
55
|
match = pattern.match(name)
|
|
44
56
|
if match and Version(match.group("version")) == version:
|
|
@@ -57,57 +69,111 @@ def _find_built_source_dist(
|
|
|
57
69
|
|
|
58
70
|
def fingerprint_downloaded_vcs_archive(
|
|
59
71
|
download_dir, # type: str
|
|
60
|
-
project_name, # type:
|
|
61
|
-
version, # type:
|
|
72
|
+
project_name, # type: ProjectName
|
|
73
|
+
version, # type: Version
|
|
62
74
|
vcs, # type: VCS.Value
|
|
63
|
-
subdirectory=None, # type: Optional[str]
|
|
64
75
|
):
|
|
65
76
|
# type: (...) -> Tuple[Fingerprint, str]
|
|
66
77
|
|
|
67
78
|
archive_path = try_(
|
|
68
|
-
_find_built_source_dist(
|
|
69
|
-
build_dir=download_dir, project_name=ProjectName(project_name), version=Version(version)
|
|
70
|
-
)
|
|
79
|
+
_find_built_source_dist(build_dir=download_dir, project_name=project_name, version=version)
|
|
71
80
|
)
|
|
72
81
|
digest = Sha256()
|
|
73
|
-
digest_vcs_archive(archive_path=archive_path, vcs=vcs, digest=digest
|
|
82
|
+
digest_vcs_archive(project_name=project_name, archive_path=archive_path, vcs=vcs, digest=digest)
|
|
74
83
|
return Fingerprint.from_digest(digest), archive_path
|
|
75
84
|
|
|
76
85
|
|
|
86
|
+
def _vcs_dir_filter(
|
|
87
|
+
vcs, # type: VCS.Value
|
|
88
|
+
project_name, # type: ProjectName
|
|
89
|
+
):
|
|
90
|
+
# type: (...) -> Callable[[Text], bool]
|
|
91
|
+
|
|
92
|
+
# Ignore VCS control directories for the purposes of fingerprinting the version controlled
|
|
93
|
+
# source tree. VCS control directories can contain non-reproducible content (Git at least
|
|
94
|
+
# has files that contain timestamps).
|
|
95
|
+
#
|
|
96
|
+
# We cannot prune these directories from the source archive directly unfortunately since
|
|
97
|
+
# some build processes use VCS version information to derive their version numbers (C.F.:
|
|
98
|
+
# https://pypi.org/project/setuptools-scm/). As such, we'll get a stable fingerprint, but be
|
|
99
|
+
# forced to re-build a wheel each time the VCS requirement is re-locked later, even when it
|
|
100
|
+
# hashes the same.
|
|
101
|
+
vcs_control_dir = ".{vcs}".format(vcs=vcs)
|
|
102
|
+
|
|
103
|
+
# N.B.: If the VCS project uses setuptools as its build backend, depending on the version of
|
|
104
|
+
# Pip used, the VCS checkout can have a `<project name>.egg-info/` directory littering its root
|
|
105
|
+
# left over from Pip generating project metadata to determine version and dependencies. No other
|
|
106
|
+
# well known build-backend has this problem at this time (checked hatchling, poetry-core,
|
|
107
|
+
# pdm-backend and uv_build).
|
|
108
|
+
# C.F.: https://github.com/pypa/pip/pull/13602
|
|
109
|
+
egg_info_dir_re = re.compile(
|
|
110
|
+
r"^{project_name_re}\.egg-info$".format(project_name_re=_project_name_re(project_name)),
|
|
111
|
+
re.IGNORECASE,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
def vcs_dir_filter(dir_path):
|
|
115
|
+
# type: (Text) -> bool
|
|
116
|
+
if is_pyc_dir(dir_path):
|
|
117
|
+
return False
|
|
118
|
+
|
|
119
|
+
base_dir_name = dir_path.split(os.sep)[0]
|
|
120
|
+
return base_dir_name != vcs_control_dir and not egg_info_dir_re.match(base_dir_name)
|
|
121
|
+
|
|
122
|
+
return vcs_dir_filter
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _vcs_file_filter(vcs):
|
|
126
|
+
# type: (VCS.Value) -> Callable[[Text], bool]
|
|
127
|
+
return lambda f: not is_pyc_file(f)
|
|
128
|
+
|
|
129
|
+
|
|
77
130
|
def digest_vcs_archive(
|
|
131
|
+
project_name, # type: ProjectName
|
|
78
132
|
archive_path, # type: str
|
|
79
133
|
vcs, # type: VCS.Value
|
|
80
134
|
digest, # type: HintedDigest
|
|
81
|
-
subdirectory=None, # type: Optional[str]
|
|
82
135
|
):
|
|
83
136
|
# type: (...) -> None
|
|
84
137
|
|
|
85
138
|
# All VCS requirements are prepared as zip archives as encoded in:
|
|
86
|
-
# `pip._internal.req.req_install.InstallRequirement.archive
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
# https://pypi.org/project/setuptools-scm/). As such, we'll get a stable fingerprint, but be
|
|
99
|
-
# forced to re-build a wheel each time the VCS requirement is re-locked later, even when it
|
|
100
|
-
# hashes the same.
|
|
101
|
-
vcs_control_dir = ".{vcs}".format(vcs=vcs)
|
|
102
|
-
|
|
103
|
-
# TODO(John Sirois): Consider implementing zip_hash to avoid the extractall.
|
|
104
|
-
hashing.dir_hash(
|
|
105
|
-
directory=os.path.join(chroot, subdirectory) if subdirectory else chroot,
|
|
106
|
-
digest=digest,
|
|
107
|
-
dir_filter=(
|
|
108
|
-
lambda dir_path: (
|
|
109
|
-
not is_pyc_dir(dir_path) and os.path.basename(dir_path) != vcs_control_dir
|
|
139
|
+
# `pip._internal.req.req_install.InstallRequirement.archive` and the archive is already offset
|
|
140
|
+
# by a subdirectory (if any).
|
|
141
|
+
|
|
142
|
+
# The zip archives created by Pip have a single project name top-level directory housing
|
|
143
|
+
# the full clone. We look for that to get a consistent clone hash with a bare clone.
|
|
144
|
+
match = _built_source_dist_pattern(project_name).match(os.path.basename(archive_path))
|
|
145
|
+
if match is None:
|
|
146
|
+
raise AssertionError(
|
|
147
|
+
reportable_unexpected_error_msg(
|
|
148
|
+
"Failed to determine the project name prefix for the VCS zip {zip} with expected "
|
|
149
|
+
"canonical project name {project_name}".format(
|
|
150
|
+
zip=archive_path, project_name=project_name
|
|
110
151
|
)
|
|
111
|
-
)
|
|
112
|
-
file_filter=lambda f: not is_pyc_file(f),
|
|
152
|
+
)
|
|
113
153
|
)
|
|
154
|
+
top_dir = match.group("project_name")
|
|
155
|
+
|
|
156
|
+
hashing.zip_hash(
|
|
157
|
+
zip_path=archive_path,
|
|
158
|
+
digest=digest,
|
|
159
|
+
relpath=top_dir,
|
|
160
|
+
dir_filter=_vcs_dir_filter(vcs, project_name),
|
|
161
|
+
file_filter=_vcs_file_filter(vcs),
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def digest_vcs_repo(
|
|
166
|
+
project_name, # type: ProjectName
|
|
167
|
+
repo_path, # type: str
|
|
168
|
+
vcs, # type: VCS.Value
|
|
169
|
+
digest, # type: HintedDigest
|
|
170
|
+
subdirectory=None, # type: Optional[str]
|
|
171
|
+
):
|
|
172
|
+
# type: (...) -> None
|
|
173
|
+
|
|
174
|
+
hashing.dir_hash(
|
|
175
|
+
directory=os.path.join(repo_path, subdirectory) if subdirectory else repo_path,
|
|
176
|
+
digest=digest,
|
|
177
|
+
dir_filter=_vcs_dir_filter(vcs, project_name),
|
|
178
|
+
file_filter=_vcs_file_filter(vcs),
|
|
179
|
+
)
|
pex/pip/version.py
CHANGED
|
@@ -366,7 +366,14 @@ class PipVersion(Enum["PipVersionValue"]):
|
|
|
366
366
|
version="25.2",
|
|
367
367
|
setuptools_version="80.9.0",
|
|
368
368
|
wheel_version="0.45.1",
|
|
369
|
-
requires_python=">=3.9,<3.
|
|
369
|
+
requires_python=">=3.9,<3.16",
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
v25_3 = PipVersionValue(
|
|
373
|
+
version="25.3",
|
|
374
|
+
setuptools_version="80.9.0",
|
|
375
|
+
wheel_version="0.45.1",
|
|
376
|
+
requires_python=">=3.9,<3.16",
|
|
370
377
|
)
|
|
371
378
|
|
|
372
379
|
VENDORED = v20_3_4_patched
|