Skip to content

Commit

Permalink
Merge pull request #8125 from radarhere/type_hint
Browse files Browse the repository at this point in the history
Added type hints
  • Loading branch information
radarhere committed Jun 10, 2024
2 parents 444faa2 + 2d1fe75 commit 9a8759d
Show file tree
Hide file tree
Showing 30 changed files with 106 additions and 81 deletions.
15 changes: 10 additions & 5 deletions src/PIL/BlpImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

from __future__ import annotations

import abc
import os
import struct
from enum import IntEnum
Expand Down Expand Up @@ -276,7 +277,7 @@ def _open(self) -> None:
class _BLPBaseDecoder(ImageFile.PyDecoder):
_pulls_fd = True

def decode(self, buffer):
def decode(self, buffer: bytes) -> tuple[int, int]:
try:
self._read_blp_header()
self._load()
Expand All @@ -285,6 +286,10 @@ def decode(self, buffer):
raise OSError(msg) from e
return -1, 0

@abc.abstractmethod
def _load(self) -> None:
pass

def _read_blp_header(self) -> None:
assert self.fd is not None
self.fd.seek(4)
Expand Down Expand Up @@ -318,7 +323,7 @@ def _read_palette(self) -> list[tuple[int, int, int, int]]:
ret.append((b, g, r, a))
return ret

def _read_bgra(self, palette):
def _read_bgra(self, palette: list[tuple[int, int, int, int]]) -> bytearray:
data = bytearray()
_data = BytesIO(self._safe_read(self._blp_lengths[0]))
while True:
Expand All @@ -327,7 +332,7 @@ def _read_bgra(self, palette):
except struct.error:
break
b, g, r, a = palette[offset]
d = (r, g, b)
d: tuple[int, ...] = (r, g, b)
if self._blp_alpha_depth:
d += (a,)
data.extend(d)
Expand Down Expand Up @@ -431,7 +436,7 @@ def _write_palette(self) -> bytes:
data += b"\x00" * 4
return data

def encode(self, bufsize):
def encode(self, bufsize: int) -> tuple[int, int, bytes]:
palette_data = self._write_palette()

offset = 20 + 16 * 4 * 2 + len(palette_data)
Expand All @@ -449,7 +454,7 @@ def encode(self, bufsize):
return len(data), 0, data


def _save(im: Image.Image, fp: IO[bytes], filename: str) -> None:
def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
if im.mode != "P":
msg = "Unsupported BLP image mode"
raise ValueError(msg)
Expand Down
4 changes: 2 additions & 2 deletions src/PIL/BmpImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,12 +395,12 @@ def _open(self) -> None:
}


def _dib_save(im: Image.Image, fp: IO[bytes], filename: str) -> None:
def _dib_save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
_save(im, fp, filename, False)


def _save(
im: Image.Image, fp: IO[bytes], filename: str, bitmap_header: bool = True
im: Image.Image, fp: IO[bytes], filename: str | bytes, bitmap_header: bool = True
) -> None:
try:
rawmode, bits, colors = SAVE[im.mode]
Expand Down
2 changes: 1 addition & 1 deletion src/PIL/BufrStubImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def _load(self) -> ImageFile.StubHandler | None:
return _handler


def _save(im: Image.Image, fp: IO[bytes], filename: str) -> None:
def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
if _handler is None or not hasattr(_handler, "save"):
msg = "BUFR save handler not installed"
raise OSError(msg)
Expand Down
2 changes: 1 addition & 1 deletion src/PIL/DdsImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ def decode(self, buffer):
return -1, 0


def _save(im: Image.Image, fp: IO[bytes], filename: str) -> None:
def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
if im.mode not in ("RGB", "RGBA", "L", "LA"):
msg = f"cannot write mode {im.mode} as DDS"
raise OSError(msg)
Expand Down
6 changes: 3 additions & 3 deletions src/PIL/GifImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -715,12 +715,12 @@ def _write_multiple_frames(im, fp, palette):
return True


def _save_all(im: Image.Image, fp: IO[bytes], filename: str) -> None:
def _save_all(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
_save(im, fp, filename, save_all=True)


def _save(
im: Image.Image, fp: IO[bytes], filename: str, save_all: bool = False
im: Image.Image, fp: IO[bytes], filename: str | bytes, save_all: bool = False
) -> None:
# header
if "palette" in im.encoderinfo or "palette" in im.info:
Expand Down Expand Up @@ -796,7 +796,7 @@ def _write_local_header(fp, im, offset, flags):
fp.write(o8(8)) # bits


def _save_netpbm(im: Image.Image, fp: IO[bytes], filename: str) -> None:
def _save_netpbm(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
# Unused by default.
# To use, uncomment the register_save call at the end of the file.
#
Expand Down
2 changes: 1 addition & 1 deletion src/PIL/GribStubImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def _load(self) -> ImageFile.StubHandler | None:
return _handler


def _save(im: Image.Image, fp: IO[bytes], filename: str) -> None:
def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
if _handler is None or not hasattr(_handler, "save"):
msg = "GRIB save handler not installed"
raise OSError(msg)
Expand Down
2 changes: 1 addition & 1 deletion src/PIL/Hdf5StubImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def _load(self) -> ImageFile.StubHandler | None:
return _handler


def _save(im: Image.Image, fp: IO[bytes], filename: str) -> None:
def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
if _handler is None or not hasattr(_handler, "save"):
msg = "HDF5 save handler not installed"
raise OSError(msg)
Expand Down
19 changes: 9 additions & 10 deletions src/PIL/IcnsImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import os
import struct
import sys
from typing import IO

from . import Image, ImageFile, PngImagePlugin, features

Expand Down Expand Up @@ -312,7 +313,7 @@ def load(self):
return px


def _save(im, fp, filename):
def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
"""
Saves the image as a series of PNG files,
that are then combined into a .icns file.
Expand Down Expand Up @@ -346,29 +347,27 @@ def _save(im, fp, filename):
entries = []
for type, size in sizes.items():
stream = size_streams[size]
entries.append(
{"type": type, "size": HEADERSIZE + len(stream), "stream": stream}
)
entries.append((type, HEADERSIZE + len(stream), stream))

# Header
fp.write(MAGIC)
file_length = HEADERSIZE # Header
file_length += HEADERSIZE + 8 * len(entries) # TOC
file_length += sum(entry["size"] for entry in entries)
file_length += sum(entry[1] for entry in entries)
fp.write(struct.pack(">i", file_length))

# TOC
fp.write(b"TOC ")
fp.write(struct.pack(">i", HEADERSIZE + len(entries) * HEADERSIZE))
for entry in entries:
fp.write(entry["type"])
fp.write(struct.pack(">i", entry["size"]))
fp.write(entry[0])
fp.write(struct.pack(">i", entry[1]))

# Data
for entry in entries:
fp.write(entry["type"])
fp.write(struct.pack(">i", entry["size"]))
fp.write(entry["stream"])
fp.write(entry[0])
fp.write(struct.pack(">i", entry[1]))
fp.write(entry[2])

if hasattr(fp, "flush"):
fp.flush()
Expand Down
2 changes: 1 addition & 1 deletion src/PIL/IcoImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
_MAGIC = b"\0\0\1\0"


def _save(im: Image.Image, fp: IO[bytes], filename: str) -> None:
def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
fp.write(_MAGIC) # (2+2)
bmp = im.encoderinfo.get("bitmap_format") == "bmp"
sizes = im.encoderinfo.get(
Expand Down
4 changes: 3 additions & 1 deletion src/PIL/ImImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ def tell(self) -> int:
}


def _save(im: Image.Image, fp: IO[bytes], filename: str) -> None:
def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
try:
image_type, rawmode = SAVE[im.mode]
except KeyError as e:
Expand All @@ -341,6 +341,8 @@ def _save(im: Image.Image, fp: IO[bytes], filename: str) -> None:
# or: SyntaxError("not an IM file")
# 8 characters are used for "Name: " and "\r\n"
# Keep just the filename, ditch the potentially overlong path
if isinstance(filename, bytes):
filename = filename.decode("ascii")
name, ext = os.path.splitext(os.path.basename(filename))
name = "".join([name[: 92 - len(ext)], ext])

Expand Down
26 changes: 17 additions & 9 deletions src/PIL/Image.py
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,7 @@ def _ensure_mutable(self) -> None:
self.load()

def _dump(
self, file: str | None = None, format: str | None = None, **options
self, file: str | None = None, format: str | None = None, **options: Any
) -> str:
suffix = ""
if format:
Expand All @@ -649,10 +649,12 @@ def _dump(

return filename

def __eq__(self, other):
def __eq__(self, other: object) -> bool:
if self.__class__ is not other.__class__:
return False
assert isinstance(other, Image)
return (
self.__class__ is other.__class__
and self.mode == other.mode
self.mode == other.mode
and self.size == other.size
and self.info == other.info
and self.getpalette() == other.getpalette()
Expand Down Expand Up @@ -2965,7 +2967,7 @@ def transform(
# Debugging


def _wedge():
def _wedge() -> Image:
"""Create grayscale wedge (for debugging only)"""

return Image()._new(core.wedge("L"))
Expand Down Expand Up @@ -3566,7 +3568,9 @@ def register_mime(id: str, mimetype: str) -> None:
MIME[id.upper()] = mimetype


def register_save(id: str, driver) -> None:
def register_save(
id: str, driver: Callable[[Image, IO[bytes], str | bytes], None]
) -> None:
"""
Registers an image save function. This function should not be
used in application code.
Expand All @@ -3577,7 +3581,9 @@ def register_save(id: str, driver) -> None:
SAVE[id.upper()] = driver


def register_save_all(id: str, driver) -> None:
def register_save_all(
id: str, driver: Callable[[Image, IO[bytes], str | bytes], None]
) -> None:
"""
Registers an image function to save all the frames
of a multiframe format. This function should not be
Expand Down Expand Up @@ -3651,7 +3657,7 @@ def register_encoder(name: str, encoder: type[ImageFile.PyEncoder]) -> None:
# Simple display support.


def _show(image, **options) -> None:
def _show(image: Image, **options: Any) -> None:
from . import ImageShow

ImageShow.show(image, **options)
Expand All @@ -3661,7 +3667,9 @@ def _show(image, **options) -> None:
# Effects


def effect_mandelbrot(size, extent, quality):
def effect_mandelbrot(
size: tuple[int, int], extent: tuple[int, int, int, int], quality: int
) -> Image:
"""
Generate a Mandelbrot set covering the given extent.
Expand Down
16 changes: 10 additions & 6 deletions src/PIL/ImageDraw.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,9 @@ def line(self, xy: Coords, fill=None, width=0, joint=None) -> None:
# This is a straight line, so no joint is required
continue

def coord_at_angle(coord, angle):
def coord_at_angle(
coord: Sequence[float], angle: float
) -> tuple[float, float]:
x, y = coord
angle -= 90
distance = width / 2 - 1
Expand Down Expand Up @@ -1109,11 +1111,13 @@ def _get_angles(n_sides: int, rotation: float) -> list[float]:
return [_compute_polygon_vertex(angle) for angle in angles]


def _color_diff(color1, color2: float | tuple[int, ...]) -> float:
def _color_diff(
color1: float | tuple[int, ...], color2: float | tuple[int, ...]
) -> float:
"""
Uses 1-norm distance to calculate difference between two values.
"""
if isinstance(color2, tuple):
return sum(abs(color1[i] - color2[i]) for i in range(0, len(color2)))
else:
return abs(color1 - color2)
first = color1 if isinstance(color1, tuple) else (color1,)
second = color2 if isinstance(color2, tuple) else (color2,)

return sum(abs(first[i] - second[i]) for i in range(0, len(second)))
2 changes: 1 addition & 1 deletion src/PIL/ImageFile.py
Original file line number Diff line number Diff line change
Expand Up @@ -763,7 +763,7 @@ class PyEncoder(PyCodec):
def pushes_fd(self):
return self._pushes_fd

def encode(self, bufsize):
def encode(self, bufsize: int) -> tuple[int, int, bytes]:
"""
Override to perform the encoding process.
Expand Down
6 changes: 4 additions & 2 deletions src/PIL/Jpeg2KImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,11 +329,13 @@ def _accept(prefix: bytes) -> bool:
# Save support


def _save(im: Image.Image, fp: IO[bytes], filename: str) -> None:
def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
# Get the keyword arguments
info = im.encoderinfo

if filename.endswith(".j2k") or info.get("no_jp2", False):
if isinstance(filename, str):
filename = filename.encode()
if filename.endswith(b".j2k") or info.get("no_jp2", False):
kind = "j2k"
else:
kind = "jp2"
Expand Down
6 changes: 3 additions & 3 deletions src/PIL/JpegImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
import sys
import tempfile
import warnings
from typing import Any
from typing import IO, Any

from . import Image, ImageFile
from ._binary import i16be as i16
Expand Down Expand Up @@ -644,7 +644,7 @@ def get_sampling(im):
return samplings.get(sampling, -1)


def _save(im, fp, filename):
def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
if im.width == 0 or im.height == 0:
msg = "cannot write empty image as JPEG"
raise ValueError(msg)
Expand Down Expand Up @@ -827,7 +827,7 @@ def validate_qtables(qtables):
ImageFile._save(im, fp, [("jpeg", (0, 0) + im.size, 0, rawmode)], bufsize)


def _save_cjpeg(im, fp, filename):
def _save_cjpeg(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
# ALTERNATIVE: handle JPEGs via the IJG command line utilities.
tempfile = im._dump()
subprocess.check_call(["cjpeg", "-outfile", filename, tempfile])
Expand Down
2 changes: 1 addition & 1 deletion src/PIL/MpoImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from ._binary import o32le


def _save(im: Image.Image, fp: IO[bytes], filename: str) -> None:
def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
JpegImagePlugin._save(im, fp, filename)


Expand Down
2 changes: 1 addition & 1 deletion src/PIL/MspImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ def decode(self, buffer: bytes) -> tuple[int, int]:
# write MSP files (uncompressed only)


def _save(im: Image.Image, fp: IO[bytes], filename: str) -> None:
def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
if im.mode != "1":
msg = f"cannot write mode {im.mode} as MSP"
raise OSError(msg)
Expand Down
Loading

0 comments on commit 9a8759d

Please sign in to comment.