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.

Files changed (180) hide show
  1. pex/auth.py +1 -1
  2. pex/bin/pex.py +15 -2
  3. pex/build_backend/configuration.py +5 -5
  4. pex/build_backend/wrap.py +27 -23
  5. pex/build_system/pep_517.py +4 -1
  6. pex/cache/dirs.py +17 -12
  7. pex/cli/commands/lock.py +302 -165
  8. pex/cli/commands/pip/core.py +4 -12
  9. pex/cli/commands/pip/wheel.py +1 -1
  10. pex/cli/commands/run.py +13 -20
  11. pex/cli/commands/venv.py +85 -16
  12. pex/cli/pex.py +11 -4
  13. pex/common.py +57 -7
  14. pex/compatibility.py +1 -1
  15. pex/dependency_configuration.py +87 -15
  16. pex/dist_metadata.py +143 -25
  17. pex/docs/html/_pagefind/fragment/en_4250138.pf_fragment +0 -0
  18. pex/docs/html/_pagefind/fragment/en_7125dad.pf_fragment +0 -0
  19. pex/docs/html/_pagefind/fragment/en_785d562.pf_fragment +0 -0
  20. pex/docs/html/_pagefind/fragment/en_8e94bb8.pf_fragment +0 -0
  21. pex/docs/html/_pagefind/fragment/en_a0396bb.pf_fragment +0 -0
  22. pex/docs/html/_pagefind/fragment/en_a8a3588.pf_fragment +0 -0
  23. pex/docs/html/_pagefind/fragment/en_c07d988.pf_fragment +0 -0
  24. pex/docs/html/_pagefind/fragment/en_d718411.pf_fragment +0 -0
  25. pex/docs/html/_pagefind/index/en_a2e3c5e.pf_index +0 -0
  26. pex/docs/html/_pagefind/pagefind-entry.json +1 -1
  27. pex/docs/html/_pagefind/pagefind.en_4ce1afa9e3.pf_meta +0 -0
  28. pex/docs/html/_static/documentation_options.js +1 -1
  29. pex/docs/html/_static/pygments.css +164 -146
  30. pex/docs/html/_static/styles/furo.css +1 -1
  31. pex/docs/html/_static/styles/furo.css.map +1 -1
  32. pex/docs/html/api/vars.html +25 -34
  33. pex/docs/html/buildingpex.html +25 -34
  34. pex/docs/html/genindex.html +24 -33
  35. pex/docs/html/index.html +25 -34
  36. pex/docs/html/recipes.html +25 -34
  37. pex/docs/html/scie.html +25 -34
  38. pex/docs/html/search.html +24 -33
  39. pex/docs/html/whatispex.html +25 -34
  40. pex/entry_points_txt.py +98 -0
  41. pex/environment.py +54 -33
  42. pex/finders.py +1 -1
  43. pex/hashing.py +71 -9
  44. pex/installed_wheel.py +141 -0
  45. pex/interpreter.py +41 -38
  46. pex/interpreter_constraints.py +25 -25
  47. pex/interpreter_implementation.py +40 -0
  48. pex/jobs.py +13 -6
  49. pex/pep_376.py +68 -384
  50. pex/pep_425.py +11 -2
  51. pex/pep_427.py +937 -205
  52. pex/pep_508.py +4 -5
  53. pex/pex_builder.py +5 -8
  54. pex/pex_info.py +14 -9
  55. pex/pip/dependencies/__init__.py +85 -13
  56. pex/pip/dependencies/requires.py +38 -3
  57. pex/pip/foreign_platform/__init__.py +4 -3
  58. pex/pip/installation.py +2 -2
  59. pex/pip/local_project.py +6 -14
  60. pex/pip/package_repositories/__init__.py +78 -0
  61. pex/pip/package_repositories/link_collector.py +96 -0
  62. pex/pip/tool.py +139 -33
  63. pex/pip/vcs.py +109 -43
  64. pex/pip/version.py +8 -1
  65. pex/requirements.py +121 -16
  66. pex/resolve/config.py +5 -1
  67. pex/resolve/configured_resolve.py +32 -10
  68. pex/resolve/configured_resolver.py +10 -39
  69. pex/resolve/downloads.py +4 -3
  70. pex/resolve/lock_downloader.py +16 -23
  71. pex/resolve/lock_resolver.py +41 -51
  72. pex/resolve/locked_resolve.py +89 -32
  73. pex/resolve/locker.py +145 -101
  74. pex/resolve/locker_patches.py +123 -197
  75. pex/resolve/lockfile/create.py +232 -87
  76. pex/resolve/lockfile/download_manager.py +5 -1
  77. pex/resolve/lockfile/json_codec.py +103 -28
  78. pex/resolve/lockfile/model.py +13 -35
  79. pex/resolve/lockfile/pep_751.py +117 -98
  80. pex/resolve/lockfile/requires_dist.py +17 -262
  81. pex/resolve/lockfile/subset.py +11 -0
  82. pex/resolve/lockfile/targets.py +445 -0
  83. pex/resolve/lockfile/updater.py +22 -10
  84. pex/resolve/package_repository.py +406 -0
  85. pex/resolve/pex_repository_resolver.py +1 -1
  86. pex/resolve/pre_resolved_resolver.py +19 -16
  87. pex/resolve/project.py +233 -47
  88. pex/resolve/requirement_configuration.py +28 -10
  89. pex/resolve/resolver_configuration.py +18 -32
  90. pex/resolve/resolver_options.py +234 -28
  91. pex/resolve/resolvers.py +3 -12
  92. pex/resolve/target_options.py +18 -2
  93. pex/resolve/target_system.py +908 -0
  94. pex/resolve/venv_resolver.py +670 -0
  95. pex/resolver.py +673 -209
  96. pex/scie/__init__.py +40 -1
  97. pex/scie/model.py +2 -0
  98. pex/scie/science.py +25 -3
  99. pex/sdist.py +219 -0
  100. pex/sh_boot.py +24 -21
  101. pex/sysconfig.py +5 -3
  102. pex/targets.py +31 -10
  103. pex/third_party/__init__.py +1 -1
  104. pex/tools/commands/repository.py +48 -25
  105. pex/vendor/__init__.py +4 -9
  106. pex/vendor/__main__.py +65 -41
  107. pex/vendor/_vendored/ansicolors/.layout.json +1 -1
  108. pex/vendor/_vendored/ansicolors/ansicolors-1.1.8.dist-info/RECORD +11 -0
  109. pex/vendor/_vendored/ansicolors/ansicolors-1.1.8.pex-info/original-whl-info.json +1 -0
  110. pex/vendor/_vendored/appdirs/.layout.json +1 -1
  111. pex/vendor/_vendored/appdirs/appdirs-1.4.4.dist-info/RECORD +7 -0
  112. pex/vendor/_vendored/appdirs/appdirs-1.4.4.pex-info/original-whl-info.json +1 -0
  113. pex/vendor/_vendored/attrs/.layout.json +1 -1
  114. pex/vendor/_vendored/attrs/attrs-21.5.0.dev0.dist-info/RECORD +37 -0
  115. pex/vendor/_vendored/attrs/attrs-21.5.0.dev0.pex-info/original-whl-info.json +1 -0
  116. pex/vendor/_vendored/packaging_20_9/.layout.json +1 -1
  117. pex/vendor/_vendored/packaging_20_9/packaging-20.9.dist-info/RECORD +20 -0
  118. pex/vendor/_vendored/packaging_20_9/packaging-20.9.pex-info/original-whl-info.json +1 -0
  119. pex/vendor/_vendored/packaging_20_9/pyparsing-2.4.7.dist-info/RECORD +7 -0
  120. pex/vendor/_vendored/packaging_20_9/pyparsing-2.4.7.pex-info/original-whl-info.json +1 -0
  121. pex/vendor/_vendored/packaging_21_3/.layout.json +1 -1
  122. pex/vendor/_vendored/packaging_21_3/packaging-21.3.dist-info/RECORD +20 -0
  123. pex/vendor/_vendored/packaging_21_3/packaging-21.3.pex-info/original-whl-info.json +1 -0
  124. pex/vendor/_vendored/packaging_21_3/pyparsing-3.0.7.dist-info/RECORD +18 -0
  125. pex/vendor/_vendored/packaging_21_3/pyparsing-3.0.7.pex-info/original-whl-info.json +1 -0
  126. pex/vendor/_vendored/packaging_24_0/.layout.json +1 -1
  127. pex/vendor/_vendored/packaging_24_0/packaging-24.0.dist-info/RECORD +22 -0
  128. pex/vendor/_vendored/packaging_24_0/packaging-24.0.pex-info/original-whl-info.json +1 -0
  129. pex/vendor/_vendored/packaging_25_0/.layout.json +1 -1
  130. pex/vendor/_vendored/packaging_25_0/packaging-25.0.dist-info/RECORD +24 -0
  131. pex/vendor/_vendored/packaging_25_0/packaging-25.0.pex-info/original-whl-info.json +1 -0
  132. pex/vendor/_vendored/pip/.layout.json +1 -1
  133. pex/vendor/_vendored/pip/pip/_vendor/certifi/cacert.pem +63 -1
  134. pex/vendor/_vendored/pip/pip-20.3.4.dist-info/RECORD +388 -0
  135. pex/vendor/_vendored/pip/pip-20.3.4.pex-info/original-whl-info.json +1 -0
  136. pex/vendor/_vendored/setuptools/.layout.json +1 -1
  137. pex/vendor/_vendored/setuptools/setuptools-44.0.0+3acb925dd708430aeaf197ea53ac8a752f7c1863.dist-info/RECORD +107 -0
  138. pex/vendor/_vendored/setuptools/setuptools-44.0.0+3acb925dd708430aeaf197ea53ac8a752f7c1863.pex-info/original-whl-info.json +1 -0
  139. pex/vendor/_vendored/toml/.layout.json +1 -1
  140. pex/vendor/_vendored/toml/toml-0.10.2.dist-info/RECORD +11 -0
  141. pex/vendor/_vendored/toml/toml-0.10.2.pex-info/original-whl-info.json +1 -0
  142. pex/vendor/_vendored/tomli/.layout.json +1 -1
  143. pex/vendor/_vendored/tomli/tomli-2.0.1.dist-info/RECORD +10 -0
  144. pex/vendor/_vendored/tomli/tomli-2.0.1.pex-info/original-whl-info.json +1 -0
  145. pex/venv/installer.py +46 -19
  146. pex/venv/venv_pex.py +6 -3
  147. pex/version.py +1 -1
  148. pex/wheel.py +188 -40
  149. pex/whl.py +67 -0
  150. pex/windows/__init__.py +14 -11
  151. {pex-2.54.2.dist-info → pex-2.69.0.dist-info}/METADATA +6 -5
  152. {pex-2.54.2.dist-info → pex-2.69.0.dist-info}/RECORD +157 -133
  153. {pex-2.54.2.dist-info → pex-2.69.0.dist-info}/entry_points.txt +1 -0
  154. {pex-2.54.2.dist-info → pex-2.69.0.dist-info}/pylock/pylock.toml +1 -1
  155. pex/docs/html/_pagefind/fragment/en_42c9d8c.pf_fragment +0 -0
  156. pex/docs/html/_pagefind/fragment/en_45dd5a2.pf_fragment +0 -0
  157. pex/docs/html/_pagefind/fragment/en_4ca74d2.pf_fragment +0 -0
  158. pex/docs/html/_pagefind/fragment/en_77273d5.pf_fragment +0 -0
  159. pex/docs/html/_pagefind/fragment/en_87a59c5.pf_fragment +0 -0
  160. pex/docs/html/_pagefind/fragment/en_8dc89b5.pf_fragment +0 -0
  161. pex/docs/html/_pagefind/fragment/en_9d1319b.pf_fragment +0 -0
  162. pex/docs/html/_pagefind/fragment/en_e55df9d.pf_fragment +0 -0
  163. pex/docs/html/_pagefind/index/en_1e98c6f.pf_index +0 -0
  164. pex/docs/html/_pagefind/pagefind.en_d1c488ecae.pf_meta +0 -0
  165. pex/vendor/_vendored/ansicolors/ansicolors-1.1.8.dist-info/INSTALLER +0 -1
  166. pex/vendor/_vendored/appdirs/appdirs-1.4.4.dist-info/INSTALLER +0 -1
  167. pex/vendor/_vendored/attrs/attrs-21.5.0.dev0.dist-info/INSTALLER +0 -1
  168. pex/vendor/_vendored/packaging_20_9/packaging-20.9.dist-info/INSTALLER +0 -1
  169. pex/vendor/_vendored/packaging_20_9/pyparsing-2.4.7.dist-info/INSTALLER +0 -1
  170. pex/vendor/_vendored/packaging_21_3/packaging-21.3.dist-info/INSTALLER +0 -1
  171. pex/vendor/_vendored/packaging_21_3/pyparsing-3.0.7.dist-info/INSTALLER +0 -1
  172. pex/vendor/_vendored/packaging_24_0/packaging-24.0.dist-info/INSTALLER +0 -1
  173. pex/vendor/_vendored/packaging_25_0/packaging-25.0.dist-info/INSTALLER +0 -1
  174. pex/vendor/_vendored/pip/pip-20.3.4.dist-info/INSTALLER +0 -1
  175. pex/vendor/_vendored/setuptools/setuptools-44.0.0+3acb925dd708430aeaf197ea53ac8a752f7c1863.dist-info/INSTALLER +0 -1
  176. pex/vendor/_vendored/toml/toml-0.10.2.dist-info/INSTALLER +0 -1
  177. pex/vendor/_vendored/tomli/tomli-2.0.1.dist-info/INSTALLER +0 -1
  178. {pex-2.54.2.dist-info → pex-2.69.0.dist-info}/WHEEL +0 -0
  179. {pex-2.54.2.dist-info → pex-2.69.0.dist-info}/licenses/LICENSE +0 -0
  180. {pex-2.54.2.dist-info → pex-2.69.0.dist-info}/top_level.txt +0 -0
