From 24dafa32e4d70273fe97d2f0191b6123b74a88da Mon Sep 17 00:00:00 2001 From: Rogdham Date: Sat, 10 May 2025 21:11:43 +0200 Subject: [PATCH 1/4] Python 3.14: PEP-784 compression except zstd --- pyproject.toml | 2 ++ stdlib/@tests/stubtest_allowlists/py314.txt | 11 ++++---- .../stubtest_allowlists/win32-py314.txt | 1 + stdlib/VERSIONS | 3 ++- stdlib/bz2.pyi | 10 +++++--- stdlib/compression/__init__.pyi | 0 stdlib/compression/_common/__init__.pyi | 0 stdlib/compression/_common/_streams.pyi | 25 +++++++++++++++++++ stdlib/compression/bz2/__init__.pyi | 1 + stdlib/compression/gzip/__init__.pyi | 1 + stdlib/compression/lzma/__init__.pyi | 1 + stdlib/compression/zlib/__init__.pyi | 1 + stdlib/gzip.pyi | 10 +++++--- stdlib/lzma.pyi | 7 +++++- 14 files changed, 59 insertions(+), 14 deletions(-) create mode 100644 stdlib/compression/__init__.pyi create mode 100644 stdlib/compression/_common/__init__.pyi create mode 100644 stdlib/compression/_common/_streams.pyi create mode 100644 stdlib/compression/bz2/__init__.pyi create mode 100644 stdlib/compression/gzip/__init__.pyi create mode 100644 stdlib/compression/lzma/__init__.pyi create mode 100644 stdlib/compression/zlib/__init__.pyi diff --git a/pyproject.toml b/pyproject.toml index e1c07d518c89..b4a430f7510c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -245,6 +245,8 @@ extra-standard-library = [ # Extra modules not recognized by Ruff # Added in Python 3.9 "zoneinfo", + # Added in Python 3.14 + "compression", ] known-first-party = ["_utils", "ts_utils"] diff --git a/stdlib/@tests/stubtest_allowlists/py314.txt b/stdlib/@tests/stubtest_allowlists/py314.txt index 3cf65860e6a6..f747826ca7ef 100644 --- a/stdlib/@tests/stubtest_allowlists/py314.txt +++ b/stdlib/@tests/stubtest_allowlists/py314.txt @@ -116,7 +116,6 @@ _ast.withitem.__annotations_cache__ _asyncio.all_tasks _asyncio.future_add_to_awaited_by _asyncio.future_discard_from_awaited_by -_compression _contextvars.Token.__enter__ _contextvars.Token.__exit__ _ctypes.POINTER @@ -308,11 +307,11 @@ builtins.staticmethod.__class_getitem__ builtins.type.__annotate__ code.compile_command codeop.compile_command -compression -compression.bz2 -compression.gzip -compression.lzma -compression.zlib +compression.gzip.GzipFile.readinto +compression.gzip.GzipFile.readinto +compression.gzip.GzipFile.readinto1 +compression.gzip.GzipFile.readinto1 +compression.gzip.compress compression.zstd concurrent.futures.__all__ concurrent.futures.Executor.map diff --git a/stdlib/@tests/stubtest_allowlists/win32-py314.txt b/stdlib/@tests/stubtest_allowlists/win32-py314.txt index 9e2f612dbd39..cf30f5056c0d 100644 --- a/stdlib/@tests/stubtest_allowlists/win32-py314.txt +++ b/stdlib/@tests/stubtest_allowlists/win32-py314.txt @@ -23,6 +23,7 @@ asyncio.windows_events.WindowsSelectorEventLoopPolicy asyncio.windows_events._DefaultEventLoopPolicy asyncio.windows_events._WindowsProactorEventLoopPolicy asyncio.windows_events._WindowsSelectorEventLoopPolicy +compression.zlib.ZLIBNG_VERSION ctypes.c_double_complex ctypes.c_float_complex ctypes.c_longdouble_complex diff --git a/stdlib/VERSIONS b/stdlib/VERSIONS index fec56ce59e36..a5e6b576f824 100644 --- a/stdlib/VERSIONS +++ b/stdlib/VERSIONS @@ -28,7 +28,7 @@ _bz2: 3.3- _codecs: 3.0- _collections_abc: 3.3- _compat_pickle: 3.1- -_compression: 3.5- +_compression: 3.5-3.13 _contextvars: 3.7- _csv: 3.0- _ctypes: 3.0- @@ -117,6 +117,7 @@ collections: 3.0- collections.abc: 3.3- colorsys: 3.0- compileall: 3.0- +compression: 3.14- concurrent: 3.2- configparser: 3.0- contextlib: 3.0- diff --git a/stdlib/bz2.pyi b/stdlib/bz2.pyi index 3b21fbcf7117..0f9d00fbc633 100644 --- a/stdlib/bz2.pyi +++ b/stdlib/bz2.pyi @@ -1,17 +1,21 @@ -import _compression +import sys from _bz2 import BZ2Compressor as BZ2Compressor, BZ2Decompressor as BZ2Decompressor -from _compression import BaseStream from _typeshed import ReadableBuffer, StrOrBytesPath, WriteableBuffer from collections.abc import Iterable from typing import IO, Literal, Protocol, SupportsIndex, TextIO, overload from typing_extensions import Self, TypeAlias +if sys.version_info >= (3, 14): + from compression._common._streams import BaseStream, _Reader +else: + from _compression import BaseStream, _Reader + __all__ = ["BZ2File", "BZ2Compressor", "BZ2Decompressor", "open", "compress", "decompress"] # The following attributes and methods are optional: # def fileno(self) -> int: ... # def close(self) -> object: ... -class _ReadableFileobj(_compression._Reader, Protocol): ... +class _ReadableFileobj(_Reader, Protocol): ... class _WritableFileobj(Protocol): def write(self, b: bytes, /) -> object: ... diff --git a/stdlib/compression/__init__.pyi b/stdlib/compression/__init__.pyi new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/stdlib/compression/_common/__init__.pyi b/stdlib/compression/_common/__init__.pyi new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/stdlib/compression/_common/_streams.pyi b/stdlib/compression/_common/_streams.pyi new file mode 100644 index 000000000000..a41a8142cc3a --- /dev/null +++ b/stdlib/compression/_common/_streams.pyi @@ -0,0 +1,25 @@ +from _typeshed import WriteableBuffer +from collections.abc import Callable +from io import DEFAULT_BUFFER_SIZE, BufferedIOBase, RawIOBase +from typing import Any, Protocol + +BUFFER_SIZE = DEFAULT_BUFFER_SIZE + +class _Reader(Protocol): + def read(self, n: int, /) -> bytes: ... + def seekable(self) -> bool: ... + def seek(self, n: int, /) -> Any: ... + +class BaseStream(BufferedIOBase): ... + +class DecompressReader(RawIOBase): + def __init__( + self, + fp: _Reader, + decomp_factory: Callable[..., object], + trailing_error: type[Exception] | tuple[type[Exception], ...] = (), + **decomp_args: Any, + ) -> None: ... + def readinto(self, b: WriteableBuffer) -> int: ... + def read(self, size: int = -1) -> bytes: ... + def seek(self, offset: int, whence: int = 0) -> int: ... diff --git a/stdlib/compression/bz2/__init__.pyi b/stdlib/compression/bz2/__init__.pyi new file mode 100644 index 000000000000..9ddc39f27c28 --- /dev/null +++ b/stdlib/compression/bz2/__init__.pyi @@ -0,0 +1 @@ +from bz2 import * diff --git a/stdlib/compression/gzip/__init__.pyi b/stdlib/compression/gzip/__init__.pyi new file mode 100644 index 000000000000..9422a735c590 --- /dev/null +++ b/stdlib/compression/gzip/__init__.pyi @@ -0,0 +1 @@ +from gzip import * diff --git a/stdlib/compression/lzma/__init__.pyi b/stdlib/compression/lzma/__init__.pyi new file mode 100644 index 000000000000..936c3813db4f --- /dev/null +++ b/stdlib/compression/lzma/__init__.pyi @@ -0,0 +1 @@ +from lzma import * diff --git a/stdlib/compression/zlib/__init__.pyi b/stdlib/compression/zlib/__init__.pyi new file mode 100644 index 000000000000..78d176c03ee8 --- /dev/null +++ b/stdlib/compression/zlib/__init__.pyi @@ -0,0 +1 @@ +from zlib import * diff --git a/stdlib/gzip.pyi b/stdlib/gzip.pyi index b7fb40fbd82e..883456b1ddc3 100644 --- a/stdlib/gzip.pyi +++ b/stdlib/gzip.pyi @@ -1,4 +1,3 @@ -import _compression import sys import zlib from _typeshed import ReadableBuffer, SizedBuffer, StrOrBytesPath @@ -6,6 +5,11 @@ from io import FileIO, TextIOWrapper from typing import Final, Literal, Protocol, overload from typing_extensions import TypeAlias +if sys.version_info >= (3, 14): + from compression._common._streams import BaseStream, DecompressReader +else: + from _compression import BaseStream, DecompressReader + __all__ = ["BadGzipFile", "GzipFile", "open", "compress", "decompress"] _ReadBinaryMode: TypeAlias = Literal["r", "rb"] @@ -84,7 +88,7 @@ class _PaddedFile: class BadGzipFile(OSError): ... -class GzipFile(_compression.BaseStream): +class GzipFile(BaseStream): myfileobj: FileIO | None mode: object name: str @@ -153,7 +157,7 @@ class GzipFile(_compression.BaseStream): def seek(self, offset: int, whence: int = 0) -> int: ... def readline(self, size: int | None = -1) -> bytes: ... -class _GzipReader(_compression.DecompressReader): +class _GzipReader(DecompressReader): def __init__(self, fp: _ReadableFileobj) -> None: ... def compress(data: SizedBuffer, compresslevel: int = 9, *, mtime: float | None = None) -> bytes: ... diff --git a/stdlib/lzma.pyi b/stdlib/lzma.pyi index 2f0279f5986b..b066d222466b 100644 --- a/stdlib/lzma.pyi +++ b/stdlib/lzma.pyi @@ -1,4 +1,4 @@ -from _compression import BaseStream +import sys from _lzma import ( CHECK_CRC32 as CHECK_CRC32, CHECK_CRC64 as CHECK_CRC64, @@ -38,6 +38,11 @@ from _typeshed import ReadableBuffer, StrOrBytesPath from typing import IO, Literal, TextIO, overload from typing_extensions import Self, TypeAlias +if sys.version_info >= (3, 14): + from compression._common._streams import BaseStream +else: + from _compression import BaseStream + __all__ = [ "CHECK_NONE", "CHECK_CRC32", From 81167528d88b0aa9e9fc923c50f89d1d2abf7a45 Mon Sep 17 00:00:00 2001 From: Rogdham Date: Sat, 10 May 2025 23:50:22 +0200 Subject: [PATCH 2/4] Followup of merge conflict --- stdlib/@tests/stubtest_allowlists/py314.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/stdlib/@tests/stubtest_allowlists/py314.txt b/stdlib/@tests/stubtest_allowlists/py314.txt index 740949747b6d..1879cc263643 100644 --- a/stdlib/@tests/stubtest_allowlists/py314.txt +++ b/stdlib/@tests/stubtest_allowlists/py314.txt @@ -5,8 +5,6 @@ _asyncio.all_tasks _asyncio.future_add_to_awaited_by _asyncio.future_discard_from_awaited_by -_contextvars.Token.__enter__ -_contextvars.Token.__exit__ _ctypes.POINTER _ctypes.byref _ctypes.pointer From 53850c347155933d0b145daa189b0beb38595c94 Mon Sep 17 00:00:00 2001 From: Rogdham Date: Sun, 11 May 2025 14:46:19 +0200 Subject: [PATCH 3/4] Review --- stdlib/_compression.pyi | 6 +++--- stdlib/compression/_common/_streams.pyi | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/stdlib/_compression.pyi b/stdlib/_compression.pyi index a41a8142cc3a..adf5ccbe5491 100644 --- a/stdlib/_compression.pyi +++ b/stdlib/_compression.pyi @@ -1,4 +1,4 @@ -from _typeshed import WriteableBuffer +from _typeshed import Incomplete, WriteableBuffer from collections.abc import Callable from io import DEFAULT_BUFFER_SIZE, BufferedIOBase, RawIOBase from typing import Any, Protocol @@ -16,9 +16,9 @@ class DecompressReader(RawIOBase): def __init__( self, fp: _Reader, - decomp_factory: Callable[..., object], + decomp_factory: Callable[..., Incomplete], trailing_error: type[Exception] | tuple[type[Exception], ...] = (), - **decomp_args: Any, + **decomp_args: Any, # These are passed to decomp_factory. ) -> None: ... def readinto(self, b: WriteableBuffer) -> int: ... def read(self, size: int = -1) -> bytes: ... diff --git a/stdlib/compression/_common/_streams.pyi b/stdlib/compression/_common/_streams.pyi index a41a8142cc3a..adf5ccbe5491 100644 --- a/stdlib/compression/_common/_streams.pyi +++ b/stdlib/compression/_common/_streams.pyi @@ -1,4 +1,4 @@ -from _typeshed import WriteableBuffer +from _typeshed import Incomplete, WriteableBuffer from collections.abc import Callable from io import DEFAULT_BUFFER_SIZE, BufferedIOBase, RawIOBase from typing import Any, Protocol @@ -16,9 +16,9 @@ class DecompressReader(RawIOBase): def __init__( self, fp: _Reader, - decomp_factory: Callable[..., object], + decomp_factory: Callable[..., Incomplete], trailing_error: type[Exception] | tuple[type[Exception], ...] = (), - **decomp_args: Any, + **decomp_args: Any, # These are passed to decomp_factory. ) -> None: ... def readinto(self, b: WriteableBuffer) -> int: ... def read(self, size: int = -1) -> bytes: ... From d634c6a8af29bc8f6cde3244d6df482d70dd3082 Mon Sep 17 00:00:00 2001 From: Rogdham Date: Sun, 11 May 2025 15:09:39 +0200 Subject: [PATCH 4/4] Add comments --- stdlib/_compression.pyi | 2 ++ stdlib/compression/_common/_streams.pyi | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/stdlib/_compression.pyi b/stdlib/_compression.pyi index adf5ccbe5491..80d38b4db824 100644 --- a/stdlib/_compression.pyi +++ b/stdlib/_compression.pyi @@ -1,3 +1,5 @@ +# _compression is replaced by compression._common._streams on Python 3.14+ (PEP-784) + from _typeshed import Incomplete, WriteableBuffer from collections.abc import Callable from io import DEFAULT_BUFFER_SIZE, BufferedIOBase, RawIOBase diff --git a/stdlib/compression/_common/_streams.pyi b/stdlib/compression/_common/_streams.pyi index adf5ccbe5491..6303a9b1d460 100644 --- a/stdlib/compression/_common/_streams.pyi +++ b/stdlib/compression/_common/_streams.pyi @@ -16,7 +16,7 @@ class DecompressReader(RawIOBase): def __init__( self, fp: _Reader, - decomp_factory: Callable[..., Incomplete], + decomp_factory: Callable[..., Incomplete], # Consider backporting changes to _compression trailing_error: type[Exception] | tuple[type[Exception], ...] = (), **decomp_args: Any, # These are passed to decomp_factory. ) -> None: ...