mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-04 01:47:47 +03:00 
			
		
		
		
	Merge pull request #7790 from radarhere/pyproject
Removed mypy excludes, except for olefile-related files
This commit is contained in:
		
						commit
						5d6f22da12
					
				| 
						 | 
				
			
			@ -10,6 +10,8 @@ exclude_also =
 | 
			
		|||
    if DEBUG:
 | 
			
		||||
    # Don't complain about compatibility code for missing optional dependencies
 | 
			
		||||
    except ImportError
 | 
			
		||||
    if TYPE_CHECKING:
 | 
			
		||||
    @abc.abstractmethod
 | 
			
		||||
 | 
			
		||||
[run]
 | 
			
		||||
omit =
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -141,16 +141,6 @@ warn_redundant_casts = true
 | 
			
		|||
warn_unreachable = true
 | 
			
		||||
warn_unused_ignores = true
 | 
			
		||||
exclude = [
 | 
			
		||||
  '^src/PIL/_tkinter_finder.py$',
 | 
			
		||||
  '^src/PIL/DdsImagePlugin.py$',
 | 
			
		||||
  '^src/PIL/FpxImagePlugin.py$',
 | 
			
		||||
  '^src/PIL/Image.py$',
 | 
			
		||||
  '^src/PIL/ImageQt.py$',
 | 
			
		||||
  '^src/PIL/ImImagePlugin.py$',
 | 
			
		||||
  '^src/PIL/MicImagePlugin.py$',
 | 
			
		||||
  '^src/PIL/PdfParser.py$',
 | 
			
		||||
  '^src/PIL/PyAccess.py$',
 | 
			
		||||
  '^src/PIL/TiffImagePlugin.py$',
 | 
			
		||||
  '^src/PIL/TiffTags.py$',
 | 
			
		||||
  '^src/PIL/WebPImagePlugin.py$',
 | 
			
		||||
]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -270,13 +270,17 @@ class D3DFMT(IntEnum):
 | 
			
		|||
# Backward compatibility layer
 | 
			
		||||
module = sys.modules[__name__]
 | 
			
		||||
for item in DDSD:
 | 
			
		||||
    assert item.name is not None
 | 
			
		||||
    setattr(module, "DDSD_" + item.name, item.value)
 | 
			
		||||
for item in DDSCAPS:
 | 
			
		||||
    setattr(module, "DDSCAPS_" + item.name, item.value)
 | 
			
		||||
for item in DDSCAPS2:
 | 
			
		||||
    setattr(module, "DDSCAPS2_" + item.name, item.value)
 | 
			
		||||
for item in DDPF:
 | 
			
		||||
    setattr(module, "DDPF_" + item.name, item.value)
 | 
			
		||||
for item1 in DDSCAPS:
 | 
			
		||||
    assert item1.name is not None
 | 
			
		||||
    setattr(module, "DDSCAPS_" + item1.name, item1.value)
 | 
			
		||||
for item2 in DDSCAPS2:
 | 
			
		||||
    assert item2.name is not None
 | 
			
		||||
    setattr(module, "DDSCAPS2_" + item2.name, item2.value)
 | 
			
		||||
for item3 in DDPF:
 | 
			
		||||
    assert item3.name is not None
 | 
			
		||||
    setattr(module, "DDPF_" + item3.name, item3.value)
 | 
			
		||||
 | 
			
		||||
DDS_FOURCC = DDPF.FOURCC
 | 
			
		||||
DDS_RGB = DDPF.RGB
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -93,8 +93,8 @@ for i in ["16", "16L", "16B"]:
 | 
			
		|||
for i in ["32S"]:
 | 
			
		||||
    OPEN[f"L {i} image"] = ("I", f"I;{i}")
 | 
			
		||||
    OPEN[f"L*{i} image"] = ("I", f"I;{i}")
 | 
			
		||||
for i in range(2, 33):
 | 
			
		||||
    OPEN[f"L*{i} image"] = ("F", f"F;{i}")
 | 
			
		||||