@@ -5,10 +5,11 @@ from __future__ import absolute_import
5
5
 
6
6
  from collections import defaultdict
7
7
 
8
- from pex.auth import PasswordDatabase, PasswordEntry
8
+ from pex.auth import PasswordDatabase
9
9
  from pex.dependency_configuration import DependencyConfiguration
10
10
  from pex.dist_metadata import Requirement, is_wheel
11
11
  from pex.exceptions import production_assert
12
+ from pex.interpreter_constraints import InterpreterConstraint
12
13
  from pex.network_configuration import NetworkConfiguration
13
14
  from pex.pep_427 import InstallableType
14
15
  from pex.pep_503 import ProjectName
@@ -19,7 +20,6 @@ from pex.resolve.locked_resolve import (
19
20
  DownloadableArtifact,
20
21
  LocalProjectArtifact,
21
22
  LockConfiguration,
22
- LockStyle,
23
23
  UnFingerprintedLocalProjectArtifact,
24
24
  )
25
25
  from pex.resolve.lockfile.download_manager import DownloadedArtifact
@@ -28,6 +28,7 @@ from pex.resolve.lockfile.pep_751 import Package, Pylock
28
28
  from pex.resolve.lockfile.pep_751 import subset as subset_pylock
29
29
  from pex.resolve.lockfile.subset import SubsetResult
