Various fixes

This commit is contained in:
Sebastian Rittau 2024-05-07 15:59:20 +02:00
parent d44e9fccb1
commit d63caf266d
5 changed files with 47 additions and 53 deletions

View File

@ -41,7 +41,7 @@ import warnings
from collections.abc import Callable, MutableMapping
from enum import IntEnum
from types import ModuleType
from typing import IO, TYPE_CHECKING, Any, Literal, Protocol, Sequence, cast, overload
from typing import IO, TYPE_CHECKING, Any, Literal, Protocol, Sequence, cast
# VERSION was removed in Pillow 6.0.0.
# PILLOW_VERSION was removed in Pillow 9.0.0.
@ -483,7 +483,9 @@ def _getscaleoffset(expr):
class _GetDataTransform(Protocol):
def getdata(self) -> tuple[Transform, Sequence[float]]: ...
def getdata(
self,
) -> tuple[Transform, Sequence[Any]]: ...
class Image:
@ -2690,41 +2692,11 @@ class Image:
# FIXME: the different transform methods need further explanation
# instead of bloating the method docs, add a separate chapter.
@overload
def transform(
self,
size: tuple[int, int],
method: Transform | ImageTransformHandler,
data: Sequence[float],
resample: int = Resampling.NEAREST,
fill: int = 1,
fillcolor: float | tuple[float, ...] | str | None = None,
) -> Image: ...
@overload
def transform(
self,
size: tuple[int, int],
method: _GetDataTransform,
data: None = None,
resample: int = Resampling.NEAREST,
fill: int = 1,
fillcolor: float | tuple[float, ...] | str | None = None,
) -> Image: ...
@overload
def transform(
self,
size: tuple[int, int],
method: Transform | ImageTransformHandler | _GetDataTransform,
data: Sequence[float] | None = None,
resample: int = Resampling.NEAREST,
fill: int = 1,
fillcolor: float | tuple[float, ...] | str | None = None,
) -> Image: ...
def transform(
self,
size: tuple[int, int],
method: Transform | ImageTransformHandler | _GetDataTransform,
data: Sequence[float] | None = None,
data: Sequence[Any] | None = None,
resample: int = Resampling.NEAREST,
fill: int = 1,
fillcolor: float | tuple[float, ...] | str | None = None,
@ -2803,7 +2775,7 @@ class Image:
im.info = self.info.copy()
if method == Transform.MESH:
# list of quads
for box, quad in data:
for box, quad in cast(Sequence[tuple[float, float]], data):
im.__transformer(
box, self, Transform.QUAD, quad, resample, fillcolor is None
)
@ -2961,7 +2933,7 @@ class ImageTransformHandler:
self,
size: tuple[int, int],
image: Image,
**options: dict[str, str | int | tuple[int, ...] | list[int]],
**options: dict[str, str | int | tuple[int, ...] | list[int]] | int,
) -> Image:
pass
@ -3830,7 +3802,7 @@ class Exif(_ExifBase):
return self._fixup_dict(info)
def _get_head(self):
version = b"\x2B" if self.bigtiff else b"\x2A"
version = b"\x2b" if self.bigtiff else b"\x2a"
if self.endian == "<":
head = b"II" + version + b"\x00" + o32le(8)
else:

View File

