Merge pull request #6195 from hugovk/cleanup

Cleanup: various
This commit is contained in:
Andrew Murray 2022-04-26 18:51:44 +10:00 committed by GitHub
commit bcded33cee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 110 additions and 93 deletions

View File

@ -16,7 +16,6 @@ trim_trailing_whitespace = true
[*.yml] [*.yml]
# Two-space indentation # Two-space indentation
indent_size = 2 indent_size = 2
indent_style = space
# Tab indentation (no size specified) # Tab indentation (no size specified)
[Makefile] [Makefile]

View File

@ -567,7 +567,7 @@ class TestTransformColorLut3D:
assert tuple(lut.size) == tuple(source.size) assert tuple(lut.size) == tuple(source.size)
assert len(lut.table) == len(source.table) assert len(lut.table) == len(source.table)
assert lut.table != source.table assert lut.table != source.table
assert lut.table[0:10] == [0.0, 0.0, 0.0, 0.25, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0] assert lut.table[:10] == [0.0, 0.0, 0.0, 0.25, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0]
def test_3_to_4_channels(self): def test_3_to_4_channels(self):
source = ImageFilter.Color3DLUT.generate((6, 5, 4), lambda r, g, b: (r, g, b)) source = ImageFilter.Color3DLUT.generate((6, 5, 4), lambda r, g, b: (r, g, b))
@ -576,7 +576,7 @@ class TestTransformColorLut3D:
assert len(lut.table) != len(source.table) assert len(lut.table) != len(source.table)
assert lut.table != source.table assert lut.table != source.table
# fmt: off # fmt: off
assert lut.table[0:16] == [ assert lut.table[:16] == [
0.0, 0.0, 0.0, 1, 0.2**2, 0.0, 0.0, 1, 0.0, 0.0, 0.0, 1, 0.2**2, 0.0, 0.0, 1,
0.4**2, 0.0, 0.0, 1, 0.6**2, 0.0, 0.0, 1] 0.4**2, 0.0, 0.0, 1, 0.6**2, 0.0, 0.0, 1]
# fmt: on # fmt: on
@ -592,7 +592,7 @@ class TestTransformColorLut3D:
assert len(lut.table) != len(source.table) assert len(lut.table) != len(source.table)
assert lut.table != source.table assert lut.table != source.table
# fmt: off # fmt: off
assert lut.table[0:18] == [ assert lut.table[:18] == [
1.0, 1.0, 1.0, 0.75, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.75, 1.0, 1.0, 0.0, 1.0, 1.0,
1.0, 0.96, 1.0, 0.75, 0.96, 1.0, 0.0, 0.96, 1.0] 1.0, 0.96, 1.0, 0.75, 0.96, 1.0, 0.0, 0.96, 1.0]
# fmt: on # fmt: on
@ -606,7 +606,7 @@ class TestTransformColorLut3D:
assert len(lut.table) == len(source.table) assert len(lut.table) == len(source.table)
assert lut.table != source.table assert lut.table != source.table
# fmt: off # fmt: off
assert lut.table[0:16] == [ assert lut.table[:16] == [
0.0, 0.0, 0.0, 0.5, 0.2**2, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5, 0.2**2, 0.0, 0.0, 0.5,
0.4**2, 0.0, 0.0, 0.5, 0.6**2, 0.0, 0.0, 0.5] 0.4**2, 0.0, 0.0, 0.5, 0.6**2, 0.0, 0.0, 0.5]
# fmt: on # fmt: on
@ -622,7 +622,7 @@ class TestTransformColorLut3D:
assert len(lut.table) == len(source.table) assert len(lut.table) == len(source.table)
assert lut.table != source.table assert lut.table != source.table
# fmt: off # fmt: off
assert lut.table[0:18] == [ assert lut.table[:18] == [
0.0, 0.0, 0.0, 0.16, 0.0, 0.0, 0.24, 0.0, 0.0, 0.0, 0.0, 0.0, 0.16, 0.0, 0.0, 0.24, 0.0, 0.0,
0.24, 0.0, 0.0, 0.8 - (0.8**2), 0, 0, 0, 0, 0] 0.24, 0.0, 0.0, 0.8 - (0.8**2), 0, 0, 0, 0, 0]
# fmt: on # fmt: on
@ -639,7 +639,7 @@ class TestTransformColorLut3D:
assert len(lut.table) == len(source.table) assert len(lut.table) == len(source.table)
assert lut.table != source.table assert lut.table != source.table
# fmt: off # fmt: off
assert lut.table[0:16] == [ assert lut.table[:16] == [
0.0, 0.0, 0.0, 0.5, 0.25, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5, 0.25, 0.0, 0.0, 0.5,
0.0, 0.0, 0.0, 0.5, 0.0, 0.16, 0.0, 0.5] 0.0, 0.0, 0.0, 0.5, 0.0, 0.16, 0.0, 0.5]
# fmt: on # fmt: on

