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

Added type hints #8167

Merged
merged 1 commit into from
Jun 25, 2024
Merged
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_spider.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ def test_load_image_series() -> None:
img_list = SpiderImagePlugin.loadImageSeries(file_list)

# Assert
assert img_list is not None
assert len(img_list) == 1
assert isinstance(img_list[0], Image.Image)
assert img_list[0].size == (128, 128)
Expand Down
4 changes: 2 additions & 2 deletions Tests/test_imagefile.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ def __init__(self, mode: str, *args: Any) -> None:

super().__init__(mode, *args)

def decode(self, buffer):
def decode(self, buffer: bytes) -> tuple[int, int]:
# eof
return -1, 0

Expand All @@ -222,7 +222,7 @@ def __init__(self, mode: str, *args: Any) -> None:

super().__init__(mode, *args)

def encode(self, buffer):
def encode(self, bufsize: int) -> tuple[int, int, bytes]:
return 1, 1, b""

def cleanup(self) -> None:
Expand Down
2 changes: 1 addition & 1 deletion Tests/test_imageops_usm.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def test_blur_accuracy(test_images: dict[str, ImageFile.ImageFile]) -> None:
assert i.im.getpixel((x, y))[c] >= 250
# Fuzzy match.

def gp(x, y):
def gp(x: int, y: int) -> tuple[int, ...]:
return i.im.getpixel((x, y))

assert 236 <= gp(7, 4)[0] <= 239
Expand Down
8 changes: 4 additions & 4 deletions Tests/test_imagepalette.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,13 @@ def test_file(tmp_path: Path) -> None:

palette.save(f)

p = ImagePalette.load(f)
lut = ImagePalette.load(f)

# load returns raw palette information
assert len(p[0]) == 768
assert p[1] == "RGB"
assert len(lut[0]) == 768
assert lut[1] == "RGB"

p = ImagePalette.raw(p[1], p[0])
p = ImagePalette.raw(lut[1], lut[0])
assert isinstance(p, ImagePalette.ImagePalette)
assert p.palette == palette.tobytes()

Expand Down
2 changes: 2 additions & 0 deletions src/PIL/BlpImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,7 @@

def _write_palette(self) -> bytes:
data = b""
assert self.im is not None

Check warning on line 433 in src/PIL/BlpImagePlugin.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/BlpImagePlugin.py#L433

