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