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
@@ -13,9 +13,10 @@ from pex.compatibility import indent
13
13
  from pex.dist_metadata import Requirement, RequirementParseError
14
14
  from pex.enum import Enum
15
15
  from pex.interpreter import PythonInterpreter
16
+ from pex.interpreter_implementation import InterpreterImplementation
16
17
  from pex.orderedset import OrderedSet
17
18
  from pex.specifier_sets import UnsatisfiableSpecifierSet, as_range
18
- from pex.third_party.packaging.specifiers import SpecifierSet
19
+ from pex.third_party.packaging.specifiers import InvalidSpecifier, SpecifierSet
19
20
  from pex.typing import TYPE_CHECKING
20
21
 
21
22
  if TYPE_CHECKING:
@@ -38,23 +39,19 @@ class InterpreterConstraint(object):
38
39
  def parse(
39
40
  cls,
40
41
  constraint, # type: str
41
- default_interpreter=None, # type: Optional[str]
42
+ default_interpreter=None, # type: Optional[InterpreterImplementation.Value]
42
43
  ):
43
44
  # type: (...) -> InterpreterConstraint
44
45
  try:
45
46
  requirement = Requirement.parse(constraint)
46
- return cls(specifier=requirement.specifier, name=requirement.name)
47
+ return cls(
48
+ specifier=requirement.specifier,
49
+ implementation=InterpreterImplementation.for_value(requirement.name),
50
+ )
47
51
  except RequirementParseError:
48
- if default_interpreter is not None:
49
- return cls.parse(
50
- constraint="{interpreter}{specifier}".format(
51
- interpreter=default_interpreter, specifier=constraint
52
- ),
53
- default_interpreter=None,
54
- )
55
52
  try:
56
- return cls(specifier=SpecifierSet(constraint))
57
- except RequirementParseError as e:
53
+ return cls(specifier=SpecifierSet(constraint), implementation=default_interpreter)
54
+ except InvalidSpecifier as e:
58
55
  raise ValueError(
59
56
  "Unparseable interpreter constraint {constraint}: {err}".format(
60
57
  constraint=constraint, err=e
@@ -74,13 +71,13 @@ class InterpreterConstraint(object):
74
71
  # type: (Optional[PythonInterpreter]) -> InterpreterConstraint
75
72
  python_identity = (interpreter or PythonInterpreter.get()).identity
76
73
  return cls.parse(
77
- "{interpreter}=={version}".format(
78
- interpreter=python_identity.interpreter, version=python_identity.version_str
74
+ "{implementation}=={version}".format(
75
+ implementation=python_identity.implementation, version=python_identity.version_str
79
76
  )
80
77
  )
81
78
 
82
79
  specifier = attr.ib() # type: SpecifierSet
83
- name = attr.ib(default=None) # type: Optional[str]
80
+ implementation = attr.ib(default=None) # type: Optional[InterpreterImplementation.Value]
84
81
 
85
82
  @specifier.validator
86
83
  def _validate_specifier(
@@ -107,12 +104,14 @@ class InterpreterConstraint(object):
107
104
 
108
105
  def __str__(self):
109
106
  # type: () -> str
110
- return "{name}{specifier}".format(name=self.name or "", specifier=self.specifier)
107
+ return "{implementation}{specifier}".format(
108
+ implementation=self.implementation or "", specifier=self.specifier
109
+ )
111
110
 
112
111
  def __contains__(self, interpreter):
113
112
  # type: (PythonInterpreter) -> bool
114
113
  python_identity = interpreter.identity
115
- if self.name and self.name != python_identity.interpreter:
114
+ if self.implementation and self.implementation is not python_identity.implementation:
116
115
  return False
117
116
  return python_identity.version_str in self.specifier
118
117
 
@@ -376,22 +375,23 @@ COMPATIBLE_PYTHON_VERSIONS = (
376
375
  PythonVersion(Lifecycle.EOL, 3, 6, 15),
377
376
  PythonVersion(Lifecycle.EOL, 3, 7, 17),
378
377
  PythonVersion(Lifecycle.EOL, 3, 8, 20),
379
- PythonVersion(Lifecycle.STABLE, 3, 9, 23),
380
- PythonVersion(Lifecycle.STABLE, 3, 10, 18),
381
- PythonVersion(Lifecycle.STABLE, 3, 11, 13),
382
- PythonVersion(Lifecycle.STABLE, 3, 12, 11),
383
- PythonVersion(Lifecycle.STABLE, 3, 13, 7),
384
- PythonVersion(Lifecycle.DEV, 3, 14, 0),
378
+ PythonVersion(Lifecycle.EOL, 3, 9, 25),
379
+ PythonVersion(Lifecycle.STABLE, 3, 10, 19),
380
+ PythonVersion(Lifecycle.STABLE, 3, 11, 14),
381
+ PythonVersion(Lifecycle.STABLE, 3, 12, 12),
382
+ PythonVersion(Lifecycle.STABLE, 3, 13, 9),
383
+ PythonVersion(Lifecycle.STABLE, 3, 14, 0),
384
+ PythonVersion(Lifecycle.DEV, 3, 15, 0),
385
385
  )
386
386
 
387
387
 
388
388
  def iter_compatible_versions(
389
- requires_python, # type: Iterable[str]
389
+ requires_python, # type: Iterable[SpecifierSet]
390
390
  max_patch=DEFAULT_MAX_PATCH, # type: int
391
391
  ):
392
392
  # type: (...) -> Iterator[Tuple[int, int, int]]
393
393
 
394
- specifier_sets = OrderedSet(SpecifierSet(req) for req in requires_python)
394
+ specifier_sets = OrderedSet(requires_python)
395
395
  return itertools.chain.from_iterable(
396
396
  python_version.iter_compatible_versions(specifier_sets, max_patch=max_patch)
397
397
  for python_version in COMPATIBLE_PYTHON_VERSIONS
@@ -0,0 +1,40 @@
1
+ # Copyright 2025 Pex project contributors.
2
+ # Licensed under the Apache License, Version 2.0 (see LICENSE).
3
+
4
+ from __future__ import absolute_import
5
+
6
+ from pex.enum import Enum
7
+ from pex.typing import TYPE_CHECKING
8
+
9
+ if TYPE_CHECKING:
10
+ from typing import Optional, Tuple
11
+
12
+
13
+ class _InterpreterImplementationValue(Enum.Value):
14
+ def __init__(
15
+ self,
16
+ value, # type: str
17
+ abbr, # type: str
18
+ binary_name, # type: str
19
+ ):
20
+ # type: (...) -> None
21
+ super(_InterpreterImplementationValue, self).__init__(value)
22
+ self.abbr = abbr
23
+ self.binary_name = binary_name
24
+
25
+ def calculate_binary_name(self, version=None):
26
+ # type: (Optional[Tuple[int, ...]]) -> str
27
+ if not version:
28
+ return self.binary_name
29
+ return "{name}{version}".format(name=self.binary_name, version=".".join(map(str, version)))
30
+
31
+
32
+ class InterpreterImplementation(Enum["InterpreterImplementation.Value"]):
33
+ class Value(_InterpreterImplementationValue):
34
+ pass
35
+
36
+ CPYTHON = Value("CPython", "cp", "python")
37
+ PYPY = Value("PyPy", "pp", "pypy")
38
+
39
+
40
+ InterpreterImplementation.seal()
pex/jobs.py CHANGED
@@ -724,6 +724,19 @@ def iter_map_parallel(
724
724
  if not input_items:
725
725
  return
726
726
 
727
+ # We want each of the job slots to process MULTIPROCESSING_DEFAULT_MIN_AVERAGE_LOAD on
728
+ # average in order to overcome multiprocessing overheads. If we don't need at least 2 slots, we
729
+ # are unlikely to get any boost from multiprocessing.
730
+ needed_slots = len(input_items) // min_average_load
731
+ if needed_slots < 2:
732
+ for item in input_items:
733
+ yield function(item)
734
+ return
735
+
736
+ # Of course, if there are fewer available cores than that or the user has pinned max jobs lower,
737
+ # we clamp to that.
738
+ pool_size = min(needed_slots, _sanitize_max_jobs(max_jobs))
739
+
727
740
  if costing_function is not None:
728
741
  # We ensure no job slot is so unlucky as to get all the biggest jobs and thus become an
729
742
  # un-necessarily long pole by sorting based on cost. Some examples to illustrate the effect
@@ -740,12 +753,6 @@ def iter_map_parallel(
740
753
  #
741
754
  input_items.sort(key=costing_function, reverse=True)
742
755
 
743
- # We want each of the job slots above to process MULTIPROCESSING_DEFAULT_MIN_AVERAGE_LOAD on
744
- # average in order to overcome multiprocessing overheads. Of course, if there are fewer
745
- # available cores than that or the user has pinned max jobs lower, we clamp to that. Finally, we
746
- # always want at least two slots to ensure we process input items in parallel.
747
- pool_size = max(2, min(len(input_items) // min_average_load, _sanitize_max_jobs(max_jobs)))
748
-
749
756
  apply_function = functools.partial(_apply_function, function)
750
757
 
751
758
  slots = defaultdict(list) # type: DefaultDict[int, List[float]]