Skip to content

Commit 4caa6c3

Browse files
authored
Merge pull request #12300 from sbidoul/packaging-upgrade
Upgrade vendored packaging lib
2 parents d2f2da9 + 84ad55a commit 4caa6c3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+3091
-12220
lines changed

news/12063.removal.rst

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Remove support for legacy versions and dependency specifiers. Packages with non
2+
standard-compliant versions or dependency specifiers are now ignored by the resolver.
3+
Already installed packages with non standard-compliant versions or dependency specifiers
4+
must be uninstalled before upgrading them.

news/packaging.vendor.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Upgrade packaging to 24.0

news/pyparsing.vendor.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Upgrade pyparsing to 3.1.2
1+
Remove pyparsing

src/pip/_internal/commands/check.py

-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
from pip._internal.operations.check import (
88
check_package_set,
99
create_package_set_from_installed,
10-
warn_legacy_versions_and_specifiers,
1110
)
1211
from pip._internal.utils.misc import write_output
1312

@@ -22,7 +21,6 @@ class CheckCommand(Command):
2221

2322
def run(self, options: Values, args: List[str]) -> int:
2423
package_set, parsing_probs = create_package_set_from_installed()
25-
warn_legacy_versions_and_specifiers(package_set)
2624
missing, conflicting = check_package_set(package_set)
2725

2826
for project_name in missing:

src/pip/_internal/commands/download.py

-1
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,6 @@ def run(self, options: Values, args: List[str]) -> int:
139139
downloaded.append(req.name)
140140

141141
preparer.prepare_linked_requirements_more(requirement_set.requirements.values())
142-
requirement_set.warn_legacy_versions_and_specifiers()
143142

144143
if downloaded:
145144
write_output("Successfully downloaded %s", " ".join(downloaded))

src/pip/_internal/commands/index.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import logging
22
from optparse import Values
3-
from typing import Any, Iterable, List, Optional, Union
3+
from typing import Any, Iterable, List, Optional
44

5-
from pip._vendor.packaging.version import LegacyVersion, Version
5+
from pip._vendor.packaging.version import Version
66

77
from pip._internal.cli import cmdoptions
88
from pip._internal.cli.req_command import IndexGroupCommand
@@ -115,7 +115,7 @@ def get_available_package_versions(self, options: Values, args: List[Any]) -> No
115115
ignore_requires_python=options.ignore_requires_python,
116116
)
117117