View File

@ -70,12 +70,12 @@ class TestDecompressionBomb:
class TestDecompressionCrop: class TestDecompressionCrop:
@classmethod @classmethod
def setup_class(self): def setup_class(cls):
width, height = 128, 128 width, height = 128, 128
Image.MAX_IMAGE_PIXELS = height * width * 4 - 1 Image.MAX_IMAGE_PIXELS = height * width * 4 - 1
@classmethod @classmethod
def teardown_class(self): def teardown_class(cls):
Image.MAX_IMAGE_PIXELS = ORIGINAL_LIMIT Image.MAX_IMAGE_PIXELS = ORIGINAL_LIMIT
def test_enlarge_crop(self): def test_enlarge_crop(self):

View File

@ -170,7 +170,7 @@ class TestImage:
temp_file = str(tmp_path / "temp.jpg") temp_file = str(tmp_path / "temp.jpg")
class FP: class FP:
def write(a, b): def write(self, b):
pass pass
fp = FP() fp = FP()

View File

@ -27,15 +27,15 @@ def test_sanity():
"HSV", "HSV",
) )
for mode in modes: for input_mode in modes:
im = hopper(mode) im = hopper(input_mode)
for mode in modes: for output_mode in modes:
convert(im, mode) convert(im, output_mode)
# Check 0 # Check 0
im = Image.new(mode, (0, 0)) im = Image.new(input_mode, (0, 0))
for mode in modes: for output_mode in modes:
convert(im, mode) convert(im, output_mode)
def test_default(): def test_default():

View File

@ -458,7 +458,7 @@ class TestCoreResampleBox:
def split_range(size, tiles): def split_range(size, tiles):
scale = size / tiles scale = size / tiles
for i in range(tiles): for i in range(tiles):
yield (int(round(scale * i)), int(round(scale * (i + 1)))) yield int(round(scale * i)), int(round(scale * (i + 1)))
tiled = Image.new(im.mode, dst_size) tiled = Image.new(im.mode, dst_size)
scale = (im.size[0] / tiled.size[0], im.size[1] / tiled.size[1]) scale = (im.size[0] / tiled.size[0], im.size[1] / tiled.size[1])

View File

@ -77,9 +77,9 @@ def test_consecutive():
def test_palette_mmap(): def test_palette_mmap():
# Using mmap in ImageFile can require to reload the palette. # Using mmap in ImageFile can require to reload the palette.
with Image.open("Tests/images/multipage-mmap.tiff") as im: with Image.open("Tests/images/multipage-mmap.tiff") as im:
color1 = im.getpalette()[0:3] color1 = im.getpalette()[:3]
im.seek(0) im.seek(0)
color2 = im.getpalette()[0:3] color2 = im.getpalette()[:3]
assert color1 == color2 assert color1 == color2

View File

@ -10,6 +10,10 @@ metadata tag numbers, names, and type information.
.. method:: lookup(tag) .. method:: lookup(tag)
:param tag: Integer tag number :param tag: Integer tag number
:param group: Which :py:data:`~PIL.TiffTags.TAGS_V2_GROUPS` to look in
.. versionadded:: 8.3.0
:returns: Taginfo namedtuple, From the :py:data:`~PIL.TiffTags.TAGS_V2` info if possible, :returns: Taginfo namedtuple, From the :py:data:`~PIL.TiffTags.TAGS_V2` info if possible,
otherwise just populating the value and name from :py:data:`~PIL.TiffTags.TAGS`. otherwise just populating the value and name from :py:data:`~PIL.TiffTags.TAGS`.
If the tag is not recognized, "unknown" is returned for the name If the tag is not recognized, "unknown" is returned for the name
@ -42,6 +46,16 @@ metadata tag numbers, names, and type information.
.. versionadded:: 3.0.0 .. versionadded:: 3.0.0
.. py:data:: PIL.TiffTags.TAGS_V2_GROUPS
:type: dict
:py:data:`~PIL.TiffTags.TAGS_V2` is one dimensional and
doesn't account for the fact that tags actually exist in
`different groups <https://exiftool.org/TagNames/EXIF.html>`_.
This dictionary is used when the tag in question is part of a group.
.. versionadded:: 8.3.0
.. py:data:: PIL.TiffTags.TAGS .. py:data:: PIL.TiffTags.TAGS
:type: dict :type: dict

