Skip to content

Commit

Permalink
Updated type hints
Browse files Browse the repository at this point in the history
  • Loading branch information
radarhere committed May 26, 2024
1 parent c0ee645 commit 641dad2
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 62 deletions.
22 changes: 9 additions & 13 deletions src/PIL/Image.py
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ def _getscaleoffset(expr):
class SupportsGetData(Protocol):
def getdata(
self,
) -> tuple[Transform, Sequence[Any]]: ...
) -> tuple[Transform, Sequence[int]]: ...


class Image:
Expand Down Expand Up @@ -1295,7 +1295,7 @@ def _crop(self, im, box):
return im.crop((x0, y0, x1, y1))

def draft(
self, mode: str, size: tuple[int, int]
self, mode: str | None, size: tuple[int, int]
) -> tuple[str, tuple[int, int, float, float]] | None:
"""
Configures the image file loader so it returns a version of the
Expand Down Expand Up @@ -1719,7 +1719,7 @@ def entropy(self, mask=None, extrema=None):

def paste(
self,
im: Image | str | int | tuple[int, ...],
im: Image | str | float | tuple[int, ...],
box: tuple[int, int, int, int] | tuple[int, int] | None = None,
mask: Image | None = None,
) -> None:
Expand Down Expand Up @@ -1750,7 +1750,7 @@ def paste(
See :py:meth:`~PIL.Image.Image.alpha_composite` if you want to
combine images with respect to their alpha channels.
:param im: Source image or pixel value (integer or tuple).
:param im: Source image or pixel value (integer, float or tuple).
:param box: An optional 4-tuple giving the region to paste into.
If a 2-tuple is used instead, it's treated as the upper left
corner. If omitted or None, the source is pasted into the
Expand Down Expand Up @@ -2228,13 +2228,9 @@ def resize(
msg = "reducing_gap must be 1.0 or greater"
raise ValueError(msg)

size = cast("tuple[int, int]", tuple(size))

self.load()
if box is None:
box = (0, 0) + self.size
else:
box = cast("tuple[float, float, float, float]", tuple(box))

if self.size == size and box == (0, 0) + self.size:
return self.copy()
Expand Down Expand Up @@ -2291,8 +2287,6 @@ def reduce(

if box is None:
box = (0, 0) + self.size
else:
box = cast("tuple[int, int, int, int]", tuple(box))

if factor == (1, 1) and box == (0, 0) + self.size:
return self.copy()
Expand Down Expand Up @@ -2692,7 +2686,9 @@ def round_aspect(number, key):
return
size = preserved_size

res = self.draft(None, (size[0] * reducing_gap, size[1] * reducing_gap)) # type: ignore[arg-type]
res = self.draft(
None, (int(size[0] * reducing_gap), int(size[1] * reducing_gap))
)
if res is not None:
box = res[1]
if box is None:
Expand Down Expand Up @@ -2799,7 +2795,7 @@ def getdata(self):
im.info = self.info.copy()
if method == Transform.MESH:
# list of quads
for box, quad in cast("Sequence[tuple[float, float]]", data):
for box, quad in data:
im.__transformer(
box, self, Transform.QUAD, quad, resample, fillcolor is None
)
Expand Down Expand Up @@ -2957,7 +2953,7 @@ def transform(
self,
size: tuple[int, int],
image: Image,
**options: dict[str, str | int | tuple[int, ...] | list[int]] | int,
**options: str | int | tuple[int, ...] | list[int],
) -> Image:
pass

Expand Down
29 changes: 21 additions & 8 deletions src/PIL/ImageDraw.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,14 +456,12 @@ def draw_corners(pieslice) -> None:
self.draw.draw_rectangle(right, ink, 1)

def _multiline_check(self, text: AnyStr) -> bool:
split_character = cast(AnyStr, "\n" if isinstance(text, str) else b"\n")
split_character = "\n" if isinstance(text, str) else b"\n"

return split_character in text

def _multiline_split(self, text: AnyStr) -> list[AnyStr]:
split_character = cast(AnyStr, "\n" if isinstance(text, str) else b"\n")

return text.split(split_character)
return text.split("\n" if isinstance(text, str) else b"\n")

def _multiline_spacing(self, font, spacing, stroke_width):
return (
Expand All @@ -477,7 +475,12 @@ def text(
xy: tuple[float, float],
text: str,
fill=None,
font: ImageFont.FreeTypeFont | ImageFont.ImageFont | None = None,
font: (
ImageFont.ImageFont
| ImageFont.FreeTypeFont
| ImageFont.TransposedFont
| None
) = None,
anchor=None,
spacing=4,
align="left",
Expand Down Expand Up @@ -597,9 +600,14 @@ def draw_text(ink, stroke_width=0, stroke_offset=None) -> None:
def multiline_text(
self,
xy: tuple[float, float],
text,
text: str,
fill=None,
font=None,
font: (
ImageFont.ImageFont
| ImageFont.FreeTypeFont
| ImageFont.TransposedFont
| None
) = None,
anchor=None,
spacing=4,
align="left",
Expand Down Expand Up @@ -684,7 +692,12 @@ def multiline_text(
def textlength(
self,
text: str,
font: ImageFont.FreeTypeFont | ImageFont.ImageFont | None = None,
font: (
ImageFont.ImageFont
| ImageFont.FreeTypeFont
| ImageFont.TransposedFont
| None
) = None,
direction=None,
features=None,
language=None,
Expand Down
53 changes: 27 additions & 26 deletions src/PIL/ImageFont.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@
import warnings
from enum import IntEnum
from io import BytesIO
from typing import TYPE_CHECKING, BinaryIO
from typing import IO, TYPE_CHECKING, Any, BinaryIO

from . import Image
from ._typing import StrOrBytesPath
from ._util import is_directory, is_path
from ._util import is_path

if TYPE_CHECKING:
from . import ImageFile
Expand All @@ -61,7 +61,7 @@ class Layout(IntEnum):
core = DeferredError.new(ex)


def _string_length_check(text: str) -> None:
def _string_length_check(text: str | bytes | bytearray) -> None:
if MAX_STRING_LENGTH is not None and len(text) > MAX_STRING_LENGTH:
msg = "too many characters in string"
raise ValueError(msg)
Expand Down Expand Up @@ -113,7 +113,7 @@ def _load_pilfont(self, filename: str) -> None:
self._load_pilfont_data(fp, image)
image.close()

def _load_pilfont_data(self, file, image):
def _load_pilfont_data(self, file: IO[bytes], image: Image.Image) -> None:
# read PILfont header
if file.readline() != b"PILfont\n":
msg = "Not a PILfont file"
Expand Down Expand Up @@ -161,7 +161,7 @@ def getmask(self, text, mode="", *args, **kwargs):
return self.font.getmask(text, mode)

def getbbox(
self, text: str, *args: object, **kwargs: object
self, text: str | bytes | bytearray, *args: Any, **kwargs: Any
) -> tuple[int, int, int, int]:
"""
Returns bounding box (in pixels) of given text.
Expand All @@ -180,7 +180,9 @@ def getbbox(
width, height = self.font.getsize(text)
return 0, 0, width, height

def getlength(self, text: str, *args: object, **kwargs: object) -> int:
def getlength(
self, text: str | bytes | bytearray, *args: Any, **kwargs: Any
) -> int:
"""
Returns length (in pixels) of given text.
This is the amount by which following text should be offset.
Expand Down Expand Up @@ -357,13 +359,13 @@ def getlength(
def getbbox(
self,
text: str,
mode="",
direction=None,
features=None,
language=None,
stroke_width=0,
anchor=None,
) -> tuple[int, int, int, int]:
mode: str = "",
direction: str | None = None,
features: str | None = None,
language: str | None = None,
stroke_width: float = 0,
anchor: str | None = None,
) -> tuple[float, float, float, float]:
"""
Returns bounding box (in pixels) of given text relative to given anchor
when rendered in font with provided direction, features, and language.
Expand Down Expand Up @@ -513,7 +515,7 @@ def getmask(

def getmask2(
self,
text,
text: str,
mode="",
direction=None,
features=None,
Expand Down Expand Up @@ -641,7 +643,7 @@ def font_variant(
layout_engine=layout_engine or self.layout_engine,
)

def get_variation_names(self):
def get_variation_names(self) -> list[bytes]:
"""
:returns: A list of the named styles in a variation font.
:exception OSError: If the font is not a variation font.
Expand Down Expand Up @@ -683,10 +685,11 @@ def get_variation_axes(self):
msg = "FreeType 2.9.1 or greater is required"
raise NotImplementedError(msg) from e
for axis in axes:
axis["name"] = axis["name"].replace(b"\x00", b"")
if axis["name"]:
axis["name"] = axis["name"].replace(b"\x00", b"")
return axes

def set_variation_by_axes(self, axes):
def set_variation_by_axes(self, axes: list[float]) -> None:
"""
:param axes: A list of values for each axis.
:exception OSError: If the font is not a variation font.
Expand Down Expand Up @@ -731,7 +734,7 @@ def getbbox(self, text, *args, **kwargs):
return 0, 0, height, width
return 0, 0, width, height

def getlength(self, text, *args, **kwargs):
def getlength(self, text: str, *args, **kwargs) -> float:
if self.orientation in (Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_270):
msg = "text length is undefined for text rotated by 90 or 270 degrees"
raise ValueError(msg)
Expand Down Expand Up @@ -878,15 +881,13 @@ def load_path(filename: str | bytes) -> ImageFont:
:return: A font object.
:exception OSError: If the file could not be read.
"""
if not isinstance(filename, str):
filename = filename.decode("utf-8")
for directory in sys.path:
if is_directory(directory):
assert isinstance(directory, str)
if not isinstance(filename, str):
filename = filename.decode("utf-8")
try:
return load(os.path.join(directory, filename))
except OSError:
pass
try:
return load(os.path.join(directory, filename))
except OSError:
pass
msg = "cannot find font file"
raise OSError(msg)

Expand Down
2 changes: 1 addition & 1 deletion src/PIL/JpegImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ def load_read(self, read_bytes: int) -> bytes:
return s

def draft(
self, mode: str, size: tuple[int, int]
self, mode: str | None, size: tuple[int, int]
) -> tuple[str, tuple[int, int, float, float]] | None:
if len(self.tile) != 1:
return None
Expand Down
4 changes: 1 addition & 3 deletions src/PIL/_imaging.pyi
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
from typing import Any

from typing_extensions import Buffer

class ImagingCore:
def __getattr__(self, name: str) -> Any: ...

Expand All @@ -14,5 +12,5 @@ class ImagingDraw:
class PixelAccess:
def __getattr__(self, name: str) -> Any: ...

def font(image, glyphdata: Buffer) -> ImagingFont: ...
def font(image, glyphdata: bytes) -> ImagingFont: ...
def __getattr__(name: str) -> Any: ...
34 changes: 23 additions & 11 deletions src/PIL/_imagingft.pyi
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from typing import Any, TypedDict

from . import _imaging

class _Axis(TypedDict):
minimum: int | None
default: int | None
Expand Down Expand Up @@ -36,22 +38,32 @@ class Font:
foreground_ink_long=...,
x_start=...,
y_start=...,
/,
) -> tuple[Any, tuple[int, int]]: ...
) -> tuple[_imaging.ImagingCore, tuple[int, int]]: ...
def getsize(
self, string: str, mode=..., dir=..., features=..., lang=..., anchor=..., /
self,
string: str | bytes | bytearray,
mode=...,
dir=...,
features=...,
lang=...,
anchor=...,
) -> tuple[tuple[int, int], tuple[int, int]]: ...
def getlength(
self, string: str, mode=..., dir=..., features=..., lang=..., /
) -> int: ...
def getvarnames(self) -> list[str]: ...
def getvaraxes(self) -> list[_Axis]: ...
def setvarname(self, instance_index: int, /) -> None: ...
def setvaraxes(self, axes: list[float], /) -> None: ...
self,
string: str,
mode=...,
dir=...,
features=...,
lang=...,
) -> float: ...
def getvarnames(self) -> list[bytes]: ...
def getvaraxes(self) -> list[_Axis] | None: ...
def setvarname(self, instance_index: int) -> None: ...
def setvaraxes(self, axes: list[float]) -> None: ...

def getfont(
filename: str | bytes | bytearray,
size,
filename: str | bytes,
size: float,
index=...,
encoding=...,
font_bytes=...,
Expand Down

0 comments on commit 641dad2

Please sign in to comment.