|
3 | 3 | import os
|
4 | 4 | import pathlib
|
5 | 5 | import zipfile
|
6 |
| -from typing import ( |
7 |
| - Collection, |
8 |
| - Dict, |
9 |
| - Iterable, |
10 |
| - Iterator, |
11 |
| - Mapping, |
12 |
| - NamedTuple, |
13 |
| - Optional, |
14 |
| - Sequence, |
15 |
| -) |
| 6 | +from typing import Collection, Dict, Iterable, Iterator, Mapping, Optional, Sequence |
16 | 7 |
|
17 | 8 | from pip._vendor.packaging.requirements import Requirement
|
18 | 9 | from pip._vendor.packaging.utils import NormalizedName, canonicalize_name
|
@@ -92,12 +83,6 @@ def read_text(self, filename: str) -> Optional[str]:
|
92 | 83 | return text
|
93 | 84 |
|
94 | 85 |
|
95 |
| -class RequiresEntry(NamedTuple): |
96 |
| - requirement: str |
97 |
| - extra: str |
98 |
| - marker: str |
99 |
| - |
100 |
| - |
101 | 86 | class Distribution(BaseDistribution):
|
102 | 87 | def __init__(
|
103 | 88 | self,
|
@@ -189,82 +174,18 @@ def iter_entry_points(self) -> Iterable[BaseEntryPoint]:
|
189 | 174 |
|
190 | 175 | @property
|
191 | 176 | def metadata(self) -> email.message.Message:
|
192 |
| - return self._dist.metadata |
193 |
| - |
194 |
| - def _iter_requires_txt_entries(self) -> Iterator[RequiresEntry]: |
195 |
| - """Parse a ``requires.txt`` in an egg-info directory. |
196 |
| -
|
197 |
| - This is an INI-ish format where an egg-info stores dependencies. A |
198 |
| - section name describes extra other environment markers, while each entry |
199 |
| - is an arbitrary string (not a key-value pair) representing a dependency |
200 |
| - as a requirement string (no markers). |
201 |
| -
|
202 |
| - There is a construct in ``importlib.metadata`` called ``Sectioned`` that |
203 |
| - does mostly the same, but the format is currently considered private. |
204 |
| - """ |
205 |
| - content = self._dist.read_text("requires.txt") |
206 |
| - if content is None: |
207 |
| - return |
208 |
| - extra = marker = "" # Section-less entries don't have markers. |
209 |
| - for line in content.splitlines(): |
210 |
| - line = line.strip() |
211 |
| - if not line or line.startswith("#"): # Comment; ignored. |
212 |
| - continue |
213 |
| - if line.startswith("[") and line.endswith("]"): # A section header. |
214 |
| - extra, _, marker = line.strip("[]").partition(":") |
215 |
| - continue |
216 |
| - yield RequiresEntry(requirement=line, extra=extra, marker=marker) |
217 |
| - |
218 |
| - def _iter_egg_info_extras(self) -> Iterable[str]: |
219 |
| - """Get extras from the egg-info directory.""" |
220 |
| - known_extras = {""} |
221 |
| - for entry in self._iter_requires_txt_entries(): |
222 |
| - if entry.extra in known_extras: |
223 |
| - continue |
224 |
| - known_extras.add(entry.extra) |
225 |
| - yield entry.extra |
| 177 | + metadata = self._dist.metadata |
| 178 | + self._add_egg_info_requires(metadata) |
| 179 | + return metadata |
226 | 180 |
|
227 | 181 | def iter_provided_extras(self) -> Iterable[str]:
|
228 |
| - iterator = ( |
229 |
| - self._dist.metadata.get_all("Provides-Extra") |
230 |
| - or self._iter_egg_info_extras() |
| 182 | + return ( |
| 183 | + safe_extra(extra) for extra in self._dist.metadata.get_all("Provides-Extra") |
231 | 184 | )
|
232 |
| - return (safe_extra(extra) for extra in iterator) |
233 |
| - |
234 |
| - def _iter_egg_info_dependencies(self) -> Iterable[str]: |
235 |
| - """Get distribution dependencies from the egg-info directory. |
236 |
| -
|
237 |
| - To ease parsing, this converts a legacy dependency entry into a PEP 508 |
238 |
| - requirement string. Like ``_iter_requires_txt_entries()``, there is code |
239 |
| - in ``importlib.metadata`` that does mostly the same, but not do exactly |
240 |
| - what we need. |
241 |
| -
|
242 |
| - Namely, ``importlib.metadata`` does not normalize the extra name before |
243 |
| - putting it into the requirement string, which causes marker comparison |
244 |
| - to fail because the dist-info format do normalize. This is consistent in |
245 |
| - all currently available PEP 517 backends, although not standardized. |
246 |
| - """ |
247 |
| - for entry in self._iter_requires_txt_entries(): |
248 |
| - if entry.extra and entry.marker: |
249 |
| - marker = f'({entry.marker}) and extra == "{safe_extra(entry.extra)}"' |
250 |
| - elif entry.extra: |
251 |
| - marker = f'extra == "{safe_extra(entry.extra)}"' |
252 |
| - elif entry.marker: |
253 |
| - marker = entry.marker |
254 |
| - else: |
255 |
| - marker = "" |
256 |
| - if marker: |
257 |
| - yield f"{entry.requirement} ; {marker}" |
258 |
| - else: |
259 |
| - yield entry.requirement |
260 | 185 |
|
261 | 186 | def iter_dependencies(self, extras: Collection[str] = ()) -> Iterable[Requirement]:
|
262 |
| - req_string_iterator = ( |
263 |
| - self._dist.metadata.get_all("Requires-Dist") |
264 |
| - or self._iter_egg_info_dependencies() |
265 |
| - ) |
266 | 187 | contexts: Sequence[Dict[str, str]] = [{"extra": safe_extra(e)} for e in extras]
|
267 |
| - for req_string in req_string_iterator: |
| 188 | + for req_string in self._dist.metadata.get_all("Requires-Dist"): |
268 | 189 | req = Requirement(req_string)
|
269 | 190 | if not req.marker:
|
270 | 191 | yield req
|
|
0 commit comments