From 2ad7f8f52226725580d0ef7f2484540f4e313307 Mon Sep 17 00:00:00 2001 From: ENIO ROCHA Date: Thu, 16 Oct 2025 12:07:33 -0300 Subject: [PATCH] Add overloads to TarFile.__init__ to ensure name or fileobj is provided (#14168) - Added overloads ensuring either 'name' or 'fileobj' must be non-None - First overload: name is required (StrOrBytesPath), fileobj is optional - Second overload: name is None, fileobj is required (keyword-only) - Applied to both Python 3.13+ and older versions This prevents the runtime TypeError when both name and fileobj are None: tarfile.TarFile(None, fileobj=None) # Now caught by type checker Fixes #14168 Sacred Code: 000.111.369.963.1618 --- stdlib/tarfile.pyi | 72 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/stdlib/tarfile.pyi b/stdlib/tarfile.pyi index f6623ea9929d..c8b9c00aa559 100644 --- a/stdlib/tarfile.pyi +++ b/stdlib/tarfile.pyi @@ -134,6 +134,43 @@ class TarFile: extraction_filter: _FilterFunction | None if sys.version_info >= (3, 13): stream: bool + @overload + def __init__( + self, + name: StrOrBytesPath, # name is required (not None) + mode: Literal["r", "a", "w", "x"] = "r", + fileobj: _Fileobj | None = None, + format: int | None = None, + tarinfo: type[TarInfo] | None = None, + dereference: bool | None = None, + ignore_zeros: bool | None = None, + encoding: str | None = None, + errors: str = "surrogateescape", + pax_headers: Mapping[str, str] | None = None, + debug: int | None = None, + errorlevel: int | None = None, + copybufsize: int | None = None, + stream: bool = False, + ) -> None: ... + @overload + def __init__( + self, + name: None = None, + mode: Literal["r", "a", "w", "x"] = "r", + *, + fileobj: _Fileobj, # fileobj is required when name is None + format: int | None = None, + tarinfo: type[TarInfo] | None = None, + dereference: bool | None = None, + ignore_zeros: bool | None = None, + encoding: str | None = None, + errors: str = "surrogateescape", + pax_headers: Mapping[str, str] | None = None, + debug: int | None = None, + errorlevel: int | None = None, + copybufsize: int | None = None, + stream: bool = False, + ) -> None: ... def __init__( self, name: StrOrBytesPath | None = None, @@ -152,6 +189,41 @@ class TarFile: stream: bool = False, ) -> None: ... else: + @overload + def __init__( + self, + name: StrOrBytesPath, # name is required (not None) + mode: Literal["r", "a", "w", "x"] = "r", + fileobj: _Fileobj | None = None, + format: int | None = None, + tarinfo: type[TarInfo] | None = None, + dereference: bool | None = None, + ignore_zeros: bool | None = None, + encoding: str | None = None, + errors: str = "surrogateescape", + pax_headers: Mapping[str, str] | None = None, + debug: int | None = None, + errorlevel: int | None = None, + copybufsize: int | None = None, + ) -> None: ... + @overload + def __init__( + self, + name: None = None, + mode: Literal["r", "a", "w", "x"] = "r", + *, + fileobj: _Fileobj, # fileobj is required when name is None + format: int | None = None, + tarinfo: type[TarInfo] | None = None, + dereference: bool | None = None, + ignore_zeros: bool | None = None, + encoding: str | None = None, + errors: str = "surrogateescape", + pax_headers: Mapping[str, str] | None = None, + debug: int | None = None, + errorlevel: int | None = None, + copybufsize: int | None = None, + ) -> None: ... def __init__( self, name: StrOrBytesPath | None = None,