View File

@ -20,7 +20,7 @@ def testimage():
>>> from PIL import Image, ImageDraw, ImageFilter, ImageMath >>> from PIL import Image, ImageDraw, ImageFilter, ImageMath
>>> im = Image.new("1", (128, 128)) # monochrome >>> im = Image.new("1", (128, 128)) # monochrome
>>> def _info(im): return (im.format, im.mode, im.size) >>> def _info(im): return im.format, im.mode, im.size
>>> _info(im) >>> _info(im)
(None, '1', (128, 128)) (None, '1', (128, 128))
>>> _info(Image.new("L", (128, 128))) # grayscale (luminance) >>> _info(Image.new("L", (128, 128))) # grayscale (luminance)

View File

@ -269,7 +269,7 @@ def _pkg_config(name):
.strip() .strip()
.replace("-I", "") .replace("-I", "")
) )
return (libs, cflags) return libs, cflags
except Exception: except Exception:
pass pass

View File

@ -69,7 +69,7 @@ def __getattr__(name):
def unpack_565(i): def unpack_565(i):
return (((i >> 11) & 0x1F) << 3, ((i >> 5) & 0x3F) << 2, (i & 0x1F) << 3) return ((i >> 11) & 0x1F) << 3, ((i >> 5) & 0x3F) << 2, (i & 0x1F) << 3
def decode_dxt1(data, alpha=False): def decode_dxt1(data, alpha=False):

View File

@ -76,10 +76,8 @@ class BmpImageFile(ImageFile.ImageFile):
read, seek = self.fp.read, self.fp.seek read, seek = self.fp.read, self.fp.seek
if header: if header:
seek(header) seek(header)
file_info = {}
# read bmp header size @offset 14 (this is part of the header size) # read bmp header size @offset 14 (this is part of the header size)
file_info["header_size"] = i32(read(4)) file_info = {"header_size": i32(read(4)), "direction": -1}
file_info["direction"] = -1
# -------------------- If requested, read header at a specific position # -------------------- If requested, read header at a specific position
# read the rest of the bmp header, without its size # read the rest of the bmp header, without its size

View File

@ -325,7 +325,7 @@ class EpsImageFile(ImageFile.ImageFile):
else: else:
raise SyntaxError("not an EPS file") raise SyntaxError("not an EPS file")
return (length, offset) return length, offset
def load(self, scale=1, transparency=False): def load(self, scale=1, transparency=False):
# Load EPS via Ghostscript # Load EPS via Ghostscript

View File

@ -22,7 +22,7 @@ from ._binary import i32le as i32
# we map from colour field tuples to (mode, rawmode) descriptors # we map from colour field tuples to (mode, rawmode) descriptors
MODES = { MODES = {
# opacity # opacity
(0x00007FFE): ("A", "L"), (0x00007FFE,): ("A", "L"),
# monochrome # monochrome
(0x00010000,): ("L", "L"), (0x00010000,): ("L", "L"),
(0x00018000, 0x00017FFE): ("RGBA", "LA"), (0x00018000, 0x00017FFE): ("RGBA", "LA"),
@ -162,7 +162,7 @@ class FpxImageFile(ImageFile.ImageFile):
"raw", "raw",
(x, y, x + xtile, y + ytile), (x, y, x + xtile, y + ytile),
i32(s, i) + 28, i32(s, i) + 28,
(self.rawmode), (self.rawmode,),
) )
) )

View File

@ -101,7 +101,7 @@ class FtexImageFile(ImageFile.ImageFile):
if format == Format.DXT1: if format == Format.DXT1:
self.mode = "RGBA" self.mode = "RGBA"
self.tile = [("bcn", (0, 0) + self.size, 0, (1))] self.tile = [("bcn", (0, 0) + self.size, 0, 1)]
elif format == Format.UNCOMPRESSED: elif format == Format.UNCOMPRESSED:
self.tile = [("raw", (0, 0) + self.size, 0, ("RGB", 0, 1))] self.tile = [("raw", (0, 0) + self.size, 0, ("RGB", 0, 1))]
else: else:

View File

@ -80,7 +80,7 @@ def open(fp, mode="r"):
""" """
Load texture from a GD image file. Load texture from a GD image file.
:param filename: GD file name, or an opened file handle. :param fp: GD file name, or an opened file handle.
:param mode: Optional mode. In this version, if the mode argument :param mode: Optional mode. In this version, if the mode argument
is given, it must be "r". is given, it must be "r".
:returns: An image instance. :returns: An image instance.

