Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assert fp is not None #8617

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Tests/test_file_bufrstub.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ def open(self, im: ImageFile.StubImageFile) -> None:

def load(self, im: ImageFile.StubImageFile) -> Image.Image:
self.loaded = True
assert im.fp is not None
im.fp.close()
return Image.new("RGB", (1, 1))

Expand Down
1 change: 1 addition & 0 deletions Tests/test_file_cur.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def test_invalid_file() -> None:
no_cursors_file = "Tests/images/no_cursors.cur"

cur = CurImagePlugin.CurImageFile(TEST_FILE)
assert cur.fp is not None
cur.fp.close()
with open(no_cursors_file, "rb") as cur.fp:
with pytest.raises(TypeError):
Expand Down
1 change: 1 addition & 0 deletions Tests/test_file_gribstub.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ def open(self, im: Image.Image) -> None:

def load(self, im: Image.Image) -> Image.Image:
self.loaded = True
assert im.fp is not None
im.fp.close()
return Image.new("RGB", (1, 1))

Expand Down
1 change: 1 addition & 0 deletions Tests/test_file_hdf5stub.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ def open(self, im: Image.Image) -> None:

def load(self, im: Image.Image) -> Image.Image:
self.loaded = True
assert im.fp is not None
im.fp.close()
return Image.new("RGB", (1, 1))

Expand Down
3 changes: 2 additions & 1 deletion Tests/test_file_jpeg.py
Original file line number Diff line number Diff line change
Expand Up @@ -1090,8 +1090,9 @@ def test_fd_leak(self, tmp_path: Path) -> None:
im.save(tmpfile)

im = Image.open(tmpfile)
assert im.fp is not None
assert not im.fp.closed
fp = im.fp
assert not fp.closed
with pytest.raises(OSError):
os.remove(tmpfile)
im.load()
Expand Down
13 changes: 11 additions & 2 deletions Tests/test_file_libtiff.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,15 @@

import pytest

from PIL import Image, ImageFilter, ImageOps, TiffImagePlugin, TiffTags, features
from PIL import (
Image,
ImageFile,
ImageFilter,
ImageOps,
TiffImagePlugin,
TiffTags,
features,
)
from PIL.TiffImagePlugin import OSUBFILETYPE, SAMPLEFORMAT, STRIPOFFSETS, SUBIFD

from .helper import (
Expand Down Expand Up @@ -556,8 +564,9 @@ def test_bw_compression_w_rgb(self, compression: str, tmp_path: Path) -> None:
im.save(out, compression=compression)

def test_fp_leak(self) -> None:
im: Image.Image | None = Image.open("Tests/images/hopper_g4_500.tif")
im: ImageFile.ImageFile | None = Image.open("Tests/images/hopper_g4_500.tif")
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image.open returns an ImageFile instance.

Pillow/src/PIL/Image.py

Lines 3404 to 3408 in 0e3f51d

def open(
fp: StrOrBytesPath | IO[bytes],
mode: Literal["r"] = "r",
formats: list[str] | tuple[str, ...] | None = None,
) -> ImageFile.ImageFile:

assert im is not None
assert im.fp is not None
fn = im.fp.fileno()

os.fstat(fn)
Expand Down
5 changes: 4 additions & 1 deletion Tests/test_file_tiff.py
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,7 @@ def test_close_on_load_exclusive(self, tmp_path: Path) -> None:

im = Image.open(tmpfile)
fp = im.fp
assert fp is not None
assert not fp.closed
im.load()
assert fp.closed
Expand All @@ -874,6 +875,7 @@ def test_close_on_load_nonexclusive(self, tmp_path: Path) -> None:
with open(tmpfile, "rb") as f:
im = Image.open(f)
fp = im.fp
assert fp is not None
assert not fp.closed
im.load()
assert not fp.closed
Expand Down Expand Up @@ -925,8 +927,9 @@ def test_fd_leak(self, tmp_path: Path) -> None:
im.save(tmpfile)

im = Image.open(tmpfile)
assert im.fp is not None
assert not im.fp.closed
fp = im.fp
assert not fp.closed
with pytest.raises(OSError):
os.remove(tmpfile)
im.load()
Expand Down
1 change: 1 addition & 0 deletions Tests/test_image_load.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def test_close_after_load(caplog: pytest.LogCaptureFixture) -> None:
def test_contextmanager() -> None:
fn = None
with Image.open("Tests/images/hopper.gif") as im:
assert im.fp is not None
fn = im.fp.fileno()
os.fstat(fn)

Expand Down
1 change: 1 addition & 0 deletions docs/example/DdsImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ class DdsImageFile(ImageFile.ImageFile):
format_description = "DirectDraw Surface"

def _open(self) -> None:
assert self.fp is not None
if not _accept(self.fp.read(4)):
msg = "not a DDS file"
raise SyntaxError(msg)
Expand Down
1 change: 1 addition & 0 deletions src/PIL/BlpImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ class BlpImageFile(ImageFile.ImageFile):
format_description = "Blizzard Mipmap Format"

def _open(self) -> None:
assert self.fp is not None
self.magic = self.fp.read(4)

self.fp.seek(5, os.SEEK_CUR)
Expand Down
2 changes: 2 additions & 0 deletions src/PIL/BmpImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class BmpImageFile(ImageFile.ImageFile):

def _bitmap(self, header: int = 0, offset: int = 0) -> None:
"""Read relevant info about the BMP"""
assert self.fp is not None
read, seek = self.fp.read, self.fp.seek
if header:
seek(header)
Expand Down Expand Up @@ -307,6 +308,7 @@ def _bitmap(self, header: int = 0, offset: int = 0) -> None:
def _open(self) -> None:
"""Open file, check magic number and read header"""
# read 14 bytes: magic number, filesize, reserved, header final offset
assert self.fp is not None
head_data = self.fp.read(14)
# choke if the file does not have the required magic bytes
if not _accept(head_data):
Expand Down
1 change: 1 addition & 0 deletions src/PIL/BufrStubImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class BufrStubImageFile(ImageFile.StubImageFile):
format_description = "BUFR"

def _open(self) -> None:
assert self.fp is not None
offset = self.fp.tell()

if not _accept(self.fp.read(4)):
Expand Down
1 change: 1 addition & 0 deletions src/PIL/CurImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class CurImageFile(BmpImagePlugin.BmpImageFile):
format_description = "Windows Cursor"

def _open(self) -> None:
assert self.fp is not None
offset = self.fp.tell()

# check magic
Expand Down
1 change: 1 addition & 0 deletions src/PIL/DcxImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class DcxImageFile(PcxImageFile):

def _open(self) -> None:
# Header
assert self.fp is not None
s = self.fp.read(4)
if not _accept(s):
msg = "not a DCX file"
Expand Down
1 change: 1 addition & 0 deletions src/PIL/DdsImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ class DdsImageFile(ImageFile.ImageFile):
format_description = "DirectDraw Surface"

def _open(self) -> None:
assert self.fp is not None
if not _accept(self.fp.read(4)):
msg = "not a DDS file"
raise SyntaxError(msg)
Expand Down
2 changes: 2 additions & 0 deletions src/PIL/EpsImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ class EpsImageFile(ImageFile.ImageFile):
mode_map = {1: "L", 2: "LAB", 3: "RGB", 4: "CMYK"}

def _open(self) -> None:
assert self.fp is not None
(length, offset) = self._find_offset(self.fp)

# go to offset - start of "%!PS"
Expand Down Expand Up @@ -398,6 +399,7 @@ def load(
) -> Image.core.PixelAccess | None:
# Load EPS via Ghostscript
if self.tile:
assert self.fp is not None
self.im = Ghostscript(self.tile, self.size, self.fp, scale, transparency)
self._mode = self.im.mode
self._size = self.im.size
Expand Down
2 changes: 2 additions & 0 deletions src/PIL/FliImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class FliImageFile(ImageFile.ImageFile):

def _open(self) -> None:
# HEAD
assert self.fp is not None
s = self.fp.read(128)
if not (_accept(s) and s[20:22] == b"\x00\x00"):
msg = "not an FLI/FLC file"
Expand Down Expand Up @@ -110,6 +111,7 @@ def _palette(self, palette: list[tuple[int, int, int]], shift: int) -> None:
# load palette

i = 0
assert self.fp is not None
for e in range(i16(self.fp.read(2))):
s = self.fp.read(2)
i = i + s[0]
Expand Down
2 changes: 2 additions & 0 deletions src/PIL/FpxImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ def _open(self) -> None:
# read the OLE directory and see if this is a likely
# to be a FlashPix file

assert self.fp is not None
try:
self.ole = olefile.OleFileIO(self.fp)
except OSError as e:
Expand Down Expand Up @@ -229,6 +230,7 @@ def _open_subimage(self, index: int = 1, subimage: int = 0) -> None:
if y >= ysize:
break # isn't really required

assert self.fp is not None
self.stream = stream
self._fp = self.fp
self.fp = None
Expand Down
1 change: 1 addition & 0 deletions src/PIL/FtexImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class FtexImageFile(ImageFile.ImageFile):
format_description = "Texture File Format (IW2:EOC)"

def _open(self) -> None:
assert self.fp is not None
if not _accept(self.fp.read(4)):
msg = "not an FTEX file"
raise SyntaxError(msg)
Expand Down
2 changes: 2 additions & 0 deletions src/PIL/GbrImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class GbrImageFile(ImageFile.ImageFile):
format_description = "GIMP brush file"

def _open(self) -> None:
assert self.fp is not None
header_size = i32(self.fp.read(4))
if header_size < 20:
msg = "not a GIMP brush"
Expand Down Expand Up @@ -90,6 +91,7 @@ def _open(self) -> None:

def load(self) -> Image.core.PixelAccess | None:
if self._im is None:
assert self.fp is not None
self.im = Image.core.new(self.mode, self.size)
self.frombytes(self.fp.read(self._data_size))
return Image.Image.load(self)
Expand Down
2 changes: 2 additions & 0 deletions src/PIL/GifImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class GifImageFile(ImageFile.ImageFile):
global_palette = None

def data(self) -> bytes | None:
assert self.fp is not None
s = self.fp.read(1)
if s and s[0]:
return self.fp.read(s[0])
Expand All @@ -96,6 +97,7 @@ def _is_palette_needed(self, p: bytes) -> bool:

def _open(self) -> None:
# Screen
assert self.fp is not None
s = self.fp.read(13)
if not _accept(s):
msg = "not a GIF file"
Expand Down
1 change: 1 addition & 0 deletions src/PIL/GribStubImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class GribStubImageFile(ImageFile.StubImageFile):
format_description = "GRIB"

def _open(self) -> None:
assert self.fp is not None
offset = self.fp.tell()

if not _accept(self.fp.read(8)):
Expand Down
1 change: 1 addition & 0 deletions src/PIL/Hdf5StubImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class HDF5StubImageFile(ImageFile.StubImageFile):
format_description = "HDF5"

def _open(self) -> None:
assert self.fp is not None
offset = self.fp.tell()

if not _accept(self.fp.read(8)):
Expand Down
1 change: 1 addition & 0 deletions src/PIL/IcnsImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ class IcnsImageFile(ImageFile.ImageFile):
format_description = "Mac OS icns resource"

def _open(self) -> None:
assert self.fp is not None
self.icns = IcnsFile(self.fp)
self._mode = "RGBA"
self.info["sizes"] = self.icns.itersizes()
Expand Down
1 change: 1 addition & 0 deletions src/PIL/IcoImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ class IcoImageFile(ImageFile.ImageFile):
format_description = "Windows Icon"

def _open(self) -> None:
assert self.fp is not None
self.ico = IcoFile(self.fp)
self.info["sizes"] = self.ico.sizes()
self.size = self.ico.entry[0].dim
Expand Down
1 change: 1 addition & 0 deletions src/PIL/ImImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ def _open(self) -> None:
# Quick rejection: if there's not an LF among the first
# 100 bytes, this is (probably) not a text header.

assert self.fp is not None
if b"\n" not in self.fp.read(100):
msg = "not an IM file"
raise SyntaxError(msg)
Expand Down
1 change: 1 addition & 0 deletions src/PIL/ImageFile.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ def load(self) -> Image.core.PixelAccess | None:
# As of pypy 2.1.0, memory mapping was failing here.
use_mmap = use_mmap and not hasattr(sys, "pypy_version_info")

assert self.fp is not None
readonly = 0

# look for read/seek overrides
Expand Down
3 changes: 3 additions & 0 deletions src/PIL/IptcImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ def getint(self, key: tuple[int, int]) -> int:
def field(self) -> tuple[tuple[int, int] | None, int]:
#
# get a IPTC field header
assert self.fp is not None
s = self.fp.read(5)
if not s.strip(b"\x00"):
return None, 0
Expand Down Expand Up @@ -104,6 +105,7 @@ def field(self) -> tuple[tuple[int, int] | None, int]:

def _open(self) -> None:
# load descriptive fields
assert self.fp is not None
while True:
offset = self.fp.tell()
tag, size = self.field()
Expand Down Expand Up @@ -157,6 +159,7 @@ def load(self) -> Image.core.PixelAccess | None:

offset, compression = self.tile[0][2:]

assert self.fp is not None
self.fp.seek(offset)

# Copy image data to temporary file
Expand Down
2 changes: 2 additions & 0 deletions src/PIL/Jpeg2KImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ class Jpeg2KImageFile(ImageFile.ImageFile):
format_description = "JPEG 2000 (ISO 15444)"

def _open(self) -> None:
assert self.fp is not None
sig = self.fp.read(4)
if sig == b"\xff\x4f\xff\x51":
self.codec = "j2k"
Expand Down Expand Up @@ -300,6 +301,7 @@ def _open(self) -> None:
]

def _parse_comment(self) -> None:
assert self.fp is not None
while True:
marker = self.fp.read(2)
if not marker:
Expand Down
Loading
Loading