118-
versions: Iterable[Union[LegacyVersion, Version]] = (
118+
versions: Iterable[Version] = (
119119
candidate.version for candidate in finder.find_all_candidates(query)
120120
)
121121

src/pip/_internal/commands/install.py

-3
Original file line numberDiff line numberDiff line change
@@ -387,9 +387,6 @@ def run(self, options: Values, args: List[str]) -> int:
387387
json.dump(report.to_dict(), f, indent=2, ensure_ascii=False)
388388

389389
if options.dry_run:
390-
# In non dry-run mode, the legacy versions and specifiers check
391-
# will be done as part of conflict detection.
392-
requirement_set.warn_legacy_versions_and_specifiers()
393390
would_install_items = sorted(
394391
(r.metadata["name"], r.metadata["version"])
395392
for r in requirement_set.requirements_to_install

src/pip/_internal/commands/list.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from typing import TYPE_CHECKING, Generator, List, Optional, Sequence, Tuple, cast
55

66
from pip._vendor.packaging.utils import canonicalize_name
7+
from pip._vendor.packaging.version import Version
78

89
from pip._internal.cli import cmdoptions
910
from pip._internal.cli.req_command import IndexGroupCommand
@@ -18,7 +19,6 @@
1819
from pip._internal.utils.misc import tabulate, write_output
1920

2021
if TYPE_CHECKING:
21-
from pip._internal.metadata.base import DistributionVersion
2222

2323
class _DistWithLatestInfo(BaseDistribution):
2424
"""Give the distribution object a couple of extra fields.
@@ -27,7 +27,7 @@ class _DistWithLatestInfo(BaseDistribution):
2727
makes the rest of the code much cleaner.
2828
"""
2929

30-
latest_version: DistributionVersion
30+
latest_version: Version
3131
latest_filetype: str
3232

3333
_ProcessedDists = Sequence[_DistWithLatestInfo]
@@ -333,7 +333,7 @@ def format_for_columns(
333333
for proj in pkgs:
334334
# if we're working on the 'outdated' list, separate out the
335335
# latest_version and type
336-
row = [proj.raw_name, str(proj.version)]
336+
row = [proj.raw_name, proj.raw_version]
337337

338338
if running_outdated:
339339
row.append(str(proj.latest_version))

src/pip/_internal/commands/show.py

+15-7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from optparse import Values
33
from typing import Generator, Iterable, Iterator, List, NamedTuple, Optional
44

5+
from pip._vendor.packaging.requirements import InvalidRequirement
56
from pip._vendor.packaging.utils import canonicalize_name
67

78
from pip._internal.cli.base_command import Command
@@ -100,12 +101,19 @@ def _get_requiring_packages(current_dist: BaseDistribution) -> Iterator[str]:
100101
except KeyError:
101102
continue
102103

103-
requires = sorted(
104-
# Avoid duplicates in requirements (e.g. due to environment markers).
105-
{req.name for req in dist.iter_dependencies()},
106-
key=str.lower,
107-
)
108-
required_by = sorted(_get_requiring_packages(dist), key=str.lower)
104+
try:
105+
requires = sorted(
106+
# Avoid duplicates in requirements (e.g. due to environment markers).
107+
{req.name for req in dist.iter_dependencies()},
108+
key=str.lower,
109+
)
110+
except InvalidRequirement:
111+
requires = sorted(dist.iter_raw_dependencies(), key=str.lower)
112+
113+
try:
114+
required_by = sorted(_get_requiring_packages(dist), key=str.lower)
115+
except InvalidRequirement:
116+
required_by = ["#N/A"]
109117

110118
try:
111119
entry_points_text = dist.read_text("entry_points.txt")
@@ -139,7 +147,7 @@ def _get_requiring_packages(current_dist: BaseDistribution) -> Iterator[str]:
139147

140148
yield _PackageInfo(
141149
name=dist.raw_name,
142-
version=str(dist.version),
150+
version=dist.raw_version,
143151
location=dist.location or "",
144152
editable_project_location=dist.editable_project_location,
145153
requires=requires,

src/pip/_internal/commands/wheel.py

-1
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,6 @@ def run(self, options: Values, args: List[str]) -> int:
154154
reqs_to_build.append(req)
155155

156156
preparer.prepare_linked_requirements_more(requirement_set.requirements.values())
157-
requirement_set.warn_legacy_versions_and_specifiers()
158157

159158
# build wheels
160159
build_successes, build_failures = build(

src/pip/_internal/exceptions.py

+11
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,17 @@ def __str__(self) -> str:
354354
)
355355

356356

357+
class MetadataInvalid(InstallationError):
358+
"""Metadata is invalid."""
359+
360+
def __init__(self, ireq: "InstallRequirement", error: str) -> None:
361+
self.ireq = ireq
362+
self.error = error
363+
364+
def __str__(self) -> str:
365+
return f"Requested {self.ireq} has invalid metadata: {self.error}"
366+
367+
357368
class InstallationSubprocessError(DiagnosticPipError, InstallationError):
358369
"""A subprocess call failed."""
359370

src/pip/_internal/index/package_finder.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from pip._vendor.packaging import specifiers
1212
from pip._vendor.packaging.tags import Tag
1313
from pip._vendor.packaging.utils import canonicalize_name
14-
from pip._vendor.packaging.version import _BaseVersion
14+
from pip._vendor.packaging.version import InvalidVersion, _BaseVersion
1515
from pip._vendor.packaging.version import parse as parse_version
1616

1717
from pip._internal.exceptions import (
@@ -752,11 +752,14 @@ def get_install_candidate(
752752
self._log_skipped_link(link, result, detail)
753753
return None
754754

755-
return InstallationCandidate(
756-
name=link_evaluator.project_name,
757-
link=link,
758-
version=detail,
759-
)
755+
try:
756+
return InstallationCandidate(
757+
name=link_evaluator.project_name,
758+
link=link,
759+
version=detail,
760+
)
761+
except InvalidVersion:
762+
return None
760763

761764
def evaluate_links(
762765
self, link_evaluator: LinkEvaluator, links: Iterable[Link]

src/pip/_internal/metadata/base.py

+16-19
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
from pip._vendor.packaging.requirements import Requirement
2626
from pip._vendor.packaging.specifiers import InvalidSpecifier, SpecifierSet
2727
from pip._vendor.packaging.utils import NormalizedName, canonicalize_name
28-
from pip._vendor.packaging.version import LegacyVersion, Version
28+
from pip._vendor.packaging.version import Version
2929

3030
from pip._internal.exceptions import NoneMetadataError
3131
from pip._internal.locations import site_packages, user_site
@@ -41,8 +41,6 @@
4141

4242
from ._json import msg_to_json
4343

44-
DistributionVersion = Union[LegacyVersion, Version]
45-
4644
InfoPath = Union[str, pathlib.PurePath]
4745

4846
logger = logging.getLogger(__name__)
@@ -140,10 +138,10 @@ def from_wheel(cls, wheel: "Wheel", name: str) -> "BaseDistribution":
140138
raise NotImplementedError()
141139

142140
def __repr__(self) -> str:
143-
return f"{self.raw_name} {self.version} ({self.location})"
141+
return f"{self.raw_name} {self.raw_version} ({self.location})"
144142

145143
def __str__(self) -> str:
146-
return f"{self.raw_name} {self.version}"
144+
return f"{self.raw_name} {self.raw_version}"
147145

148146
@property
149147
def location(self) -> Optional[str]:
@@ -274,7 +272,11 @@ def canonical_name(self) -> NormalizedName:
274272
raise NotImplementedError()
275273

276274
@property
277-
def version(self) -> DistributionVersion:
275+
def version(self) -> Version:
276+
raise NotImplementedError()
277+
278+
@property
279+
def raw_version(self) -> str:
278280
raise NotImplementedError()
279281

280282
@property
@@ -443,24 +445,19 @@ def iter_dependencies(self, extras: Collection[str] = ()) -> Iterable[Requiremen
443445
"""
444446
raise NotImplementedError()
445447

446-
def iter_provided_extras(self) -> Iterable[str]:
448+
def iter_raw_dependencies(self) -> Iterable[str]:
449+
"""Raw Requires-Dist metadata."""
450+
return self.metadata.get_all("Requires-Dist", [])
451+
452+
def iter_provided_extras(self) -> Iterable[NormalizedName]:
447453
"""Extras provided by this distribution.
448454
449455
For modern .dist-info distributions, this is the collection of
450456
"Provides-Extra:" entries in distribution metadata.
451457
452-
The return value of this function is not particularly useful other than
453-
display purposes due to backward compatibility issues and the extra
454-
names being poorly normalized prior to PEP 685. If you want to perform
455-
logic operations on extras, use :func:`is_extra_provided` instead.
456-
"""
457-
raise NotImplementedError()
458-
459-
def is_extra_provided(self, extra: str) -> bool:
460-
"""Check whether an extra is provided by this distribution.
461-
462-
This is needed mostly for compatibility issues with pkg_resources not
463-
following the extra normalization rules defined in PEP 685.
458+
The return value of this function is expected to be normalised names,
459+
per PEP 685, with the returned value being handled appropriately by
460+
`iter_dependencies`.
464461
"""
465462
raise NotImplementedError()
466463

src/pip/_internal/metadata/importlib/_dists.py

+14-11
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@
1616

1717
from pip._vendor.packaging.requirements import Requirement
1818
from pip._vendor.packaging.utils import NormalizedName, canonicalize_name
19+
from pip._vendor.packaging.version import Version
1920
from pip._vendor.packaging.version import parse as parse_version
2021

2122
from pip._internal.exceptions import InvalidWheel, UnsupportedWheel
2223
from pip._internal.metadata.base import (
2324
BaseDistribution,
2425
BaseEntryPoint,
25-
DistributionVersion,
2626
InfoPath,
2727
Wheel,
2828
)
@@ -171,9 +171,13 @@ def canonical_name(self) -> NormalizedName:
171171
return canonicalize_name(name)
172172

173173
@property
174-
def version(self) -> DistributionVersion:
174+
def version(self) -> Version:
175175
return parse_version(self._dist.version)
176176

177+
@property
178+
def raw_version(self) -> str:
179+
return self._dist.version
180+
177181
def is_file(self, path: InfoPath) -> bool:
178182
return self._dist.read_text(str(path)) is not None
179183

@@ -204,19 +208,18 @@ def _metadata_impl(self) -> email.message.Message:
204208
# until upstream can improve the protocol. (python/cpython#94952)
205209
return cast(email.message.Message, self._dist.metadata)
206210

207-
def iter_provided_extras(self) -> Iterable[str]:
208-
return self.metadata.get_all("Provides-Extra", [])
209-
210-
def is_extra_provided(self, extra: str) -> bool:
211-
return any(
212-
canonicalize_name(provided_extra) == canonicalize_name(extra)
213-
for provided_extra in self.metadata.get_all("Provides-Extra", [])
214-
)
211+
def iter_provided_extras(self) -> Iterable[NormalizedName]:
212+
return [
213+
canonicalize_name(extra)
214+
for extra in self.metadata.get_all("Provides-Extra", [])
215+
]
215216

216217
def iter_dependencies(self, extras: Collection[str] = ()) -> Iterable[Requirement]:
217218
contexts: Sequence[Dict[str, str]] = [{"extra": e} for e in extras]
218219
for req_string in self.metadata.get_all("Requires-Dist", []):
219-
req = Requirement(req_string)
220+
# strip() because email.message.Message.get_all() may return a leading \n
221+
# in case a long header was wrapped.
222+
req = Requirement(req_string.strip())
220223
if not req.marker:
221224
yield req
222225
elif not extras and req.marker.evaluate({"extra": ""}):

0 commit comments

Comments
 (0)