From 6b8df6b753719c416d850e6cdc20f0bbfdd55d6e Mon Sep 17 00:00:00 2001 From: Brian Schubert Date: Fri, 25 Jul 2025 23:24:09 -0400 Subject: [PATCH] Mark `tarfile` constants as `Final` (#14456) --- stdlib/tarfile.pyi | 84 ++++++++++++++++++++++++---------------------- 1 file changed, 44 insertions(+), 40 deletions(-) diff --git a/stdlib/tarfile.pyi b/stdlib/tarfile.pyi index dba250f2d..5ebbd5e38 100644 --- a/stdlib/tarfile.pyi +++ b/stdlib/tarfile.pyi @@ -6,7 +6,7 @@ from builtins import list as _list # aliases to avoid name clashes with fields from collections.abc import Callable, Iterable, Iterator, Mapping from gzip import _ReadableFileobj as _GzipReadableFileobj, _WritableFileobj as _GzipWritableFileobj from types import TracebackType -from typing import IO, ClassVar, Literal, Protocol, overload +from typing import IO, ClassVar, Final, Literal, Protocol, overload, type_check_only from typing_extensions import Self, TypeAlias, deprecated if sys.version_info >= (3, 14): @@ -47,6 +47,7 @@ if sys.version_info >= (3, 13): _FilterFunction: TypeAlias = Callable[[TarInfo, str], TarInfo | None] _TarfileFilter: TypeAlias = Literal["fully_trusted", "tar", "data"] | _FilterFunction +@type_check_only class _Fileobj(Protocol): def read(self, size: int, /) -> bytes: ... def write(self, b: bytes, /) -> object: ... @@ -57,58 +58,61 @@ class _Fileobj(Protocol): # name: str | bytes # mode: Literal["rb", "r+b", "wb", "xb"] +@type_check_only class _Bz2ReadableFileobj(bz2._ReadableFileobj): def close(self) -> object: ... +@type_check_only class _Bz2WritableFileobj(bz2._WritableFileobj): def close(self) -> object: ... # tar constants -NUL: bytes -BLOCKSIZE: int -RECORDSIZE: int -GNU_MAGIC: bytes -POSIX_MAGIC: bytes +NUL: Final = b"\0" +BLOCKSIZE: Final = 512 +RECORDSIZE: Final = 10240 +GNU_MAGIC: Final = b"ustar \0" +POSIX_MAGIC: Final = b"ustar\x0000" -LENGTH_NAME: int -LENGTH_LINK: int -LENGTH_PREFIX: int +LENGTH_NAME: Final = 100 +LENGTH_LINK: Final = 100 +LENGTH_PREFIX: Final = 155 -REGTYPE: bytes -AREGTYPE: bytes -LNKTYPE: bytes -SYMTYPE: bytes -CONTTYPE: bytes -BLKTYPE: bytes -DIRTYPE: bytes -FIFOTYPE: bytes -CHRTYPE: bytes +REGTYPE: Final = b"0" +AREGTYPE: Final = b"\0" +LNKTYPE: Final = b"1" +SYMTYPE: Final = b"2" +CHRTYPE: Final = b"3" +BLKTYPE: Final = b"4" +DIRTYPE: Final = b"5" +FIFOTYPE: Final = b"6" +CONTTYPE: Final = b"7" -GNUTYPE_LONGNAME: bytes -GNUTYPE_LONGLINK: bytes -GNUTYPE_SPARSE: bytes +GNUTYPE_LONGNAME: Final = b"L" +GNUTYPE_LONGLINK: Final = b"K" +GNUTYPE_SPARSE: Final = b"S" -XHDTYPE: bytes -XGLTYPE: bytes -SOLARIS_XHDTYPE: bytes +XHDTYPE: Final = b"x" +XGLTYPE: Final = b"g" +SOLARIS_XHDTYPE: Final = b"X" -USTAR_FORMAT: int -GNU_FORMAT: int -PAX_FORMAT: int -DEFAULT_FORMAT: int +_TarFormat: TypeAlias = Literal[0, 1, 2] # does not exist at runtime +USTAR_FORMAT: Final = 0 +GNU_FORMAT: Final = 1 +PAX_FORMAT: Final = 2 +DEFAULT_FORMAT: Final = PAX_FORMAT # tarfile constants -SUPPORTED_TYPES: tuple[bytes, ...] -REGULAR_TYPES: tuple[bytes, ...] -GNU_TYPES: tuple[bytes, ...] -PAX_FIELDS: tuple[str, ...] -PAX_NUMBER_FIELDS: dict[str, type] -PAX_NAME_FIELDS: set[str] +SUPPORTED_TYPES: Final[tuple[bytes, ...]] +REGULAR_TYPES: Final[tuple[bytes, ...]] +GNU_TYPES: Final[tuple[bytes, ...]] +PAX_FIELDS: Final[tuple[str, ...]] +PAX_NUMBER_FIELDS: Final[dict[str, type]] +PAX_NAME_FIELDS: Final[set[str]] -ENCODING: str +ENCODING: Final[str] -class ExFileObject(io.BufferedReader): +class ExFileObject(io.BufferedReader): # undocumented def __init__(self, tarfile: TarFile, tarinfo: TarInfo) -> None: ... class TarFile: @@ -116,13 +120,13 @@ class TarFile: name: StrOrBytesPath | None mode: Literal["r", "a", "w", "x"] fileobj: _Fileobj | None - format: int | None + format: _TarFormat | None tarinfo: type[TarInfo] dereference: bool | None ignore_zeros: bool | None encoding: str | None errors: str - fileobject: type[ExFileObject] + fileobject: type[ExFileObject] # undocumented pax_headers: Mapping[str, str] | None debug: int | None errorlevel: int | None @@ -751,7 +755,7 @@ class TarInfo: offset_data: int sparse: bytes | None mode: int - type: bytes + type: bytes # usually one of the TYPE constants, but could be an arbitrary byte linkname: str uid: int gid: int @@ -791,7 +795,7 @@ class TarInfo: deep: bool = True, ) -> Self: ... def get_info(self) -> Mapping[str, str | int | bytes | Mapping[str, str]]: ... - def tobuf(self, format: int | None = 2, encoding: str | None = "utf-8", errors: str = "surrogateescape") -> bytes: ... + def tobuf(self, format: _TarFormat | None = 2, encoding: str | None = "utf-8", errors: str = "surrogateescape") -> bytes: ... def create_ustar_header( self, info: Mapping[str, str | int | bytes | Mapping[str, str]], encoding: str, errors: str ) -> bytes: ...