Skip to content

Commit 71d9ebd

Browse files
committed
v26.0
1 parent 5588d3d commit 71d9ebd

18 files changed

Lines changed: 1561 additions & 481 deletions

addon.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
22
<addon id="script.module.packaging"
33
name="packaging"
4-
version="25.0"
4+
version="26.0"
55
provider-name="Donald Stufft and individual contributors">
66

77
<requires>

lib/packaging/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
__summary__ = "Core utilities for Python packages"
77
__uri__ = "https://github.com/pypa/packaging"
88

9-
__version__ = "25.0"
9+
__version__ = "26.0"
1010

1111
__author__ = "Donald Stufft and individual contributors"
1212
__email__ = "donald@stufft.io"

lib/packaging/_elffile.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
This provides a class ``ELFFile`` that parses an ELF executable in a similar
55
interface to ``ZipFile``. Only the read interface is implemented.
66
7-
Based on: https://gist.github.com/lyssdod/f51579ae8d93c8657a5564aefc2ffbca
87
ELF header: https://refspecs.linuxfoundation.org/elf/gabi4+/ch4.eheader.html
98
"""
109

lib/packaging/_manylinux.py

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,16 @@
1515
EF_ARM_ABI_VER5 = 0x05000000
1616
EF_ARM_ABI_FLOAT_HARD = 0x00000400
1717

18+
_ALLOWED_ARCHS = {
19+
"x86_64",
20+
"aarch64",
21+
"ppc64",
22+
"ppc64le",
23+
"s390x",
24+
"loongarch64",
25+
"riscv64",
26+
}
27+
1828

1929
# `os.PathLike` not a generic type until Python 3.9, so sticking with `str`
2030
# as the type for `path` until then.
@@ -57,16 +67,7 @@ def _have_compatible_abi(executable: str, archs: Sequence[str]) -> bool:
5767
return _is_linux_armhf(executable)
5868
if "i686" in archs:
5969
return _is_linux_i686(executable)
60-
allowed_archs = {
61-
"x86_64",
62-
"aarch64",
63-
"ppc64",
64-
"ppc64le",
65-
"s390x",
66-
"loongarch64",
67-
"riscv64",
68-
}
69-
return any(arch in allowed_archs for arch in archs)
70+
return any(arch in _ALLOWED_ARCHS for arch in archs)
7071

7172

7273
# If glibc ever changes its major version, we need to know what the last
@@ -106,7 +107,7 @@ def _glibc_version_string_ctypes() -> str | None:
106107
Fallback implementation of glibc_version_string using ctypes.
107108
"""
108109
try:
109-
import ctypes
110+
import ctypes # noqa: PLC0415
110111
except ImportError:
111112
return None
112113

@@ -150,7 +151,7 @@ def _glibc_version_string() -> str | None:
150151
return _glibc_version_string_confstr() or _glibc_version_string_ctypes()
151152

152153

