Skip to content

Commit

Permalink
Added type hints
Browse files Browse the repository at this point in the history
  • Loading branch information
radarhere committed May 13, 2024
1 parent e39ee95 commit 652d883
Show file tree
Hide file tree
Showing 13 changed files with 52 additions and 44 deletions.
2 changes: 1 addition & 1 deletion src/PIL/FliImagePlugin.py
Expand Up @@ -132,7 +132,7 @@ def seek(self, frame: int) -> None:
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)
Expand Down
10 changes: 5 additions & 5 deletions src/PIL/GifImagePlugin.py
Expand Up @@ -82,7 +82,7 @@ def data(self) -> bytes | None:
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
Expand Down Expand Up @@ -474,7 +474,7 @@ def tell(self) -> int:
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.
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/PIL/GimpPaletteFile.py
Expand Up @@ -53,5 +53,5 @@ def __init__(self, fp):

self.palette = b"".join(self.palette)

def getpalette(self):
def getpalette(self) -> tuple[bytes, str]:
return self.palette, self.rawmode
4 changes: 2 additions & 2 deletions src/PIL/ImImagePlugin.py
Expand Up @@ -271,11 +271,11 @@ def _open(self) -> None:
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:
Expand Down
7 changes: 5 additions & 2 deletions src/PIL/ImageDraw.py
Expand Up @@ -34,7 +34,7 @@
import math
import numbers
import struct
from typing import Sequence, cast
from typing import Sequence, TYPE_CHECKING, cast

from . import Image, ImageColor
from ._typing import Coords
Expand Down Expand Up @@ -92,7 +92,10 @@ def __init__(self, im: Image.Image, mode: str | None = None) -> None:
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.
Expand Down
2 changes: 1 addition & 1 deletion src/PIL/ImageFilter.py
Expand Up @@ -544,7 +544,7 @@ def transform(self, callback, with_normals=False, channels=None, target_mode=Non
_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),
Expand Down
6 changes: 3 additions & 3 deletions src/PIL/ImagePalette.py
Expand Up @@ -66,7 +66,7 @@ def colors(self):
def colors(self, colors):
self._colors = colors

def copy(self):
def copy(self) -> ImagePalette:
new = ImagePalette()

new.mode = self.mode
Expand All @@ -77,7 +77,7 @@ def copy(self):

return new

def getdata(self):
def getdata(self) -> tuple[str, bytes]:
"""
Get palette contents in format suitable for the low-level
``im.putpalette`` primitive.
Expand All @@ -88,7 +88,7 @@ def getdata(self):
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.
Expand Down
12 changes: 6 additions & 6 deletions src/PIL/ImageTk.py
Expand Up @@ -136,7 +136,7 @@ def __del__(self) -> None:
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
Expand All @@ -146,15 +146,15 @@ def __str__(self):
"""
return str(self.__photo)

def width(self):
def width(self) -> int:
"""
Get the width of the image.
:return: The width, in pixels.
"""
return self.__size[0]

def height(self):
def height(self) -> int:
"""
Get the height of the image.
Expand Down Expand Up @@ -227,23 +227,23 @@ def __del__(self) -> None:
except Exception:
pass # ignore internal errors

def width(self):
def width(self) -> int:
"""
Get the width of the image.
:return: The width, in pixels.
"""
return self.__size[0]

def height(self):
def height(self) -> int:
"""
Get the height of the image.
:return: The height, in pixels.
"""
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
Expand Down
4 changes: 2 additions & 2 deletions src/PIL/Jpeg2KImagePlugin.py
Expand Up @@ -63,12 +63,12 @@ def read_fields(self, field_format):
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:
Expand Down
20 changes: 10 additions & 10 deletions src/PIL/PdfParser.py
Expand Up @@ -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):
Expand All @@ -108,7 +108,7 @@ def __hash__(self):


class IndirectObjectDef(IndirectReference):
def __str__(self):
def __str__(self) -> str:
return f"{self.object_id} {self.generation} obj"


Expand Down Expand Up @@ -150,7 +150,7 @@ def __delitem__(self, key):
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())
Expand Down Expand Up @@ -211,7 +211,7 @@ def __init__(self, name):
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):
Expand All @@ -222,7 +222,7 @@ def __eq__(self, other):
def __hash__(self):
return hash(self.name)

def __repr__(self):
def __repr__(self) -> str:
return f"{self.__class__.__name__}({repr(self.name)})"

@classmethod
Expand All @@ -231,7 +231,7 @@ def from_pdf_stream(cls, data):

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:
Expand All @@ -242,7 +242,7 @@ def __bytes__(self):


class PdfArray(List[Any]):
def __bytes__(self):
def __bytes__(self) -> bytes:
return b"[ " + b" ".join(pdf_repr(x) for x in self) + b" ]"


Expand Down Expand Up @@ -286,7 +286,7 @@ def __getattr__(self, key):
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:
Expand All @@ -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)


Expand Down
11 changes: 8 additions & 3 deletions src/PIL/SpiderImagePlugin.py
Expand Up @@ -40,6 +40,8 @@

from . import Image, ImageFile

from typing import TYPE_CHECKING


def isInt(f):
try:
Expand Down Expand Up @@ -157,11 +159,11 @@ def _open(self) -> None:
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)
Expand Down Expand Up @@ -191,8 +193,11 @@ def convert2byte(self, depth=255):
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)
Expand Down
14 changes: 7 additions & 7 deletions src/PIL/TiffImagePlugin.py
Expand Up @@ -381,7 +381,7 @@ def limit_rational(self, max_denominator):
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):
Expand Down Expand Up @@ -603,7 +603,7 @@ def reset(self):
self._next = None
self._offset = None

def __str__(self):
def __str__(self) -> str:
return str(dict(self))

def named(self):
Expand All @@ -617,7 +617,7 @@ def named(self):
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):
Expand Down Expand Up @@ -1041,7 +1041,7 @@ def from_v2(cls, original):
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
Expand All @@ -1061,7 +1061,7 @@ def to_v2(self):
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):
Expand Down Expand Up @@ -1154,7 +1154,7 @@ def seek(self, frame: int) -> None:
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
Expand Down Expand Up @@ -2003,7 +2003,7 @@ def __exit__(self, exc_type, exc_value, traceback):
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):
Expand Down
2 changes: 1 addition & 1 deletion src/PIL/WebPImagePlugin.py
Expand Up @@ -144,7 +144,7 @@ def _get_next(self):
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:
Expand Down

0 comments on commit 652d883

Please sign in to comment.