Added type hints

This commit is contained in:
Andrew Murray 2024-05-13 18:47:51 +10:00
parent e39ee95f56
commit a8d154877d
13 changed files with 51 additions and 44 deletions

View File

@ -132,7 +132,7 @@ class FliImageFile(ImageFile.ImageFile):
for f in range(self.__frame + 1, frame + 1):
self._seek(f)
def _seek(self, frame):
def _seek(self, frame: int) -> None:
if frame == 0:
self.__frame = -1
self._fp.seek(self.__rewind)

View File

@ -82,7 +82,7 @@ class GifImageFile(ImageFile.ImageFile):
return self.fp.read(s[0])
return None
def _is_palette_needed(self, p):
def _is_palette_needed(self, p: bytes) -> bool:
for i in range(0, len(p), 3):
if not (i // 3 == p[i] == p[i + 1] == p[i + 2]):
return True
@ -474,7 +474,7 @@ class GifImageFile(ImageFile.ImageFile):
RAWMODE = {"1": "L", "L": "L", "P": "P"}
def _normalize_mode(im):
def _normalize_mode(im: Image.Image) -> Image.Image:
"""
Takes an image (or frame), returns an image in a mode that is appropriate
for saving in a Gif.
@ -887,7 +887,7 @@ def _get_optimize(im, info):
return used_palette_colors
def _get_color_table_size(palette_bytes):
def _get_color_table_size(palette_bytes: bytes) -> int:
# calculate the palette size for the header
if not palette_bytes:
return 0
@ -897,7 +897,7 @@ def _get_color_table_size(palette_bytes):
return math.ceil(math.log(len(palette_bytes) // 3, 2)) - 1
def _get_header_palette(palette_bytes):
def _get_header_palette(palette_bytes: bytes) -> bytes:
"""
Returns the palette, null padded to the next power of 2 (*3) bytes
suitable for direct inclusion in the GIF header
@ -915,7 +915,7 @@ def _get_header_palette(palette_bytes):
return palette_bytes
def _get_palette_bytes(im):
def _get_palette_bytes(im: Image.Image) -> bytes:
"""
Gets the palette for inclusion in the gif header

View File

@ -53,5 +53,5 @@ class GimpPaletteFile:
self.palette = b"".join(self.palette)
def getpalette(self):
def getpalette(self) -> tuple[bytes, str]:
return self.palette, self.rawmode

View File

@ -271,11 +271,11 @@ class ImImageFile(ImageFile.ImageFile):
self.tile = [("raw", (0, 0) + self.size, offs, (self.rawmode, 0, -1))]
@property
def n_frames(self):
def n_frames(self) -> int:
return self.info[FRAMES]
@property
def is_animated(self):
def is_animated(self) -> bool:
return self.info[FRAMES] > 1
def seek(self, frame: int) -> None:

View File

@ -34,7 +34,7 @@ from __future__ import annotations
import math
import numbers
import struct
from typing import Sequence, cast
from typing import TYPE_CHECKING, Sequence, cast
from . import Image, ImageColor
from ._typing import Coords
@ -92,7 +92,10 @@ class ImageDraw:
self.fontmode = "L" # aliasing is okay for other modes
self.fill = False
def getfont(self):
if TYPE_CHECKING:
from . import ImageFont
def getfont(self) -> ImageFont.FreeTypeFont | ImageFont.ImageFont:
"""
Get the current default font.

View File

@ -544,7 +544,7 @@ class Color3DLUT(MultibandFilter):
_copy_table=False,
)
def __repr__(self):
def __repr__(self) -> str:
r = [
f"{self.__class__.__name__} from {self.table.__class__.__name__}",
"size={:d}x{:d}x{:d}".format(*self.size),

View File

@ -66,7 +66,7 @@ class ImagePalette:
def colors(self, colors):
self._colors = colors
def copy(self):
def copy(self) -> ImagePalette:
new = ImagePalette()
new.mode = self.mode
@ -77,7 +77,7 @@ class ImagePalette:
return new
def getdata(self):
def getdata(self) -> tuple[str, bytes]:
"""
Get palette contents in format suitable for the low-level
``im.putpalette`` primitive.
@ -88,7 +88,7 @@ class ImagePalette:
return self.rawmode, self.palette
return self.mode, self.tobytes()
def tobytes(self):
def tobytes(self) -> bytes:
"""Convert palette to bytes.
.. warning:: This method is experimental.

View File

@ -136,7 +136,7 @@ class PhotoImage:
except Exception:
pass # ignore internal errors
def __str__(self):
def __str__(self) -> str:
"""
Get the Tkinter photo image identifier. This method is automatically
called by Tkinter whenever a PhotoImage object is passed to a Tkinter
@ -146,7 +146,7 @@ class PhotoImage:
"""
return str(self.__photo)
def width(self):
def width(self) -> int:
"""
Get the width of the image.
@ -154,7 +154,7 @@ class PhotoImage:
"""
return self.__size[0]
def height(self):
def height(self) -> int:
"""
Get the height of the image.
@ -227,7 +227,7 @@ class BitmapImage:
except Exception:
pass # ignore internal errors
def width(self):
def width(self) -> int:
"""
Get the width of the image.
@ -235,7 +235,7 @@ class BitmapImage:
"""
return self.__size[0]
def height(self):
def height(self) -> int:
"""
Get the height of the image.
@ -243,7 +243,7 @@ class BitmapImage:
"""
return self.__size[1]
def __str__(self):
def __str__(self) -> str:
"""
Get the Tkinter bitmap image identifier. This method is automatically
called by Tkinter whenever a BitmapImage object is passed to a Tkinter

View File

@ -63,12 +63,12 @@ class BoxReader:
data = self._read_bytes(size)
return struct.unpack(field_format, data)
def read_boxes(self):
def read_boxes(self) -> BoxReader:
size = self.remaining_in_box
data = self._read_bytes(size)
return BoxReader(io.BytesIO(data), size)
def has_next_box(self):
def has_next_box(self) -> bool:
if self.has_length:
return self.fp.tell() + self.remaining_in_box < self.length
else:

View File

@ -87,10 +87,10 @@ class IndirectReferenceTuple(NamedTuple):
class IndirectReference(IndirectReferenceTuple):
def __str__(self):
def __str__(self) -> str:
return f"{self.object_id} {self.generation} R"
def __bytes__(self):
def __bytes__(self) -> bytes:
return self.__str__().encode("us-ascii")
def __eq__(self, other):
@ -108,7 +108,7 @@ class IndirectReference(IndirectReferenceTuple):
class IndirectObjectDef(IndirectReference):
def __str__(self):
def __str__(self) -> str:
return f"{self.object_id} {self.generation} obj"
@ -150,7 +150,7 @@ class XrefTable:
def __contains__(self, key):
return key in self.existing_entries or key in self.new_entries
def __len__(self):
def __len__(self) -> int:
return len(
set(self.existing_entries.keys())
| set(self.new_entries.keys())
@ -211,7 +211,7 @@ class PdfName:
else:
self.name = name.encode("us-ascii")
def name_as_str(self):
def name_as_str(self) -> str:
return self.name.decode("us-ascii")
def __eq__(self, other):
@ -222,7 +222,7 @@ class PdfName:
def __hash__(self):
return hash(self.name)
def __repr__(self):
def __repr__(self) -> str:
return f"{self.__class__.__name__}({repr(self.name)})"
@classmethod
@ -231,7 +231,7 @@ class PdfName:
allowed_chars = set(range(33, 127)) - {ord(c) for c in "#%/()<>[]{}"}
def __bytes__(self):
def __bytes__(self) -> bytes:
result = bytearray(b"/")
for b in self.name:
if b in self.allowed_chars:
@ -242,7 +242,7 @@ class PdfName:
class PdfArray(List[Any]):
def __bytes__(self):
def __bytes__(self) -> bytes:
return b"[ " + b" ".join(pdf_repr(x) for x in self) + b" ]"
@ -286,7 +286,7 @@ class PdfDict(_DictBase):
value = time.gmtime(calendar.timegm(value) + offset)
return value
def __bytes__(self):
def __bytes__(self) -> bytes:
out = bytearray(b"<<")
for key, value in self.items():
if value is None:
@ -304,7 +304,7 @@ class PdfBinary:
def __init__(self, data):
self.data = data
def __bytes__(self):
def __bytes__(self) -> bytes:
return b"<%s>" % b"".join(b"%02X" % b for b in self.data)

View File

@ -37,6 +37,7 @@ from __future__ import annotations
import os
import struct
import sys
from typing import TYPE_CHECKING
from . import Image, ImageFile
@ -157,11 +158,11 @@ class SpiderImageFile(ImageFile.ImageFile):
self._fp = self.fp # FIXME: hack
@property
def n_frames(self):
def n_frames(self) -> int:
return self._nimages
@property
def is_animated(self):
def is_animated(self) -> bool:
return self._nimages > 1
# 1st image index is zero (although SPIDER imgnumber starts at 1)
@ -191,8 +192,11 @@ class SpiderImageFile(ImageFile.ImageFile):
b = -m * minimum
return self.point(lambda i, m=m, b=b: i * m + b).convert("L")
if TYPE_CHECKING:
from . import ImageTk
# returns a ImageTk.PhotoImage object, after rescaling to 0..255
def tkPhotoImage(self):
def tkPhotoImage(self) -> ImageTk.PhotoImage:
from . import ImageTk
return ImageTk.PhotoImage(self.convert2byte(), palette=256)

View File

@ -381,7 +381,7 @@ class IFDRational(Rational):
f = self._val.limit_denominator(max_denominator)
return f.numerator, f.denominator
def __repr__(self):
def __repr__(self) -> str:
return str(float(self._val))
def __hash__(self):
@ -603,7 +603,7 @@ class ImageFileDirectory_v2(_IFDv2Base):
self._next = None
self._offset = None
def __str__(self):
def __str__(self) -> str:
return str(dict(self))
def named(self):
@ -617,7 +617,7 @@ class ImageFileDirectory_v2(_IFDv2Base):
for code, value in self.items()
}
def __len__(self):
def __len__(self) -> int:
return len(set(self._tagdata) | set(self._tags_v2))
def __getitem__(self, tag):
@ -1041,7 +1041,7 @@ class ImageFileDirectory_v1(ImageFileDirectory_v2):
ifd.next = original.next # an indicator for multipage tiffs
return ifd
def to_v2(self):
def to_v2(self) -> ImageFileDirectory_v2:
"""Returns an
:py:class:`~PIL.TiffImagePlugin.ImageFileDirectory_v2`
instance with the same data as is contained in the original
@ -1061,7 +1061,7 @@ class ImageFileDirectory_v1(ImageFileDirectory_v2):
def __contains__(self, tag):
return tag in self._tags_v1 or tag in self._tagdata
def __len__(self):
def __len__(self) -> int:
return len(set(self._tagdata) | set(self._tags_v1))
def __iter__(self):
@ -1154,7 +1154,7 @@ class TiffImageFile(ImageFile.ImageFile):
Image._decompression_bomb_check(self.size)
self.im = Image.core.new(self.mode, self.size)
def _seek(self, frame):
def _seek(self, frame: int) -> None:
self.fp = self._fp
# reset buffered io handle in case fp
@ -2003,7 +2003,7 @@ class AppendingTiffWriter:
self.close()
return False
def tell(self):
def tell(self) -> int:
return self.f.tell() - self.offsetOfNewPage
def seek(self, offset, whence=io.SEEK_SET):

View File

@ -144,7 +144,7 @@ class WebPImageFile(ImageFile.ImageFile):
timestamp -= duration
return data, timestamp, duration
def _seek(self, frame):
def _seek(self, frame: int) -> None:
if self.__physical_frame == frame:
return # Nothing to do
if frame < self.__physical_frame: