Skip to content

Commit af7b816

Browse files
committed
Upgrade packaging to 24.2
1 parent 6ed4387 commit af7b816

File tree

14 files changed

+1104
-246
lines changed

14 files changed

+1104
-246
lines changed

news/packaging.vendor.rst

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

src/pip/_vendor/packaging/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
__summary__ = "Core utilities for Python packages"
77
__uri__ = "https://github.com/pypa/packaging"
88

9-
__version__ = "24.1"
9+
__version__ = "24.2"
1010

1111
__author__ = "Donald Stufft and individual contributors"
1212
__email__ = "[email protected]"
1313

1414
__license__ = "BSD-2-Clause or Apache-2.0"
15-
__copyright__ = "2014 %s" % __author__
15+
__copyright__ = f"2014 {__author__}"

src/pip/_vendor/packaging/_elffile.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ def __init__(self, f: IO[bytes]) -> None:
4848

4949
try:
5050
ident = self._read("16B")
51-
except struct.error:
52-
raise ELFInvalid("unable to parse identification")
51+
except struct.error as e:
52+
raise ELFInvalid("unable to parse identification") from e
5353
magic = bytes(ident[:4])
5454
if magic != b"\x7fELF":
5555
raise ELFInvalid(f"invalid magic: {magic!r}")
@@ -67,11 +67,11 @@ def __init__(self, f: IO[bytes]) -> None:
6767
(2, 1): ("<HHIQQQIHHH", "<IIQQQQQQ", (0, 2, 5)), # 64-bit LSB.
6868
(2, 2): (">HHIQQQIHHH", ">IIQQQQQQ", (0, 2, 5)), # 64-bit MSB.
6969
}[(self.capacity, self.encoding)]
70-
except KeyError:
70+
except KeyError as e:
7171
raise ELFInvalid(
7272
f"unrecognized capacity ({self.capacity}) or "
7373
f"encoding ({self.encoding})"
74-
)
74+
) from e
7575