for j in range(2, 33):
 | 
			
		||||
    OPEN[f"L*{j} image"] = ("F", f"F;{j}")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# --------------------------------------------------------------------
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,6 +26,7 @@
 | 
			
		|||
 | 
			
		||||
from __future__ import annotations
 | 
			
		||||
 | 
			
		||||
import abc
 | 
			
		||||
import atexit
 | 
			
		||||
import builtins
 | 
			
		||||
import io
 | 
			
		||||
| 
						 | 
				
			
			@ -40,11 +41,8 @@ import warnings
 | 
			
		|||
from collections.abc import Callable, MutableMapping
 | 
			
		||||
from enum import IntEnum
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    from defusedxml import ElementTree
 | 
			
		||||
except ImportError:
 | 
			
		||||
    ElementTree = None
 | 
			
		||||
from types import ModuleType
 | 
			
		||||
from typing import IO, TYPE_CHECKING, Any
 | 
			
		||||
 | 
			
		||||
# VERSION was removed in Pillow 6.0.0.
 | 
			
		||||
# PILLOW_VERSION was removed in Pillow 9.0.0.
 | 
			
		||||
| 
						 | 
				
			
			@ -60,6 +58,12 @@ from . import (
 | 
			
		|||
from ._binary import i32le, o32be, o32le
 | 
			
		||||
from ._util import DeferredError, is_path
 | 
			
		||||
 | 
			
		||||
ElementTree: ModuleType | None
 | 
			
		||||
try:
 | 
			
		||||
    from defusedxml import ElementTree
 | 
			
		||||
except ImportError:
 | 
			
		||||
    ElementTree = None
 | 
			
		||||
 | 
			
		||||
logger = logging.getLogger(__name__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -110,6 +114,7 @@ except ImportError as v:
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
USE_CFFI_ACCESS = False
 | 
			
		||||
cffi: ModuleType | None
 | 
			
		||||
try:
 | 
			
		||||
    import cffi
 | 
			
		||||
except ImportError:
 | 
			
		||||
| 
						 | 
				
			
			@ -211,14 +216,22 @@ if hasattr(core, "DEFAULT_STRATEGY"):
 | 
			
		|||
# --------------------------------------------------------------------
 | 
			
		||||
# Registries
 | 
			
		||||
 | 
			
		||||
ID = []
 | 
			
		||||
OPEN = {}
 | 
			
		||||
MIME = {}
 | 
			
		||||
SAVE = {}
 | 
			
		||||
SAVE_ALL = {}
 | 
			
		||||
EXTENSION = {}
 | 
			
		||||
DECODERS = {}
 | 
			
		||||
ENCODERS = {}
 | 
			
		||||
if TYPE_CHECKING:
 | 
			
		||||
    from . import ImageFile
 | 
			
		||||
ID: list[str] = []
 | 
			
		||||
OPEN: dict[
 | 
			
		||||
    str,
 | 
			
		||||
    tuple[
 | 
			
		||||
        Callable[[IO[bytes], str | bytes], ImageFile.ImageFile],
 | 
			
		||||
        Callable[[bytes], bool] | None,
 | 
			
		||||
    ],
 | 
			
		||||
] = {}
 | 
			
		||||
MIME: dict[str, str] = {}
 | 
			
		||||
SAVE: dict[str, Callable[[Image, IO[bytes], str | bytes], None]] = {}
 | 
			
		||||
SAVE_ALL: dict[str, Callable[[Image, IO[bytes], str | bytes], None]] = {}
 | 
			
		||||
EXTENSION: dict[str, str] = {}
 | 
			
		||||
DECODERS: dict[str, object] = {}
 | 
			
		||||
ENCODERS: dict[str, object] = {}
 | 
			
		||||
 | 
			
		||||
# --------------------------------------------------------------------
 | 
			
		||||
# Modes
 | 
			
		||||
| 
						 | 
				
			
			@ -2383,12 +2396,12 @@ class Image:
 | 
			
		|||
           may have been created, and may contain partial data.
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        filename = ""
 | 
			
		||||
        filename: str | bytes = ""
 | 
			
		||||
        open_fp = False
 | 
			
		||||
        if isinstance(fp, Path):
 | 
			
		||||
            filename = str(fp)
 | 
			
		||||
            open_fp = True
 | 
			
		||||
        elif is_path(fp):
 | 
			
		||||
        elif isinstance(fp, (str, bytes)):
 | 
			
		||||
            filename = fp
 | 
			
		||||
            open_fp = True
 | 
			
		||||
        elif fp == sys.stdout:
 | 
			
		||||
| 
						 | 
				
			
			@ -2398,7 +2411,7 @@ class Image:
 | 
			
		|||
                pass
 | 
			
		||||
        if not filename and hasattr(fp, "name") and is_path(fp.name):
 | 
			
		||||
            # only set the name for metadata purposes
 | 
			
		||||
            filename = fp.name
 | 
			
		||||
            filename = os.path.realpath(os.fspath(fp.name))
 | 
			
		||||
 | 
			
		||||
        # may mutate self!
 | 
			
		||||
        self._ensure_mutable()
 | 
			
		||||
| 
						 | 
				
			
			@ -2409,7 +2422,8 @@ class Image:
 | 
			
		|||
 | 
			
		||||
        preinit()
 | 
			
		||||
 | 
			
		||||
        ext = os.path.splitext(filename)[1].lower()
 | 
			
		||||
        filename_ext = os.path.splitext(filename)[1].lower()
 | 
			
		||||
        ext = filename_ext.decode() if isinstance(filename_ext, bytes) else filename_ext
 | 
			
		||||
 | 
			
		||||
        if not format:
 | 
			
		||||
            if ext not in EXTENSION:
 | 
			
		||||
| 
						 | 
				
			
			@ -2451,7 +2465,7 @@ class Image:
 | 
			
		|||
        if open_fp:
 | 
			
		||||
            fp.close()
 | 
			
		||||
 | 
			
		||||
    def seek(self, frame) -> Image:
 | 
			
		||||
    def seek(self, frame) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Seeks to the given frame in this sequence file. If you seek
 | 
			
		||||
        beyond the end of the sequence, the method raises an
 | 
			
		||||
| 
						 | 
				
			
			@ -2511,10 +2525,8 @@ class Image:
 | 
			
		|||
 | 
			
		||||
        self.load()
 | 
			
		||||
        if self.im.bands == 1:
 | 
			
		||||
            ims = [self.copy()]
 | 
			
		||||
        else:
 | 
			
		||||
            ims = map(self._new, self.im.split())
 | 
			
		||||
        return tuple(ims)
 | 
			
		||||
            return (self.copy(),)
 | 
			
		||||
        return tuple(map(self._new, self.im.split()))
 | 
			
		||||
 | 
			
		||||
    def getchannel(self, channel):
 | 
			
		||||
        """
 | 
			
		||||
| 
						 | 
				
			
			@ -2871,7 +2883,14 @@ class ImageTransformHandler:
 | 
			
		|||
    (for use with :py:meth:`~PIL.Image.Image.transform`)
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    pass
 | 
			
		||||
    @abc.abstractmethod
 | 
			
		||||
    def transform(
 | 
			
		||||
        self,
 | 
			
		||||
        size: tuple[int, int],
 | 
			
		||||
        image: Image,
 | 
			
		||||
        **options: dict[str, str | int | tuple[int, ...] | list[int]],
 | 
			
		||||
    ) -> Image:
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# --------------------------------------------------------------------
 | 
			
		||||
| 
						 | 
				
			
			@ -3243,11 +3262,9 @@ def open(fp, mode="r", formats=None) -> Image:
 | 
			
		|||
        raise TypeError(msg)
 | 
			
		||||
 | 
			
		||||
    exclusive_fp = False
 | 
			
		||||
    filename = ""
 | 
			
		||||
    if isinstance(fp, Path):
 | 
			
		||||
        filename = str(fp.resolve())
 | 
			
		||||
    elif is_path(fp):
 | 
			
		||||
        filename = fp
 | 
			
		||||
    filename: str | bytes = ""
 | 
			
		||||
    if is_path(fp):
 | 
			
		||||
        filename = os.path.realpath(os.fspath(fp))
 | 
			
		||||
 | 
			
		||||
    if filename:
 | 
			
		||||
        fp = builtins.open(filename, "rb")
 | 
			
		||||
| 
						 | 
				
			
			@ -3421,7 +3438,11 @@ def merge(mode, bands):
 | 
			
		|||
# Plugin registry
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def register_open(id, factory, accept=None) -> None:
 | 
			
		||||
def register_open(
 | 
			
		||||
    id,
 | 
			
		||||
    factory: Callable[[IO[bytes], str | bytes], ImageFile.ImageFile],
 | 
			
		||||
    accept: Callable[[bytes], bool] | None = None,
 | 
			
		||||
) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    Register an image file plugin.  This function should not be used
 | 
			
		||||
    in application code.
 | 
			
		||||
| 
						 | 
				
			
			@ -3631,7 +3652,13 @@ _apply_env_variables()
 | 
			
		|||
atexit.register(core.clear_cache)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Exif(MutableMapping):
 | 
			
		||||
if TYPE_CHECKING:
 | 
			
		||||
    _ExifBase = MutableMapping[int, Any]
 | 
			
		||||
else:
 | 
			
		||||
    _ExifBase = MutableMapping
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Exif(_ExifBase):
 | 
			
		||||
    """
 | 
			
		||||
    This class provides read and write access to EXIF image data::
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,19 +19,26 @@ from __future__ import annotations
 | 
			
		|||
 | 
			
		||||
import sys
 | 
			
		||||
from io import BytesIO
 | 
			
		||||
from typing import Callable
 | 
			
		||||
 | 
			
		||||
from . import Image
 | 
			
		||||
from ._util import is_path
 | 
			
		||||
 | 
			
		||||
qt_version: str | None
 | 
			
		||||
qt_versions = [
 | 
			
		||||
    ["6", "PyQt6"],
 | 
			
		||||
    ["side6", "PySide6"],
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
# If a version has already been imported, attempt it first
 | 
			
		||||
qt_versions.sort(key=lambda qt_version: qt_version[1] in sys.modules, reverse=True)
 | 
			
		||||
for qt_version, qt_module in qt_versions:
 | 
			
		||||
qt_versions.sort(key=lambda version: version[1] in sys.modules, reverse=True)
 | 
			
		||||
for version, qt_module in qt_versions:
 | 
			
		||||
    try:
 | 
			
		||||
        QBuffer: type
 | 
			
		||||
        QIODevice: type
 | 
			
		||||
        QImage: type
 | 
			
		||||
        QPixmap: type
 | 
			
		||||
        qRgba: Callable[[int, int, int, int], int]
 | 
			
		||||
        if qt_module == "PyQt6":
 | 
			
		||||
            from PyQt6.QtCore import QBuffer, QIODevice
 | 
			
		||||
            from PyQt6.QtGui import QImage, QPixmap, qRgba
 | 
			
		||||
| 
						 | 
				
			
			@ -41,6 +48,7 @@ for qt_version, qt_module in qt_versions:
 | 
			
		|||
    except (ImportError, RuntimeError):
 | 
			
		||||
        continue
 | 
			
		||||
    qt_is_installed = True
 | 
			
		||||
    qt_version = version
 | 
			
		||||
    break
 | 
			
		||||
else:
 | 
			
		||||
    qt_is_installed = False
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -184,7 +184,7 @@ class UnixViewer(Viewer):
 | 
			
		|||
 | 
			
		||||
    @abc.abstractmethod
 | 
			
		||||
    def get_command_ex(self, file: str, **options: Any) -> tuple[str, str]:
 | 
			
		||||
        pass  # pragma: no cover
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def get_command(self, file: str, **options: Any) -> str:
 | 
			
		||||
        command = self.get_command_ex(file, **options)[0]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,7 @@ import os
 | 
			
		|||
import re
 | 
			
		||||
import time
 | 
			
		||||
import zlib
 | 
			
		||||
from typing import TYPE_CHECKING, Any, List, Union
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# see 7.9.2.2 Text String Type on page 86 and D.3 PDFDocEncoding Character Set
 | 
			
		||||
| 
						 | 
				
			
			@ -239,12 +240,18 @@ class PdfName:
 | 
			
		|||
        return bytes(result)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PdfArray(list):
 | 
			
		||||
class PdfArray(List[Any]):
 | 
			
		||||
    def __bytes__(self):
 | 
			
		||||
        return b"[ " + b" ".join(pdf_repr(x) for x in self) + b" ]"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PdfDict(collections.UserDict):
 | 
			
		||||
if TYPE_CHECKING:
 | 
			
		||||
    _DictBase = collections.UserDict[Union[str, bytes], Any]
 | 
			
		||||
else:
 | 
			
		||||
    _DictBase = collections.UserDict
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PdfDict(_DictBase):
 | 
			
		||||
    def __setattr__(self, key, value):
 | 
			
		||||
        if key == "data":
 | 
			
		||||
            collections.UserDict.__setattr__(self, key, value)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,7 @@ import sys
 | 
			
		|||
 | 
			
		||||
from ._deprecate import deprecate
 | 
			
		||||
 | 
			
		||||
FFI: type
 | 
			
		||||
try:
 | 
			
		||||
    from cffi import FFI
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,6 +50,7 @@ import warnings
 | 
			
		|||
from collections.abc import MutableMapping
 | 
			
		||||
from fractions import Fraction
 | 
			
		||||
from numbers import Number, Rational
 | 
			
		||||
from typing import TYPE_CHECKING, Any, Callable
 | 
			
		||||
 | 
			
		||||
from . import ExifTags, Image, ImageFile, ImageOps, ImagePalette, TiffTags
 | 
			
		||||
from ._binary import i16be as i16
 | 
			
		||||
| 
						 | 
				
			
			@ -306,6 +307,13 @@ _load_dispatch = {}
 | 
			
		|||
_write_dispatch = {}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _delegate(op):
 | 
			
		||||
    def delegate(self, *args):
 | 
			
		||||
        return getattr(self._val, op)(*args)
 | 
			
		||||
 | 
			
		||||
    return delegate
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IFDRational(Rational):
 | 
			
		||||
    """Implements a rational class where 0/0 is a legal value to match
 | 
			
		||||
    the in the wild use of exif rationals.
 | 
			
		||||
| 
						 | 
				
			
			@ -391,12 +399,6 @@ class IFDRational(Rational):
 | 
			
		|||
        self._numerator = _numerator
 | 
			
		||||
        self._denominator = _denominator
 | 
			
		||||
 | 
			
		||||
    def _delegate(op):
 | 
			
		||||
        def delegate(self, *args):
 | 
			
		||||
            return getattr(self._val, op)(*args)
 | 
			
		||||
 | 
			
		||||
        return delegate
 | 
			
		||||
 | 
			
		||||
    """ a = ['add','radd', 'sub', 'rsub', 'mul', 'rmul',
 | 
			
		||||
             'truediv', 'rtruediv', 'floordiv', 'rfloordiv',
 | 
			
		||||
             'mod','rmod', 'pow','rpow', 'pos', 'neg',
 | 
			
		||||
| 
						 | 
				
			
			@ -436,7 +438,50 @@ class IFDRational(Rational):
 | 
			
		|||
        __int__ = _delegate("__int__")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ImageFileDirectory_v2(MutableMapping):
 | 
			
		||||
def _register_loader(idx, size):
 | 
			
		||||
    def decorator(func):
 | 
			
		||||
        from .TiffTags import TYPES
 | 
			
		||||
 | 
			
		||||
        if func.__name__.startswith("load_"):
 | 
			
		||||
            TYPES[idx] = func.__name__[5:].replace("_", " ")
 | 
			
		||||
        _load_dispatch[idx] = size, func  # noqa: F821
 | 
			
		||||
        return func
 | 
			
		||||
 | 
			
		||||
    return decorator
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _register_writer(idx):
 | 
			
		||||
    def decorator(func):
 | 
			
		||||
        _write_dispatch[idx] = func  # noqa: F821
 | 
			
		||||
        return func
 | 
			
		||||
 | 
			
		||||
    return decorator
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _register_basic(idx_fmt_name):
 | 
			
		||||
    from .TiffTags import TYPES
 | 
			
		||||
 | 
			
		||||
    idx, fmt, name = idx_fmt_name
 | 
			
		||||
    TYPES[idx] = name
 | 
			
		||||
    size = struct.calcsize("=" + fmt)
 | 
			
		||||
    _load_dispatch[idx] = (  # noqa: F821
 | 
			
		||||
        size,
 | 
			
		||||
        lambda self, data, legacy_api=True: (
 | 
			
		||||
            self._unpack(f"{len(data) // size}{fmt}", data)
 | 
			
		||||
        ),
 | 
			
		||||
    )
 | 
			
		||||
    _write_dispatch[idx] = lambda self, *values: (  # noqa: F821
 | 
			
		||||
        b"".join(self._pack(fmt, value) for value in values)
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if TYPE_CHECKING:
 | 
			
		||||
    _IFDv2Base = MutableMapping[int, Any]
 | 
			
		||||
else:
 | 
			
		||||
    _IFDv2Base = MutableMapping
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ImageFileDirectory_v2(_IFDv2Base):
 | 
			
		||||
    """This class represents a TIFF tag directory.  To speed things up, we
 | 
			
		||||
    don't decode tags unless they're asked for.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -497,6 +542,9 @@ class ImageFileDirectory_v2(MutableMapping):
 | 
			
		|||
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    _load_dispatch: dict[int, Callable[[ImageFileDirectory_v2, bytes, bool], Any]] = {}
 | 
			
		||||
    _write_dispatch: dict[int, Callable[..., Any]] = {}
 | 
			
		||||
 | 
			
		||||
    def __init__(self, ifh=b"II\052\0\0\0\0\0", prefix=None, group=None):
 | 
			
		||||
        """Initialize an ImageFileDirectory.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -531,7 +579,10 @@ class ImageFileDirectory_v2(MutableMapping):
 | 
			
		|||
 | 
			
		||||
    prefix = property(lambda self: self._prefix)
 | 
			
		||||
    offset = property(lambda self: self._offset)
 | 
			
		||||
    legacy_api = property(lambda self: self._legacy_api)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def legacy_api(self):
 | 
			
		||||
        return self._legacy_api
 | 
			
		||||
 | 
			
		||||
    @legacy_api.setter
 | 
			
		||||
    def legacy_api(self, value):
 | 
			
		||||
| 
						 | 
				
			
			@ -674,40 +725,6 @@ class ImageFileDirectory_v2(MutableMapping):
 | 
			
		|||
    def _pack(self, fmt, *values):
 | 
			
		||||
        return struct.pack(self._endian + fmt, *values)
 | 
			
		||||
 | 
			
		||||
    def _register_loader(idx, size):
 | 
			
		||||
        def decorator(func):
 | 
			
		||||
            from .TiffTags import TYPES
 | 
			
		||||
 | 
			
		||||
            if func.__name__.startswith("load_"):
 | 
			
		||||
                TYPES[idx] = func.__name__[5:].replace("_", " ")
 | 
			
		||||
            _load_dispatch[idx] = size, func  # noqa: F821
 | 
			
		||||
            return func
 | 
			
		||||
 | 
			
		||||
        return decorator
 | 
			
		||||
 | 
			
		||||
    def _register_writer(idx):
 | 
			
		||||
        def decorator(func):
 | 
			
		||||
            _write_dispatch[idx] = func  # noqa: F821
 | 
			
		||||
            return func
 | 
			
		||||
 | 
			
		||||
        return decorator
 | 
			
		||||
 | 
			
		||||
    def _register_basic(idx_fmt_name):
 | 
			
		||||
        from .TiffTags import TYPES
 | 
			
		||||
 | 
			
		||||
        idx, fmt, name = idx_fmt_name
 | 
			
		||||
        TYPES[idx] = name
 | 
			
		||||
        size = struct.calcsize("=" + fmt)
 | 
			
		||||
        _load_dispatch[idx] = (  # noqa: F821
 | 
			
		||||
            size,
 | 
			
		||||
            lambda self, data, legacy_api=True: (
 | 
			
		||||
                self._unpack(f"{len(data) // size}{fmt}", data)
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
        _write_dispatch[idx] = lambda self, *values: (  # noqa: F821
 | 
			
		||||
            b"".join(self._pack(fmt, value) for value in values)
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    list(
 | 
			
		||||
        map(
 | 
			
		||||
            _register_basic,
 | 
			
		||||
| 
						 | 
				
			
			@ -995,7 +1012,7 @@ class ImageFileDirectory_v1(ImageFileDirectory_v2):
 | 
			
		|||
    tagdata = property(lambda self: self._tagdata)
 | 
			
		||||
 | 
			
		||||
    # defined in ImageFileDirectory_v2
 | 
			
		||||
    tagtype: dict
 | 
			
		||||
    tagtype: dict[int, int]
 | 
			
		||||
    """Dictionary of tag types"""
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
| 
						 | 
				
			
			@ -1835,11 +1852,11 @@ def _save(im, fp, filename):
 | 
			
		|||
        tags = list(atts.items())
 | 
			
		||||
        tags.sort()
 | 
			
		||||
        a = (rawmode, compression, _fp, filename, tags, types)
 | 
			
		||||
        e = Image._getencoder(im.mode, "libtiff", a, encoderconfig)
 | 
			
		||||
        e.setimage(im.im, (0, 0) + im.size)
 | 
			
		||||
        encoder = Image._getencoder(im.mode, "libtiff", a, encoderconfig)
 | 
			
		||||
        encoder.setimage(im.im, (0, 0) + im.size)
 | 
			
		||||
        while True:
 | 
			
		||||
            # undone, change to self.decodermaxblock:
 | 
			
		||||
            errcode, data = e.encode(16 * 1024)[1:]
 | 
			
		||||
            errcode, data = encoder.encode(16 * 1024)[1:]
 | 
			
		||||
            if not _fp:
 | 
			
		||||
                fp.write(data)
 | 
			
		||||
            if errcode:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,7 +22,7 @@ from collections import namedtuple
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
class TagInfo(namedtuple("_TagInfo", "value name type length enum")):
 | 
			
		||||
    __slots__ = []
 | 
			
		||||
    __slots__: list[str] = []
 | 
			
		||||
 | 
			
		||||
    def __new__(cls, value=None, name="unknown", type=None, length=None, enum=None):
 | 
			
		||||
        return super().__new__(cls, value, name, type, length, enum or {})
 | 
			
		||||
| 
						 | 
				
			
			@ -437,7 +437,7 @@ _populate()
 | 
			
		|||
##
 | 
			
		||||
# Map type numbers to type names -- defined in ImageFileDirectory.
 | 
			
		||||
 | 
			
		||||
TYPES = {}
 | 
			
		||||
TYPES: dict[int, str] = {}
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# These tags are handled by default in libtiff, without
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										5
									
								
								src/PIL/_imaging.pyi
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/PIL/_imaging.pyi
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
from __future__ import annotations
 | 
			
		||||
 | 
			
		||||
from typing import Any
 | 
			
		||||
 | 
			
		||||
def __getattr__(name: str) -> Any: ...
 | 
			
		||||
| 
						 | 
				
			
			@ -5,7 +5,8 @@ from __future__ import annotations
 | 
			
		|||
 | 
			
		||||
import sys
 | 
			
		||||
import tkinter
 | 
			
		||||
from tkinter import _tkinter as tk
 | 
			
		||||
 | 
			
		||||
tk = getattr(tkinter, "_tkinter")
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    if hasattr(sys, "pypy_find_executable"):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										5
									
								
								src/PIL/_webp.pyi
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/PIL/_webp.pyi
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
from __future__ import annotations
 | 
			
		||||
 | 
			
		||||
from typing import Any
 | 
			
		||||
 | 
			
		||||
def __getattr__(name: str) -> Any: ...
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user