View File

@ -990,8 +990,6 @@ def getheader(im, palette=None, info=None):
return header, used_palette_colors return header, used_palette_colors
# To specify duration, add the time in milliseconds to getdata(),
# e.g. getdata(im_frame, duration=1000)
def getdata(im, offset=(0, 0), **params): def getdata(im, offset=(0, 0), **params):
""" """
Legacy Method Legacy Method
@ -1000,10 +998,13 @@ def getdata(im, offset=(0, 0), **params):
The first string is a local image header, the rest contains The first string is a local image header, the rest contains
encoded image data. encoded image data.
To specify duration, add the time in milliseconds,
e.g. ``getdata(im_frame, duration=1000)``
:param im: Image object :param im: Image object
:param offset: Tuple of (x, y) pixels. Defaults to (0,0) :param offset: Tuple of (x, y) pixels. Defaults to (0, 0)
:param \\**params: E.g. duration or other encoder info parameters :param \\**params: e.g. duration or other encoder info parameters
:returns: List of Bytes containing gif encoded frame data :returns: List of bytes containing GIF encoded frame data
""" """

View File

@ -29,7 +29,7 @@ def register_handler(handler):
def _accept(prefix): def _accept(prefix):
return prefix[0:4] == b"GRIB" and prefix[7] == 1 return prefix[:4] == b"GRIB" and prefix[7] == 1
class GribStubImageFile(ImageFile.StubImageFile): class GribStubImageFile(ImageFile.StubImageFile):

View File

@ -210,7 +210,7 @@ class ImImageFile(ImageFile.ImageFile):
self.mode = self.info[MODE] self.mode = self.info[MODE]
# Skip forward to start of image data # Skip forward to start of image data
while s and s[0:1] != b"\x1A": while s and s[:1] != b"\x1A":
s = self.fp.read(1) s = self.fp.read(1)
if not s: if not s:
raise SyntaxError("File truncated") raise SyntaxError("File truncated")

View File

@ -2546,7 +2546,7 @@ class Image:
h = box[3] - box[1] h = box[3] - box[1]
if method == Transform.AFFINE: if method == Transform.AFFINE:
data = data[0:6] data = data[:6]
elif method == Transform.EXTENT: elif method == Transform.EXTENT:
# convert extent to an affine transform # convert extent to an affine transform
@ -2557,12 +2557,12 @@ class Image:
data = (xs, 0, x0, 0, ys, y0) data = (xs, 0, x0, 0, ys, y0)
elif method == Transform.PERSPECTIVE: elif method == Transform.PERSPECTIVE:
data = data[0:8] data = data[:8]
elif method == Transform.QUAD: elif method == Transform.QUAD:
# quadrilateral warp. data specifies the four corners # quadrilateral warp. data specifies the four corners
# given as NW, SW, SE, and NE. # given as NW, SW, SE, and NE.
nw = data[0:2] nw = data[:2]
sw = data[2:4] sw = data[2:4]
se = data[4:6] se = data[4:6]
ne = data[6:8] ne = data[6:8]
@ -2956,12 +2956,11 @@ _fromarray_typemap = {
((1, 1, 2), "|u1"): ("LA", "LA"), ((1, 1, 2), "|u1"): ("LA", "LA"),
((1, 1, 3), "|u1"): ("RGB", "RGB"), ((1, 1, 3), "|u1"): ("RGB", "RGB"),
((1, 1, 4), "|u1"): ("RGBA", "RGBA"), ((1, 1, 4), "|u1"): ("RGBA", "RGBA"),
# shortcuts:
((1, 1), _ENDIAN + "i4"): ("I", "I"),
((1, 1), _ENDIAN + "f4"): ("F", "F"),
} }
# shortcuts
_fromarray_typemap[((1, 1), _ENDIAN + "i4")] = ("I", "I")
_fromarray_typemap[((1, 1), _ENDIAN + "f4")] = ("F", "F")
def _decompression_bomb_check(size): def _decompression_bomb_check(size):
if MAX_IMAGE_PIXELS is None: if MAX_IMAGE_PIXELS is None:

View File

@ -316,6 +316,7 @@ def offset(image, xoffset, yoffset=None):
distances. Data wraps around the edges. If ``yoffset`` is omitted, it distances. Data wraps around the edges. If ``yoffset`` is omitted, it
is assumed to be equal to ``xoffset``. is assumed to be equal to ``xoffset``.
:param image: Input image.
:param xoffset: The horizontal distance. :param xoffset: The horizontal distance.
:param yoffset: The vertical distance. If omitted, both :param yoffset: The vertical distance. If omitted, both
distances are set to the same value. distances are set to the same value.