@ -118,7 +118,7 @@ class ImageDraw:
self.font = ImageFont.load_default()
return self.font
def _getfont(self, font_size: float | None):
def _getfont(self, font_size: float | None) -> FreeTypeFont | ImageFont:
if font_size is not None:
from . import ImageFont
@ -451,13 +451,13 @@ class ImageDraw:
right[3] -= r + 1
self.draw.draw_rectangle(right, ink, 1)
def _multiline_check(self, text: str | bytes) -> bool:
split_character = "\n" if isinstance(text, str) else b"\n"
def _multiline_check(self, text: AnyStr) -> bool:
split_character = cast(AnyStr, "\n" if isinstance(text, str) else b"\n")
return split_character in text
def _multiline_split(self, text: AnyStr) -> list[AnyStr]:
split_character = "\n" if isinstance(text, str) else b"\n"
split_character = cast(AnyStr, "\n" if isinstance(text, str) else b"\n")
return text.split(split_character)
@ -470,10 +470,10 @@ class ImageDraw:
def text(
self,
xy: tuple[int, int],
text,
xy: tuple[float, float],
text: str,
fill=None,
font=None,
font: FreeTypeFont | ImageFont | None = None,
anchor=None,
spacing=4,
align="left",
@ -527,7 +527,7 @@ class ImageDraw:
coord.append(int(xy[i]))
start.append(math.modf(xy[i])[0])
try:
mask, offset = font.getmask2(
mask, offset = font.getmask2( # type: ignore[union-attr,misc]
text,
mode,
direction=direction,
@ -543,7 +543,7 @@ class ImageDraw:
coord = [coord[0] + offset[0], coord[1] + offset[1]]
except AttributeError:
try:
mask = font.getmask(
mask = font.getmask( # type: ignore[misc]
text,
mode,
direction,
@ -592,7 +592,7 @@ class ImageDraw:
def multiline_text(
self,
xy: tuple[int, int],
xy: tuple[float, float],
text,
fill=None,
font=None,
@ -625,7 +625,7 @@ class ImageDraw:
font = self._getfont(font_size)
widths = []
max_width = 0
max_width: float = 0
lines = self._multiline_split(text)
line_spacing = self._multiline_spacing(font, spacing, stroke_width)
for line in lines:
@ -779,7 +779,7 @@ class ImageDraw:
font = self._getfont(font_size)
widths = []
max_width = 0
max_width: float = 0
lines = self._multiline_split(text)
line_spacing = self._multiline_spacing(font, spacing, stroke_width)
for line in lines:

View File

@ -35,11 +35,14 @@ from enum import IntEnum
from io import BytesIO
from typing import TYPE_CHECKING, BinaryIO
from PIL import ImageFile
from . import Image
from ._typing import StrOrBytesPath
from ._util import is_directory, is_path
if TYPE_CHECKING:
from ._imaging import ImagingFont
from ._imagingft import Font
@ -84,11 +87,11 @@ def _string_length_check(text: str | bytes) -> None:
class ImageFont:
"""PIL font wrapper"""
font: Font
font: ImagingFont
def _load_pilfont(self, filename: str) -> None:
with open(filename, "rb") as fp:
image = None
image: ImageFile.ImageFile | None = None
for ext in (".png", ".gif", ".pbm"):
if image:
image.close()
@ -198,6 +201,8 @@ class ImageFont:
class FreeTypeFont:
"""FreeType font wrapper (requires _imagingft service)"""
font: Font
def __init__(
self,
font: StrOrBytesPath | BinaryIO | None = None,
@ -261,7 +266,7 @@ class FreeTypeFont:
path, size, index, encoding, layout_engine = state
self.__init__(path, size, index, encoding, layout_engine)
def getname(self) -> tuple[str, str]:
def getname(self) -> tuple[str | None, str | None]:
"""
:return: A tuple of the font family (e.g. Helvetica) and the font style
(e.g. Bold)
@ -876,6 +881,7 @@ def load_path(filename: str | bytes) -> ImageFont:
"""
for directory in sys.path:
if is_directory(directory):
assert isinstance(directory, str)
if not isinstance(filename, str):
filename = filename.decode("utf-8")
try:
@ -900,6 +906,7 @@ def load_default(size: float | None = None) -> FreeTypeFont | ImageFont:
:return: A font object.
"""
f: FreeTypeFont | ImageFont
if core.__class__.__name__ == "module" or size is not None:
f = truetype(
BytesIO(

View File

@ -14,7 +14,7 @@
#
from __future__ import annotations
from typing import Sequence
from typing import Any, Sequence
from . import Image
@ -34,7 +34,7 @@ class Transform(Image.ImageTransformHandler):
self,
size: tuple[int, int],
image: Image.Image,
**options: dict[str, str | int | tuple[int, ...] | list[int]],
**options: Any,
) -> Image.Image:
"""Perform the transform. Called from :py:meth:`.Image.transform`."""
# can be overridden

View File

@ -1,3 +1,18 @@
from typing import Any
from typing_extensions import Buffer
class ImagingCore:
def __getattr__(self, name: str) -> Any: ...
class ImagingFont:
def __getattr__(self, name: str) -> Any: ...
class ImagingDraw:
def __getattr__(self, name: str) -> Any: ...
class PixelAccess:
def __getattr__(self, name: str) -> Any: ...
def font(image, glyphdata: Buffer) -> ImagingFont: ...
def __getattr__(name: str) -> Any: ...