From 42c8e231b30de14cfc4831656927221c6359db6a Mon Sep 17 00:00:00 2001 From: David Robertson Date: Fri, 6 Jan 2023 17:04:43 +0000 Subject: [PATCH 01/11] Create dummy PixelAccess stub --- stubs/Pillow/PIL/_imaging.pyi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/stubs/Pillow/PIL/_imaging.pyi b/stubs/Pillow/PIL/_imaging.pyi index b9435b8fe506..5b396e10ead8 100644 --- a/stubs/Pillow/PIL/_imaging.pyi +++ b/stubs/Pillow/PIL/_imaging.pyi @@ -8,6 +8,12 @@ HUFFMAN_ONLY: Literal[2] RLE: Literal[3] FIXED: Literal[4] +class PixelAccess: + # As well as the C extension source, this is also documented at + # Pillow's docs/reference/PixelAccess.rst, e.g. + # https://github.com/python-pillow/Pillow/blob/main/docs/reference/PixelAccess.rst + def __getattr__(self, item: str) -> Incomplete: ... + class _Path: def __getattr__(self, item: str) -> Incomplete: ... From 7f646a6b2c56c787187c0a6e8331cab4965323e3 Mon Sep 17 00:00:00 2001 From: David Robertson Date: Fri, 6 Jan 2023 17:18:14 +0000 Subject: [PATCH 02/11] Mark `load` as returning PixelAccess | PyAccess --- stubs/Pillow/PIL/EpsImagePlugin.pyi | 4 +++- stubs/Pillow/PIL/GbrImagePlugin.pyi | 4 +++- stubs/Pillow/PIL/IcnsImagePlugin.pyi | 4 +++- stubs/Pillow/PIL/IcoImagePlugin.pyi | 4 +++- stubs/Pillow/PIL/Image.pyi | 3 ++- stubs/Pillow/PIL/ImageFile.pyi | 6 ++++-- stubs/Pillow/PIL/WalImageFile.pyi | 4 +++- stubs/Pillow/PIL/WmfImagePlugin.pyi | 4 +++- 8 files changed, 24 insertions(+), 9 deletions(-) diff --git a/stubs/Pillow/PIL/EpsImagePlugin.pyi b/stubs/Pillow/PIL/EpsImagePlugin.pyi index 7e76e8681069..6230963462a5 100644 --- a/stubs/Pillow/PIL/EpsImagePlugin.pyi +++ b/stubs/Pillow/PIL/EpsImagePlugin.pyi @@ -1,7 +1,9 @@ from typing import Any, ClassVar from typing_extensions import Literal +from ._imaging import PixelAccess from .ImageFile import ImageFile +from .PyAccess import PyAccess split: Any field: Any @@ -24,5 +26,5 @@ class EpsImageFile(ImageFile): im: Any mode: Any tile: Any - def load(self, scale: int = ..., transparency: bool = ...) -> None: ... + def load(self, scale: int = ..., transparency: bool = ...) -> PixelAccess | PyAccess: ... def load_seek(self, *args, **kwargs) -> None: ... diff --git a/stubs/Pillow/PIL/GbrImagePlugin.pyi b/stubs/Pillow/PIL/GbrImagePlugin.pyi index b5ede10c8644..1eff66aaea8d 100644 --- a/stubs/Pillow/PIL/GbrImagePlugin.pyi +++ b/stubs/Pillow/PIL/GbrImagePlugin.pyi @@ -1,10 +1,12 @@ from typing import Any, ClassVar from typing_extensions import Literal +from ._imaging import PixelAccess from .ImageFile import ImageFile +from .PyAccess import PyAccess class GbrImageFile(ImageFile): format: ClassVar[Literal["GBR"]] format_description: ClassVar[str] im: Any - def load(self) -> None: ... + def load(self) -> PixelAccess | PyAccess: ... diff --git a/stubs/Pillow/PIL/IcnsImagePlugin.pyi b/stubs/Pillow/PIL/IcnsImagePlugin.pyi index 42714148c49f..d2395d717c0f 100644 --- a/stubs/Pillow/PIL/IcnsImagePlugin.pyi +++ b/stubs/Pillow/PIL/IcnsImagePlugin.pyi @@ -1,7 +1,9 @@ from typing import Any, ClassVar from typing_extensions import Literal +from ._imaging import PixelAccess from .ImageFile import ImageFile +from .PyAccess import PyAccess enable_jpeg2k: Any HEADERSIZE: int @@ -32,4 +34,4 @@ class IcnsImageFile(ImageFile): best_size: Any im: Any mode: Any - def load(self) -> None: ... + def load(self) -> PixelAccess | PyAccess: ... diff --git a/stubs/Pillow/PIL/IcoImagePlugin.pyi b/stubs/Pillow/PIL/IcoImagePlugin.pyi index f84ed76d50e5..49943ce15bb8 100644 --- a/stubs/Pillow/PIL/IcoImagePlugin.pyi +++ b/stubs/Pillow/PIL/IcoImagePlugin.pyi @@ -1,7 +1,9 @@ from typing import Any, ClassVar from typing_extensions import Literal +from ._imaging import PixelAccess from .ImageFile import ImageFile +from .PyAccess import PyAccess class IcoFile: buf: Any @@ -22,5 +24,5 @@ class IcoImageFile(ImageFile): def size(self, value) -> None: ... im: Any mode: Any - def load(self) -> None: ... + def load(self) -> PixelAccess | PyAccess: ... def load_seek(self) -> None: ... diff --git a/stubs/Pillow/PIL/Image.pyi b/stubs/Pillow/PIL/Image.pyi index d6f169f84aa0..51db6d63516e 100644 --- a/stubs/Pillow/PIL/Image.pyi +++ b/stubs/Pillow/PIL/Image.pyi @@ -13,6 +13,7 @@ from ._imaging import ( FIXED as FIXED, HUFFMAN_ONLY as HUFFMAN_ONLY, RLE as RLE, + PixelAccess, ) from .ImageFilter import Filter from .ImagePalette import ImagePalette @@ -180,7 +181,7 @@ class Image: def tobytes(self, encoder_name: str = ..., *args) -> bytes: ... def tobitmap(self, name: str = ...) -> bytes: ... def frombytes(self, data: bytes, decoder_name: str = ..., *args) -> None: ... - def load(self) -> None: ... + def load(self) -> PixelAccess | PyAccess: ... def verify(self) -> None: ... def convert( self, diff --git a/stubs/Pillow/PIL/ImageFile.pyi b/stubs/Pillow/PIL/ImageFile.pyi index f90d975dc6dc..43bf6e8b2871 100644 --- a/stubs/Pillow/PIL/ImageFile.pyi +++ b/stubs/Pillow/PIL/ImageFile.pyi @@ -1,7 +1,9 @@ from _typeshed import Incomplete, Self from typing import Any, NoReturn +from ._imaging import PixelAccess from .Image import Image +from .PyAccess import PyAccess MAXBLOCK: int SAFEBLOCK: Any @@ -23,12 +25,12 @@ class ImageFile(Image): def verify(self) -> None: ... map: Any im: Any - def load(self): ... + def load(self) -> PixelAccess | PyAccess: ... def load_prepare(self) -> None: ... def load_end(self) -> None: ... class StubImageFile(ImageFile): - def load(self) -> None: ... + def load(self) -> PixelAccess | PyAccess: ... class Parser: incremental: Any | None diff --git a/stubs/Pillow/PIL/WalImageFile.pyi b/stubs/Pillow/PIL/WalImageFile.pyi index 24d1cb5cc35f..45479a94c589 100644 --- a/stubs/Pillow/PIL/WalImageFile.pyi +++ b/stubs/Pillow/PIL/WalImageFile.pyi @@ -2,11 +2,13 @@ from typing import ClassVar from typing_extensions import Literal from . import ImageFile +from ._imaging import PixelAccess +from .PyAccess import PyAccess class WalImageFile(ImageFile.ImageFile): format: ClassVar[Literal["WAL"]] format_description: ClassVar[str] - def load(self) -> None: ... + def load(self) -> PixelAccess | PyAccess: ... def open(filename): ... diff --git a/stubs/Pillow/PIL/WmfImagePlugin.pyi b/stubs/Pillow/PIL/WmfImagePlugin.pyi index b975868536fc..c98014894158 100644 --- a/stubs/Pillow/PIL/WmfImagePlugin.pyi +++ b/stubs/Pillow/PIL/WmfImagePlugin.pyi @@ -2,7 +2,9 @@ import sys from typing import Any, ClassVar from typing_extensions import Literal +from ._imaging import PixelAccess from .ImageFile import StubImageFile +from .PyAccess import PyAccess def register_handler(handler) -> None: ... @@ -15,4 +17,4 @@ if sys.platform == "win32": class WmfStubImageFile(StubImageFile): format: ClassVar[Literal["WMF"]] format_description: ClassVar[str] - def load(self, dpi: Any | None = ...) -> None: ... + def load(self, dpi: Any | None = ...) -> PixelAccess | PyAccess: ... From e75bd7c93f1bba7fc756ab9ec0208b1fc71e5cee Mon Sep 17 00:00:00 2001 From: David Robertson Date: Fri, 6 Jan 2023 17:20:31 +0000 Subject: [PATCH 03/11] Use an underscore to keep stubtest happy --- stubs/Pillow/PIL/EpsImagePlugin.pyi | 4 ++-- stubs/Pillow/PIL/GbrImagePlugin.pyi | 4 ++-- stubs/Pillow/PIL/IcnsImagePlugin.pyi | 4 ++-- stubs/Pillow/PIL/IcoImagePlugin.pyi | 4 ++-- stubs/Pillow/PIL/Image.pyi | 4 ++-- stubs/Pillow/PIL/ImageFile.pyi | 6 +++--- stubs/Pillow/PIL/WalImageFile.pyi | 4 ++-- stubs/Pillow/PIL/WmfImagePlugin.pyi | 4 ++-- stubs/Pillow/PIL/_imaging.pyi | 4 +++- 9 files changed, 20 insertions(+), 18 deletions(-) diff --git a/stubs/Pillow/PIL/EpsImagePlugin.pyi b/stubs/Pillow/PIL/EpsImagePlugin.pyi index 6230963462a5..5175be62f7ed 100644 --- a/stubs/Pillow/PIL/EpsImagePlugin.pyi +++ b/stubs/Pillow/PIL/EpsImagePlugin.pyi @@ -1,7 +1,7 @@ from typing import Any, ClassVar from typing_extensions import Literal -from ._imaging import PixelAccess +from ._imaging import _PixelAccess from .ImageFile import ImageFile from .PyAccess import PyAccess @@ -26,5 +26,5 @@ class EpsImageFile(ImageFile): im: Any mode: Any tile: Any - def load(self, scale: int = ..., transparency: bool = ...) -> PixelAccess | PyAccess: ... + def load(self, scale: int = ..., transparency: bool = ...) -> _PixelAccess | PyAccess: ... def load_seek(self, *args, **kwargs) -> None: ... diff --git a/stubs/Pillow/PIL/GbrImagePlugin.pyi b/stubs/Pillow/PIL/GbrImagePlugin.pyi index 1eff66aaea8d..1e08821c06c6 100644 --- a/stubs/Pillow/PIL/GbrImagePlugin.pyi +++ b/stubs/Pillow/PIL/GbrImagePlugin.pyi @@ -1,7 +1,7 @@ from typing import Any, ClassVar from typing_extensions import Literal -from ._imaging import PixelAccess +from ._imaging import _PixelAccess from .ImageFile import ImageFile from .PyAccess import PyAccess @@ -9,4 +9,4 @@ class GbrImageFile(ImageFile): format: ClassVar[Literal["GBR"]] format_description: ClassVar[str] im: Any - def load(self) -> PixelAccess | PyAccess: ... + def load(self) -> _PixelAccess | PyAccess: ... diff --git a/stubs/Pillow/PIL/IcnsImagePlugin.pyi b/stubs/Pillow/PIL/IcnsImagePlugin.pyi index d2395d717c0f..d5fb04f091b3 100644 --- a/stubs/Pillow/PIL/IcnsImagePlugin.pyi +++ b/stubs/Pillow/PIL/IcnsImagePlugin.pyi @@ -1,7 +1,7 @@ from typing import Any, ClassVar from typing_extensions import Literal -from ._imaging import PixelAccess +from ._imaging import _PixelAccess from .ImageFile import ImageFile from .PyAccess import PyAccess @@ -34,4 +34,4 @@ class IcnsImageFile(ImageFile): best_size: Any im: Any mode: Any - def load(self) -> PixelAccess | PyAccess: ... + def load(self) -> _PixelAccess | PyAccess: ... diff --git a/stubs/Pillow/PIL/IcoImagePlugin.pyi b/stubs/Pillow/PIL/IcoImagePlugin.pyi index 49943ce15bb8..d7cbe25f1d3e 100644 --- a/stubs/Pillow/PIL/IcoImagePlugin.pyi +++ b/stubs/Pillow/PIL/IcoImagePlugin.pyi @@ -1,7 +1,7 @@ from typing import Any, ClassVar from typing_extensions import Literal -from ._imaging import PixelAccess +from ._imaging import _PixelAccess from .ImageFile import ImageFile from .PyAccess import PyAccess @@ -24,5 +24,5 @@ class IcoImageFile(ImageFile): def size(self, value) -> None: ... im: Any mode: Any - def load(self) -> PixelAccess | PyAccess: ... + def load(self) -> _PixelAccess | PyAccess: ... def load_seek(self) -> None: ... diff --git a/stubs/Pillow/PIL/Image.pyi b/stubs/Pillow/PIL/Image.pyi index 51db6d63516e..31cfb3d74879 100644 --- a/stubs/Pillow/PIL/Image.pyi +++ b/stubs/Pillow/PIL/Image.pyi @@ -13,7 +13,7 @@ from ._imaging import ( FIXED as FIXED, HUFFMAN_ONLY as HUFFMAN_ONLY, RLE as RLE, - PixelAccess, + _PixelAccess, ) from .ImageFilter import Filter from .ImagePalette import ImagePalette @@ -181,7 +181,7 @@ class Image: def tobytes(self, encoder_name: str = ..., *args) -> bytes: ... def tobitmap(self, name: str = ...) -> bytes: ... def frombytes(self, data: bytes, decoder_name: str = ..., *args) -> None: ... - def load(self) -> PixelAccess | PyAccess: ... + def load(self) -> _PixelAccess | PyAccess: ... def verify(self) -> None: ... def convert( self, diff --git a/stubs/Pillow/PIL/ImageFile.pyi b/stubs/Pillow/PIL/ImageFile.pyi index 43bf6e8b2871..2a61e37c2175 100644 --- a/stubs/Pillow/PIL/ImageFile.pyi +++ b/stubs/Pillow/PIL/ImageFile.pyi @@ -1,7 +1,7 @@ from _typeshed import Incomplete, Self from typing import Any, NoReturn -from ._imaging import PixelAccess +from ._imaging import _PixelAccess from .Image import Image from .PyAccess import PyAccess @@ -25,12 +25,12 @@ class ImageFile(Image): def verify(self) -> None: ... map: Any im: Any - def load(self) -> PixelAccess | PyAccess: ... + def load(self) -> _PixelAccess | PyAccess: ... def load_prepare(self) -> None: ... def load_end(self) -> None: ... class StubImageFile(ImageFile): - def load(self) -> PixelAccess | PyAccess: ... + def load(self) -> _PixelAccess | PyAccess: ... class Parser: incremental: Any | None diff --git a/stubs/Pillow/PIL/WalImageFile.pyi b/stubs/Pillow/PIL/WalImageFile.pyi index 45479a94c589..998febfc7667 100644 --- a/stubs/Pillow/PIL/WalImageFile.pyi +++ b/stubs/Pillow/PIL/WalImageFile.pyi @@ -2,13 +2,13 @@ from typing import ClassVar from typing_extensions import Literal from . import ImageFile -from ._imaging import PixelAccess +from ._imaging import _PixelAccess from .PyAccess import PyAccess class WalImageFile(ImageFile.ImageFile): format: ClassVar[Literal["WAL"]] format_description: ClassVar[str] - def load(self) -> PixelAccess | PyAccess: ... + def load(self) -> _PixelAccess | PyAccess: ... def open(filename): ... diff --git a/stubs/Pillow/PIL/WmfImagePlugin.pyi b/stubs/Pillow/PIL/WmfImagePlugin.pyi index c98014894158..e3f9d0157c2d 100644 --- a/stubs/Pillow/PIL/WmfImagePlugin.pyi +++ b/stubs/Pillow/PIL/WmfImagePlugin.pyi @@ -2,7 +2,7 @@ import sys from typing import Any, ClassVar from typing_extensions import Literal -from ._imaging import PixelAccess +from ._imaging import _PixelAccess from .ImageFile import StubImageFile from .PyAccess import PyAccess @@ -17,4 +17,4 @@ if sys.platform == "win32": class WmfStubImageFile(StubImageFile): format: ClassVar[Literal["WMF"]] format_description: ClassVar[str] - def load(self, dpi: Any | None = ...) -> PixelAccess | PyAccess: ... + def load(self, dpi: Any | None = ...) -> _PixelAccess | PyAccess: ... diff --git a/stubs/Pillow/PIL/_imaging.pyi b/stubs/Pillow/PIL/_imaging.pyi index 5b396e10ead8..b9873df6e407 100644 --- a/stubs/Pillow/PIL/_imaging.pyi +++ b/stubs/Pillow/PIL/_imaging.pyi @@ -8,10 +8,12 @@ HUFFMAN_ONLY: Literal[2] RLE: Literal[3] FIXED: Literal[4] -class PixelAccess: +class _PixelAccess: # As well as the C extension source, this is also documented at # Pillow's docs/reference/PixelAccess.rst, e.g. # https://github.com/python-pillow/Pillow/blob/main/docs/reference/PixelAccess.rst + # The name is prefixed here with an underscore as PixelAccess is not + # runtime-importable. def __getattr__(self, item: str) -> Incomplete: ... class _Path: From 79a30ee77bc65cc1122eb0a9dc05e1e47f996cd9 Mon Sep 17 00:00:00 2001 From: David Robertson Date: Fri, 6 Jan 2023 17:27:37 +0000 Subject: [PATCH 04/11] Add documented PixelAccess and PyAccess methods --- stubs/Pillow/PIL/PyAccess.pyi | 6 +++--- stubs/Pillow/PIL/_imaging.pyi | 7 ++++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/stubs/Pillow/PIL/PyAccess.pyi b/stubs/Pillow/PIL/PyAccess.pyi index 3d9231274c76..d6c4b98c03c3 100644 --- a/stubs/Pillow/PIL/PyAccess.pyi +++ b/stubs/Pillow/PIL/PyAccess.pyi @@ -11,9 +11,9 @@ class PyAccess: image: Any def __init__(self, img, readonly: bool = ...) -> None: ... def __setitem__(self, xy, color) -> None: ... - def __getitem__(self, xy): ... - putpixel: Any - getpixel: Any + def __getitem__(self, xy) -> Any: ... + def putpixel(self, xy, color) -> None: ... + def getpixel(self, xy) -> Any: ... def check_xy(self, xy): ... class _PyAccess32_2(PyAccess): diff --git a/stubs/Pillow/PIL/_imaging.pyi b/stubs/Pillow/PIL/_imaging.pyi index b9873df6e407..a2d16c491236 100644 --- a/stubs/Pillow/PIL/_imaging.pyi +++ b/stubs/Pillow/PIL/_imaging.pyi @@ -1,5 +1,6 @@ from _typeshed import Incomplete from collections.abc import Sequence +from typing import Any from typing_extensions import Literal DEFAULT_STRATEGY: Literal[0] @@ -14,7 +15,11 @@ class _PixelAccess: # https://github.com/python-pillow/Pillow/blob/main/docs/reference/PixelAccess.rst # The name is prefixed here with an underscore as PixelAccess is not # runtime-importable. - def __getattr__(self, item: str) -> Incomplete: ... + + def __setitem__(self, xy, color) -> None: ... + def __getitem__(self, xy) -> Any: ... + def putpixel(self, xy, color) -> None: ... + def getpixel(self, xy) -> Any: ... class _Path: def __getattr__(self, item: str) -> Incomplete: ... From d577e0aa79112e307725b993e89fcfeccfa0a9b7 Mon Sep 17 00:00:00 2001 From: David Robertson Date: Fri, 6 Jan 2023 17:50:33 +0000 Subject: [PATCH 05/11] Use coordinate type for xy arguments --- stubs/Pillow/PIL/PyAccess.pyi | 10 +++++----- stubs/Pillow/PIL/_imaging.pyi | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/stubs/Pillow/PIL/PyAccess.pyi b/stubs/Pillow/PIL/PyAccess.pyi index d6c4b98c03c3..5f357a7daf3f 100644 --- a/stubs/Pillow/PIL/PyAccess.pyi +++ b/stubs/Pillow/PIL/PyAccess.pyi @@ -10,11 +10,11 @@ class PyAccess: image32: Any image: Any def __init__(self, img, readonly: bool = ...) -> None: ... - def __setitem__(self, xy, color) -> None: ... - def __getitem__(self, xy) -> Any: ... - def putpixel(self, xy, color) -> None: ... - def getpixel(self, xy) -> Any: ... - def check_xy(self, xy): ... + def __setitem__(self, xy: tuple[int, int], color) -> None: ... + def __getitem__(self, xy: tuple[int, int]) -> Any: ... + def putpixel(self, xy: tuple[int, int], color) -> None: ... + def getpixel(self, xy: tuple[int, int]) -> Any: ... + def check_xy(self, xy: tuple[int, int]): ... class _PyAccess32_2(PyAccess): def get_pixel(self, x, y): ... diff --git a/stubs/Pillow/PIL/_imaging.pyi b/stubs/Pillow/PIL/_imaging.pyi index a2d16c491236..4977c2b7a06a 100644 --- a/stubs/Pillow/PIL/_imaging.pyi +++ b/stubs/Pillow/PIL/_imaging.pyi @@ -16,10 +16,10 @@ class _PixelAccess: # The name is prefixed here with an underscore as PixelAccess is not # runtime-importable. - def __setitem__(self, xy, color) -> None: ... - def __getitem__(self, xy) -> Any: ... - def putpixel(self, xy, color) -> None: ... - def getpixel(self, xy) -> Any: ... + def __setitem__(self, xy: tuple[int, int], color) -> None: ... + def __getitem__(self, xy: tuple[int, int]) -> Any: ... + def putpixel(self, xy: tuple[int, int], color) -> None: ... + def getpixel(self, xy: tuple[int, int]) -> Any: ... class _Path: def __getattr__(self, item: str) -> Incomplete: ... From 083cf4226e19e4e3cfac0c6d69c492e758853417 Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sat, 8 Apr 2023 17:46:16 +0100 Subject: [PATCH 06/11] Introduce a protocol and update return types --- stubs/Pillow/PIL/EpsImagePlugin.pyi | 5 ++--- stubs/Pillow/PIL/GbrImagePlugin.pyi | 5 ++--- stubs/Pillow/PIL/IcnsImagePlugin.pyi | 5 ++--- stubs/Pillow/PIL/IcoImagePlugin.pyi | 5 ++--- stubs/Pillow/PIL/Image.pyi | 5 ++--- stubs/Pillow/PIL/ImageFile.pyi | 7 +++---- stubs/Pillow/PIL/PyAccess.pyi | 4 +++- stubs/Pillow/PIL/WalImageFile.pyi | 5 ++--- stubs/Pillow/PIL/WmfImagePlugin.pyi | 5 ++--- stubs/Pillow/PIL/_imaging.pyi | 26 ++++++++++++++------------ 10 files changed, 34 insertions(+), 38 deletions(-) diff --git a/stubs/Pillow/PIL/EpsImagePlugin.pyi b/stubs/Pillow/PIL/EpsImagePlugin.pyi index c7b636abfac8..c8cc6d504cc1 100644 --- a/stubs/Pillow/PIL/EpsImagePlugin.pyi +++ b/stubs/Pillow/PIL/EpsImagePlugin.pyi @@ -1,9 +1,8 @@ from typing import Any, ClassVar from typing_extensions import Literal -from ._imaging import _PixelAccess +from ._imaging import _PixelAccessor from .ImageFile import ImageFile -from .PyAccess import PyAccess split: Any field: Any @@ -26,5 +25,5 @@ class EpsImageFile(ImageFile): im: Any mode: Any tile: Any - def load(self, scale: int = 1, transparency: bool = False) -> _PixelAccess | PyAccess: ... + def load(self, scale: int = 1, transparency: bool = False) -> _PixelAccessor: ... def load_seek(self, *args, **kwargs) -> None: ... diff --git a/stubs/Pillow/PIL/GbrImagePlugin.pyi b/stubs/Pillow/PIL/GbrImagePlugin.pyi index 1e08821c06c6..f03101f26b7c 100644 --- a/stubs/Pillow/PIL/GbrImagePlugin.pyi +++ b/stubs/Pillow/PIL/GbrImagePlugin.pyi @@ -1,12 +1,11 @@ from typing import Any, ClassVar from typing_extensions import Literal -from ._imaging import _PixelAccess +from ._imaging import _PixelAccessor from .ImageFile import ImageFile -from .PyAccess import PyAccess class GbrImageFile(ImageFile): format: ClassVar[Literal["GBR"]] format_description: ClassVar[str] im: Any - def load(self) -> _PixelAccess | PyAccess: ... + def load(self) -> _PixelAccessor: ... diff --git a/stubs/Pillow/PIL/IcnsImagePlugin.pyi b/stubs/Pillow/PIL/IcnsImagePlugin.pyi index 2c18efb98b47..bbd3827e7085 100644 --- a/stubs/Pillow/PIL/IcnsImagePlugin.pyi +++ b/stubs/Pillow/PIL/IcnsImagePlugin.pyi @@ -2,9 +2,8 @@ from _typeshed import Incomplete from typing import Any, ClassVar from typing_extensions import Literal -from ._imaging import _PixelAccess +from ._imaging import _PixelAccessor from .ImageFile import ImageFile -from .PyAccess import PyAccess enable_jpeg2k: Any HEADERSIZE: int @@ -35,4 +34,4 @@ class IcnsImageFile(ImageFile): best_size: Any im: Any mode: Any - def load(self) -> _PixelAccess | PyAccess: ... + def load(self) -> _PixelAccessor: ... diff --git a/stubs/Pillow/PIL/IcoImagePlugin.pyi b/stubs/Pillow/PIL/IcoImagePlugin.pyi index 0decc82b4c83..da5fea503382 100644 --- a/stubs/Pillow/PIL/IcoImagePlugin.pyi +++ b/stubs/Pillow/PIL/IcoImagePlugin.pyi @@ -1,9 +1,8 @@ from typing import Any, ClassVar from typing_extensions import Literal -from ._imaging import _PixelAccess +from ._imaging import _PixelAccessor from .ImageFile import ImageFile -from .PyAccess import PyAccess class IcoFile: buf: Any @@ -24,5 +23,5 @@ class IcoImageFile(ImageFile): def size(self, value) -> None: ... im: Any mode: Any - def load(self) -> _PixelAccess | PyAccess: ... + def load(self) -> _PixelAccessor: ... def load_seek(self) -> None: ... diff --git a/stubs/Pillow/PIL/Image.pyi b/stubs/Pillow/PIL/Image.pyi index 8eb9311061bf..3c52692fb0af 100644 --- a/stubs/Pillow/PIL/Image.pyi +++ b/stubs/Pillow/PIL/Image.pyi @@ -5,7 +5,6 @@ from pathlib import Path from typing import Any, ClassVar, Protocol, SupportsBytes from typing_extensions import Literal, Self, TypeAlias -from PIL.PyAccess import PyAccess from ._imaging import ( DEFAULT_STRATEGY as DEFAULT_STRATEGY, @@ -13,7 +12,7 @@ from ._imaging import ( FIXED as FIXED, HUFFMAN_ONLY as HUFFMAN_ONLY, RLE as RLE, - _PixelAccess, + _PixelAccessor, ) from .ImageFilter import Filter from .ImagePalette import ImagePalette @@ -181,7 +180,7 @@ class Image: def tobytes(self, encoder_name: str = "raw", *args) -> bytes: ... def tobitmap(self, name: str = "image") -> bytes: ... def frombytes(self, data: bytes, decoder_name: str = "raw", *args) -> None: ... - def load(self) -> _PixelAccess | PyAccess: ... + def load(self) -> _PixelAccessor: ... def verify(self) -> None: ... def convert( self, diff --git a/stubs/Pillow/PIL/ImageFile.pyi b/stubs/Pillow/PIL/ImageFile.pyi index a435dee43c80..6ae0c50f7500 100644 --- a/stubs/Pillow/PIL/ImageFile.pyi +++ b/stubs/Pillow/PIL/ImageFile.pyi @@ -2,9 +2,8 @@ from _typeshed import Incomplete, Unused from typing import Any, NoReturn from typing_extensions import Self -from ._imaging import _PixelAccess +from ._imaging import _PixelAccessor from .Image import Image -from .PyAccess import PyAccess MAXBLOCK: int SAFEBLOCK: Any @@ -26,12 +25,12 @@ class ImageFile(Image): def verify(self) -> None: ... map: Any im: Any - def load(self) -> _PixelAccess | PyAccess: ... + def load(self) -> _PixelAccessor: ... def load_prepare(self) -> None: ... def load_end(self) -> None: ... class StubImageFile(ImageFile): - def load(self) -> _PixelAccess | PyAccess: ... + def load(self) -> _PixelAccessor: ... class Parser: incremental: Incomplete | None diff --git a/stubs/Pillow/PIL/PyAccess.pyi b/stubs/Pillow/PIL/PyAccess.pyi index 4f6363d35b2f..862527be6eca 100644 --- a/stubs/Pillow/PIL/PyAccess.pyi +++ b/stubs/Pillow/PIL/PyAccess.pyi @@ -1,10 +1,12 @@ from logging import Logger from typing import Any +from PIL._imaging import _PixelAccessoror + ffi: Any logger: Logger -class PyAccess: +class PyAccess(_PixelAccessoror): readonly: Any image8: Any image32: Any diff --git a/stubs/Pillow/PIL/WalImageFile.pyi b/stubs/Pillow/PIL/WalImageFile.pyi index 998febfc7667..176f47eca59d 100644 --- a/stubs/Pillow/PIL/WalImageFile.pyi +++ b/stubs/Pillow/PIL/WalImageFile.pyi @@ -2,13 +2,12 @@ from typing import ClassVar from typing_extensions import Literal from . import ImageFile -from ._imaging import _PixelAccess -from .PyAccess import PyAccess +from ._imaging import _PixelAccessor class WalImageFile(ImageFile.ImageFile): format: ClassVar[Literal["WAL"]] format_description: ClassVar[str] - def load(self) -> _PixelAccess | PyAccess: ... + def load(self) -> _PixelAccessor: ... def open(filename): ... diff --git a/stubs/Pillow/PIL/WmfImagePlugin.pyi b/stubs/Pillow/PIL/WmfImagePlugin.pyi index 8a16125363d9..2cb78d884801 100644 --- a/stubs/Pillow/PIL/WmfImagePlugin.pyi +++ b/stubs/Pillow/PIL/WmfImagePlugin.pyi @@ -3,9 +3,8 @@ from _typeshed import Incomplete from typing import Any, ClassVar from typing_extensions import Literal -from ._imaging import _PixelAccess +from ._imaging import _PixelAccessor from .ImageFile import StubImageFile -from .PyAccess import PyAccess def register_handler(handler) -> None: ... @@ -18,4 +17,4 @@ if sys.platform == "win32": class WmfStubImageFile(StubImageFile): format: ClassVar[Literal["WMF"]] format_description: ClassVar[str] - def load(self, dpi: Incomplete | None = None) -> _PixelAccess | PyAccess: ... + def load(self, dpi: Incomplete | None = None) -> _PixelAccessor: ... diff --git a/stubs/Pillow/PIL/_imaging.pyi b/stubs/Pillow/PIL/_imaging.pyi index 4977c2b7a06a..2e523f7d2856 100644 --- a/stubs/Pillow/PIL/_imaging.pyi +++ b/stubs/Pillow/PIL/_imaging.pyi @@ -1,6 +1,6 @@ from _typeshed import Incomplete from collections.abc import Sequence -from typing import Any +from typing import Protocol from typing_extensions import Literal DEFAULT_STRATEGY: Literal[0] @@ -9,17 +9,19 @@ HUFFMAN_ONLY: Literal[2] RLE: Literal[3] FIXED: Literal[4] -class _PixelAccess: - # As well as the C extension source, this is also documented at - # Pillow's docs/reference/PixelAccess.rst, e.g. - # https://github.com/python-pillow/Pillow/blob/main/docs/reference/PixelAccess.rst - # The name is prefixed here with an underscore as PixelAccess is not - # runtime-importable. - - def __setitem__(self, xy: tuple[int, int], color) -> None: ... - def __getitem__(self, xy: tuple[int, int]) -> Any: ... - def putpixel(self, xy: tuple[int, int], color) -> None: ... - def getpixel(self, xy: tuple[int, int]) -> Any: ... +class _PixelAccessor(Protocol): # noqa: Y046 + # PIL has two concrete types for accessing an image's pixels by coordinate lookup: + # PixelAccess (written in C; not runtime-importable) and PyAccess (written in + # Python + cffi; is runtime-importable). PixelAccess came first. PyAccess was added + # in later to support PyPy, but otherwise is intended to expose the same interface + # PixelAccess. + # + # This protocol describes that interface. + # TODO: should the color args and getter return types be _Color? + def __setitem__(self, xy: tuple[int, int], color: Incomplete) -> None: ... + def __getitem__(self, xy: tuple[int, int]) -> Incomplete: ... + def putpixel(self, xy: tuple[int, int], color: Incomplete) -> None: ... + def getpixel(self, xy: tuple[int, int]) -> Incomplete: ... class _Path: def __getattr__(self, item: str) -> Incomplete: ... From 076843d28984edb5eaad455e12fa49988cce3443 Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sat, 8 Apr 2023 17:46:32 +0100 Subject: [PATCH 07/11] Add return type for the other load methods --- stubs/Pillow/PIL/FpxImagePlugin.pyi | 3 ++- stubs/Pillow/PIL/Image.pyi | 1 - stubs/Pillow/PIL/IptcImagePlugin.pyi | 3 ++- stubs/Pillow/PIL/Jpeg2KImagePlugin.pyi | 3 ++- stubs/Pillow/PIL/TiffImagePlugin.pyi | 3 ++- stubs/Pillow/PIL/WebPImagePlugin.pyi | 3 ++- 6 files changed, 10 insertions(+), 6 deletions(-) diff --git a/stubs/Pillow/PIL/FpxImagePlugin.pyi b/stubs/Pillow/PIL/FpxImagePlugin.pyi index 226a10f27a16..a8871589d18d 100644 --- a/stubs/Pillow/PIL/FpxImagePlugin.pyi +++ b/stubs/Pillow/PIL/FpxImagePlugin.pyi @@ -2,6 +2,7 @@ from _typeshed import Incomplete from typing import Any, ClassVar from typing_extensions import Literal, TypeAlias +from ._imaging import _PixelAccessor from .ImageFile import ImageFile _OleFileIO: TypeAlias = Any # olefile.OleFileIO @@ -19,4 +20,4 @@ class FpxImageFile(ImageFile): jpeg: dict[int, Incomplete] tile_prefix: Incomplete stream: list[str] - def load(self): ... + def load(self) -> _PixelAccessor: ... diff --git a/stubs/Pillow/PIL/Image.pyi b/stubs/Pillow/PIL/Image.pyi index 3c52692fb0af..26f382a87540 100644 --- a/stubs/Pillow/PIL/Image.pyi +++ b/stubs/Pillow/PIL/Image.pyi @@ -5,7 +5,6 @@ from pathlib import Path from typing import Any, ClassVar, Protocol, SupportsBytes from typing_extensions import Literal, Self, TypeAlias - from ._imaging import ( DEFAULT_STRATEGY as DEFAULT_STRATEGY, FILTERED as FILTERED, diff --git a/stubs/Pillow/PIL/IptcImagePlugin.pyi b/stubs/Pillow/PIL/IptcImagePlugin.pyi index 738caa991214..3430a35660bc 100644 --- a/stubs/Pillow/PIL/IptcImagePlugin.pyi +++ b/stubs/Pillow/PIL/IptcImagePlugin.pyi @@ -1,6 +1,7 @@ from typing import Any, ClassVar from typing_extensions import Literal +from ._imaging import _PixelAccessor from .ImageFile import ImageFile COMPRESSION: Any @@ -15,6 +16,6 @@ class IptcImageFile(ImageFile): def getint(self, key): ... def field(self): ... im: Any - def load(self): ... + def load(self) -> _PixelAccessor: ... def getiptcinfo(im): ... diff --git a/stubs/Pillow/PIL/Jpeg2KImagePlugin.pyi b/stubs/Pillow/PIL/Jpeg2KImagePlugin.pyi index a37d618f97f1..1c82de8205a8 100644 --- a/stubs/Pillow/PIL/Jpeg2KImagePlugin.pyi +++ b/stubs/Pillow/PIL/Jpeg2KImagePlugin.pyi @@ -1,6 +1,7 @@ from typing import Any, ClassVar from typing_extensions import Literal +from ._imaging import _PixelAccessor from .ImageFile import ImageFile class Jpeg2KImageFile(ImageFile): @@ -8,4 +9,4 @@ class Jpeg2KImageFile(ImageFile): format_description: ClassVar[str] reduce: Any tile: Any - def load(self): ... + def load(self) -> _PixelAccessor: ... diff --git a/stubs/Pillow/PIL/TiffImagePlugin.pyi b/stubs/Pillow/PIL/TiffImagePlugin.pyi index bb1ad85d6470..ba34fc3144d0 100644 --- a/stubs/Pillow/PIL/TiffImagePlugin.pyi +++ b/stubs/Pillow/PIL/TiffImagePlugin.pyi @@ -5,6 +5,7 @@ from types import TracebackType from typing import Any, ClassVar from typing_extensions import Literal +from ._imaging import _PixelAccessor from .ImageFile import ImageFile logger: Any @@ -153,7 +154,7 @@ class TiffImageFile(ImageFile): im: Any def seek(self, frame) -> None: ... def tell(self): ... - def load(self): ... + def load(self) -> _PixelAccessor: ... def load_end(self) -> None: ... SAVE_INFO: Any diff --git a/stubs/Pillow/PIL/WebPImagePlugin.pyi b/stubs/Pillow/PIL/WebPImagePlugin.pyi index 1b3d97718f86..43e06c67578e 100644 --- a/stubs/Pillow/PIL/WebPImagePlugin.pyi +++ b/stubs/Pillow/PIL/WebPImagePlugin.pyi @@ -1,6 +1,7 @@ from typing import Any, ClassVar from typing_extensions import Literal, TypeAlias +from ._imaging import _PixelAccessor from .ImageFile import ImageFile SUPPORTED: bool @@ -13,5 +14,5 @@ class WebPImageFile(ImageFile): def seek(self, frame) -> None: ... fp: Any tile: Any - def load(self): ... + def load(self) -> _PixelAccessor: ... def tell(self): ... From 155782b408a6f66a99395ee1cfe01ff8e46838ff Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sat, 8 Apr 2023 18:00:21 +0100 Subject: [PATCH 08/11] Fix missing import --- stubs/Pillow/PIL/Image.pyi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stubs/Pillow/PIL/Image.pyi b/stubs/Pillow/PIL/Image.pyi index 26f382a87540..704cbf3210f8 100644 --- a/stubs/Pillow/PIL/Image.pyi +++ b/stubs/Pillow/PIL/Image.pyi @@ -3,6 +3,8 @@ from collections.abc import Callable, Iterable, Iterator, MutableMapping, Sequen from enum import IntEnum from pathlib import Path from typing import Any, ClassVar, Protocol, SupportsBytes + +from PIL.PyAccess import PyAccess from typing_extensions import Literal, Self, TypeAlias from ._imaging import ( From 72e6aa1f3befad29e4b6a03d39c213ff50eef55a Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sat, 8 Apr 2023 18:00:29 +0100 Subject: [PATCH 09/11] Remove pyaccess attribute from PngImageFile Already defined on Image --- stubs/Pillow/PIL/PngImagePlugin.pyi | 1 - 1 file changed, 1 deletion(-) diff --git a/stubs/Pillow/PIL/PngImagePlugin.pyi b/stubs/Pillow/PIL/PngImagePlugin.pyi index 178ffa9ac61c..4cae9d92d46d 100644 --- a/stubs/Pillow/PIL/PngImagePlugin.pyi +++ b/stubs/Pillow/PIL/PngImagePlugin.pyi @@ -102,7 +102,6 @@ class PngImageFile(ImageFile): def load_read(self, read_bytes): ... png: Any im: Any - pyaccess: Any def load_end(self) -> None: ... def getexif(self): ... From 921641f5baa05d9f1a9a76e7bfee7a2ccd54dd71 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 8 Apr 2023 17:03:49 +0000 Subject: [PATCH 10/11] [pre-commit.ci] auto fixes from pre-commit.com hooks --- stubs/Pillow/PIL/Image.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stubs/Pillow/PIL/Image.pyi b/stubs/Pillow/PIL/Image.pyi index 704cbf3210f8..c965d1489b98 100644 --- a/stubs/Pillow/PIL/Image.pyi +++ b/stubs/Pillow/PIL/Image.pyi @@ -3,9 +3,9 @@ from collections.abc import Callable, Iterable, Iterator, MutableMapping, Sequen from enum import IntEnum from pathlib import Path from typing import Any, ClassVar, Protocol, SupportsBytes +from typing_extensions import Literal, Self, TypeAlias from PIL.PyAccess import PyAccess -from typing_extensions import Literal, Self, TypeAlias from ._imaging import ( DEFAULT_STRATEGY as DEFAULT_STRATEGY, From 9383c345080c96e4d8da1982c17590cac2073e1e Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sat, 8 Apr 2023 18:08:59 +0100 Subject: [PATCH 11/11] Fix stupid find-and-replace typo --- stubs/Pillow/PIL/PyAccess.pyi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stubs/Pillow/PIL/PyAccess.pyi b/stubs/Pillow/PIL/PyAccess.pyi index 862527be6eca..bed128c38a67 100644 --- a/stubs/Pillow/PIL/PyAccess.pyi +++ b/stubs/Pillow/PIL/PyAccess.pyi @@ -1,12 +1,12 @@ from logging import Logger from typing import Any -from PIL._imaging import _PixelAccessoror +from PIL._imaging import _PixelAccessor ffi: Any logger: Logger -class PyAccess(_PixelAccessoror): +class PyAccess(_PixelAccessor): readonly: Any image8: Any image32: Any