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
pex/dist_metadata.py CHANGED
@@ -9,6 +9,7 @@ import functools
9
9
  import glob
10
10
  import importlib
11
11
  import itertools
12
+ import json
12
13
  import os
13
14
  import sys
14
15
  import tarfile
@@ -22,8 +23,9 @@ from textwrap import dedent
22
23
 
23
24
  from pex import pex_warnings, specifier_sets
24
25
  from pex.common import open_zip, pluralize
25
- from pex.compatibility import PY2, to_unicode
26
+ from pex.compatibility import PY2, string, to_unicode
26
27
  from pex.enum import Enum
28
+ from pex.exceptions import reportable_unexpected_error_msg
27
29
  from pex.pep_440 import Version
28
30
  from pex.pep_503 import ProjectName
29
31
  from pex.third_party.packaging.markers import Marker
@@ -42,6 +44,7 @@ if TYPE_CHECKING:
42
44
  Iterable,
43
45
  Iterator,
44
46
  List,
47
+ Mapping,
45
48
  Optional,
46
49
  Text,
47
50
  Tuple,
@@ -152,15 +155,24 @@ class DistMetadataFile(object):
152
155
  version = attr.ib() # type: Version
153
156
  pkg_info = attr.ib(eq=False) # type: Message
154
157
 
155
- def render_description(self):
156
- # type: () -> str
158
+ def render_metadata_file_description(self, metadata_file_rel_path):
159
+ # type: (Text) -> str
157
160
  return "{project_name} {version} metadata from {rel_path} at {location}".format(
158
161
  project_name=self.project_name,
159
162
  version=self.version,
160
- rel_path=self.rel_path,
163
+ rel_path=metadata_file_rel_path,
161
164
  location=self.location,
162
165
  )
163
166
 
167
+ def render_description(self):
168
+ # type: () -> str
169
+ return self.render_metadata_file_description(self.rel_path)
170
+
171
+ @property
172
+ def path(self):
173
+ # type: () -> Text
174
+ return os.path.join(self.location, self.rel_path)
175
+
164
176
 
165
177
  @attr.s(frozen=True)
166
178
  class MetadataFiles(object):
@@ -182,6 +194,14 @@ class MetadataFiles(object):
182
194
  return None
183
195
  return self._read_function(rel_path)
184
196
 
197
+ def render_description(self, metadata_file_name):
198
+ # type: (Text) -> str
199
+ rel_path = self.metadata_file_rel_path(metadata_file_name)
200
+ return self.metadata.render_metadata_file_description(
201
+ rel_path
202
+ or "{metadata_file_name} not found".format(metadata_file_name=metadata_file_name)
203
+ )
204
+
185
205
 
186
206
  class MetadataType(Enum["MetadataType.Value"]):
187
207
  class Value(Enum.Value):
@@ -210,6 +230,15 @@ class MetadataKey(object):
210
230
  location = attr.ib() # type: Text
211
231
 
212
232
 