Added line #L433 was not covered by tests
palette = self.im.getpalette("RGBA", "RGBA")
for i in range(len(palette) // 4):
r, g, b, a = palette[i * 4 : (i + 1) * 4]
Expand All @@ -444,6 +445,7 @@
offset = 20 + 16 * 4 * 2 + len(palette_data)
data = struct.pack("<16I", offset, *((0,) * 15))

assert self.im is not None

Check warning on line 448 in src/PIL/BlpImagePlugin.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/BlpImagePlugin.py#L448

Added line #L448 was not covered by tests
w, h = self.im.size
data += struct.pack("<16I", w * h, *((0,) * 15))

Expand Down
7 changes: 6 additions & 1 deletion src/PIL/ImageDraw2.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@
"""
from __future__ import annotations

from typing import BinaryIO

Check warning on line 27 in src/PIL/ImageDraw2.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageDraw2.py#L27

Added line #L27 was not covered by tests

from . import Image, ImageColor, ImageDraw, ImageFont, ImagePath
from ._typing import StrOrBytesPath

Check warning on line 30 in src/PIL/ImageDraw2.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageDraw2.py#L30

Added line #L30 was not covered by tests


class Pen:
Expand All @@ -45,7 +48,9 @@
class Font:
"""Stores a TrueType font and color"""

def __init__(self, color, file, size=12):
def __init__(

Check warning on line 51 in src/PIL/ImageDraw2.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageDraw2.py#L51

Added line #L51 was not covered by tests
self, color: str, file: StrOrBytesPath | BinaryIO, size: float = 12
) -> None:
# FIXME: add support for bitmap fonts
self.color = ImageColor.getrgb(color)
self.font = ImageFont.truetype(file, size)
Expand Down
25 changes: 14 additions & 11 deletions src/PIL/ImageFile.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
# Helpers


def _get_oserror(error, *, encoder):
def _get_oserror(error: int, *, encoder: bool) -> OSError:

Check warning on line 68 in src/PIL/ImageFile.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageFile.py#L68

Added line #L68 was not covered by tests
try:
msg = Image.core.getcodecstatus(error)
except AttributeError:
Expand All @@ -76,7 +76,7 @@
return OSError(msg)


def raise_oserror(error):
def raise_oserror(error: int) -> OSError:

Check warning on line 79 in src/PIL/ImageFile.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageFile.py#L79

Added line #L79 was not covered by tests
deprecate(
"raise_oserror",
12,
Expand Down Expand Up @@ -154,11 +154,12 @@
self.fp.close()
raise

def get_format_mimetype(self):
def get_format_mimetype(self) -> str | None:

Check warning on line 157 in src/PIL/ImageFile.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageFile.py#L157

Added line #L157 was not covered by tests
if self.custom_mimetype:
return self.custom_mimetype
if self.format is not None:
return Image.MIME.get(self.format.upper())
return None

Check warning on line 162 in src/PIL/ImageFile.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageFile.py#L162

Added line #L162 was not covered by tests

def __setstate__(self, state):
self.tile = []
Expand Down Expand Up @@ -365,7 +366,7 @@
certain format, but relies on external code to load the file.
"""

def _open(self):
def _open(self) -> None:

Check warning on line 369 in src/PIL/ImageFile.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageFile.py#L369

Added line #L369 was not covered by tests
msg = "StubImageFile subclass must implement _open"
raise NotImplementedError(msg)

Expand All @@ -381,7 +382,7 @@
self.__dict__ = image.__dict__
return image.load()

def _load(self):
def _load(self) -> StubHandler | None:

Check warning on line 385 in src/PIL/ImageFile.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageFile.py#L385

Added line #L385 was not covered by tests
"""(Hook) Find actual image loader."""
msg = "StubImageFile subclass must implement _load"
raise NotImplementedError(msg)
Expand Down Expand Up @@ -621,7 +622,7 @@
self.xoff = 0
self.yoff = 0

def extents(self):
def extents(self) -> tuple[int, int, int, int]:

Check warning on line 625 in src/PIL/ImageFile.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageFile.py#L625

Added line #L625 was not covered by tests
return self.xoff, self.yoff, self.xoff + self.xsize, self.yoff + self.ysize


Expand Down Expand Up @@ -661,7 +662,7 @@
"""
self.fd = fd

def setimage(self, im, extents=None):
def setimage(self, im, extents: tuple[int, int, int, int] | None = None) -> None:

Check warning on line 665 in src/PIL/ImageFile.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageFile.py#L665

Added line #L665 was not covered by tests
"""
Called from ImageFile to set the core output image for the codec

Expand Down Expand Up @@ -710,10 +711,10 @@
_pulls_fd = False

@property
def pulls_fd(self):
def pulls_fd(self) -> bool:

Check warning on line 714 in src/PIL/ImageFile.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageFile.py#L714

Added line #L714 was not covered by tests
return self._pulls_fd

def decode(self, buffer):
def decode(self, buffer: bytes) -> tuple[int, int]:

Check warning on line 717 in src/PIL/ImageFile.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageFile.py#L717

Added line #L717 was not covered by tests
"""
Override to perform the decoding process.

Expand All @@ -738,6 +739,7 @@
if not rawmode:
rawmode = self.mode
d = Image._getdecoder(self.mode, "raw", rawmode)
assert self.im is not None

Check warning on line 742 in src/PIL/ImageFile.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageFile.py#L742

Added line #L742 was not covered by tests
d.setimage(self.im, self.state.extents())
s = d.decode(data)

Expand All @@ -760,7 +762,7 @@
_pushes_fd = False

@property
def pushes_fd(self):
def pushes_fd(self) -> bool:

Check warning on line 765 in src/PIL/ImageFile.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageFile.py#L765

Added line #L765 was not covered by tests
return self._pushes_fd

def encode(self, bufsize: int) -> tuple[int, int, bytes]:
Expand All @@ -775,7 +777,7 @@
msg = "unavailable in base encoder"
raise NotImplementedError(msg)

def encode_to_pyfd(self):
def encode_to_pyfd(self) -> tuple[int, int]:

Check warning on line 780 in src/PIL/ImageFile.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageFile.py#L780

Added line #L780 was not covered by tests
"""
If ``pushes_fd`` is ``True``, then this method will be used,
and ``encode()`` will only be called once.
Expand All @@ -787,6 +789,7 @@
return 0, -8 # bad configuration
bytes_consumed, errcode, data = self.encode(0)
if data:
assert self.fd is not None

Check warning on line 792 in src/PIL/ImageFile.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageFile.py#L792

Added line #L792 was not covered by tests
self.fd.write(data)
return bytes_consumed, errcode

Expand Down
48 changes: 29 additions & 19 deletions src/PIL/ImagePalette.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,23 +38,27 @@
Defaults to an empty palette.
"""

def __init__(self, mode: str = "RGB", palette: Sequence[int] | None = None) -> None:
def __init__(

Check warning on line 41 in src/PIL/ImagePalette.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImagePalette.py#L41

Added line #L41 was not covered by tests
self,
mode: str = "RGB",
palette: Sequence[int] | bytes | bytearray | None = None,
) -> None:
self.mode = mode
self.rawmode = None # if set, palette contains raw data
self.rawmode: str | None = None # if set, palette contains raw data

Check warning on line 47 in src/PIL/ImagePalette.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImagePalette.py#L47

Added line #L47 was not covered by tests
self.palette = palette or bytearray()
self.dirty: int | None = None

@property
def palette(self):
def palette(self) -> Sequence[int] | bytes | bytearray:

Check warning on line 52 in src/PIL/ImagePalette.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImagePalette.py#L52

Added line #L52 was not covered by tests
return self._palette

@palette.setter
def palette(self, palette):
self._colors = None
def palette(self, palette: Sequence[int] | bytes | bytearray) -> None:
self._colors: dict[tuple[int, ...], int] | None = None

Check warning on line 57 in src/PIL/ImagePalette.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImagePalette.py#L56-L57

Added lines #L56 - L57 were not covered by tests
self._palette = palette

@property
def colors(self) -> dict[tuple[int, int, int] | tuple[int, int, int, int], int]:
def colors(self) -> dict[tuple[int, ...], int]:

Check warning on line 61 in src/PIL/ImagePalette.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImagePalette.py#L61

Added line #L61 was not covered by tests
if self._colors is None:
mode_len = len(self.mode)
self._colors = {}
Expand All @@ -66,9 +70,7 @@
return self._colors

@colors.setter
def colors(
self, colors: dict[tuple[int, int, int] | tuple[int, int, int, int], int]
) -> None:
def colors(self, colors: dict[tuple[int, ...], int]) -> None:

Check warning on line 73 in src/PIL/ImagePalette.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImagePalette.py#L73

Added line #L73 was not covered by tests
self._colors = colors

def copy(self) -> ImagePalette:
Expand All @@ -82,7 +84,7 @@

return new

def getdata(self) -> tuple[str, bytes]:
def getdata(self) -> tuple[str, Sequence[int] | bytes | bytearray]:

Check warning on line 87 in src/PIL/ImagePalette.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImagePalette.py#L87

Added line #L87 was not covered by tests
"""
Get palette contents in format suitable for the low-level
``im.putpalette`` primitive.
Expand Down Expand Up @@ -137,7 +139,7 @@

def getcolor(
self,
color: tuple[int, int, int] | tuple[int, int, int, int],
color: tuple[int, ...],
image: Image.Image | None = None,
) -> int:
"""Given an rgb tuple, allocate palette entry.
Expand All @@ -162,12 +164,13 @@
except KeyError as e:
# allocate new color slot
index = self._new_color_index(image, e)
assert isinstance(self._palette, bytearray)

Check warning on line 167 in src/PIL/ImagePalette.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImagePalette.py#L167

Added line #L167 was not covered by tests
self.colors[color] = index
if index * 3 < len(self.palette):
self._palette = (
self.palette[: index * 3]
self._palette[: index * 3]
+ bytes(color)
+ self.palette[index * 3 + 3 :]
+ self._palette[index * 3 + 3 :]
)
else:
self._palette += bytes(color)
Expand Down Expand Up @@ -204,7 +207,7 @@
# Internal


def raw(rawmode, data) -> ImagePalette:
def raw(rawmode, data: Sequence[int] | bytes | bytearray) -> ImagePalette:

Check warning on line 210 in src/PIL/ImagePalette.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImagePalette.py#L210

Added line #L210 was not covered by tests
palette = ImagePalette()
palette.rawmode = rawmode
palette.palette = data
Expand All @@ -216,9 +219,9 @@
# Factories


def make_linear_lut(black, white):
def make_linear_lut(black: int, white: float) -> list[int]:

Check warning on line 222 in src/PIL/ImagePalette.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImagePalette.py#L222

Added line #L222 was not covered by tests
if black == 0:
return [white * i // 255 for i in range(256)]
return [int(white * i // 255) for i in range(256)]

Check warning on line 224 in src/PIL/ImagePalette.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImagePalette.py#L224

Added line #L224 was not covered by tests

msg = "unavailable when black is non-zero"
raise NotImplementedError(msg) # FIXME
Expand Down Expand Up @@ -251,15 +254,22 @@
return ImagePalette(mode, [i // len(mode) for i in palette])


def load(filename):
def load(filename: str) -> tuple[bytes, str]:

Check warning on line 257 in src/PIL/ImagePalette.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImagePalette.py#L257

Added line #L257 was not covered by tests
# FIXME: supports GIMP gradients only

with open(filename, "rb") as fp:
for paletteHandler in [
paletteHandlers: list[

Check warning on line 261 in src/PIL/ImagePalette.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImagePalette.py#L261

Added line #L261 was not covered by tests
type[
GimpPaletteFile.GimpPaletteFile
| GimpGradientFile.GimpGradientFile
| PaletteFile.PaletteFile
]
] = [
GimpPaletteFile.GimpPaletteFile,
GimpGradientFile.GimpGradientFile,
PaletteFile.PaletteFile,
]:
]
for paletteHandler in paletteHandlers:

Check warning on line 272 in src/PIL/ImagePalette.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImagePalette.py#L272

Added line #L272 was not covered by tests
try:
fp.seek(0)
lut = paletteHandler(fp).getpalette()
Expand Down
13 changes: 8 additions & 5 deletions src/PIL/ImageWin.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,19 +69,22 @@
defines the size of the image.
"""

def __init__(self, image, size=None):
if hasattr(image, "mode") and hasattr(image, "size"):
def __init__(

Check warning on line 72 in src/PIL/ImageWin.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageWin.py#L72

Added line #L72 was not covered by tests
self, image: Image.Image | str, size: tuple[int, int] | list[int] | None = None
) -> None:
if isinstance(image, str):
mode = image
image = ""

Check warning on line 77 in src/PIL/ImageWin.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageWin.py#L75-L77

Added lines #L75 - L77 were not covered by tests
else:
mode = image.mode
size = image.size
else:
mode = image
image = None
if mode not in ["1", "L", "P", "RGB"]:
mode = Image.getmodebase(mode)
self.image = Image.core.display(mode, size)
self.mode = mode
self.size = size
if image:
assert not isinstance(image, str)

Check warning on line 87 in src/PIL/ImageWin.py

View check run for this annotation

Codecov / codecov/patch

src/PIL/ImageWin.py#L87

Added line #L87 was not covered by tests
self.paste(image)

def expose(self, handle):
Expand Down
Loading
Loading