From a5aa51563151cf2b4644c68a68f06a60b8e329e6 Mon Sep 17 00:00:00 2001 From: matejcik Date: Thu, 2 May 2024 14:49:49 +0200 Subject: [PATCH] style(python): upgrade to pyright 1.1.361 had to add a typestub for PIL due to https://github.com/microsoft/pyright/issues/7832 We should remove it if that is either fixed or, if I fail to convince Eric, after the relevant type information is added to Pillow [no changelog] --- python/pyrightconfig.json | 5 +- python/src/trezorlib/cli/__init__.py | 2 +- python/src/trezorlib/cli/ethereum.py | 2 +- python/src/trezorlib/cli/trezorctl.py | 4 +- python/src/trezorlib/client.py | 2 +- python/src/trezorlib/definitions.py | 2 +- python/src/trezorlib/mapping.py | 6 +- python/src/trezorlib/protobuf.py | 5 +- python/src/trezorlib/qt/pinmatrix.py | 2 +- python/src/trezorlib/tools.py | 6 +- python/src/trezorlib/transport/webusb.py | 2 +- python/stubs/PIL/Image.pyi | 1455 ++++++++++++++++++++++ python/tools/pybridge.py | 2 +- python/tools/trezorctl_script_client.py | 14 +- 14 files changed, 1488 insertions(+), 21 deletions(-) create mode 100644 python/stubs/PIL/Image.pyi diff --git a/python/pyrightconfig.json b/python/pyrightconfig.json index a6257e044d..397dc629e3 100644 --- a/python/pyrightconfig.json +++ b/python/pyrightconfig.json @@ -4,10 +4,13 @@ "tools", "helper-scripts" ], + "stubPath": "./stubs", "pythonVersion": "3.8", "typeCheckingMode": "basic", "reportMissingImports": false, "reportUntypedFunctionDecorator": true, "reportUntypedClassDecorator": true, - "reportMissingParameterType": true + "reportMissingParameterType": true, + "useLibraryCodeForTypes": false, + "reportMissingModuleSource": false } diff --git a/python/src/trezorlib/cli/__init__.py b/python/src/trezorlib/cli/__init__.py index 91cd0ce1e3..050e3788f7 100644 --- a/python/src/trezorlib/cli/__init__.py +++ b/python/src/trezorlib/cli/__init__.py @@ -158,7 +158,7 @@ def with_client(func: "Callable[Concatenate[TrezorClient, P], R]") -> "Callable[ # the return type of @click.pass_obj is improperly specified and pyright doesn't # understand that it converts f(obj, *args, **kwargs) to f(*args, **kwargs) - return trezorctl_command_with_client # type: ignore [cannot be assigned to return type] + return trezorctl_command_with_client # type: ignore [is incompatible with return type] class AliasedGroup(click.Group): diff --git a/python/src/trezorlib/cli/ethereum.py b/python/src/trezorlib/cli/ethereum.py index 38b536bceb..e5aac60720 100644 --- a/python/src/trezorlib/cli/ethereum.py +++ b/python/src/trezorlib/cli/ethereum.py @@ -94,7 +94,7 @@ def _amount_to_int( if value.isdigit(): return int(value) try: - number, unit = re.match(r"^(\d+(?:.\d+)?)([a-z]+)", value).groups() # type: ignore ["groups" is not a known member of "None"] + number, unit = re.match(r"^(\d+(?:.\d+)?)([a-z]+)", value).groups() # type: ignore ["groups" is not a known attribute of "None"] scale = ETHER_UNITS[unit] decoded_number = Decimal(number) return int(decoded_number * scale) diff --git a/python/src/trezorlib/cli/trezorctl.py b/python/src/trezorlib/cli/trezorctl.py index 611cbf1a74..2e030ed931 100755 --- a/python/src/trezorlib/cli/trezorctl.py +++ b/python/src/trezorlib/cli/trezorctl.py @@ -119,7 +119,7 @@ class TrezorctlGroup(AliasedGroup): command, subcommand = cmd_name.split("-", maxsplit=1) # get_command can return None and the following line will fail. # We don't care, we ignore the exception anyway. - return super().get_command(ctx, command).get_command(ctx, subcommand) # type: ignore ["get_command" is not a known member of "None";;Cannot access member "get_command" for type "Command"] + return super().get_command(ctx, command).get_command(ctx, subcommand) # type: ignore [get_command] except Exception: pass @@ -143,7 +143,7 @@ class TrezorctlGroup(AliasedGroup): from click import __version__ as click_version if click_version.startswith("7."): - return super().resultcallback() # type: ignore [Cannot access member] + return super().resultcallback() # type: ignore [Cannot access attribute] else: return super().result_callback() diff --git a/python/src/trezorlib/client.py b/python/src/trezorlib/client.py index 8a7870486d..7fd6dae32b 100644 --- a/python/src/trezorlib/client.py +++ b/python/src/trezorlib/client.py @@ -123,7 +123,7 @@ class TrezorClient(Generic[UI]): LOG.info(f"creating client instance for device: {transport.get_path()}") # Here, self.model could be set to None. Unless _init_device is False, it will # get correctly reconfigured as part of the init_device flow. - self.model = model # type: ignore [Type "None" cannot be assigned] + self.model = model # type: ignore ["None" is incompatible with "TrezorModel"] if self.model: self.mapping = self.model.default_mapping else: diff --git a/python/src/trezorlib/definitions.py b/python/src/trezorlib/definitions.py index 2960678c3f..94672e38e3 100644 --- a/python/src/trezorlib/definitions.py +++ b/python/src/trezorlib/definitions.py @@ -139,7 +139,7 @@ class TarSource(Source): inner_name = "/".join(components) LOG.info("Extracting definition from %s:%s", self.archive.name, inner_name) try: - return self.archive.extractfile(inner_name).read() # type: ignore [not a known member] + return self.archive.extractfile(inner_name).read() # type: ignore [not a known attribute] except Exception: LOG.info("Requested definition at %s was not found", inner_name) return None diff --git a/python/src/trezorlib/mapping.py b/python/src/trezorlib/mapping.py index e8fb60edb5..d50324d586 100644 --- a/python/src/trezorlib/mapping.py +++ b/python/src/trezorlib/mapping.py @@ -14,10 +14,14 @@ # You should have received a copy of the License along with this library. # If not, see . +from __future__ import annotations + import io from types import ModuleType from typing import Dict, Optional, Tuple, Type, TypeVar +from typing_extensions import Self + from . import messages, protobuf T = TypeVar("T") @@ -71,7 +75,7 @@ class ProtobufMapping: return protobuf.load_message(buf, cls) @classmethod - def from_module(cls: Type[T], module: ModuleType) -> T: + def from_module(cls, module: ModuleType) -> Self: """Generate a mapping from a module. The module must have a `MessageType` enum that specifies individual wire types. diff --git a/python/src/trezorlib/protobuf.py b/python/src/trezorlib/protobuf.py index e6fdcdbf0e..f0d407191a 100644 --- a/python/src/trezorlib/protobuf.py +++ b/python/src/trezorlib/protobuf.py @@ -183,9 +183,9 @@ class Field: class _MessageTypeMeta(type): def __init__(cls, name: str, bases: tuple, d: dict) -> None: - super().__init__(name, bases, d) # type: ignore [Expected 1 positional argument] + super().__init__(name, bases, d) if name != "MessageType": - cls.__init__ = MessageType.__init__ # type: ignore ["__init__" is obscured by a declaration of the same name;;Cannot assign member "__init__" for type "_MessageTypeMeta"] + cls.__init__ = MessageType.__init__ # type: ignore [Parameter] class MessageType(metaclass=_MessageTypeMeta): @@ -209,6 +209,7 @@ class MessageType(metaclass=_MessageTypeMeta): for field, val in zip_longest(self.FIELDS.values(), args, fillvalue=MISSING): if field is MISSING: raise TypeError("too many positional arguments") + assert isinstance(field, Field) if field.name in kwargs and val is not MISSING: # both *args and **kwargs specify the same thing raise TypeError(f"got multiple values for argument '{field.name}'") diff --git a/python/src/trezorlib/qt/pinmatrix.py b/python/src/trezorlib/qt/pinmatrix.py index 09c757e2dd..06b6b650e8 100644 --- a/python/src/trezorlib/qt/pinmatrix.py +++ b/python/src/trezorlib/qt/pinmatrix.py @@ -158,7 +158,7 @@ if __name__ == "__main__": if QT_VERSION_STR >= "5": ok.clicked.connect(clicked) elif QT_VERSION_STR >= "4": - QObject.connect(ok, SIGNAL("clicked()"), clicked) # type: ignore ["QObject" is possibly unbound;;"SIGNAL" is possibly unbound] + QObject.connect(ok, SIGNAL("clicked()"), clicked) else: raise RuntimeError("Unsupported Qt version") diff --git a/python/src/trezorlib/tools.py b/python/src/trezorlib/tools.py index 259a99a948..4fd1558ec2 100644 --- a/python/src/trezorlib/tools.py +++ b/python/src/trezorlib/tools.py @@ -42,13 +42,15 @@ if TYPE_CHECKING: from typing_extensions import Concatenate, ParamSpec - from .client import TrezorClient + from . import client from .protobuf import MessageType MT = TypeVar("MT", bound=MessageType) P = ParamSpec("P") R = TypeVar("R") + TrezorClient = TypeVar("TrezorClient", bound=client.TrezorClient) + HARDENED_FLAG = 1 << 31 Address = NewType("Address", List[int]) @@ -154,7 +156,7 @@ def b58decode_int(v: str) -> int: for char in v: decimal = decimal * __b58base + __b58chars.index(char) except KeyError: - raise ValueError(f"Invalid character {char!r}") from None # type: ignore [possibly unbound] + raise ValueError(f"Invalid character {char!r}") from None return decimal diff --git a/python/src/trezorlib/transport/webusb.py b/python/src/trezorlib/transport/webusb.py index d733ce6669..1b60df61bd 100644 --- a/python/src/trezorlib/transport/webusb.py +++ b/python/src/trezorlib/transport/webusb.py @@ -124,7 +124,7 @@ class WebUsbTransport(ProtocolBasedTransport): if cls.context is None: cls.context = usb1.USBContext() cls.context.open() - atexit.register(cls.context.close) # type: ignore [Param spec "_P@register" has no bound value] + atexit.register(cls.context.close) if models is None: models = TREZORS diff --git a/python/stubs/PIL/Image.pyi b/python/stubs/PIL/Image.pyi new file mode 100644 index 0000000000..3426ce1b9f --- /dev/null +++ b/python/stubs/PIL/Image.pyi @@ -0,0 +1,1455 @@ +""" +This type stub file was generated by pyright. +""" + +import abc +from collections.abc import Callable, MutableMapping +from enum import IntEnum +from typing import Any, IO, TYPE_CHECKING + +from PIL import ImageFile + +class Transpose(IntEnum): + FLIP_LEFT_RIGHT = ... + FLIP_TOP_BOTTOM = ... + ROTATE_90 = ... + ROTATE_180 = ... + ROTATE_270 = ... + TRANSPOSE = ... + TRANSVERSE = ... + +class Transform(IntEnum): + AFFINE = ... + EXTENT = ... + PERSPECTIVE = ... + QUAD = ... + MESH = ... + +class Resampling(IntEnum): + NEAREST = ... + BOX = ... + BILINEAR = ... + HAMMING = ... + BICUBIC = ... + LANCZOS = ... + +_filters_support = ... + +class Dither(IntEnum): + NONE = ... + ORDERED = ... + RASTERIZE = ... + FLOYDSTEINBERG = ... + +class Palette(IntEnum): + WEB = ... + ADAPTIVE = ... + +class Quantize(IntEnum): + MEDIANCUT = ... + MAXCOVERAGE = ... + FASTOCTREE = ... + LIBIMAGEQUANT = ... + +class Image: + """ + This class represents an image object. To create + :py:class:`~PIL.Image.Image` objects, use the appropriate factory + functions. There's hardly ever any reason to call the Image constructor + directly. + + * :py:func:`~PIL.Image.open` + * :py:func:`~PIL.Image.new` + * :py:func:`~PIL.Image.frombytes` + """ + + format: str | None = ... + format_description: str | None = ... + _close_exclusive_fp_after_loading = ... + def __init__(self) -> None: ... + @property + def width(self) -> int: ... + @property + def height(self) -> int: ... + @property + def size(self) -> tuple[int, int]: ... + @property + def mode(self): # -> str | Any: + ... + + def __enter__(self): # -> Self: + ... + + def __exit__(self, *args): # -> None: + ... + + def close(self) -> None: + """ + Closes the file pointer, if possible. + + This operation will destroy the image core and release its memory. + The image data will be unusable afterward. + + This function is required to close images that have multiple frames or + have not had their file read and closed by the + :py:meth:`~PIL.Image.Image.load` method. See :ref:`file-handling` for + more information. + """ + ... + + def __eq__(self, other) -> bool: ... + def __repr__(self) -> str: ... + @property + def __array_interface__(self): # -> dict[str, int]: + ... + + def __getstate__(self): # -> list[Any]: + ... + + def __setstate__(self, state) -> None: ... + def tobytes(self, encoder_name: str = ..., *args) -> bytes: + """ + Return image as a bytes object. + + .. warning:: + + This method returns the raw image data from the internal + storage. For compressed image data (e.g. PNG, JPEG) use + :meth:`~.save`, with a BytesIO parameter for in-memory + data. + + :param encoder_name: What encoder to use. The default is to + use the standard "raw" encoder. + + A list of C encoders can be seen under + codecs section of the function array in + :file:`_imaging.c`. Python encoders are + registered within the relevant plugins. + :param args: Extra arguments to the encoder. + :returns: A :py:class:`bytes` object. + """ + ... + + def tobitmap(self, name: str = ...) -> bytes: + """ + Returns the image converted to an X11 bitmap. + + .. note:: This method only works for mode "1" images. + + :param name: The name prefix to use for the bitmap variables. + :returns: A string containing an X11 bitmap. + :raises ValueError: If the mode is not "1" + """ + ... + + def frombytes(self, data: bytes, decoder_name: str = ..., *args) -> None: + """ + Loads this image with pixel data from a bytes object. + + This method is similar to the :py:func:`~PIL.Image.frombytes` function, + but loads data into this image instead of creating a new image object. + """ + ... + + def load(self): # -> Any | None: + """ + Allocates storage for the image and loads the pixel data. In + normal cases, you don't need to call this method, since the + Image class automatically loads an opened image when it is + accessed for the first time. + + If the file associated with the image was opened by Pillow, then this + method will close it. The exception to this is if the image has + multiple frames, in which case the file will be left open for seek + operations. See :ref:`file-handling` for more information. + + :returns: An image access object. + :rtype: :ref:`PixelAccess` or :py:class:`PIL.PyAccess` + """ + ... + + def verify(self): # -> None: + """ + Verifies the contents of a file. For data read from a file, this + method attempts to determine if the file is broken, without + actually decoding the image data. If this method finds any + problems, it raises suitable exceptions. If you need to load + the image after using this method, you must reopen the image + file. + """ + ... + + def convert( + self, + mode: str | None = ..., + matrix: tuple[float, ...] | None = ..., + dither: Dither | None = ..., + palette: Palette = ..., + colors: int = ..., + ) -> Image: + """ + Returns a converted copy of this image. For the "P" mode, this + method translates pixels through the palette. If mode is + omitted, a mode is chosen so that all information in the image + and the palette can be represented without a palette. + + This supports all possible conversions between "L", "RGB" and "CMYK". The + ``matrix`` argument only supports "L" and "RGB". + + When translating a color image to grayscale (mode "L"), + the library uses the ITU-R 601-2 luma transform:: + + L = R * 299/1000 + G * 587/1000 + B * 114/1000 + + The default method of converting a grayscale ("L") or "RGB" + image into a bilevel (mode "1") image uses Floyd-Steinberg + dither to approximate the original image luminosity levels. If + dither is ``None``, all values larger than 127 are set to 255 (white), + all other values to 0 (black). To use other thresholds, use the + :py:meth:`~PIL.Image.Image.point` method. + + When converting from "RGBA" to "P" without a ``matrix`` argument, + this passes the operation to :py:meth:`~PIL.Image.Image.quantize`, + and ``dither`` and ``palette`` are ignored. + + When converting from "PA", if an "RGBA" palette is present, the alpha + channel from the image will be used instead of the values from the palette. + + :param mode: The requested mode. See: :ref:`concept-modes`. + :param matrix: An optional conversion matrix. If given, this + should be 4- or 12-tuple containing floating point values. + :param dither: Dithering method, used when converting from + mode "RGB" to "P" or from "RGB" or "L" to "1". + Available methods are :data:`Dither.NONE` or :data:`Dither.FLOYDSTEINBERG` + (default). Note that this is not used when ``matrix`` is supplied. + :param palette: Palette to use when converting from mode "RGB" + to "P". Available palettes are :data:`Palette.WEB` or + :data:`Palette.ADAPTIVE`. + :param colors: Number of colors to use for the :data:`Palette.ADAPTIVE` + palette. Defaults to 256. + :rtype: :py:class:`~PIL.Image.Image` + :returns: An :py:class:`~PIL.Image.Image` object. + """ + ... + + def quantize( + self, + colors: int = ..., + method: Quantize | None = ..., + kmeans: int = ..., + palette=..., + dither: Dither = ..., + ) -> Image: + """ + Convert the image to 'P' mode with the specified number + of colors. + + :param colors: The desired number of colors, <= 256 + :param method: :data:`Quantize.MEDIANCUT` (median cut), + :data:`Quantize.MAXCOVERAGE` (maximum coverage), + :data:`Quantize.FASTOCTREE` (fast octree), + :data:`Quantize.LIBIMAGEQUANT` (libimagequant; check support + using :py:func:`PIL.features.check_feature` with + ``feature="libimagequant"``). + + By default, :data:`Quantize.MEDIANCUT` will be used. + + The exception to this is RGBA images. :data:`Quantize.MEDIANCUT` + and :data:`Quantize.MAXCOVERAGE` do not support RGBA images, so + :data:`Quantize.FASTOCTREE` is used by default instead. + :param kmeans: Integer greater than or equal to zero. + :param palette: Quantize to the palette of given + :py:class:`PIL.Image.Image`. + :param dither: Dithering method, used when converting from + mode "RGB" to "P" or from "RGB" or "L" to "1". + Available methods are :data:`Dither.NONE` or :data:`Dither.FLOYDSTEINBERG` + (default). + :returns: A new image + """ + ... + + def copy(self) -> Image: + """ + Copies this image. Use this method if you wish to paste things + into an image, but still retain the original. + + :rtype: :py:class:`~PIL.Image.Image` + :returns: An :py:class:`~PIL.Image.Image` object. + """ + ... + __copy__ = ... + def crop(self, box: tuple[int, int, int, int] | None = ...) -> Image: + """ + Returns a rectangular region from this image. The box is a + 4-tuple defining the left, upper, right, and lower pixel + coordinate. See :ref:`coordinate-system`. + + Note: Prior to Pillow 3.4.0, this was a lazy operation. + + :param box: The crop rectangle, as a (left, upper, right, lower)-tuple. + :rtype: :py:class:`~PIL.Image.Image` + :returns: An :py:class:`~PIL.Image.Image` object. + """ + ... + + def draft(self, mode, size): # -> None: + """ + Configures the image file loader so it returns a version of the + image that as closely as possible matches the given mode and + size. For example, you can use this method to convert a color + JPEG to grayscale while loading it. + + If any changes are made, returns a tuple with the chosen ``mode`` and + ``box`` with coordinates of the original image within the altered one. + + Note that this method modifies the :py:class:`~PIL.Image.Image` object + in place. If the image has already been loaded, this method has no + effect. + + Note: This method is not implemented for most images. It is + currently implemented only for JPEG and MPO images. + + :param mode: The requested mode. + :param size: The requested size in pixels, as a 2-tuple: + (width, height). + """ + ... + + def filter(self, filter): # -> Image: + """ + Filters this image using the given filter. For a list of + available filters, see the :py:mod:`~PIL.ImageFilter` module. + + :param filter: Filter kernel. + :returns: An :py:class:`~PIL.Image.Image` object.""" + ... + + def getbands(self) -> tuple[str, ...]: + """ + Returns a tuple containing the name of each band in this image. + For example, ``getbands`` on an RGB image returns ("R", "G", "B"). + + :returns: A tuple containing band names. + :rtype: tuple + """ + ... + + def getbbox(self, *, alpha_only: bool = ...) -> tuple[int, int, int, int]: + """ + Calculates the bounding box of the non-zero regions in the + image. + + :param alpha_only: Optional flag, defaulting to ``True``. + If ``True`` and the image has an alpha channel, trim transparent pixels. + Otherwise, trim pixels when all channels are zero. + Keyword-only argument. + :returns: The bounding box is returned as a 4-tuple defining the + left, upper, right, and lower pixel coordinate. See + :ref:`coordinate-system`. If the image is completely empty, this + method returns None. + + """ + ... + + def getcolors(self, maxcolors: int = ...): # -> list[tuple[Any, int]] | Any | None: + """ + Returns a list of colors used in this image. + + The colors will be in the image's mode. For example, an RGB image will + return a tuple of (red, green, blue) color values, and a P image will + return the index of the color in the palette. + + :param maxcolors: Maximum number of colors. If this number is + exceeded, this method returns None. The default limit is + 256 colors. + :returns: An unsorted list of (count, pixel) values. + """ + ... + + def getdata(self, band: int | None = ...): # -> Any | DeferredError | None: + """ + Returns the contents of this image as a sequence object + containing pixel values. The sequence object is flattened, so + that values for line one follow directly after the values of + line zero, and so on. + + Note that the sequence object returned by this method is an + internal PIL data type, which only supports certain sequence + operations. To convert it to an ordinary sequence (e.g. for + printing), use ``list(im.getdata())``. + + :param band: What band to return. The default is to return + all bands. To return a single band, pass in the index + value (e.g. 0 to get the "R" band from an "RGB" image). + :returns: A sequence-like object. + """ + ... + + def getextrema(self) -> tuple[float, float] | tuple[tuple[int, int], ...]: + """ + Gets the minimum and maximum pixel values for each band in + the image. + + :returns: For a single-band image, a 2-tuple containing the + minimum and maximum pixel value. For a multi-band image, + a tuple containing one 2-tuple for each band. + """ + ... + + def getexif(self) -> Exif: + """ + Gets EXIF data from the image. + + :returns: an :py:class:`~PIL.Image.Exif` object. + """ + ... + + def get_child_images(self): # -> list[Any]: + ... + + def getim(self): # -> Any: + """ + Returns a capsule that points to the internal image memory. + + :returns: A capsule object. + """ + ... + + def getpalette(self, rawmode: str | None = ...) -> list[int] | None: + """ + Returns the image palette as a list. + + :param rawmode: The mode in which to return the palette. ``None`` will + return the palette in its current mode. + + .. versionadded:: 9.1.0 + + :returns: A list of color values [r, g, b, ...], or None if the + image has no palette. + """ + ... + + @property + def has_transparency_data(self) -> bool: + """ + Determine if an image has transparency data, whether in the form of an + alpha channel, a palette with an alpha channel, or a "transparency" key + in the info dictionary. + + Note the image might still appear solid, if all of the values shown + within are opaque. + + :returns: A boolean. + """ + ... + + def apply_transparency(self): # -> None: + """ + If a P mode image has a "transparency" key in the info dictionary, + remove the key and instead apply the transparency to the palette. + Otherwise, the image is unchanged. + """ + ... + + def getpixel(self, xy): # -> Any: + """ + Returns the pixel value at a given position. + + :param xy: The coordinate, given as (x, y). See + :ref:`coordinate-system`. + :returns: The pixel value. If the image is a multi-layer image, + this method returns a tuple. + """ + ... + + def getprojection(self) -> tuple[list[int], list[int]]: + """ + Get projection to x and y axes + + :returns: Two sequences, indicating where there are non-zero + pixels along the X-axis and the Y-axis, respectively. + """ + ... + + def histogram(self, mask: Image | None = ..., extrema=...) -> list[int]: + """ + Returns a histogram for the image. The histogram is returned as a + list of pixel counts, one for each pixel value in the source + image. Counts are grouped into 256 bins for each band, even if + the image has more than 8 bits per band. If the image has more + than one band, the histograms for all bands are concatenated (for + example, the histogram for an "RGB" image contains 768 values). + + A bilevel image (mode "1") is treated as a grayscale ("L") image + by this method. + + If a mask is provided, the method returns a histogram for those + parts of the image where the mask image is non-zero. The mask + image must have the same size as the image, and be either a + bi-level image (mode "1") or a grayscale image ("L"). + + :param mask: An optional mask. + :param extrema: An optional tuple of manually-specified extrema. + :returns: A list containing pixel counts. + """ + ... + + def entropy(self, mask=..., extrema=...): # -> Any: + """ + Calculates and returns the entropy for the image. + + A bilevel image (mode "1") is treated as a grayscale ("L") + image by this method. + + If a mask is provided, the method employs the histogram for + those parts of the image where the mask image is non-zero. + The mask image must have the same size as the image, and be + either a bi-level image (mode "1") or a grayscale image ("L"). + + :param mask: An optional mask. + :param extrema: An optional tuple of manually-specified extrema. + :returns: A float value representing the image entropy + """ + ... + + def paste(self, im, box=..., mask=...) -> None: + """ + Pastes another image into this image. The box argument is either + a 2-tuple giving the upper left corner, a 4-tuple defining the + left, upper, right, and lower pixel coordinate, or None (same as + (0, 0)). See :ref:`coordinate-system`. If a 4-tuple is given, the size + of the pasted image must match the size of the region. + + If the modes don't match, the pasted image is converted to the mode of + this image (see the :py:meth:`~PIL.Image.Image.convert` method for + details). + + Instead of an image, the source can be a integer or tuple + containing pixel values. The method then fills the region + with the given color. When creating RGB images, you can + also use color strings as supported by the ImageColor module. + + If a mask is given, this method updates only the regions + indicated by the mask. You can use either "1", "L", "LA", "RGBA" + or "RGBa" images (if present, the alpha band is used as mask). + Where the mask is 255, the given image is copied as is. Where + the mask is 0, the current value is preserved. Intermediate + values will mix the two images together, including their alpha + channels if they have them. + + 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 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 + upper left corner. + + If an image is given as the second argument and there is no + third, the box defaults to (0, 0), and the second argument + is interpreted as a mask image. + :param mask: An optional mask image. + """ + ... + + def alpha_composite(self, im, dest=..., source=...): # -> None: + """'In-place' analog of Image.alpha_composite. Composites an image + onto this image. + + :param im: image to composite over this one + :param dest: Optional 2 tuple (left, top) specifying the upper + left corner in this (destination) image. + :param source: Optional 2 (left, top) tuple for the upper left + corner in the overlay source image, or 4 tuple (left, top, right, + bottom) for the bounds of the source rectangle + + Performance Note: Not currently implemented in-place in the core layer. + """ + ... + + def point(self, lut, mode: str | None = ...) -> Image: + """ + Maps this image through a lookup table or function. + + :param lut: A lookup table, containing 256 (or 65536 if + self.mode=="I" and mode == "L") values per band in the + image. A function can be used instead, it should take a + single argument. The function is called once for each + possible pixel value, and the resulting table is applied to + all bands of the image. + + It may also be an :py:class:`~PIL.Image.ImagePointHandler` + object:: + + class Example(Image.ImagePointHandler): + def point(self, data): + # Return result + :param mode: Output mode (default is same as input). This can only be used if + the source image has mode "L" or "P", and the output has mode "1" or the + source image mode is "I" and the output mode is "L". + :returns: An :py:class:`~PIL.Image.Image` object. + """ + ... + + def putalpha(self, alpha): # -> None: + """ + Adds or replaces the alpha layer in this image. If the image + does not have an alpha layer, it's converted to "LA" or "RGBA". + The new layer must be either "L" or "1". + + :param alpha: The new alpha layer. This can either be an "L" or "1" + image having the same size as this image, or an integer or + other color value. + """ + ... + + def putdata(self, data, scale=..., offset=...): # -> None: + """ + Copies pixel data from a flattened sequence object into the image. The + values should start at the upper left corner (0, 0), continue to the + end of the line, followed directly by the first value of the second + line, and so on. Data will be read until either the image or the + sequence ends. The scale and offset values are used to adjust the + sequence values: **pixel = value*scale + offset**. + + :param data: A flattened sequence object. + :param scale: An optional scale value. The default is 1.0. + :param offset: An optional offset value. The default is 0.0. + """ + ... + + def putpalette(self, data, rawmode=...) -> None: + """ + Attaches a palette to this image. The image must be a "P", "PA", "L" + or "LA" image. + + The palette sequence must contain at most 256 colors, made up of one + integer value for each channel in the raw mode. + For example, if the raw mode is "RGB", then it can contain at most 768 + values, made up of red, green and blue values for the corresponding pixel + index in the 256 colors. + If the raw mode is "RGBA", then it can contain at most 1024 values, + containing red, green, blue and alpha values. + + Alternatively, an 8-bit string may be used instead of an integer sequence. + + :param data: A palette sequence (either a list or a string). + :param rawmode: The raw mode of the palette. Either "RGB", "RGBA", or a mode + that can be transformed to "RGB" or "RGBA" (e.g. "R", "BGR;15", "RGBA;L"). + """ + ... + + def putpixel(self, xy, value): # -> Any: + """ + Modifies the pixel at the given position. The color is given as + a single numerical value for single-band images, and a tuple for + multi-band images. In addition to this, RGB and RGBA tuples are + accepted for P and PA images. + + Note that this method is relatively slow. For more extensive changes, + use :py:meth:`~PIL.Image.Image.paste` or the :py:mod:`~PIL.ImageDraw` + module instead. + + See: + + * :py:meth:`~PIL.Image.Image.paste` + * :py:meth:`~PIL.Image.Image.putdata` + * :py:mod:`~PIL.ImageDraw` + + :param xy: The pixel coordinate, given as (x, y). See + :ref:`coordinate-system`. + :param value: The pixel value. + """ + ... + + def remap_palette(self, dest_map, source_palette=...): # -> Image: + """ + Rewrites the image to reorder the palette. + + :param dest_map: A list of indexes into the original palette. + e.g. ``[1,0]`` would swap a two item palette, and ``list(range(256))`` + is the identity transform. + :param source_palette: Bytes or None. + :returns: An :py:class:`~PIL.Image.Image` object. + + """ + ... + + def resize(self, size, resample=..., box=..., reducing_gap=...) -> Image: + """ + Returns a resized copy of this image. + + :param size: The requested size in pixels, as a 2-tuple: + (width, height). + :param resample: An optional resampling filter. This can be + one of :py:data:`Resampling.NEAREST`, :py:data:`Resampling.BOX`, + :py:data:`Resampling.BILINEAR`, :py:data:`Resampling.HAMMING`, + :py:data:`Resampling.BICUBIC` or :py:data:`Resampling.LANCZOS`. + If the image has mode "1" or "P", it is always set to + :py:data:`Resampling.NEAREST`. If the image mode specifies a number + of bits, such as "I;16", then the default filter is + :py:data:`Resampling.NEAREST`. Otherwise, the default filter is + :py:data:`Resampling.BICUBIC`. See: :ref:`concept-filters`. + :param box: An optional 4-tuple of floats providing + the source image region to be scaled. + The values must be within (0, 0, width, height) rectangle. + If omitted or None, the entire source is used. + :param reducing_gap: Apply optimization by resizing the image + in two steps. First, reducing the image by integer times + using :py:meth:`~PIL.Image.Image.reduce`. + Second, resizing using regular resampling. The last step + changes size no less than by ``reducing_gap`` times. + ``reducing_gap`` may be None (no first step is performed) + or should be greater than 1.0. The bigger ``reducing_gap``, + the closer the result to the fair resampling. + The smaller ``reducing_gap``, the faster resizing. + With ``reducing_gap`` greater or equal to 3.0, the result is + indistinguishable from fair resampling in most cases. + The default value is None (no optimization). + :returns: An :py:class:`~PIL.Image.Image` object. + """ + ... + + def reduce(self, factor, box=...): # -> Image: + """ + Returns a copy of the image reduced ``factor`` times. + If the size of the image is not dividable by ``factor``, + the resulting size will be rounded up. + + :param factor: A greater than 0 integer or tuple of two integers + for width and height separately. + :param box: An optional 4-tuple of ints providing + the source image region to be reduced. + The values must be within ``(0, 0, width, height)`` rectangle. + If omitted or ``None``, the entire source is used. + """ + ... + + def rotate( + self, angle, resample=..., expand=..., center=..., translate=..., fillcolor=... + ): # -> Image: + """ + Returns a rotated copy of this image. This method returns a + copy of this image, rotated the given number of degrees counter + clockwise around its centre. + + :param angle: In degrees counter clockwise. + :param resample: An optional resampling filter. This can be + one of :py:data:`Resampling.NEAREST` (use nearest neighbour), + :py:data:`Resampling.BILINEAR` (linear interpolation in a 2x2 + environment), or :py:data:`Resampling.BICUBIC` (cubic spline + interpolation in a 4x4 environment). If omitted, or if the image has + mode "1" or "P", it is set to :py:data:`Resampling.NEAREST`. + See :ref:`concept-filters`. + :param expand: Optional expansion flag. If true, expands the output + image to make it large enough to hold the entire rotated image. + If false or omitted, make the output image the same size as the + input image. Note that the expand flag assumes rotation around + the center and no translation. + :param center: Optional center of rotation (a 2-tuple). Origin is + the upper left corner. Default is the center of the image. + :param translate: An optional post-rotate translation (a 2-tuple). + :param fillcolor: An optional color for area outside the rotated image. + :returns: An :py:class:`~PIL.Image.Image` object. + """ + ... + + def save(self, fp, format=..., **params) -> None: + """ + Saves this image under the given filename. If no format is + specified, the format to use is determined from the filename + extension, if possible. + + Keyword options can be used to provide additional instructions + to the writer. If a writer doesn't recognise an option, it is + silently ignored. The available options are described in the + :doc:`image format documentation + <../handbook/image-file-formats>` for each writer. + + You can use a file object instead of a filename. In this case, + you must always specify the format. The file object must + implement the ``seek``, ``tell``, and ``write`` + methods, and be opened in binary mode. + + :param fp: A filename (string), os.PathLike object or file object. + :param format: Optional format override. If omitted, the + format to use is determined from the filename extension. + If a file object was used instead of a filename, this + parameter should always be used. + :param params: Extra parameters to the image writer. + :returns: None + :exception ValueError: If the output format could not be determined + from the file name. Use the format option to solve this. + :exception OSError: If the file could not be written. The file + may have been created, and may contain partial data. + """ + ... + + def seek(self, frame: int) -> None: + """ + Seeks to the given frame in this sequence file. If you seek + beyond the end of the sequence, the method raises an + ``EOFError`` exception. When a sequence file is opened, the + library automatically seeks to frame 0. + + See :py:meth:`~PIL.Image.Image.tell`. + + If defined, :attr:`~PIL.Image.Image.n_frames` refers to the + number of available frames. + + :param frame: Frame number, starting at 0. + :exception EOFError: If the call attempts to seek beyond the end + of the sequence. + """ + ... + + def show(self, title: str | None = ...) -> None: + """ + Displays this image. This method is mainly intended for debugging purposes. + + This method calls :py:func:`PIL.ImageShow.show` internally. You can use + :py:func:`PIL.ImageShow.register` to override its default behaviour. + + The image is first saved to a temporary file. By default, it will be in + PNG format. + + On Unix, the image is then opened using the **xdg-open**, **display**, + **gm**, **eog** or **xv** utility, depending on which one can be found. + + On macOS, the image is opened with the native Preview application. + + On Windows, the image is opened with the standard PNG display utility. + + :param title: Optional title to use for the image window, where possible. + """ + ... + + def split(self) -> tuple[Image, ...]: + """ + Split this image into individual bands. This method returns a + tuple of individual image bands from an image. For example, + splitting an "RGB" image creates three new images each + containing a copy of one of the original bands (red, green, + blue). + + If you need only one band, :py:meth:`~PIL.Image.Image.getchannel` + method can be more convenient and faster. + + :returns: A tuple containing bands. + """ + ... + + def getchannel(self, channel: int | str) -> Image: + """ + Returns an image containing a single channel of the source image. + + :param channel: What channel to return. Could be index + (0 for "R" channel of "RGB") or channel name + ("A" for alpha channel of "RGBA"). + :returns: An image in "L" mode. + + .. versionadded:: 4.3.0 + """ + ... + + def tell(self) -> int: + """ + Returns the current frame number. See :py:meth:`~PIL.Image.Image.seek`. + + If defined, :attr:`~PIL.Image.Image.n_frames` refers to the + number of available frames. + + :returns: Frame number, starting with 0. + """ + ... + + def thumbnail(self, size, resample=..., reducing_gap=...): # -> None: + """ + Make this image into a thumbnail. This method modifies the + image to contain a thumbnail version of itself, no larger than + the given size. This method calculates an appropriate thumbnail + size to preserve the aspect of the image, calls the + :py:meth:`~PIL.Image.Image.draft` method to configure the file reader + (where applicable), and finally resizes the image. + + Note that this function modifies the :py:class:`~PIL.Image.Image` + object in place. If you need to use the full resolution image as well, + apply this method to a :py:meth:`~PIL.Image.Image.copy` of the original + image. + + :param size: The requested size in pixels, as a 2-tuple: + (width, height). + :param resample: Optional resampling filter. This can be one + of :py:data:`Resampling.NEAREST`, :py:data:`Resampling.BOX`, + :py:data:`Resampling.BILINEAR`, :py:data:`Resampling.HAMMING`, + :py:data:`Resampling.BICUBIC` or :py:data:`Resampling.LANCZOS`. + If omitted, it defaults to :py:data:`Resampling.BICUBIC`. + (was :py:data:`Resampling.NEAREST` prior to version 2.5.0). + See: :ref:`concept-filters`. + :param reducing_gap: Apply optimization by resizing the image + in two steps. First, reducing the image by integer times + using :py:meth:`~PIL.Image.Image.reduce` or + :py:meth:`~PIL.Image.Image.draft` for JPEG images. + Second, resizing using regular resampling. The last step + changes size no less than by ``reducing_gap`` times. + ``reducing_gap`` may be None (no first step is performed) + or should be greater than 1.0. The bigger ``reducing_gap``, + the closer the result to the fair resampling. + The smaller ``reducing_gap``, the faster resizing. + With ``reducing_gap`` greater or equal to 3.0, the result is + indistinguishable from fair resampling in most cases. + The default value is 2.0 (very close to fair resampling + while still being faster in many cases). + :returns: None + """ + ... + + def transform( + self, size, method, data=..., resample=..., fill=..., fillcolor=... + ) -> Image: + """ + Transforms this image. This method creates a new image with the + given size, and the same mode as the original, and copies data + to the new image using the given transform. + + :param size: The output size in pixels, as a 2-tuple: + (width, height). + :param method: The transformation method. This is one of + :py:data:`Transform.EXTENT` (cut out a rectangular subregion), + :py:data:`Transform.AFFINE` (affine transform), + :py:data:`Transform.PERSPECTIVE` (perspective transform), + :py:data:`Transform.QUAD` (map a quadrilateral to a rectangle), or + :py:data:`Transform.MESH` (map a number of source quadrilaterals + in one operation). + + It may also be an :py:class:`~PIL.Image.ImageTransformHandler` + object:: + + class Example(Image.ImageTransformHandler): + def transform(self, size, data, resample, fill=1): + # Return result + + Implementations of :py:class:`~PIL.Image.ImageTransformHandler` + for some of the :py:class:`Transform` methods are provided + in :py:mod:`~PIL.ImageTransform`. + + It may also be an object with a ``method.getdata`` method + that returns a tuple supplying new ``method`` and ``data`` values:: + + class Example: + def getdata(self): + method = Image.Transform.EXTENT + data = (0, 0, 100, 100) + return method, data + :param data: Extra data to the transformation method. + :param resample: Optional resampling filter. It can be one of + :py:data:`Resampling.NEAREST` (use nearest neighbour), + :py:data:`Resampling.BILINEAR` (linear interpolation in a 2x2 + environment), or :py:data:`Resampling.BICUBIC` (cubic spline + interpolation in a 4x4 environment). If omitted, or if the image + has mode "1" or "P", it is set to :py:data:`Resampling.NEAREST`. + See: :ref:`concept-filters`. + :param fill: If ``method`` is an + :py:class:`~PIL.Image.ImageTransformHandler` object, this is one of + the arguments passed to it. Otherwise, it is unused. + :param fillcolor: Optional fill color for the area outside the + transform in the output image. + :returns: An :py:class:`~PIL.Image.Image` object. + """ + ... + + def transpose(self, method: Transpose) -> Image: + """ + Transpose image (flip or rotate in 90 degree steps) + + :param method: One of :py:data:`Transpose.FLIP_LEFT_RIGHT`, + :py:data:`Transpose.FLIP_TOP_BOTTOM`, :py:data:`Transpose.ROTATE_90`, + :py:data:`Transpose.ROTATE_180`, :py:data:`Transpose.ROTATE_270`, + :py:data:`Transpose.TRANSPOSE` or :py:data:`Transpose.TRANSVERSE`. + :returns: Returns a flipped or rotated copy of this image. + """ + ... + + def effect_spread(self, distance): # -> Image: + """ + Randomly spread pixels in an image. + + :param distance: Distance to spread pixels. + """ + ... + + def toqimage(self): # -> ImageQt: + """Returns a QImage copy of this image""" + ... + + def toqpixmap(self): + """Returns a QPixmap copy of this image""" + ... + +class ImagePointHandler: + """ + Used as a mixin by point transforms + (for use with :py:meth:`~PIL.Image.Image.point`) + """ + + @abc.abstractmethod + def point(self, im: Image) -> Image: ... + +class ImageTransformHandler: + """ + Used as a mixin by geometry transforms + (for use with :py:meth:`~PIL.Image.Image.transform`) + """ + + @abc.abstractmethod + def transform( + self, + size: tuple[int, int], + image: Image, + **options: dict[str, str | int | tuple[int, ...] | list[int]] + ) -> Image: ... + +def new( + mode: str, + size: tuple[int, int], + color: float | tuple[float, ...] | str | None = ..., +) -> Image: + """ + Creates a new image with the given mode and size. + + :param mode: The mode to use for the new image. See: + :ref:`concept-modes`. + :param size: A 2-tuple, containing (width, height) in pixels. + :param color: What color to use for the image. Default is black. + If given, this should be a single integer or floating point value + for single-band modes, and a tuple for multi-band modes (one value + per band). When creating RGB or HSV images, you can also use color + strings as supported by the ImageColor module. If the color is + None, the image is not initialised. + :returns: An :py:class:`~PIL.Image.Image` object. + """ + ... + +def frombytes(mode, size, data, decoder_name=..., *args) -> Image: + """ + Creates a copy of an image memory from pixel data in a buffer. + + In its simplest form, this function takes three arguments + (mode, size, and unpacked pixel data). + + You can also use any pixel decoder supported by PIL. For more + information on available decoders, see the section + :ref:`Writing Your Own File Codec `. + + Note that this function decodes pixel data only, not entire images. + If you have an entire image in a string, wrap it in a + :py:class:`~io.BytesIO` object, and use :py:func:`~PIL.Image.open` to load + it. + + :param mode: The image mode. See: :ref:`concept-modes`. + :param size: The image size. + :param data: A byte buffer containing raw data for the given mode. + :param decoder_name: What decoder to use. + :param args: Additional parameters for the given decoder. + :returns: An :py:class:`~PIL.Image.Image` object. + """ + ... + +def frombuffer(mode, size, data, decoder_name=..., *args): # -> Image: + """ + Creates an image memory referencing pixel data in a byte buffer. + + This function is similar to :py:func:`~PIL.Image.frombytes`, but uses data + in the byte buffer, where possible. This means that changes to the + original buffer object are reflected in this image). Not all modes can + share memory; supported modes include "L", "RGBX", "RGBA", and "CMYK". + + Note that this function decodes pixel data only, not entire images. + If you have an entire image file in a string, wrap it in a + :py:class:`~io.BytesIO` object, and use :py:func:`~PIL.Image.open` to load it. + + The default parameters used for the "raw" decoder differs from that used for + :py:func:`~PIL.Image.frombytes`. This is a bug, and will probably be fixed in a + future release. The current release issues a warning if you do this; to disable + the warning, you should provide the full set of parameters. See below for details. + + :param mode: The image mode. See: :ref:`concept-modes`. + :param size: The image size. + :param data: A bytes or other buffer object containing raw + data for the given mode. + :param decoder_name: What decoder to use. + :param args: Additional parameters for the given decoder. For the + default encoder ("raw"), it's recommended that you provide the + full set of parameters:: + + frombuffer(mode, size, data, "raw", mode, 0, 1) + + :returns: An :py:class:`~PIL.Image.Image` object. + + .. versionadded:: 1.1.4 + """ + ... + +def fromarray(obj, mode=...): # -> Image: + """ + Creates an image memory from an object exporting the array interface + (using the buffer protocol):: + + from PIL import Image + import numpy as np + a = np.zeros((5, 5)) + im = Image.fromarray(a) + + If ``obj`` is not contiguous, then the ``tobytes`` method is called + and :py:func:`~PIL.Image.frombuffer` is used. + + In the case of NumPy, be aware that Pillow modes do not always correspond + to NumPy dtypes. Pillow modes only offer 1-bit pixels, 8-bit pixels, + 32-bit signed integer pixels, and 32-bit floating point pixels. + + Pillow images can also be converted to arrays:: + + from PIL import Image + import numpy as np + im = Image.open("hopper.jpg") + a = np.asarray(im) + + When converting Pillow images to arrays however, only pixel values are + transferred. This means that P and PA mode images will lose their palette. + + :param obj: Object with array interface + :param mode: Optional mode to use when reading ``obj``. Will be determined from + type if ``None``. + + This will not be used to convert the data after reading, but will be used to + change how the data is read:: + + from PIL import Image + import numpy as np + a = np.full((1, 1), 300) + im = Image.fromarray(a, mode="L") + im.getpixel((0, 0)) # 44 + im = Image.fromarray(a, mode="RGB") + im.getpixel((0, 0)) # (44, 1, 0) + + See: :ref:`concept-modes` for general information about modes. + :returns: An image object. + + .. versionadded:: 1.1.6 + """ + ... + +def fromqimage(im): # -> Image: + """Creates an image instance from a QImage image""" + ... + +def fromqpixmap(im): # -> Image: + """Creates an image instance from a QPixmap image""" + ... + +_fromarray_typemap = ... + +def open(fp, mode=..., formats=...) -> Image: + """ + Opens and identifies the given image file. + + This is a lazy operation; this function identifies the file, but + the file remains open and the actual image data is not read from + the file until you try to process the data (or call the + :py:meth:`~PIL.Image.Image.load` method). See + :py:func:`~PIL.Image.new`. See :ref:`file-handling`. + + :param fp: A filename (string), os.PathLike object or a file object. + The file object must implement ``file.read``, + ``file.seek``, and ``file.tell`` methods, + and be opened in binary mode. The file object will also seek to zero + before reading. + :param mode: The mode. If given, this argument must be "r". + :param formats: A list or tuple of formats to attempt to load the file in. + This can be used to restrict the set of formats checked. + Pass ``None`` to try all supported formats. You can print the set of + available formats by running ``python3 -m PIL`` or using + the :py:func:`PIL.features.pilinfo` function. + :returns: An :py:class:`~PIL.Image.Image` object. + :exception FileNotFoundError: If the file cannot be found. + :exception PIL.UnidentifiedImageError: If the image cannot be opened and + identified. + :exception ValueError: If the ``mode`` is not "r", or if a ``StringIO`` + instance is used for ``fp``. + :exception TypeError: If ``formats`` is not ``None``, a list or a tuple. + """ + ... + +def alpha_composite(im1: Image, im2: Image) -> Image: + """ + Alpha composite im2 over im1. + + :param im1: The first image. Must have mode RGBA. + :param im2: The second image. Must have mode RGBA, and the same size as + the first image. + :returns: An :py:class:`~PIL.Image.Image` object. + """ + ... + +def blend(im1: Image, im2: Image, alpha: float) -> Image: + """ + Creates a new image by interpolating between two input images, using + a constant alpha:: + + out = image1 * (1.0 - alpha) + image2 * alpha + + :param im1: The first image. + :param im2: The second image. Must have the same mode and size as + the first image. + :param alpha: The interpolation alpha factor. If alpha is 0.0, a + copy of the first image is returned. If alpha is 1.0, a copy of + the second image is returned. There are no restrictions on the + alpha value. If necessary, the result is clipped to fit into + the allowed output range. + :returns: An :py:class:`~PIL.Image.Image` object. + """ + ... + +def composite(image1: Image, image2: Image, mask: Image) -> Image: + """ + Create composite image by blending images using a transparency mask. + + :param image1: The first image. + :param image2: The second image. Must have the same mode and + size as the first image. + :param mask: A mask image. This image can have mode + "1", "L", or "RGBA", and must have the same size as the + other two images. + """ + ... + +def eval(image, *args): + """ + Applies the function (which should take one argument) to each pixel + in the given image. If the image has more than one band, the same + function is applied to each band. Note that the function is + evaluated once for each possible pixel value, so you cannot use + random components or other generators. + + :param image: The input image. + :param function: A function object, taking one integer argument. + :returns: An :py:class:`~PIL.Image.Image` object. + """ + ... + +def merge(mode, bands): + """ + Merge a set of single band images into a new multiband image. + + :param mode: The mode to use for the output image. See: + :ref:`concept-modes`. + :param bands: A sequence containing one single-band image for + each band in the output image. All bands must have the + same size. + :returns: An :py:class:`~PIL.Image.Image` object. + """ + ... + +def register_open( + id, + factory: Callable[[IO[bytes], str | bytes], ImageFile.ImageFile], + accept: Callable[[bytes], bool] | None = ..., +) -> None: + """ + Register an image file plugin. This function should not be used + in application code. + + :param id: An image format identifier. + :param factory: An image file factory method. + :param accept: An optional function that can be used to quickly + reject images having another format. + """ + ... + +def register_mime(id: str, mimetype: str) -> None: + """ + Registers an image MIME type by populating ``Image.MIME``. This function + should not be used in application code. + + ``Image.MIME`` provides a mapping from image format identifiers to mime + formats, but :py:meth:`~PIL.ImageFile.ImageFile.get_format_mimetype` can + provide a different result for specific images. + + :param id: An image format identifier. + :param mimetype: The image MIME type for this format. + """ + ... + +def register_save(id: str, driver) -> None: + """ + Registers an image save function. This function should not be + used in application code. + + :param id: An image format identifier. + :param driver: A function to save images in this format. + """ + ... + +def register_save_all(id, driver) -> None: + """ + Registers an image function to save all the frames + of a multiframe format. This function should not be + used in application code. + + :param id: An image format identifier. + :param driver: A function to save images in this format. + """ + ... + +def register_extension(id, extension) -> None: + """ + Registers an image extension. This function should not be + used in application code. + + :param id: An image format identifier. + :param extension: An extension used for this format. + """ + ... + +def register_extensions(id, extensions) -> None: + """ + Registers image extensions. This function should not be + used in application code. + + :param id: An image format identifier. + :param extensions: A list of extensions used for this format. + """ + ... + +def registered_extensions(): # -> dict[str, str]: + """ + Returns a dictionary containing all file extensions belonging + to registered plugins + """ + ... + +def register_decoder(name: str, decoder: type[ImageFile.PyDecoder]) -> None: + """ + Registers an image decoder. This function should not be + used in application code. + + :param name: The name of the decoder + :param decoder: An ImageFile.PyDecoder object + + .. versionadded:: 4.1.0 + """ + ... + +def register_encoder(name: str, encoder: type[ImageFile.PyEncoder]) -> None: + """ + Registers an image encoder. This function should not be + used in application code. + + :param name: The name of the encoder + :param encoder: An ImageFile.PyEncoder object + + .. versionadded:: 4.1.0 + """ + ... + +def effect_mandelbrot(size, extent, quality): # -> Image: + """ + Generate a Mandelbrot set covering the given extent. + + :param size: The requested size in pixels, as a 2-tuple: + (width, height). + :param extent: The extent to cover, as a 4-tuple: + (x0, y0, x1, y1). + :param quality: Quality. + """ + ... + +def effect_noise(size, sigma): # -> Image: + """ + Generate Gaussian noise centered around 128. + + :param size: The requested size in pixels, as a 2-tuple: + (width, height). + :param sigma: Standard deviation of noise. + """ + ... + +def linear_gradient(mode): # -> Image: + """ + Generate 256x256 linear gradient from black to white, top to bottom. + + :param mode: Input mode. + """ + ... + +def radial_gradient(mode): # -> Image: + """ + Generate 256x256 radial gradient from black to white, centre to edge. + + :param mode: Input mode. + """ + ... + +if TYPE_CHECKING: + _ExifBase = MutableMapping[int, Any] +else: + ... + +class Exif(_ExifBase): + """ + This class provides read and write access to EXIF image data:: + + from PIL import Image + im = Image.open("exif.png") + exif = im.getexif() # Returns an instance of this class + + Information can be read and written, iterated over or deleted:: + + print(exif[274]) # 1 + exif[274] = 2 + for k, v in exif.items(): + print("Tag", k, "Value", v) # Tag 274 Value 2 + del exif[274] + + To access information beyond IFD0, :py:meth:`~PIL.Image.Exif.get_ifd` + returns a dictionary:: + + from PIL import ExifTags + im = Image.open("exif_gps.jpg") + exif = im.getexif() + gps_ifd = exif.get_ifd(ExifTags.IFD.GPSInfo) + print(gps_ifd) + + Other IFDs include ``ExifTags.IFD.Exif``, ``ExifTags.IFD.Makernote``, + ``ExifTags.IFD.Interop`` and ``ExifTags.IFD.IFD1``. + + :py:mod:`~PIL.ExifTags` also has enum classes to provide names for data:: + + print(exif[ExifTags.Base.Software]) # PIL + print(gps_ifd[ExifTags.GPS.GPSDateStamp]) # 1999:99:99 99:99:99 + """ + + endian = ... + bigtiff = ... + _loaded = ... + def __init__(self) -> None: ... + def load(self, data): # -> None: + ... + + def load_from_fp(self, fp, offset=...): # -> None: + ... + + def tobytes(self, offset: int = ...) -> bytes: ... + def get_ifd(self, tag): # -> dict[Any, Any]: + ... + + def hide_offsets(self) -> None: ... + def __str__(self) -> str: ... + def __len__(self) -> int: ... + def __getitem__(self, tag): ... + def __contains__(self, tag) -> bool: ... + def __setitem__(self, tag, value) -> None: ... + def __delitem__(self, tag: int) -> None: ... + def __iter__(self): # -> Iterator[Any]: + ... diff --git a/python/tools/pybridge.py b/python/tools/pybridge.py index 225fc6c15c..30d69bbc9b 100644 --- a/python/tools/pybridge.py +++ b/python/tools/pybridge.py @@ -213,7 +213,7 @@ def do_enumerate(): def do_acquire(path: str, sid: str): check_origin() if sid == "null": - sid = None # type: ignore [cannot be assigned to declared type] + sid = None # type: ignore [is incompatible with declared type] trezor = Transport.find(path) if trezor is None: response.status = 404 diff --git a/python/tools/trezorctl_script_client.py b/python/tools/trezorctl_script_client.py index c77d703be3..311434bd74 100644 --- a/python/tools/trezorctl_script_client.py +++ b/python/tools/trezorctl_script_client.py @@ -6,18 +6,20 @@ Function `get_address()` is showing the communication with ScriptUI on a specific example """ +from __future__ import annotations + import os import subprocess -from typing import Dict, List, Optional, Tuple, Union +import typing as t import click -def parse_args_from_line(line: str) -> Tuple[str, Dict[str, Union[str, bool]]]: +def parse_args_from_line(line: str) -> tuple[str, dict[str, t.Any]]: # ?PIN code=123 # ?PASSPHRASE available_on_device command, *args = line.split(" ") - result: Dict[str, Union[str, bool]] = {} + result = {} for arg in args: if "=" in arg: key, value = arg.split("=") @@ -27,7 +29,7 @@ def parse_args_from_line(line: str) -> Tuple[str, Dict[str, Union[str, bool]]]: return command, result -def get_pin_from_user(code: Optional[str] = None) -> str: +def get_pin_from_user(code: str | None = None) -> str: # ?PIN # ?PIN code=Current while True: @@ -47,7 +49,7 @@ def get_pin_from_user(code: Optional[str] = None) -> str: def show_button_request( - code: Optional[str] = None, pages: Optional[str] = None, name: Optional[str] = None + code: str | None = None, pages: str | None = None, name: str | None = None ) -> None: # ?BUTTON code=Other # ?BUTTON code=SignTx pages=2 @@ -98,7 +100,7 @@ def get_address() -> str: assert p.stdout is not None assert p.stdin is not None - text_result: List[str] = [] + text_result = [] while True: line = p.stdout.readline().strip() if not line: