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
@@ -3,212 +3,82 @@
3
3
 
4
4
  from __future__ import absolute_import
5
5
 
6
+ import json
6
7
  import os
7
8
 
8
- try:
9
- from . import requires_python # type:ignore[attr-defined] # This file will be relocated.
10
-
11
- python_full_versions = requires_python.PYTHON_FULL_VERSIONS
12
- python_versions = requires_python.PYTHON_VERSIONS
13
- python_majors = sorted(set(version[0] for version in python_full_versions))
14
- except ImportError:
15
- python_full_versions = []
16
- python_versions = []
17
- python_majors = []
18
-
19
- os_names = []
20
- platform_systems = []
21
- sys_platforms = []
22
- platform_tag_regexps = []
9
+ from pex.interpreter_implementation import InterpreterImplementation
10
+ from pex.resolve.target_system import UniversalTarget
23
11
 
24
12
  # N.B.: The following environment variables are used by the Pex runtime to control Pip and must be
25
13
  # kept in-sync with `locker.py`.
26
- target_systems_file = os.environ.pop("_PEX_TARGET_SYSTEMS_FILE", None)
27
-
28
- if target_systems_file:
29
- import json
30
-
31
- with open(target_systems_file) as fp:
32
- target_systems = json.load(fp)
33
- os_names = target_systems["os_names"]
34
- platform_systems = target_systems["platform_systems"]
35
- sys_platforms = target_systems["sys_platforms"]
36
- platform_tag_regexps = target_systems["platform_tag_regexps"]
14
+ target_systems_file = os.environ.pop("_PEX_UNIVERSAL_TARGET_FILE")
15
+ with open(target_systems_file) as fp:
16
+ universal_target = UniversalTarget.from_dict(json.load(fp))
37
17
 
38
18
 
39
19
  def patch_marker_evaluate():
40
20
  from pip._vendor.packaging import markers
41
21
 
42
- from pex.exceptions import production_assert
43
- from pex.typing import TYPE_CHECKING
44
-
45
- if TYPE_CHECKING:
46
- from typing import Any, Callable, Dict, Iterable, List, Tuple, Type
47
-
48
- original_eval_op = markers._eval_op
49
-
50
- # N.B.: The `packaging` distribution vendored with Pip>=24.1 has a patch that tests the
51
- # `python_full_version` marker environment value to see if it ends with "+", in which case it
52
- # appends "local" to it (see: https://github.com/pypa/packaging/pull/802). We support this test
53
- # by ensuring our value for `python_full_version`, either a `skip` sentinel or a list value,
54
- # both support the `endswith(value)` test and always return `False`.
55
- class NeverEndsWithMixin(object):
56
- def endswith(self, *args, **kwargs):
57
- # type: (...) -> bool
58
- return False
59
-
60
- class NeverEndsWithStr(NeverEndsWithMixin, str):
61
- pass
62
-
63
- skip = NeverEndsWithStr()
64
-
65
- class NeverEndsWithList(NeverEndsWithMixin, list):
66
- pass
67
-
68
- def versions_to_string(
69
- versions, # type: Iterable[Tuple[int, ...]]
70
- version_modifier=lambda version: version, # type: Callable[[str], str]
71
- list_type=list, # type: Type[List]
72
- ):
73
- # type: (...) -> List[str]
74
- return list_type(version_modifier(".".join(map(str, version))) for version in versions)
75
-
76
- original_extra = markers.default_environment().get("extra")
77
- python_versions_strings = versions_to_string(python_versions) or skip
78
- python_full_versions_strings = (
79
- versions_to_string(
80
- python_full_versions,
81
- # N.B.: We replicate the logic `packaging` vendored with Pip>=24.1 has for dealing with
82
- # non-tagged CPython builds, which is fine to apply across all versions of Pip and its
83
- # vendored packaging that we support.
84
- version_modifier=lambda version: (
85
- version + "local" if version.endswith("+") else version
86
- ),
87
- list_type=NeverEndsWithList,
88
- )
89
- or skip
90
- )
91
- os_names_strings = os_names or skip
92
- platform_systems_strings = platform_systems or skip
93
- sys_platforms_strings = sys_platforms or skip
94
-
95
- class EvaluationEnvironment(dict):
96
- @classmethod
97
- def get_env(
98
- cls,
99
- environment, # type: Dict[Any, Any]
100
- name, # type: Any
101
- ):
102
- # type: (...) -> Any
103
- production_assert(
104
- isinstance(environment, cls),
105
- "Expected environment to come from the {function} function, "
106
- "which we patch to return {expected_type}, but was {actual_type}",
107
- function=markers.default_environment,
108
- expected_type=cls,
109
- actual_type=type(environment),
110
- )
111
- return environment[name]
112
-
113
- def __missing__(self, name):
114
- # type: (Any) -> Any
115
- if name == "extra":
116
- if original_extra is None:
117
- raise markers.UndefinedEnvironmentName(
118
- "'extra' does not exist in evaluation environment."
119
- )
120
- return original_extra
121
- if name == "python_version":
122
- return python_versions_strings
123
- if name == "python_full_version":
124
- return python_full_versions_strings
125
- if name == "os_name":
126
- return os_names_strings
127
- if name == "platform_system":
128
- return platform_systems_strings
129
- if name == "sys_platform":
130
- return sys_platforms_strings
131
- return skip
132
-
133
- def _eval_op(
134
- lhs, # type: Any
135
- op, # type: Any
136
- rhs, # type: Any
137
- ):
138
- # type: (...) -> bool
139
- if lhs is skip or rhs is skip:
140
- return True
141
- return any(
142
- original_eval_op(left, op, right)
143
- for left in (lhs if isinstance(lhs, list) else [lhs])
144
- for right in (rhs if isinstance(rhs, list) else [rhs])
145
- )
146
-
147
- def _evaluate_markers(
148
- marker_values, # type: List[Any]
149
- environment, # type: Dict[str, str]
150
- ):
151
- # type: (...) -> bool
152
- groups = [[]] # type: List[List[bool]]
153
-
154
- for marker in marker_values:
155
- if isinstance(marker, list):
156
- groups[-1].append(_evaluate_markers(marker, environment))
157
- elif isinstance(marker, tuple):
158
- lhs, op, rhs = marker
159
-
160
- if isinstance(lhs, markers.Variable):
161
- lhs_value = EvaluationEnvironment.get_env(environment, lhs.value)
162
- rhs_value = rhs.value
163
- else:
164
- lhs_value = lhs.value
165
- rhs_value = EvaluationEnvironment.get_env(environment, rhs.value)
166
-
167
- groups[-1].append(_eval_op(lhs_value, op, rhs_value))
168
- else:
169
- assert marker in ["and", "or"]
170
- if marker == "or":
171
- groups.append([])
172
-
173
- return any(all(item) for item in groups)
174
-
175
- # Works with all Pip vendored packaging distributions.
176
- markers.default_environment = EvaluationEnvironment
22
+ from pex.pep_503 import ProjectName
23
+ from pex.sorted_tuple import SortedTuple
24
+ from pex.third_party import attr
177
25
 
178
- # Covers Pip<24.1 vendored packaging.
179
- markers._get_env = EvaluationEnvironment.get_env
26
+ no_extras_marker_env = universal_target.marker_env()
180
27
 
181
- markers._eval_op = _eval_op
28
+ def evaluate(self, environment=None):
29
+ extra = environment.get("extra") if environment else None
30
+ if extra:
31
+ return attr.evolve(
32
+ no_extras_marker_env, extras=SortedTuple([ProjectName(extra).normalized])
33
+ ).evaluate(self)
34
+ return no_extras_marker_env.evaluate(self)
182
35
 
183
- # Covers Pip>=25.1 vendored packaging where an assertion is added in the tuple case that lhs is
184
- # a string, defeating our EvaluationEnvironment patching above which returns lists of strings
185
- # for some environment markers. If it weren't for the assertion, we could use the existing
186
- # function.
187
- markers._evaluate_markers = _evaluate_markers
36
+ markers.Marker.evaluate = evaluate
188
37
 
189
38
 
190
39
  def patch_wheel_model():
191
40
  from pip._internal.models.wheel import Wheel
192
41
 
42
+ from pex.interpreter_constraints import iter_compatible_versions
43
+ from pex.resolve.target_system import TargetSystem
44
+
45
+ python_versions = sorted(
46
+ set(version[:2] for version in iter_compatible_versions(universal_target.requires_python))
47
+ )
48
+ python_majors = sorted(set(version[0] for version in python_versions))
49
+
193
50
  Wheel.support_index_min = lambda *args, **kwargs: 0
194
51
 
195
52
  # N.B.: Pip 25.1 updated the Wheel model, removing pyversions, abis and plats and replacing
196
53
  # these with a set of file-tags Tag objects. We unify with these helpers.
197
54
 
198
55
  def get_abi_info(self):
199
- if hasattr(self, "abis"):
200
- abis = set(self.abis)
201
- else:
202
- abis = {file_tag.abi for file_tag in self.file_tags}
203
-
204
- is_abi3 = {"abi3"} == abis
205
- is_abi_none = {"none"} == abis
206
- return is_abi3, is_abi_none
207
-
208
- def get_py_versions(self):
209
- if hasattr(self, "pyversions"):
210
- return self.pyversions
211
- return tuple(file_tag.interpreter for file_tag in self.file_tags)
56
+ if not hasattr(self, "is_abi3"):
57
+ abis = (
58
+ set(self.abis)
59
+ if hasattr(self, "abis")
60
+ else {file_tag.abi for file_tag in self.file_tags}
61
+ )
62
+ self.is_abi3 = {"abi3"} == abis
63
+ self.is_abi_none = {"none"} == abis
64
+ return self.is_abi3, self.is_abi_none
65
+
66
+ def get_py_versions_info(self):
67
+ if not hasattr(self, "pyversions_info"):
68
+ pyversions_info = []
69
+ for file_tag in self.file_tags:
70
+ # For the format, see: https://peps.python.org/pep-0425/#python-tag
71
+ match = re.search(
72
+ r"^(?P<impl>\D{2,})(?P<major>\d)(?P<minor>\d+)?", file_tag.interpreter
73
+ )
74
+ if not match:
75
+ continue
76
+ impl = match.group("impl")
77
+ major = int(match.group("major"))
78
+ minor = match.group("minor")
79
+ pyversions_info.append((impl, major, minor))
80
+ self.pyversions_info = tuple(pyversions_info)
81
+ return self.pyversions_info
212
82
 
213
83
  def get_platforms(self):
214
84
  if hasattr(self, "plats"):
@@ -223,18 +93,10 @@ def patch_wheel_model():
223
93
  if not hasattr(self, "_versions"):
224
94
  versions = set()
225
95
  is_abi3, is_abi_none = get_abi_info(self)
226
- for pyversion in get_py_versions(self):
227
- # For the format, see: https://peps.python.org/pep-0425/#python-tag
228
- match = re.search(r"^(?P<impl>\D{2,})(?P<major>\d)(?P<minor>\d+)?", pyversion)
229
- if not match:
96
+ for impl, major, minor in get_py_versions_info(self):
97
+ if impl not in ("py", "cp", "cpython", "pp", "pypy"):
230
98
  continue
231
99
 
232
- impl = match.group("impl")
233
- if impl not in ("cp", "pp", "py", "cpython", "pypy"):
234
- continue
235
-
236
- major = int(match.group("major"))
237
- minor = match.group("minor")
238
100
  if is_abi_none or (is_abi3 and major == 3):
239
101
  versions.add(major)
240
102
  elif minor:
@@ -251,19 +113,83 @@ def patch_wheel_model():
251
113
 
252
114
  supported_checks.append(supported_version)
253
115
 
254
- if platform_tag_regexps:
116
+ if universal_target.systems and set(universal_target.systems) != set(TargetSystem.values()):
255
117
  import re
256
118
 
257
- def supported_platform_tag(self, *_args, **_kwargs):
119
+ # See: https://peps.python.org/pep-0425/#platform-tag for more about the wheel platform tag.
120
+ platform_tag_substrings = []
121
+ for system in universal_target.systems:
122
+ if system is TargetSystem.LINUX:
123
+ platform_tag_substrings.append("linux")
124
+ elif system is TargetSystem.MAC:
125
+ platform_tag_substrings.append("macosx")
126
+ elif system is TargetSystem.WINDOWS:
127
+ platform_tag_substrings.append("win")
128
+
129
+ def supported_os_tag(self, *_args, **_kwargs):
258
130
  platforms = get_platforms(self)
259
131
  if any(plat == "any" for plat in platforms):
260
132
  return True
261
- for platform_tag_regexp in platform_tag_regexps:
262
- if any(re.search(platform_tag_regexp, plat) for plat in platforms):
133
+ for platform_tag_substring in platform_tag_substrings:
134
+ if any((platform_tag_substring in plat) for plat in platforms):
135
+ return True
136
+ return False
137
+
138
+ supported_checks.append(supported_os_tag)
139
+
140
+ platform_machine_values = universal_target.extra_markers.get_values("platform_machine")
141
+ if platform_machine_values:
142
+ import re
143
+
144
+ # See: https://peps.python.org/pep-0425/#platform-tag for more about the wheel platform tag.
145
+ platform_machine_regexps = tuple(
146
+ re.compile(re.escape(machine), flags=re.IGNORECASE)
147
+ for machine in platform_machine_values
148
+ )
149
+
150
+ def supported_machine_tag(self, *_args, **_kwargs):
151
+ platforms = get_platforms(self)
152
+
153
+ if any(plat == "any" for plat in platforms):
154
+ return True
155
+
156
+ if platform_machine_values.inclusive:
157
+ for platform_machine_regexp in platform_machine_regexps:
158
+ if any(platform_machine_regexp.search(plat) for plat in platforms):
159
+ return True
160
+ return False
161
+
162
+ if all(
163
+ all(platform_machine_regexp.search(plat) for plat in platforms)
164
+ for platform_machine_regexp in platform_machine_regexps
165
+ ):
166
+ return False
167
+
168
+ return True
169
+
170
+ supported_checks.append(supported_machine_tag)
171
+
172
+ if universal_target.implementation:
173
+
174
+ def supported_impl(self, *_args, **_kwargs):
175
+ for impl, _, _ in get_py_versions_info(self):
176
+ if impl == "py":
177
+ return True
178
+
179
+ if (
180
+ universal_target.implementation is InterpreterImplementation.CPYTHON
181
+ and impl in ("cp", "cpython")
182
+ ):
183
+ return True
184
+
185
+ if universal_target.implementation is InterpreterImplementation.PYPY and impl in (
186
+ "pp",
187
+ "pypy",
188
+ ):
263
189
  return True
264
190
  return False
265
191
 
266
- supported_checks.append(supported_platform_tag)
192
+ supported_checks.append(supported_impl)
267
193
 
268
194
  Wheel.supported = lambda *args, **kwargs: all(
269
195
  check(*args, **kwargs) for check in supported_checks