View File

@ -150,7 +150,7 @@ FLAGS = {
"SOFTPROOFING": 16384, # Do softproofing "SOFTPROOFING": 16384, # Do softproofing
"PRESERVEBLACK": 32768, # Black preservation "PRESERVEBLACK": 32768, # Black preservation
"NODEFAULTRESOURCEDEF": 16777216, # CRD special "NODEFAULTRESOURCEDEF": 16777216, # CRD special
"GRIDPOINTS": lambda n: ((n) & 0xFF) << 16, # Gridpoints "GRIDPOINTS": lambda n: (n & 0xFF) << 16, # Gridpoints
} }
_MAX_FLAG = 0 _MAX_FLAG = 0
@ -1014,4 +1014,4 @@ def versions():
(pyCMS) Fetches versions. (pyCMS) Fetches versions.
""" """
return (VERSION, core.littlecms_version, sys.version.split()[0], Image.__version__) return VERSION, core.littlecms_version, sys.version.split()[0], Image.__version__

View File

@ -45,7 +45,7 @@ def getrgb(color):
# check for known string formats # check for known string formats
if re.match("#[a-f0-9]{3}$", color): if re.match("#[a-f0-9]{3}$", color):
return (int(color[1] * 2, 16), int(color[2] * 2, 16), int(color[3] * 2, 16)) return int(color[1] * 2, 16), int(color[2] * 2, 16), int(color[3] * 2, 16)
if re.match("#[a-f0-9]{4}$", color): if re.match("#[a-f0-9]{4}$", color):
return ( return (
@ -56,7 +56,7 @@ def getrgb(color):
) )
if re.match("#[a-f0-9]{6}$", color): if re.match("#[a-f0-9]{6}$", color):
return (int(color[1:3], 16), int(color[3:5], 16), int(color[5:7], 16)) return int(color[1:3], 16), int(color[3:5], 16), int(color[5:7], 16)
if re.match("#[a-f0-9]{8}$", color): if re.match("#[a-f0-9]{8}$", color):
return ( return (
@ -68,7 +68,7 @@ def getrgb(color):
m = re.match(r"rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$", color) m = re.match(r"rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$", color)
if m: if m:
return (int(m.group(1)), int(m.group(2)), int(m.group(3))) return int(m.group(1)), int(m.group(2)), int(m.group(3))
m = re.match(r"rgb\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)$", color) m = re.match(r"rgb\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)$", color)
if m: if m:
@ -114,25 +114,26 @@ def getrgb(color):
m = re.match(r"rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$", color) m = re.match(r"rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$", color)
if m: if m:
return (int(m.group(1)), int(m.group(2)), int(m.group(3)), int(m.group(4))) return int(m.group(1)), int(m.group(2)), int(m.group(3)), int(m.group(4))
raise ValueError(f"unknown color specifier: {repr(color)}") raise ValueError(f"unknown color specifier: {repr(color)}")
def getcolor(color, mode): def getcolor(color, mode):
""" """
Same as :py:func:`~PIL.ImageColor.getrgb`, but converts the RGB value to a Same as :py:func:`~PIL.ImageColor.getrgb`, but converts the RGB value to a
greyscale value if the mode is not color or a palette image. If the string greyscale value if ``mode`` is not color or a palette image. If the string
cannot be parsed, this function raises a :py:exc:`ValueError` exception. cannot be parsed, this function raises a :py:exc:`ValueError` exception.
.. versionadded:: 1.1.4 .. versionadded:: 1.1.4
:param color: A color string :param color: A color string
:return: ``(graylevel [, alpha]) or (red, green, blue[, alpha])`` :param mode: Convert result to this mode
:return: ``(graylevel[, alpha]) or (red, green, blue[, alpha])``
""" """
# same as getrgb, but converts the result to the given mode # same as getrgb, but converts the result to the given mode
color, alpha = getrgb(color), 255 color, alpha = getrgb(color), 255
if len(color) == 4: if len(color) == 4:
color, alpha = color[0:3], color[3] color, alpha = color[:3], color[3]
if Image.getmodebase(mode) == "L": if Image.getmodebase(mode) == "L":
r, g, b = color r, g, b = color
@ -140,7 +141,7 @@ def getcolor(color, mode):
# scaled to 24 bits to match the convert's implementation. # scaled to 24 bits to match the convert's implementation.
color = (r * 19595 + g * 38470 + b * 7471 + 0x8000) >> 16 color = (r * 19595 + g * 38470 + b * 7471 + 0x8000) >> 16
if mode[-1] == "A": if mode[-1] == "A":
return (color, alpha) return color, alpha
else: else:
if mode[-1] == "A": if mode[-1] == "A":
return color + (alpha,) return color + (alpha,)

View File

@ -571,7 +571,7 @@ class PyCodecState:
self.yoff = 0 self.yoff = 0
def extents(self): def extents(self):
return (self.xoff, self.yoff, self.xoff + self.xsize, self.yoff + self.ysize) return self.xoff, self.yoff, self.xoff + self.xsize, self.yoff + self.ysize
class PyCodec: class PyCodec:
@ -681,7 +681,7 @@ class PyDecoder(PyCodec):
if not rawmode: if not rawmode:
rawmode = self.mode rawmode = self.mode
d = Image._getdecoder(self.mode, "raw", (rawmode)) d = Image._getdecoder(self.mode, "raw", rawmode)
d.setimage(self.im, self.state.extents()) d.setimage(self.im, self.state.extents())
s = d.decode(data) s = d.decode(data)

View File

@ -84,7 +84,7 @@ _UNSPECIFIED = object()
class ImageFont: class ImageFont:
"PIL font wrapper" """PIL font wrapper"""
def _load_pilfont(self, filename): def _load_pilfont(self, filename):
@ -172,7 +172,7 @@ class ImageFont:
class FreeTypeFont: class FreeTypeFont:
"FreeType font wrapper (requires _imagingft service)" """FreeType font wrapper (requires _imagingft service)"""
def __init__(self, font=None, size=10, index=0, encoding="", layout_engine=None): def __init__(self, font=None, size=10, index=0, encoding="", layout_engine=None):
# FIXME: use service provider instead # FIXME: use service provider instead
@ -774,7 +774,7 @@ class FreeTypeFont:
class TransposedFont: class TransposedFont:
"Wrapper for writing rotated or mirrored text" """Wrapper for writing rotated or mirrored text"""
def __init__(self, font, orientation=None): def __init__(self, font, orientation=None):
""" """

View File

@ -119,13 +119,13 @@ class LutBuilder:
# mirror # mirror
if "M" in options: if "M" in options:
n = len(patterns) n = len(patterns)
for pattern, res in patterns[0:n]: for pattern, res in patterns[:n]:
patterns.append((self._string_permute(pattern, MIRROR_MATRIX), res)) patterns.append((self._string_permute(pattern, MIRROR_MATRIX), res))
# negate # negate
if "N" in options: if "N" in options:
n = len(patterns) n = len(patterns)
for pattern, res in patterns[0:n]: for pattern, res in patterns[:n]:
# Swap 0 and 1 # Swap 0 and 1
pattern = pattern.replace("0", "Z").replace("1", "0").replace("Z", "1") pattern = pattern.replace("0", "Z").replace("1", "0").replace("Z", "1")
res = 1 - int(res) res = 1 - int(res)

View File

@ -184,6 +184,8 @@ class PhotoImage:
:param im: A PIL image. The size must match the target region. If the :param im: A PIL image. The size must match the target region. If the
mode does not match, the image is converted to the mode of mode does not match, the image is converted to the mode of
the bitmap image. the bitmap image.
:param box: Deprecated. This parameter will be removed in Pillow 10
(2023-07-01).
""" """
if box is not None: if box is not None:

View File

@ -124,7 +124,7 @@ def _parse_codestream(fp):
else: else:
mode = None mode = None
return (size, mode) return size, mode
def _res_to_dpi(num, denom, exp): def _res_to_dpi(num, denom, exp):
@ -191,7 +191,7 @@ def _parse_jp2_header(fp):
if size is None or mode is None: if size is None or mode is None:
raise SyntaxError("Malformed JP2 header") raise SyntaxError("Malformed JP2 header")
return (size, mode, mimetype, dpi) return size, mode, mimetype, dpi
## ##

View File

@ -331,7 +331,7 @@ MARKER = {
def _accept(prefix): def _accept(prefix):
# Magic number was taken from https://en.wikipedia.org/wiki/JPEG # Magic number was taken from https://en.wikipedia.org/wiki/JPEG
return prefix[0:3] == b"\xFF\xD8\xFF" return prefix[:3] == b"\xFF\xD8\xFF"
## ##
@ -445,7 +445,7 @@ class JpegImageFile(ImageFile.ImageFile):
self.decoderconfig = (scale, 0) self.decoderconfig = (scale, 0)
box = (0, 0, original_size[0] / scale, original_size[1] / scale) box = (0, 0, original_size[0] / scale, original_size[1] / scale)
return (self.mode, box) return self.mode, box
def load_djpeg(self): def load_djpeg(self):

View File

@ -31,7 +31,7 @@ class PaletteFile:
if not s: if not s:
break break
if s[0:1] == b"#": if s[:1] == b"#":
continue continue
if len(s) > 100: if len(s) > 100:
raise SyntaxError("bad palette file") raise SyntaxError("bad palette file")

View File

@ -590,7 +590,7 @@ class PdfParser:
whitespace_mandatory whitespace_mandatory
+ rb"trailer" + rb"trailer"
+ whitespace_optional + whitespace_optional
+ rb"\<\<(.*\>\>)" + rb"<<(.*>>)"
+ newline + newline
+ rb"startxref" + rb"startxref"
+ newline + newline
@ -605,7 +605,7 @@ class PdfParser:
whitespace_optional whitespace_optional
+ rb"trailer" + rb"trailer"
+ whitespace_optional + whitespace_optional
+ rb"\<\<(.*?\>\>)" + rb"<<(.*?>>)"
+ newline + newline
+ rb"startxref" + rb"startxref"
+ newline + newline
@ -659,8 +659,8 @@ class PdfParser:
+ delimiter_or_ws + delimiter_or_ws
+ rb")" + rb")"
) )
re_dict_start = re.compile(whitespace_optional + rb"\<\<") re_dict_start = re.compile(whitespace_optional + rb"<<")
re_dict_end = re.compile(whitespace_optional + rb"\>\>" + whitespace_optional) re_dict_end = re.compile(whitespace_optional + rb">>" + whitespace_optional)
@classmethod @classmethod
def interpret_trailer(cls, trailer_data): def interpret_trailer(cls, trailer_data):
@ -719,7 +719,7 @@ class PdfParser:
re_array_start = re.compile(whitespace_optional + rb"\[") re_array_start = re.compile(whitespace_optional + rb"\[")
re_array_end = re.compile(whitespace_optional + rb"]") re_array_end = re.compile(whitespace_optional + rb"]")
re_string_hex = re.compile( re_string_hex = re.compile(
whitespace_optional + rb"\<(" + whitespace_or_hex + rb"*)\>" whitespace_optional + rb"<(" + whitespace_or_hex + rb"*)>"
) )
re_string_lit = re.compile(whitespace_optional + rb"\(") re_string_lit = re.compile(whitespace_optional + rb"\(")
re_indirect_reference = re.compile( re_indirect_reference = re.compile(

View File

@ -178,7 +178,7 @@ def _layerinfo(fp, ct_bytes):
if ct_bytes < (abs(ct) * 20): if ct_bytes < (abs(ct) * 20):
raise SyntaxError("Layer block too short for number of layers requested") raise SyntaxError("Layer block too short for number of layers requested")
for i in range(abs(ct)): for _ in range(abs(ct)):
# bounding box # bounding box
y0 = i32(read(4)) y0 = i32(read(4))
@ -193,7 +193,7 @@ def _layerinfo(fp, ct_bytes):
if len(types) > 4: if len(types) > 4:
continue continue
for i in types: for _ in types:
type = i16(read(2)) type = i16(read(2))
if type == 65535: if type == 65535:

View File

@ -135,7 +135,7 @@ class _PyAccess32_2(PyAccess):
def get_pixel(self, x, y): def get_pixel(self, x, y):
pixel = self.pixels[y][x] pixel = self.pixels[y][x]
return (pixel.r, pixel.a) return pixel.r, pixel.a
def set_pixel(self, x, y, color): def set_pixel(self, x, y, color):
pixel = self.pixels[y][x] pixel = self.pixels[y][x]
@ -152,7 +152,7 @@ class _PyAccess32_3(PyAccess):
def get_pixel(self, x, y): def get_pixel(self, x, y):
pixel = self.pixels[y][x] pixel = self.pixels[y][x]
return (pixel.r, pixel.g, pixel.b) return pixel.r, pixel.g, pixel.b
def set_pixel(self, x, y, color): def set_pixel(self, x, y, color):
pixel = self.pixels[y][x] pixel = self.pixels[y][x]
@ -171,7 +171,7 @@ class _PyAccess32_4(PyAccess):
def get_pixel(self, x, y): def get_pixel(self, x, y):
pixel = self.pixels[y][x] pixel = self.pixels[y][x]
return (pixel.r, pixel.g, pixel.b, pixel.a) return pixel.r, pixel.g, pixel.b, pixel.a
def set_pixel(self, x, y, color): def set_pixel(self, x, y, color):
pixel = self.pixels[y][x] pixel = self.pixels[y][x]

View File

@ -338,12 +338,12 @@ class IFDRational(Rational):
self._val = Fraction(value, denominator) self._val = Fraction(value, denominator)
@property @property
def numerator(a): def numerator(self):
return a._numerator return self._numerator
@property @property
def denominator(a): def denominator(self):
return a._denominator return self._denominator
def limit_rational(self, max_denominator): def limit_rational(self, max_denominator):
""" """
@ -353,10 +353,10 @@ class IFDRational(Rational):
""" """
if self.denominator == 0: if self.denominator == 0:
return (self.numerator, self.denominator) return self.numerator, self.denominator
f = self._val.limit_denominator(max_denominator) f = self._val.limit_denominator(max_denominator)
return (f.numerator, f.denominator) return f.numerator, f.denominator
def __repr__(self): def __repr__(self):
return str(float(self._val)) return str(float(self._val))
@ -1748,9 +1748,8 @@ def _save(im, fp, filename):
SUBIFD, SUBIFD,
] ]
atts = {}
# bits per sample is a single short in the tiff directory, not a list. # bits per sample is a single short in the tiff directory, not a list.
atts[BITSPERSAMPLE] = bits[0] atts = {BITSPERSAMPLE: bits[0]}
# Merge the ones that we have with (optional) more bits from # Merge the ones that we have with (optional) more bits from
# the original file, e.g x,y resolution so that we can # the original file, e.g x,y resolution so that we can
# save(load('')) == original file. # save(load('')) == original file.

View File

@ -36,8 +36,12 @@ class TagInfo(namedtuple("_TagInfo", "value name type length enum")):
def lookup(tag, group=None): def lookup(tag, group=None):
""" """
:param tag: Integer tag number :param tag: Integer tag number
:returns: Taginfo namedtuple, From the TAGS_V2 info if possible, :param group: Which :py:data:`~PIL.TiffTags.TAGS_V2_GROUPS` to look in
otherwise just populating the value and name from TAGS.
.. versionadded:: 8.3.0
:returns: Taginfo namedtuple, From the ``TAGS_V2`` info if possible,
otherwise just populating the value and name from ``TAGS``.
If the tag is not recognized, "unknown" is returned for the name If the tag is not recognized, "unknown" is returned for the name
""" """

View File

@ -222,11 +222,10 @@ def _save_all(im, fp, filename):
if ( if (
not isinstance(background, (list, tuple)) not isinstance(background, (list, tuple))
or len(background) != 4 or len(background) != 4
or not all(v >= 0 and v < 256 for v in background) or not all(0 <= v < 256 for v in background)
): ):
raise OSError( raise OSError(
"Background color is not an RGBA tuple clamped to (0-255): %s" f"Background color is not an RGBA tuple clamped to (0-255): {background}"
% str(background)
) )
# Convert to packed uint # Convert to packed uint

View File

@ -31,7 +31,7 @@ xbm_head = re.compile(
b"#define[ \t]+[^_]*_x_hot[ \t]+(?P<xhot>[0-9]+)[\r\n]+" b"#define[ \t]+[^_]*_x_hot[ \t]+(?P<xhot>[0-9]+)[\r\n]+"
b"#define[ \t]+[^_]*_y_hot[ \t]+(?P<yhot>[0-9]+)[\r\n]+" b"#define[ \t]+[^_]*_y_hot[ \t]+(?P<yhot>[0-9]+)[\r\n]+"
b")?" b")?"
b"[\\000-\\377]*_bits\\[\\]" rb"[\000-\377]*_bits\[]"
) )

View File

@ -64,7 +64,7 @@ class XpmImageFile(ImageFile.ImageFile):
palette = [b"\0\0\0"] * 256 palette = [b"\0\0\0"] * 256
for i in range(pal): for _ in range(pal):
s = self.fp.readline() s = self.fp.readline()
if s[-2:] == b"\r\n": if s[-2:] == b"\r\n":
@ -83,7 +83,7 @@ class XpmImageFile(ImageFile.ImageFile):
rgb = s[i + 1] rgb = s[i + 1]
if rgb == b"None": if rgb == b"None":
self.info["transparency"] = c self.info["transparency"] = c
elif rgb[0:1] == b"#": elif rgb[:1] == b"#":
# FIXME: handle colour names (see ImagePalette.py) # FIXME: handle colour names (see ImagePalette.py)
rgb = int(rgb[1:], 16) rgb = int(rgb[1:], 16)
palette[c] = ( palette[c] = (