153-
def _parse_glibc_version(version_str: str) -> tuple[int, int]:
154+
def _parse_glibc_version(version_str: str) -> _GLibCVersion:
154155
"""Parse glibc version.
155156
156157
We use a regexp instead of str.split because we want to discard any
@@ -165,15 +166,15 @@ def _parse_glibc_version(version_str: str) -> tuple[int, int]:
165166
RuntimeWarning,
166167
stacklevel=2,
167168
)
168-
return -1, -1
169-
return int(m.group("major")), int(m.group("minor"))
169+
return _GLibCVersion(-1, -1)
170+
return _GLibCVersion(int(m.group("major")), int(m.group("minor")))
170171

171172

172173
@functools.lru_cache
173-
def _get_glibc_version() -> tuple[int, int]:
174+
def _get_glibc_version() -> _GLibCVersion:
174175
version_str = _glibc_version_string()
175176
if version_str is None:
176-
return (-1, -1)
177+
return _GLibCVersion(-1, -1)
177178
return _parse_glibc_version(version_str)
178179

179180

@@ -184,33 +185,34 @@ def _is_compatible(arch: str, version: _GLibCVersion) -> bool:
184185
return False
185186
# Check for presence of _manylinux module.
186187
try:
187-
import _manylinux
188+
import _manylinux # noqa: PLC0415
188189
except ImportError:
189190
return True
190191
if hasattr(_manylinux, "manylinux_compatible"):
191192
result = _manylinux.manylinux_compatible(version[0], version[1], arch)
192193
if result is not None:
193194
return bool(result)
194195
return True
195-
if version == _GLibCVersion(2, 5):
196-
if hasattr(_manylinux, "manylinux1_compatible"):
197-
return bool(_manylinux.manylinux1_compatible)
198-
if version == _GLibCVersion(2, 12):
199-
if hasattr(_manylinux, "manylinux2010_compatible"):
200-
return bool(_manylinux.manylinux2010_compatible)
201-
if version == _GLibCVersion(2, 17):
202-
if hasattr(_manylinux, "manylinux2014_compatible"):
203-
return bool(_manylinux.manylinux2014_compatible)
196+
if version == _GLibCVersion(2, 5) and hasattr(_manylinux, "manylinux1_compatible"):
197+
return bool(_manylinux.manylinux1_compatible)
198+
if version == _GLibCVersion(2, 12) and hasattr(
199+
_manylinux, "manylinux2010_compatible"
200+
):
201+
return bool(_manylinux.manylinux2010_compatible)
202+
if version == _GLibCVersion(2, 17) and hasattr(
203+
_manylinux, "manylinux2014_compatible"
204+
):
205+
return bool(_manylinux.manylinux2014_compatible)
204206
return True
205207

206208

207-
_LEGACY_MANYLINUX_MAP = {
209+
_LEGACY_MANYLINUX_MAP: dict[_GLibCVersion, str] = {
208210
# CentOS 7 w/ glibc 2.17 (PEP 599)
209-
(2, 17): "manylinux2014",
211+
_GLibCVersion(2, 17): "manylinux2014",
210212
# CentOS 6 w/ glibc 2.12 (PEP 571)
211-
(2, 12): "manylinux2010",
213+
_GLibCVersion(2, 12): "manylinux2010",
212214
# CentOS 5 w/ glibc 2.5 (PEP 513)
213-
(2, 5): "manylinux1",
215+
_GLibCVersion(2, 5): "manylinux1",
214216
}
215217

216218

@@ -252,11 +254,9 @@ def platform_tags(archs: Sequence[str]) -> Iterator[str]:
252254
min_minor = -1
253255
for glibc_minor in range(glibc_max.minor, min_minor, -1):
254256
glibc_version = _GLibCVersion(glibc_max.major, glibc_minor)
255-
tag = "manylinux_{}_{}".format(*glibc_version)
256257
if _is_compatible(arch, glibc_version):
257-
yield f"{tag}_{arch}"
258-
# Handle the legacy manylinux1, manylinux2010, manylinux2014 tags.
259-
if glibc_version in _LEGACY_MANYLINUX_MAP:
260-
legacy_tag = _LEGACY_MANYLINUX_MAP[glibc_version]
261-
if _is_compatible(arch, glibc_version):
258+
yield "manylinux_{}_{}_{}".format(*glibc_version, arch)
259+
260+
# Handle the legacy manylinux1, manylinux2010, manylinux2014 tags.
261+
if legacy_tag := _LEGACY_MANYLINUX_MAP.get(glibc_version):
262262
yield f"{legacy_tag}_{arch}"

lib/packaging/_musllinux.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def _get_musl_version(executable: str) -> _MuslVersion | None:
4949
return None
5050
if ld is None or "musl" not in ld:
5151
return None
52-
proc = subprocess.run([ld], stderr=subprocess.PIPE, text=True)
52+
proc = subprocess.run([ld], check=False, stderr=subprocess.PIPE, text=True)
5353
return _parse_musl_version(proc.stderr)
5454

5555

lib/packaging/_parser.py

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,44 +7,53 @@
77
from __future__ import annotations
88

99
import ast
10-
from typing import NamedTuple, Sequence, Tuple, Union
10+
from typing import List, Literal, NamedTuple, Sequence, Tuple, Union
1111

1212
from ._tokenizer import DEFAULT_RULES, Tokenizer
1313

1414

1515
class Node:
16+
__slots__ = ("value",)
17+
1618
def __init__(self, value: str) -> None:
1719
self.value = value
1820

1921
def __str__(self) -> str:
2022
return self.value
2123

2224
def __repr__(self) -> str:
23-
return f"<{self.__class__.__name__}('{self}')>"
25+
return f"<{self.__class__.__name__}({self.value!r})>"
2426

2527
def serialize(self) -> str:
2628
raise NotImplementedError
2729

2830

2931
class Variable(Node):
32+
__slots__ = ()
33+
3034
def serialize(self) -> str:
3135
return str(self)
3236

3337

3438
class Value(Node):
39+
__slots__ = ()
40+
3541
def serialize(self) -> str:
3642
return f'"{self}"'
3743

3844

3945
class Op(Node):
46+
__slots__ = ()
47+
4048
def serialize(self) -> str:
4149
return str(self)
4250

4351

52+
MarkerLogical = Literal["and", "or"]
4453
MarkerVar = Union[Variable, Value]
4554
MarkerItem = Tuple[MarkerVar, Op, MarkerVar]
4655
MarkerAtom = Union[MarkerItem, Sequence["MarkerAtom"]]
47-
MarkerList = Sequence[Union["MarkerList", MarkerAtom, str]]
56+
MarkerList = List[Union["MarkerList", MarkerAtom, MarkerLogical]]
4857

4958

5059
class ParsedRequirement(NamedTuple):
@@ -111,7 +120,9 @@ def _parse_requirement_details(
111120
return (url, specifier, marker)
112121

113122
marker = _parse_requirement_marker(
114-
tokenizer, span_start=url_start, after="URL and whitespace"
123+
tokenizer,
124+
span_start=url_start,
125+
expected="semicolon (after URL and whitespace)",
115126
)
116127
else:
117128
specifier_start = tokenizer.position
@@ -124,27 +135,28 @@ def _parse_requirement_details(
124135
marker = _parse_requirement_marker(
125136
tokenizer,
126137
span_start=specifier_start,
127-
after=(
128-
"version specifier"
138+
expected=(
139+
"comma (within version specifier), semicolon (after version specifier)"
129140
if specifier
130-
else "name and no valid version specifier"
141+
else "semicolon (after name with no version specifier)"
131142
),
132143
)
133144

134145
return (url, specifier, marker)
135146

136147

137148
def _parse_requirement_marker(
138-
tokenizer: Tokenizer, *, span_start: int, after: str
149+
tokenizer: Tokenizer, *, span_start: int, expected: str
139150
) -> MarkerList:
140151
"""
141152
requirement_marker = SEMICOLON marker WS?
142153
"""
143154

144155
if not tokenizer.check("SEMICOLON"):
145156
tokenizer.raise_syntax_error(
146-
f"Expected end or semicolon (after {after})",
157+
f"Expected {expected} or end",
147158
span_start=span_start,
159+
span_end=None,
148160
)
149161
tokenizer.read()
150162

@@ -307,7 +319,7 @@ def _parse_marker_item(tokenizer: Tokenizer) -> MarkerItem:
307319
return (marker_var_left, marker_op, marker_var_right)
308320

309321

310-
def _parse_marker_var(tokenizer: Tokenizer) -> MarkerVar:
322+
def _parse_marker_var(tokenizer: Tokenizer) -> MarkerVar: # noqa: RET503
311323
"""
312324
marker_var = VARIABLE | QUOTED_STRING
313325
"""

lib/packaging/_structures.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@
22
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
33
# for complete details.
44

5+
import typing
56

7+
8+
@typing.final
69
class InfinityType:
10+
__slots__ = ()
11+
712
def __repr__(self) -> str:
813
return "Infinity"
914

@@ -32,7 +37,10 @@ def __neg__(self: object) -> "NegativeInfinityType":
3237
Infinity = InfinityType()
3338

3439

40+
@typing.final
3541
class NegativeInfinityType:
42+
__slots__ = ()
43+
3644
def __repr__(self) -> str:
3745
return "-Infinity"
3846

0 commit comments

Comments
 (0)