From d0e66ac854714a170fb0a48285d07b22ee405f18 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Fri, 8 May 2026 12:38:57 -0700 Subject: [PATCH] Add small Python 3.15 stdlib APIs --- stdlib/@tests/stubtest_allowlists/py315.txt | 23 --------------------- stdlib/pyexpat/__init__.pyi | 5 +++++ stdlib/stat.pyi | 12 +++++++++++ stdlib/symtable.pyi | 5 +++++ stdlib/unicodedata.pyi | 12 +++++++++++ stdlib/zlib.pyi | 7 +++++++ 6 files changed, 41 insertions(+), 23 deletions(-) diff --git a/stdlib/@tests/stubtest_allowlists/py315.txt b/stdlib/@tests/stubtest_allowlists/py315.txt index cd9095754ce7..659ad9939571 100644 --- a/stdlib/@tests/stubtest_allowlists/py315.txt +++ b/stdlib/@tests/stubtest_allowlists/py315.txt @@ -285,8 +285,6 @@ profiling.tracing pstats.Stats.print_call_subheading pydoc.Doc.STDLIB_DIR pydoc.Doc.getdocloc -pyexpat.XMLParserType.SetBillionLaughsAttackProtectionActivationThreshold -pyexpat.XMLParserType.SetBillionLaughsAttackProtectionMaximumAmplification re.Pattern.prefixmatch re.__all__ re.prefixmatch @@ -317,18 +315,6 @@ ssl.SSLObject.server_sigalg ssl.SSLSocket.client_sigalg ssl.SSLSocket.group ssl.SSLSocket.server_sigalg -stat.STATX_ATTR_APPEND -stat.STATX_ATTR_AUTOMOUNT -stat.STATX_ATTR_COMPRESSED -stat.STATX_ATTR_DAX -stat.STATX_ATTR_ENCRYPTED -stat.STATX_ATTR_IMMUTABLE -stat.STATX_ATTR_MOUNT_ROOT -stat.STATX_ATTR_NODUMP -stat.STATX_ATTR_VERITY -stat.STATX_ATTR_WRITE_ATOMIC -symtable.Function.get_cells -symtable.Symbol.is_cell symtable.symtable sys.__jit sys._monitoring @@ -390,13 +376,6 @@ typing.Union typing._SpecialForm.__mro_entries__ typing_extensions.__all__ typing_extensions.Protocol -unicodedata.block -unicodedata.extended_pictographic -unicodedata.grapheme_cluster_break -unicodedata.indic_conjunct_break -unicodedata.isxidcontinue -unicodedata.isxidstart -unicodedata.iter_graphemes unittest._log._AssertLogsContext.__init__ unittest.case.TestCase.assertLogs urllib.parse._DefragResultBase.geturl @@ -423,5 +402,3 @@ xml.etree.ElementTree.__all__ xml.is_valid_name xml.utils zipimport.zipimporter.load_module -zlib.adler32_combine -zlib.crc32_combine diff --git a/stdlib/pyexpat/__init__.pyi b/stdlib/pyexpat/__init__.pyi index 0b6d70e7306a..806db63693b5 100644 --- a/stdlib/pyexpat/__init__.pyi +++ b/stdlib/pyexpat/__init__.pyi @@ -1,3 +1,4 @@ +import sys from _typeshed import ReadableBuffer, SupportsRead from collections.abc import Callable from pyexpat import errors as errors, model as model @@ -32,6 +33,10 @@ class XMLParserType: # Added in Python 3.10.20, 3.11.15, 3.12.3, 3.13.10, 3.14.1 def SetAllocTrackerActivationThreshold(self, threshold: int, /) -> None: ... def SetAllocTrackerMaximumAmplification(self, max_factor: float, /) -> None: ... + if sys.version_info >= (3, 15): + def SetBillionLaughsAttackProtectionActivationThreshold(self, threshold: int, /) -> None: ... + def SetBillionLaughsAttackProtectionMaximumAmplification(self, max_factor: float, /) -> None: ... + @property def intern(self) -> dict[str, str]: ... buffer_size: int diff --git a/stdlib/stat.pyi b/stdlib/stat.pyi index 6c26080e0665..155d765d2b16 100644 --- a/stdlib/stat.pyi +++ b/stdlib/stat.pyi @@ -112,3 +112,15 @@ FILE_ATTRIBUTE_VIRTUAL: Final = 65536 if sys.version_info >= (3, 13): # https://github.com/python/cpython/issues/114081#issuecomment-2119017790 SF_RESTRICTED: Final = 0x00080000 + +if sys.version_info >= (3, 15): + STATX_ATTR_COMPRESSED: Final = 0x00000004 + STATX_ATTR_IMMUTABLE: Final = 0x00000010 + STATX_ATTR_APPEND: Final = 0x00000020 + STATX_ATTR_NODUMP: Final = 0x00000040 + STATX_ATTR_ENCRYPTED: Final = 0x00000800 + STATX_ATTR_AUTOMOUNT: Final = 0x00001000 + STATX_ATTR_MOUNT_ROOT: Final = 0x00002000 + STATX_ATTR_VERITY: Final = 0x00100000 + STATX_ATTR_DAX: Final = 0x00200000 + STATX_ATTR_WRITE_ATOMIC: Final = 0x00400000 diff --git a/stdlib/symtable.pyi b/stdlib/symtable.pyi index a727b878688e..4142e7c3f52e 100644 --- a/stdlib/symtable.pyi +++ b/stdlib/symtable.pyi @@ -46,6 +46,9 @@ class Function(SymbolTable): def get_locals(self) -> tuple[str, ...]: ... def get_globals(self) -> tuple[str, ...]: ... def get_frees(self) -> tuple[str, ...]: ... + if sys.version_info >= (3, 15): + def get_cells(self) -> tuple[str, ...]: ... + def get_nonlocals(self) -> tuple[str, ...]: ... class Class(SymbolTable): @@ -79,6 +82,8 @@ class Symbol: if sys.version_info >= (3, 14): def is_comp_iter(self) -> bool: ... def is_comp_cell(self) -> bool: ... + if sys.version_info >= (3, 15): + def is_cell(self) -> bool: ... def is_namespace(self) -> bool: ... def get_namespaces(self) -> Sequence[SymbolTable]: ... diff --git a/stdlib/unicodedata.pyi b/stdlib/unicodedata.pyi index 20acf0428158..172ddd3ac653 100644 --- a/stdlib/unicodedata.pyi +++ b/stdlib/unicodedata.pyi @@ -1,4 +1,6 @@ +import sys from _typeshed import ReadOnlyBuffer +from collections.abc import Iterator from typing import Final, Literal, TypeAlias, TypeVar, final, overload ucd_3_2_0: UCD @@ -25,6 +27,16 @@ _EastAsianWidth: TypeAlias = Literal["F", "H", "W", "Na", "A", "N"] def east_asian_width(chr: str, /) -> _EastAsianWidth: ... def is_normalized(form: _NormalizationForm, unistr: str, /) -> bool: ... + +if sys.version_info >= (3, 15): + def block(chr: str, /) -> str: ... + def extended_pictographic(chr: str, /) -> bool: ... + def grapheme_cluster_break(chr: str, /) -> str: ... + def indic_conjunct_break(chr: str, /) -> str: ... + def isxidstart(chr: str, /) -> bool: ... + def isxidcontinue(chr: str, /) -> bool: ... + def iter_graphemes(unistr: str, start: int = 0, end: int = sys.maxsize, /) -> Iterator[str]: ... + def lookup(name: str | ReadOnlyBuffer, /) -> str: ... def mirrored(chr: str, /) -> int: ... @overload diff --git a/stdlib/zlib.pyi b/stdlib/zlib.pyi index d5998cab90fe..557fa761feeb 100644 --- a/stdlib/zlib.pyi +++ b/stdlib/zlib.pyi @@ -60,6 +60,9 @@ class _Decompress: def adler32(data: ReadableBuffer, value: int = 1, /) -> int: ... +if sys.version_info >= (3, 15): + def adler32_combine(adler1: int, adler2: int, len2: int, /) -> int: ... + if sys.version_info >= (3, 11): def compress(data: ReadableBuffer, /, level: int = -1, wbits: int = 15) -> bytes: ... @@ -70,5 +73,9 @@ def compressobj( level: int = -1, method: int = 8, wbits: int = 15, memLevel: int = 8, strategy: int = 0, zdict: ReadableBuffer | None = None ) -> _Compress: ... def crc32(data: ReadableBuffer, value: int = 0, /) -> int: ... + +if sys.version_info >= (3, 15): + def crc32_combine(crc1: int, crc2: int, len2: int, /) -> int: ... + def decompress(data: ReadableBuffer, /, wbits: int = 15, bufsize: int = 16384) -> bytes: ... def decompressobj(wbits: int = 15, zdict: ReadableBuffer = b"") -> _Decompress: ...