233
+ def _read_function(
234
+ location, # type: Text
235
+ rel_path, # type: Text
236
+ ):
237
+ # type: (...) -> bytes
238
+ with open(os.path.join(location, rel_path), "rb") as fp:
239
+ return fp.read()
240
+
241
+
213
242
  def _find_installed_metadata_files(
214
243
  location, # type: Text
215
244
  metadata_type, # type: MetadataType.Value
@@ -218,6 +247,7 @@ def _find_installed_metadata_files(
218
247
  ):
219
248
  # type: (...) -> Iterator[MetadataFiles]
220
249
  metadata_files = glob.glob(os.path.join(location, metadata_dir_glob, metadata_file_name))
250
+ read_function = functools.partial(_read_function, location)
221
251
  for path in metadata_files:
222
252
  with open(path, "rb") as fp:
223
253
  metadata = parse_message(fp.read())
@@ -225,11 +255,6 @@ def _find_installed_metadata_files(
225
255
  source=path, pkg_info=metadata
226
256
  )
227
257
 
228
- def read_function(rel_path):
229
- # type: (Text) -> bytes
230
- with open(os.path.join(location, rel_path), "rb") as fp:
231
- return fp.read()
232
-
233
258
  yield MetadataFiles(
234
259
  metadata=DistMetadataFile(
235
260
  type=metadata_type,
@@ -756,7 +781,7 @@ class Constraint(object):
756
781
  )
757
782
 
758
783
  name = attr.ib(eq=False) # type: str
759
- specifier = attr.ib(factory=SpecifierSet) # type: SpecifierSet
784
+ specifier = attr.ib(factory=SpecifierSet, order=False) # type: SpecifierSet
760
785
  marker = attr.ib(default=None, eq=str) # type: Optional[Marker]
761
786
 
762
787
  project_name = attr.ib(init=False, repr=False) # type: ProjectName
@@ -924,19 +949,29 @@ class Requirement(Constraint):
924
949
  return Constraint(name=self.name, specifier=self.specifier, marker=self.marker)
925
950
 
926
951
 
927
- # N.B.: DistributionMetadata can have an expensive hash when a distribution has many requirements;
952
+ # N.B.: ProjectMetadata can have an expensive hash when a distribution has many requirements;
928
953
  # so we cache the hash. See: https://github.com/pex-tool/pex/issues/1928
929
954
  @attr.s(frozen=True, cache_hash=True)
955
+ class ProjectMetadata(object):
956
+ project_name = attr.ib() # type: ProjectName
957
+ version = attr.ib() # type: Version
958
+ requires_dists = attr.ib(default=()) # type: Tuple[Requirement, ...]
959
+ requires_python = attr.ib(default=SpecifierSet()) # type: Optional[SpecifierSet]
960
+
961
+
962
+ @attr.s(frozen=True)
930
963
  class DistMetadata(object):
931
964
  @classmethod
932
965
  def from_metadata_files(cls, metadata_files):
933
966
  # type: (MetadataFiles) -> DistMetadata
934
967
  return cls(
935
968
  files=metadata_files,
936
- project_name=metadata_files.metadata.project_name,
937
- version=metadata_files.metadata.version,
938
- requires_dists=tuple(requires_dists(metadata_files)),
939
- requires_python=requires_python(metadata_files),
969
+ project_metadata=ProjectMetadata(
970
+ project_name=metadata_files.metadata.project_name,
971
+ version=metadata_files.metadata.version,
972
+ requires_dists=tuple(requires_dists(metadata_files)),
973
+ requires_python=requires_python(metadata_files),
974
+ ),
940
975
  )
941
976
 
942
977
  @classmethod
@@ -956,10 +991,27 @@ class DistMetadata(object):
956
991
  return cls.from_metadata_files(metadata_files)
957
992
 
958
993
  files = attr.ib(eq=False) # type: MetadataFiles
959
- project_name = attr.ib() # type: ProjectName
960
- version = attr.ib() # type: Version
961
- requires_dists = attr.ib(default=()) # type: Tuple[Requirement, ...]
962
- requires_python = attr.ib(default=SpecifierSet()) # type: Optional[SpecifierSet]
994
+ project_metadata = attr.ib() # type: ProjectMetadata
995
+
996
+ @property
997
+ def project_name(self):
998
+ # type: () -> ProjectName
999
+ return self.project_metadata.project_name
1000
+
1001
+ @property
1002
+ def version(self):
1003
+ # type: () -> Version
1004
+ return self.project_metadata.version
1005
+
1006
+ @property
1007
+ def requires_dists(self):
1008
+ # type: () -> Tuple[Requirement, ...]
1009
+ return self.project_metadata.requires_dists
1010
+
1011
+ @property
1012
+ def requires_python(self):
1013
+ # type: () -> Optional[SpecifierSet]
1014
+ return self.project_metadata.requires_python
963
1015
 
964
1016
  @property
965
1017
  def type(self):
@@ -993,6 +1045,34 @@ class DistributionType(Enum["DistributionType.Value"]):
993
1045
  DistributionType.seal()
994
1046
 
995
1047
 
1048
+ @attr.s(frozen=True)
1049
+ class EntryPoints(object):
1050
+ _values = attr.ib(
1051
+ factory=lambda: defaultdict(dict)
1052
+ ) # type: Mapping[str, Mapping[str, NamedEntryPoint]]
1053
+ source = attr.ib(default=None) # type: Optional[Text]
1054
+
1055
+ def __attrs_post_init__(self):
1056
+ if len(self._values) > 0 and not self.source:
1057
+ raise ValueError("A source must be supplied when there are entry points values.")
1058
+
1059
+ def __getitem__(self, item):
1060
+ # type: (str) -> Mapping[str, NamedEntryPoint]
1061
+ return self._values[item]
1062
+
1063
+ def get(
1064
+ self,
1065
+ item, # type: str
1066
+ default, # type: Mapping[str, NamedEntryPoint]
1067
+ ):
1068
+ # type: (...) -> Mapping[str, NamedEntryPoint]
1069
+ return self._values.get(item, default)
1070
+
1071
+ def __len__(self):
1072
+ # type: () -> int
1073
+ return len(self._values)
1074
+
1075
+
996
1076
  @attr.s(frozen=True)
997
1077
  class Distribution(object):
998
1078
  @staticmethod
@@ -1009,8 +1089,12 @@ class Distribution(object):
1009
1089
  yield normalized
1010
1090
 
1011
1091
  @classmethod
1012
- def parse_entry_map(cls, entry_points_contents):
1013
- # type: (bytes) -> Dict[str, Dict[str, NamedEntryPoint]]
1092
+ def parse_entry_map(
1093
+ cls,
1094
+ entry_points_contents, # type: bytes
1095
+ source, # type: Text
1096
+ ):
1097
+ # type: (...) -> EntryPoints
1014
1098
 
1015
1099
  # This file format is defined here:
1016
1100
  # https://packaging.python.org/en/latest/specifications/entry-points/#file-format
@@ -1028,7 +1112,7 @@ class Distribution(object):
1028
1112
  else:
1029
1113
  entry_point = NamedEntryPoint.parse(line)
1030
1114
  entry_map[group][entry_point.name] = entry_point
1031
- return entry_map
1115
+ return EntryPoints(values=entry_map, source=source)
1032
1116
 
1033
1117
  @classmethod
1034
1118
  def load(cls, location):
@@ -1096,11 +1180,45 @@ class Distribution(object):
1096
1180
  yield line
1097
1181
 
1098
1182
  def get_entry_map(self):
1099
- # type: () -> Dict[str, Dict[str, NamedEntryPoint]]
1183
+ # type: () -> EntryPoints
1100
1184
  entry_points_metadata_file = self._read_metadata_file("entry_points.txt")
1101
1185
  if entry_points_metadata_file is None:
1102
- return defaultdict(dict)
1103
- return self.parse_entry_map(entry_points_metadata_file)
1186
+ return EntryPoints(values=defaultdict(dict))
1187
+
1188
+ entry_points_txt_relpath = self.metadata.files.metadata_file_rel_path("entry_points.txt")
1189
+ if entry_points_txt_relpath is None:
1190
+ raise AssertionError(reportable_unexpected_error_msg())
1191
+
1192
+ return self.parse_entry_map(
1193
+ entry_points_metadata_file,
1194
+ source=os.path.join(self.metadata.files.metadata.location, entry_points_txt_relpath),
1195
+ )
1196
+
1197
+ def editable_install_url(self):
1198
+ # type: () -> Optional[Text]
1199
+
1200
+ # For the spec, see: https://peps.python.org/pep-0660/#frontend-requirements
1201
+ direct_url_json_bytes = self._read_metadata_file("direct_url.json")
1202
+ if not direct_url_json_bytes:
1203
+ return None
1204
+
1205
+ direct_url_json_data = json.loads(direct_url_json_bytes)
1206
+ if not direct_url_json_data.get("dir_info", {}).get("editable", False):
1207
+ return None
1208
+
1209
+ url = direct_url_json_data.get("url", None)
1210
+ if url is None:
1211
+ return None
1212
+
1213
+ if not isinstance(url, string):
1214
+ raise InvalidMetadataError(
1215
+ "The direct_url.json metadata for {dist} at {location} is invalid.\n"
1216
+ "Expected `url` to be a string but found {value} of type {type}".format(
1217
+ dist=self, location=self.location, value=url, type=type(url)
1218
+ )
1219
+ )
1220
+
1221
+ return cast("Text", url)
1104
1222
 
1105
1223
  def __str__(self):
1106
1224
  # type: () -> str
@@ -1 +1 @@
1
- {"version":"1.3.0","languages":{"en":{"hash":"en_d1c488ecae","wasm":"en","page_count":8}}}
1
+ {"version":"1.3.0","languages":{"en":{"hash":"en_4ce1afa9e3","wasm":"en","page_count":8}}}
@@ -1,5 +1,5 @@
1
1
  const DOCUMENTATION_OPTIONS = {
2
- VERSION: '2.54.2',
2
+ VERSION: '2.69.0',
3
3
  LANGUAGE: 'en',
4
4
  COLLAPSE_INDEX: false,
5
5
  BUILDER: 'html',