7676
try:
7777
(

src/pip/_vendor/packaging/_manylinux.py

+1
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ def _parse_glibc_version(version_str: str) -> tuple[int, int]:
164164
f"Expected glibc version with 2 components major.minor,"
165165
f" got: {version_str}",
166166
RuntimeWarning,
167+
stacklevel=2,
167168
)
168169
return -1, -1
169170
return int(m.group("major")), int(m.group("minor"))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
#######################################################################################
2+
#
3+
# Adapted from:
4+
# https://github.com/pypa/hatch/blob/5352e44/backend/src/hatchling/licenses/parse.py
5+
#
6+
# MIT License
7+
#
8+
# Copyright (c) 2017-present Ofek Lev <[email protected]>
9+
#
10+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this
11+
# software and associated documentation files (the "Software"), to deal in the Software
12+
# without restriction, including without limitation the rights to use, copy, modify,
13+
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
14+
# permit persons to whom the Software is furnished to do so, subject to the following
15+
# conditions:
16+
#
17+
# The above copyright notice and this permission notice shall be included in all copies
18+
# or substantial portions of the Software.
19+
#
20+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
21+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
22+
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23+
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
24+
# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
25+
# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26+
#
27+
#
28+
# With additional allowance of arbitrary `LicenseRef-` identifiers, not just
29+
# `LicenseRef-Public-Domain` and `LicenseRef-Proprietary`.
30+
#
31+
#######################################################################################
32+
from __future__ import annotations
33+
34+
import re
35+
from typing import NewType, cast
36+
37+
from pip._vendor.packaging.licenses._spdx import EXCEPTIONS, LICENSES
38+
39+
__all__ = [
40+
"NormalizedLicenseExpression",
41+
"InvalidLicenseExpression",
42+
"canonicalize_license_expression",
43+
]
44+
45+
license_ref_allowed = re.compile("^[A-Za-z0-9.-]*$")
46+
47+
NormalizedLicenseExpression = NewType("NormalizedLicenseExpression", str)
48+
49+
50+
class InvalidLicenseExpression(ValueError):
51+
"""Raised when a license-expression string is invalid
52+
53+
>>> canonicalize_license_expression("invalid")
54+
Traceback (most recent call last):
55+
...
56+
packaging.licenses.InvalidLicenseExpression: Invalid license expression: 'invalid'
57+
"""
58+
59+
60+
def canonicalize_license_expression(
61+
raw_license_expression: str,
62+
) -> NormalizedLicenseExpression:
63+
if not raw_license_expression:
64+
message = f"Invalid license expression: {raw_license_expression!r}"
65+
raise InvalidLicenseExpression(message)
66+
67+
# Pad any parentheses so tokenization can be achieved by merely splitting on
68+
# whitespace.
69+
license_expression = raw_license_expression.replace("(", " ( ").replace(")", " ) ")
70+
licenseref_prefix = "LicenseRef-"
71+
license_refs = {
72+
ref.lower(): "LicenseRef-" + ref[len(licenseref_prefix) :]
73+
for ref in license_expression.split()
74+
if ref.lower().startswith(licenseref_prefix.lower())
75+
}
76+
77+
# Normalize to lower case so we can look up licenses/exceptions
78+
# and so boolean operators are Python-compatible.
79+
license_expression = license_expression.lower()
80+
81+
tokens = license_expression.split()
82+
83+
# Rather than implementing boolean logic, we create an expression that Python can
84+
# parse. Everything that is not involved with the grammar itself is treated as
85+
# `False` and the expression should evaluate as such.
86+
python_tokens = []
87+
for token in tokens:
88+
if token not in {"or", "and", "with", "(", ")"}:
89+
python_tokens.append("False")
90+
elif token == "with":
91+
python_tokens.append("or")
92+
elif token == "(" and python_tokens and python_tokens[-1] not in {"or", "and"}:
93+
message = f"Invalid license expression: {raw_license_expression!r}"
94+
raise InvalidLicenseExpression(message)
95+
else:
96+
python_tokens.append(token)
97+
98+
python_expression = " ".join(python_tokens)
99+
try:
100+
invalid = eval(python_expression, globals(), locals())
101+
except Exception:
102+
invalid = True
103+
104+
if invalid is not False:
105+
message = f"Invalid license expression: {raw_license_expression!r}"
106+
raise InvalidLicenseExpression(message) from None
107+
108+
# Take a final pass to check for unknown licenses/exceptions.
109+
normalized_tokens = []
110+
for token in tokens:
111+
if token in {"or", "and", "with", "(", ")"}:
112+
normalized_tokens.append(token.upper())
113+
continue
114+
115+
if normalized_tokens and normalized_tokens[-1] == "WITH":
116+
if token not in EXCEPTIONS:
117+
message = f"Unknown license exception: {token!r}"
118+
raise InvalidLicenseExpression(message)
119+
120+
normalized_tokens.append(EXCEPTIONS[token]["id"])
121+
else:
122+
if token.endswith("+"):
123+
final_token = token[:-1]
124+
suffix = "+"
125+
else:
126+
final_token = token
127+
suffix = ""
128+
129+
if final_token.startswith("licenseref-"):
130+
if not license_ref_allowed.match(final_token):
131+
message = f"Invalid licenseref: {final_token!r}"
132+
raise InvalidLicenseExpression(message)
133+
normalized_tokens.append(license_refs[final_token] + suffix)
134+
else:
135+
if final_token not in LICENSES:
136+
message = f"Unknown license: {final_token!r}"
137+
raise InvalidLicenseExpression(message)
138+
normalized_tokens.append(LICENSES[final_token]["id"] + suffix)
139+
140+
normalized_expression = " ".join(normalized_tokens)
141+
142+
return cast(
143+
NormalizedLicenseExpression,
144+
normalized_expression.replace("( ", "(").replace(" )", ")"),
145+
)

0 commit comments

Comments
 (0)