30
30
  from pex.resolve.lockfile.subset import subset as subset_pex_lock
31
+ from pex.resolve.package_repository import ReposConfiguration
31
32
  from pex.resolve.requirement_configuration import RequirementConfiguration
32
33
  from pex.resolve.resolver_configuration import BuildConfiguration, ResolverVersion
33
34
  from pex.resolve.resolvers import ResolvedDistribution, Resolver, ResolveResult
@@ -51,6 +52,10 @@ if TYPE_CHECKING:
51
52
  Union,
52
53
  )
53
54
 
55
+ import attr # vendor:skip
56
+ else:
57
+ from pex.third_party import attr
58
+
54
59
 
55
60
  def _check_subset(
56
61
  pylock, # type: Pylock
@@ -116,11 +121,9 @@ def resolve_from_pylock(
116
121
  extras=frozenset(), # type: FrozenSet[str]
117
122
  dependency_groups=frozenset(), # type: FrozenSet[str]
118
123
  constraint_files=None, # type: Optional[Iterable[str]]
119
- indexes=None, # type: Optional[Sequence[str]]
120
- find_links=None, # type: Optional[Sequence[str]]
124
+ repos_configuration=ReposConfiguration(), # type: ReposConfiguration
121
125
  resolver_version=None, # type: Optional[ResolverVersion.Value]
122
126
  network_configuration=None, # type: Optional[NetworkConfiguration]
123
- password_entries=(), # type: Iterable[PasswordEntry]
124
127
  build_configuration=BuildConfiguration(), # type: BuildConfiguration
125
128
  compile=False, # type: bool
126
129
  transitive=True, # type: bool
@@ -157,16 +160,17 @@ def resolve_from_pylock(
157
160
  pylock_subset_result.subset_result,
158
161
  # This ensures artifact downloads via Pip will not be rejected by Pip for mismatched
159
162
  # target interpreters, etc.
160
- lock_configuration=LockConfiguration(
161
- style=LockStyle.UNIVERSAL,
162
- requires_python=tuple([pylock.requires_python]) if pylock.requires_python else (),
163
+ lock_configuration=LockConfiguration.universal(
164
+ interpreter_constraints=(
165
+ [InterpreterConstraint(specifier=pylock.requires_python)]
166
+ if pylock.requires_python
167
+ else []
168
+ )
163
169
  ),
164
170
  resolver=resolver,
165
- indexes=indexes,
166
- find_links=find_links,
171
+ repos_configuration=repos_configuration,
167
172
  resolver_version=resolver_version,
168
173
  network_configuration=network_configuration,
169
- password_entries=password_entries,
170
174
  build_configuration=build_configuration,
171
175
  compile=compile,
172
176
  verify_wheels=verify_wheels,
@@ -204,11 +208,9 @@ def download_from_pylock(
204
208
  extras=frozenset(), # type: FrozenSet[str]
205
209
  dependency_groups=frozenset(), # type: FrozenSet[str]
206
210
  constraint_files=None, # type: Optional[Iterable[str]]
207
- indexes=None, # type: Optional[Sequence[str]]
208
- find_links=None, # type: Optional[Sequence[str]]
211
+ repos_configuration=ReposConfiguration(), # type: ReposConfiguration
209
212
  resolver_version=None, # type: Optional[ResolverVersion.Value]
210
213
  network_configuration=None, # type: Optional[NetworkConfiguration]
211
- password_entries=(), # type: Iterable[PasswordEntry]
212
214
  build_configuration=BuildConfiguration(), # type: BuildConfiguration
213
215
  transitive=True, # type: bool
214
216
  max_parallel_jobs=None, # type: Optional[int]
@@ -242,16 +244,17 @@ def download_from_pylock(
242
244
  pylock_subset_result.subset_result,
243
245
  # This ensures artifact downloads via Pip will not be rejected by Pip for mismatched
244
246
  # target interpreters, etc.
245
- lock_configuration=LockConfiguration(
246
- style=LockStyle.UNIVERSAL,
247
- requires_python=tuple([pylock.requires_python]) if pylock.requires_python else (),
247
+ lock_configuration=LockConfiguration.universal(
248
+ interpreter_constraints=(
249
+ [InterpreterConstraint(specifier=pylock.requires_python)]
250
+ if pylock.requires_python
251
+ else []
252
+ ),
248
253
  ),
249
254
  resolver=resolver,
250
- indexes=indexes,
251
- find_links=find_links,
255
+ repos_configuration=repos_configuration,
252
256
  resolver_version=resolver_version,
253
257
  network_configuration=network_configuration,
254
- password_entries=password_entries,
255
258
  build_configuration=build_configuration,
256
259
  max_parallel_jobs=max_parallel_jobs,
257
260
  pip_version=pip_version,
@@ -271,11 +274,9 @@ def resolve_from_pex_lock(
271
274
  requirements=None, # type: Optional[Iterable[str]]
272
275
  requirement_files=None, # type: Optional[Iterable[str]]
273
276
  constraint_files=None, # type: Optional[Iterable[str]]
274
- indexes=None, # type: Optional[Sequence[str]]
275
- find_links=None, # type: Optional[Sequence[str]]
277
+ repos_configuration=ReposConfiguration(), # type: ReposConfiguration
276
278
  resolver_version=None, # type: Optional[ResolverVersion.Value]
277
279
  network_configuration=None, # type: Optional[NetworkConfiguration]
278
- password_entries=(), # type: Iterable[PasswordEntry]
279
280
  build_configuration=BuildConfiguration(), # type: BuildConfiguration
280
281
  compile=False, # type: bool
281
282
  transitive=True, # type: bool
@@ -308,13 +309,11 @@ def resolve_from_pex_lock(
308
309
  )
309
310
  return _resolve_from_subset_result(
310
311
  subset_result,
311
- lock_configuration=lock.lock_configuration(),
312
+ lock_configuration=lock.configuration,
312
313
  resolver=resolver,
313
- indexes=indexes,
314
- find_links=find_links,
314
+ repos_configuration=repos_configuration,
315
315
  resolver_version=resolver_version,
316
316
  network_configuration=network_configuration,
317
- password_entries=password_entries,
318
317
  build_configuration=build_configuration,
319
318
  compile=compile,
320
319
  verify_wheels=verify_wheels,
@@ -335,11 +334,9 @@ def download_from_pex_lock(
335
334
  requirements=None, # type: Optional[Iterable[str]]
336
335
  requirement_files=None, # type: Optional[Iterable[str]]
337
336
  constraint_files=None, # type: Optional[Iterable[str]]
338
- indexes=None, # type: Optional[Sequence[str]]
339
- find_links=None, # type: Optional[Sequence[str]]
337
+ repos_configuration=ReposConfiguration(), # type: ReposConfiguration
340
338
  resolver_version=None, # type: Optional[ResolverVersion.Value]
341
339
  network_configuration=None, # type: Optional[NetworkConfiguration]
342
- password_entries=(), # type: Iterable[PasswordEntry]
343
340
  build_configuration=BuildConfiguration(), # type: BuildConfiguration
344
341
  transitive=True, # type: bool
345
342
  max_parallel_jobs=None, # type: Optional[int]
@@ -369,13 +366,11 @@ def download_from_pex_lock(
369
366
  )
370
367
  downloaded_artifacts = _download_from_subset_result(
371
368
  subset_result,
372
- lock_configuration=lock.lock_configuration(),
369
+ lock_configuration=lock.configuration,
373
370
  resolver=resolver,
374
- indexes=indexes,
375
- find_links=find_links,
371
+ repos_configuration=repos_configuration,
376
372
  resolver_version=resolver_version,
377
373
  network_configuration=network_configuration,
378
- password_entries=password_entries,
379
374
  build_configuration=build_configuration,
380
375
  max_parallel_jobs=max_parallel_jobs,
381
376
  pip_version=pip_version,
@@ -392,11 +387,9 @@ def _download_from_subset_result(
392
387
  subset_result, # type: SubsetResult
393
388
  lock_configuration, # type: LockConfiguration
394
389
  resolver, # type: Resolver
395
- indexes=None, # type: Optional[Sequence[str]]
396
- find_links=None, # type: Optional[Sequence[str]]
390
+ repos_configuration=ReposConfiguration(), # type: ReposConfiguration
397
391
  resolver_version=None, # type: Optional[ResolverVersion.Value]
398
392
  network_configuration=None, # type: Optional[NetworkConfiguration]
399
- password_entries=(), # type: Iterable[PasswordEntry]
400
393
  build_configuration=BuildConfiguration(), # type: BuildConfiguration
401
394
  max_parallel_jobs=None, # type: Optional[int]
402
395
  pip_version=None, # type: Optional[PipVersionValue]
@@ -415,13 +408,11 @@ def _download_from_subset_result(
415
408
  targets=tuple(resolved_subset.target for resolved_subset in subset_result.subsets),
416
409
  lock_configuration=lock_configuration,
417
410
  resolver=resolver,
418
- indexes=indexes,
419
- find_links=find_links,
411
+ repos_configuration=repos_configuration,
420
412
  max_parallel_jobs=max_parallel_jobs,
421
413
  pip_version=pip_version,
422
414
  resolver_version=resolver_version,
423
415
  network_configuration=network_configuration,
424
- password_entries=password_entries,
425
416
  build_configuration=build_configuration,
426
417
  use_pip_config=use_pip_config,
427
418
  extra_pip_requirements=extra_pip_requirements,
@@ -440,11 +431,9 @@ def _resolve_from_subset_result(
440
431
  subset_result, # type: SubsetResult
441
432
  lock_configuration, # type: LockConfiguration
442
433
  resolver, # type: Resolver
443
- indexes=None, # type: Optional[Sequence[str]]
444
- find_links=None, # type: Optional[Sequence[str]]
434
+ repos_configuration=ReposConfiguration(), # type: ReposConfiguration
445
435
  resolver_version=None, # type: Optional[ResolverVersion.Value]
446
436
  network_configuration=None, # type: Optional[NetworkConfiguration]
447
- password_entries=(), # type: Iterable[PasswordEntry]
448
437
  build_configuration=BuildConfiguration(), # type: BuildConfiguration
449
438
  compile=False, # type: bool
450
439
  verify_wheels=True, # type: bool
@@ -462,11 +451,9 @@ def _resolve_from_subset_result(
462
451
  subset_result,
463
452
  lock_configuration=lock_configuration,
464
453
  resolver=resolver,
465
- indexes=indexes,
466
- find_links=find_links,
454
+ repos_configuration=repos_configuration,
467
455
  resolver_version=resolver_version,
468
456
  network_configuration=network_configuration,
469
- password_entries=password_entries,
470
457
  build_configuration=build_configuration,
471
458
  max_parallel_jobs=max_parallel_jobs,
472
459
  pip_version=pip_version,
@@ -486,7 +473,7 @@ def _resolve_from_subset_result(
486
473
  if is_wheel(downloaded_artifact.path):
487
474
  install_requests.append(
488
475
  InstallRequest(
489
- target=resolved_subset.target,
476
+ download_target=resolved_subset.target,
490
477
  wheel_path=downloaded_artifact.path,
491
478
  fingerprint=downloaded_artifact.fingerprint,
492
479
  )
@@ -494,7 +481,7 @@ def _resolve_from_subset_result(
494
481
  else:
495
482
  build_requests.append(
496
483
  BuildRequest(
497
- target=resolved_subset.target,
484
+ download_target=resolved_subset.target,
498
485
  source_path=downloaded_artifact.path,
499
486
  fingerprint=downloaded_artifact.fingerprint,
500
487
  subdirectory=downloaded_artifact.subdirectory,
@@ -505,6 +492,9 @@ def _resolve_from_subset_result(
505
492
  len(build_requests), len(build_requests) + len(install_requests)
506
493
  )
507
494
  ):
495
+ password_database = PasswordDatabase.from_netrc().append(
496
+ repos_configuration.password_entries
497
+ )
508
498
  build_and_install_request = BuildAndInstallRequest(
509
499
  build_requests=build_requests,
510
500
  install_requests=install_requests,
@@ -512,10 +502,10 @@ def _resolve_from_subset_result(
512
502
  package_index_configuration=PackageIndexConfiguration.create(
513
503
  pip_version=pip_version,
514
504
  resolver_version=resolver_version,
515
- indexes=indexes,
516
- find_links=find_links,
505
+ repos_configuration=attr.evolve(
506
+ repos_configuration, password_entries=password_database.entries
507
+ ),
517
508
  network_configuration=network_configuration,
518
- password_entries=PasswordDatabase.from_netrc().append(password_entries).entries,
519
509
  use_pip_config=use_pip_config,
520
510
  extra_pip_requirements=extra_pip_requirements,
521
511
  keyring_provider=keyring_provider,
@@ -12,18 +12,23 @@ from functools import total_ordering
12
12
  from pex.artifact_url import VCS, ArtifactURL, Fingerprint, VCSScheme
13
13
  from pex.common import pluralize
14
14
  from pex.dependency_configuration import DependencyConfiguration
15
- from pex.dist_metadata import DistMetadata, Requirement, is_sdist, is_wheel
15
+ from pex.dist_metadata import ProjectMetadata, Requirement, is_sdist, is_wheel
16
16
  from pex.enum import Enum
17
17
  from pex.exceptions import production_assert
18
+ from pex.interpreter_constraints import InterpreterConstraint
19
+ from pex.interpreter_implementation import InterpreterImplementation
18
20
  from pex.orderedset import OrderedSet
19
21
  from pex.pep_425 import CompatibilityTags, TagRank
22
+ from pex.pep_440 import Version
20
23
  from pex.pep_503 import ProjectName
21
24
  from pex.rank import Rank
22
25
  from pex.resolve.resolved_requirement import PartialArtifact, Pin, ResolvedRequirement
23
26
  from pex.resolve.resolver_configuration import BuildConfiguration
27
+ from pex.resolve.target_system import TargetSystem, UniversalTarget
24
28
  from pex.result import Error
25
29
  from pex.sorted_tuple import SortedTuple
26
30
  from pex.targets import Target
31
+ from pex.third_party.packaging.markers import Marker
27
32
  from pex.tracer import TRACER
28
33
  from pex.typing import TYPE_CHECKING, Generic
29
34
 
@@ -67,33 +72,71 @@ class LockStyle(Enum["LockStyle.Value"]):
67
72
  LockStyle.seal()
68
73
 
69
74
 
70
- class TargetSystem(Enum["TargetSystem.Value"]):
71
- class Value(Enum.Value):
72
- pass
73
-
74
- LINUX = Value("linux")
75
- MAC = Value("mac")
76
- WINDOWS = Value("windows")
77
-
78
-
79
- TargetSystem.seal()
80
-
81
-
82
75
  @attr.s(frozen=True)
83
76
  class LockConfiguration(object):
77
+ @classmethod
78
+ def universal(
79
+ cls,
80
+ interpreter_constraints=(), # type: Iterable[InterpreterConstraint]
81
+ systems=(), # type: Iterable[TargetSystem.Value]
82
+ elide_unused_requires_dist=False, # type: bool
83
+ ):
84
+ # type: (...) -> LockConfiguration
85
+
86
+ implementations = defaultdict(
87
+ set
88
+ ) # type: DefaultDict[Optional[InterpreterImplementation.Value], Set[SpecifierSet]]
89
+ for interpreter_constraint in interpreter_constraints:
90
+ implementations[interpreter_constraint.implementation].add(
91
+ interpreter_constraint.requires_python
92
+ )
93
+ if len(implementations) > 1 and frozenset(implementations) != frozenset(
94
+ InterpreterImplementation.values()
95
+ ):
96
+ raise ValueError(
97
+ "The interpreter constraints for a universal resolve cannot have mixed "
98
+ "implementations unless they are all explicit and span the full set of Pex "
99
+ "supported implementations: {implementations}.\n"
100
+ "Given: {constraints}".format(
101
+ implementations=" and ".join(map(str, InterpreterImplementation.values())),
102
+ constraints=" or ".join(map(str, interpreter_constraints)),
103
+ )
104
+ )
105
+ elif len(set(map(frozenset, implementations.values()))) > 1:
106
+ raise ValueError(
107
+ "The interpreter constraints for a universal resolve cannot have mixed "
108
+ "implementations with differing specifiers.\n"
109
+ "If you feel you need this support, please comment here: "
110
+ "https://github.com/pex-tool/pex/issues/2897#issuecomment-3256619591\n"
111
+ "Given: {constraints}".format(
112
+ constraints=" or ".join(map(str, interpreter_constraints))
113
+ )
114
+ )
115
+
116
+ return cls(
117
+ style=LockStyle.UNIVERSAL,
118
+ universal_target=UniversalTarget(
119
+ implementation=next(iter(implementations)) if len(implementations) == 1 else None,
120
+ requires_python=tuple(
121
+ interpreter_constraint.requires_python
122
+ for interpreter_constraint in interpreter_constraints
123
+ ),
124
+ systems=tuple(systems),
125
+ ),
126
+ elide_unused_requires_dist=elide_unused_requires_dist,
127
+ )
128
+
84
129
  style = attr.ib() # type: LockStyle.Value
85
- requires_python = attr.ib(default=()) # type: Tuple[str, ...]
86
- target_systems = attr.ib(default=()) # type: Tuple[TargetSystem.Value, ...]
130
+ universal_target = attr.ib(default=None) # type: Optional[UniversalTarget]
87
131
  elide_unused_requires_dist = attr.ib(default=False) # type: bool
88
132
 
89
- @requires_python.validator
90
- @target_systems.validator
133
+ @universal_target.validator
91
134
  def _validate_only_set_for_universal(
92
135
  self,
93
136
  attribute, # type: Any
94
137
  value, # type: Any
95
138
  ):
96
- if value and self.style != LockStyle.UNIVERSAL:
139
+ if value and self.style is not LockStyle.UNIVERSAL:
97
140
  raise ValueError(
98
141
  "The {field_name} field should only be set for {universal} style locks; "
99
142
  "this lock is {style} style and given {field_name} value of {value}".format(
@@ -238,7 +281,11 @@ class VCSArtifact(Artifact):
238
281
  def split_requested_revision(artifact_url):
239
282
  # type: (ArtifactURL) -> Tuple[ArtifactURL, Optional[str]]
240
283
 
241
- vcs_url, _, requested_revision = artifact_url.normalized_url.partition("@")
284
+ vcs_url = artifact_url.normalized_url
285
+ if "@" in artifact_url.path:
286
+ vcs_url, _, requested_revision = vcs_url.rpartition("@")
287
+ else:
288
+ requested_revision = None
242
289
  return ArtifactURL.parse(vcs_url), requested_revision or None
243
290
 
244
291
  @classmethod
@@ -541,7 +588,7 @@ class DownloadableArtifact(object):
541
588
  attr.ib()
542
589
  ) # type: Union[FileArtifact, LocalProjectArtifact, UnFingerprintedLocalProjectArtifact, UnFingerprintedVCSArtifact, VCSArtifact]
543
590
  satisfied_direct_requirements = attr.ib(default=SortedTuple()) # type: SortedTuple[Requirement]
544
- version = attr.ib(default=None)
591
+ version = attr.ib(default=None) # type: Optional[Version]
545
592
 
546
593
  def specifier(self):
547
594
  # type: () -> str
@@ -613,9 +660,10 @@ class LockedResolve(object):
613
660
  def create(
614
661
  cls,
615
662
  resolved_requirements, # type: Iterable[ResolvedRequirement]
616
- dist_metadatas, # type: Iterable[DistMetadata]
663
+ project_metadatas, # type: Iterable[ProjectMetadata]
617
664
  fingerprinter, # type: Fingerprinter
618
665
  platform_tag=None, # type: Optional[tags.Tag]
666
+ marker=None, # type: Optional[Marker]
619
667
  ):
620
668
  # type: (...) -> LockedResolve
621
669
 
@@ -655,21 +703,21 @@ class LockedResolve(object):
655
703
  editable=partial_artifact.editable,
656
704
  )
657
705
 
658
- dist_metadata_by_pin = {
706
+ project_metadata_by_pin = {
659
707
  Pin(dist_info.project_name, dist_info.version): dist_info
660
- for dist_info in dist_metadatas
708
+ for dist_info in project_metadatas
661
709
  }
662
710
  locked_requirements = []
663
711
  for resolved_requirement in resolved_requirements:
664
- distribution_metadata = dist_metadata_by_pin.get(resolved_requirement.pin)
665
- if distribution_metadata is None:
712
+ project_metadata = project_metadata_by_pin.get(resolved_requirement.pin)
713
+ if project_metadata is None:
666
714
  raise ValueError(
667
- "No distribution metadata found for {project}.\n"
668
- "Given distribution metadata for:\n"
715
+ "No project metadata found for {project}.\n"
716
+ "Given project metadata for:\n"
669
717
  "{projects}".format(
670
718
  project=resolved_requirement.pin.as_requirement(),
671
719
  projects="\n".join(
672
- sorted(str(pin.as_requirement()) for pin in dist_metadata_by_pin)
720
+ sorted(str(pin.as_requirement()) for pin in project_metadata_by_pin)
673
721
  ),
674
722
  )
675
723
  )
@@ -677,23 +725,32 @@ class LockedResolve(object):
677
725
  LockedRequirement.create(
678
726
  pin=resolved_requirement.pin,
679
727
  artifact=resolve_fingerprint(resolved_requirement.artifact),
680
- requires_dists=distribution_metadata.requires_dists,
681
- requires_python=distribution_metadata.requires_python,
728
+ requires_dists=project_metadata.requires_dists,
729
+ requires_python=project_metadata.requires_python,
682
730
  additional_artifacts=(
683
731
  resolve_fingerprint(artifact)
684
732
  for artifact in resolved_requirement.additional_artifacts
685
733
  ),
686
734
  )
687
735
  )
688
- return cls(locked_requirements=SortedTuple(locked_requirements), platform_tag=platform_tag)
736
+ return cls(
737
+ locked_requirements=SortedTuple(locked_requirements),
738
+ platform_tag=platform_tag,
739
+ marker=marker,
740
+ )
689
741
 
690
742
  locked_requirements = attr.ib() # type: SortedTuple[LockedRequirement]
691
743
  platform_tag = attr.ib(order=str, default=None) # type: Optional[tags.Tag]
744
+ marker = attr.ib(order=str, default=None) # type: Optional[Marker]
692
745
 
693
746
  @property
694
747
  def target_platform(self):
695
748
  # type: () -> str
696
- return str(self.platform_tag) if self.platform_tag else "universal"
749
+ if self.platform_tag:
750
+ return str(self.platform_tag)
751
+ if self.marker:
752
+ return "universal {marker}".format(marker=self.marker)
753
+ return "universal"
697
754
 
698
755
  def create_resolved_artifacts(
699
756
  self,