Skip to content

Commit

Permalink
Merge branch 'main' into context_manager
Browse files Browse the repository at this point in the history
  • Loading branch information
radarhere authored Feb 6, 2025
2 parents b9d3bb6 + b57b4e5 commit 9ca85eb
Show file tree
Hide file tree
Showing 50 changed files with 305 additions and 312 deletions.
6 changes: 1 addition & 5 deletions .github/workflows/macos-install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,11 @@ brew install \
ghostscript \
jpeg-turbo \
libimagequant \
libraqm \
libtiff \
little-cms2 \
openjpeg \
webp
if [[ "$ImageOS" == "macos13" ]]; then
brew install --ignore-dependencies libraqm
else
brew install libraqm
fi
export PKG_CONFIG_PATH="/usr/local/opt/openblas/lib/pkgconfig"

python3 -m pip install coverage
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/test-mingw.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ jobs:
mingw-w64-x86_64-gcc \
mingw-w64-x86_64-ghostscript \
mingw-w64-x86_64-lcms2 \
mingw-w64-x86_64-libimagequant \
mingw-w64-x86_64-libjpeg-turbo \
mingw-w64-x86_64-libraqm \
mingw-w64-x86_64-libtiff \
Expand Down
14 changes: 7 additions & 7 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.6
rev: v0.9.4
hooks:
- id: ruff
args: [--exit-non-zero-on-fix]

- repo: https://github.com/psf/black-pre-commit-mirror
rev: 24.10.0
rev: 25.1.0
hooks:
- id: black

- repo: https://github.com/PyCQA/bandit
rev: 1.8.0
rev: 1.8.2
hooks:
- id: bandit
args: [--severity-level=high]
Expand All @@ -24,7 +24,7 @@ repos:
exclude: (Makefile$|\.bat$|\.cmake$|\.eps$|\.fits$|\.gd$|\.opt$)

- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v19.1.6
rev: v19.1.7
hooks:
- id: clang-format
types: [c]
Expand All @@ -50,14 +50,14 @@ repos:
exclude: ^.github/.*TEMPLATE|^Tests/(fonts|images)/

- repo: https://github.com/python-jsonschema/check-jsonschema
rev: 0.30.0
rev: 0.31.1
hooks:
- id: check-github-workflows
- id: check-readthedocs
- id: check-renovate

- repo: https://github.com/woodruffw/zizmor-pre-commit
rev: v1.0.0
rev: v1.3.0
hooks:
- id: zizmor

Expand All @@ -78,7 +78,7 @@ repos:
additional_dependencies: [trove-classifiers>=2024.10.12]

- repo: https://github.com/tox-dev/tox-ini-fmt
rev: 1.4.1
rev: 1.5.0
hooks:
- id: tox-ini-fmt

Expand Down
Binary file added Tests/images/multiline_text_justify.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 9 additions & 11 deletions Tests/test_color_lut.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
class TestColorLut3DCoreAPI:
def generate_identity_table(
self, channels: int, size: int | tuple[int, int, int]
) -> tuple[int, int, int, int, list[float]]:
) -> tuple[int, tuple[int, int, int], list[float]]:
if isinstance(size, tuple):
size_1d, size_2d, size_3d = size
else:
Expand All @@ -39,9 +39,7 @@ def generate_identity_table(
]
return (
channels,
size_1d,
size_2d,
size_3d,
(size_1d, size_2d, size_3d),
[item for sublist in table for item in sublist],
)

Expand Down Expand Up @@ -89,21 +87,21 @@ def test_wrong_args(self) -> None:

with pytest.raises(ValueError, match=r"size1D \* size2D \* size3D"):
im.im.color_lut_3d(
"RGB", Image.Resampling.BILINEAR, 3, 2, 2, 2, [0, 0, 0] * 7
"RGB", Image.Resampling.BILINEAR, 3, (2, 2, 2), [0, 0, 0] * 7
)

with pytest.raises(ValueError, match=r"size1D \* size2D \* size3D"):
im.im.color_lut_3d(
"RGB", Image.Resampling.BILINEAR, 3, 2, 2, 2, [0, 0, 0] * 9
"RGB", Image.Resampling.BILINEAR, 3, (2, 2, 2), [0, 0, 0] * 9
)

with pytest.raises(TypeError):
im.im.color_lut_3d(
"RGB", Image.Resampling.BILINEAR, 3, 2, 2, 2, [0, 0, "0"] * 8
"RGB", Image.Resampling.BILINEAR, 3, (2, 2, 2), [0, 0, "0"] * 8
)

with pytest.raises(TypeError):
im.im.color_lut_3d("RGB", Image.Resampling.BILINEAR, 3, 2, 2, 2, 16)
im.im.color_lut_3d("RGB", Image.Resampling.BILINEAR, 3, (2, 2, 2), 16)

@pytest.mark.parametrize(
"lut_mode, table_channels, table_size",
Expand Down Expand Up @@ -264,7 +262,7 @@ def test_channels_order(self) -> None:
assert_image_equal(
Image.merge('RGB', im.split()[::-1]),
im._new(im.im.color_lut_3d('RGB', Image.Resampling.BILINEAR,
3, 2, 2, 2, [
3, (2, 2, 2), [
0, 0, 0, 0, 0, 1,
0, 1, 0, 0, 1, 1,

Expand All @@ -286,7 +284,7 @@ def test_overflow(self) -> None:

# fmt: off
transformed = im._new(im.im.color_lut_3d('RGB', Image.Resampling.BILINEAR,
3, 2, 2, 2,
3, (2, 2, 2),
[
-1, -1, -1, 2, -1, -1,
-1, 2, -1, 2, 2, -1,
Expand All @@ -307,7 +305,7 @@ def test_overflow(self) -> None:

# fmt: off
transformed = im._new(im.im.color_lut_3d('RGB', Image.Resampling.BILINEAR,
3, 2, 2, 2,
3, (2, 2, 2),
[
-3, -3, -3, 5, -3, -3,
-3, 5, -3, 5, 5, -3,
Expand Down
24 changes: 6 additions & 18 deletions Tests/test_file_gif.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,16 +86,12 @@ def test_invalid_file() -> None:
def test_l_mode_transparency() -> None:
with Image.open("Tests/images/no_palette_with_transparency.gif") as im:
assert im.mode == "L"
px = im.load()
assert px is not None
assert px[0, 0] == 128
assert im.getpixel((0, 0)) == 128
assert im.info["transparency"] == 255

im.seek(1)
assert im.mode == "L"
px = im.load()
assert px is not None
assert px[0, 0] == 128
assert im.getpixel((0, 0)) == 128


def test_l_mode_after_rgb() -> None:
Expand Down Expand Up @@ -319,24 +315,18 @@ def test_loading_multiple_palettes(path: str, mode: str) -> None:
assert im.mode == "P"
assert im.palette is not None
first_frame_colors = im.palette.colors.keys()
px = im.convert("RGB").load()
assert px is not None
original_color = px[0, 0]
original_color = im.convert("RGB").getpixel((0, 0))

im.seek(1)
assert im.mode == mode
if mode == "RGBA":
im = im.convert("RGB")

# Check a color only from the old palette
px = im.load()
assert px is not None
assert px[0, 0] == original_color
assert im.getpixel((0, 0)) == original_color

# Check a color from the new palette
px = im.load()
assert px is not None
assert px[24, 24] not in first_frame_colors
assert im.getpixel((24, 24)) not in first_frame_colors


def test_headers_saving_for_animated_gifs(tmp_path: Path) -> None:
Expand Down Expand Up @@ -510,9 +500,7 @@ def test_eoferror() -> None:

def test_first_frame_transparency() -> None:
with Image.open("Tests/images/first_frame_transparency.gif") as im:
px = im.load()
assert px is not None
assert px[0, 0] == im.info["transparency"]
assert im.getpixel((0, 0)) == im.info["transparency"]


def test_dispose_none() -> None:
Expand Down
2 changes: 1 addition & 1 deletion Tests/test_file_jpeg.py
Original file line number Diff line number Diff line change
Expand Up @@ -964,7 +964,7 @@ def test_icc_after_SOF(self) -> None:

def test_jpeg_magic_number(self, monkeypatch: pytest.MonkeyPatch) -> None:
size = 4097
buffer = BytesIO(b"\xFF" * size) # Many xFF bytes
buffer = BytesIO(b"\xff" * size) # Many xff bytes
max_pos = 0
orig_read = buffer.read

Expand Down
2 changes: 1 addition & 1 deletion Tests/test_file_libtiff.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ class Tc(NamedTuple):
}

def check_tags(
tiffinfo: TiffImagePlugin.ImageFileDirectory_v2 | dict[int, str]
tiffinfo: TiffImagePlugin.ImageFileDirectory_v2 | dict[int, str],
) -> None:
im = hopper()

Expand Down
4 changes: 2 additions & 2 deletions Tests/test_file_pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ def test_pdf_append(tmp_path: Path) -> None:
# append some info
pdf.info.Title = "abc"
pdf.info.Author = "def"
pdf.info.Subject = "ghi\uABCD"
pdf.info.Subject = "ghi\uabcd"
pdf.info.Keywords = "qw)e\\r(ty"
pdf.info.Creator = "hopper()"
pdf.start_writing()
Expand Down Expand Up @@ -292,7 +292,7 @@ def test_pdf_append(tmp_path: Path) -> None:
assert pdf.info.Title == "abc"
assert pdf.info.Producer == "PdfParser"
assert pdf.info.Keywords == "qw)e\\r(ty"
assert pdf.info.Subject == "ghi\uABCD"
assert pdf.info.Subject == "ghi\uabcd"
assert b"CreationDate" in pdf.info
assert b"ModDate" in pdf.info
check_pdf_pages_consistency(pdf)
Expand Down
4 changes: 2 additions & 2 deletions Tests/test_file_ppm.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def test_sanity() -> None:
(b"P5 3 1 257 \x00\x00\x00\x80\x01\x01", "I", (0, 32640, 65535)),
# P6 with maxval < 255
(
b"P6 3 1 17 \x00\x01\x02\x08\x09\x0A\x0F\x10\x11",
b"P6 3 1 17 \x00\x01\x02\x08\x09\x0a\x0f\x10\x11",
"RGB",
(
(0, 15, 30),
Expand All @@ -60,7 +60,7 @@ def test_sanity() -> None:
# P6 with maxval > 255
(
b"P6 3 1 257 \x00\x00\x00\x01\x00\x02"
b"\x00\x80\x00\x81\x00\x82\x01\x00\x01\x01\xFF\xFF",
b"\x00\x80\x00\x81\x00\x82\x01\x00\x01\x01\xff\xff",
"RGB",
(
(0, 1, 2),
Expand Down
16 changes: 9 additions & 7 deletions Tests/test_file_tiff.py
Original file line number Diff line number Diff line change
Expand Up @@ -783,7 +783,7 @@ def im_generator(ims: list[Image.Image]) -> Generator[Image.Image, None, None]:
assert reread.n_frames == 3

def test_fixoffsets(self) -> None:
b = BytesIO(b"II\x2A\x00\x00\x00\x00\x00")
b = BytesIO(b"II\x2a\x00\x00\x00\x00\x00")
with TiffImagePlugin.AppendingTiffWriter(b) as a:
b.seek(0)
a.fixOffsets(1, isShort=True)
Expand All @@ -796,14 +796,14 @@ def test_fixoffsets(self) -> None:
with pytest.raises(RuntimeError):
a.fixOffsets(1)

b = BytesIO(b"II\x2A\x00\x00\x00\x00\x00")
b = BytesIO(b"II\x2a\x00\x00\x00\x00\x00")
with TiffImagePlugin.AppendingTiffWriter(b) as a:
a.offsetOfNewPage = 2**16

b.seek(0)
a.fixOffsets(1, isShort=True)

b = BytesIO(b"II\x2B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
b = BytesIO(b"II\x2b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
with TiffImagePlugin.AppendingTiffWriter(b) as a:
a.offsetOfNewPage = 2**32

Expand All @@ -814,18 +814,20 @@ def test_fixoffsets(self) -> None:
a.fixOffsets(1, isLong=True)

def test_appending_tiff_writer_writelong(self) -> None:
data = b"II\x2A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
data = b"II\x2a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
b = BytesIO(data)
with TiffImagePlugin.AppendingTiffWriter(b) as a:
a.seek(-4, os.SEEK_CUR)
a.writeLong(2**32 - 1)
assert b.getvalue() == data + b"\xff\xff\xff\xff"
assert b.getvalue() == data[:-4] + b"\xff\xff\xff\xff"

def test_appending_tiff_writer_rewritelastshorttolong(self) -> None:
data = b"II\x2A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
data = b"II\x2a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
b = BytesIO(data)
with TiffImagePlugin.AppendingTiffWriter(b) as a:
a.seek(-2, os.SEEK_CUR)
a.rewriteLastShortToLong(2**32 - 1)
assert b.getvalue() == data[:-2] + b"\xff\xff\xff\xff"
assert b.getvalue() == data[:-4] + b"\xff\xff\xff\xff"

def test_saving_icc_profile(self, tmp_path: Path) -> None:
# Tests saving TIFF with icc_profile set.
Expand Down
2 changes: 1 addition & 1 deletion Tests/test_file_wmf.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def test_load_float_dpi() -> None:

with open("Tests/images/drawing.emf", "rb") as fp:
data = fp.read()
b = BytesIO(data[:8] + b"\x06\xFA" + data[10:])
b = BytesIO(data[:8] + b"\x06\xfa" + data[10:])
with Image.open(b) as im:
assert im.info["dpi"][0] == 2540

Expand Down
4 changes: 1 addition & 3 deletions Tests/test_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -578,9 +578,7 @@ def test_storage_neg(self) -> None:
def test_one_item_tuple(self) -> None:
for mode in ("I", "F", "L"):
im = Image.new(mode, (100, 100), (5,))
px = im.load()
assert px is not None
assert px[0, 0] == 5
assert im.getpixel((0, 0)) == 5

def test_linear_gradient_wrong_mode(self) -> None:
# Arrange
Expand Down
4 changes: 1 addition & 3 deletions Tests/test_image_convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,7 @@ def test_l_macro_rounding(convert_mode: str) -> None:
im.palette.getcolor((0, 1, 2))

converted_im = im.convert(convert_mode)
px = converted_im.load()
assert px is not None
converted_color = px[0, 0]
converted_color = converted_im.getpixel((0, 0))
if convert_mode == "LA":
assert isinstance(converted_color, tuple)
converted_color = converted_color[0]
Expand Down
4 changes: 1 addition & 3 deletions Tests/test_image_quantize.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,8 @@ def test_palette(method: Image.Quantize, color: tuple[int, ...]) -> None:
im = Image.new("RGBA" if len(color) == 4 else "RGB", (1, 1), color)

converted = im.quantize(method=method)
converted_px = converted.load()
assert converted_px is not None
assert converted.palette is not None
assert converted_px[0, 0] == converted.palette.colors[color]
assert converted.getpixel((0, 0)) == converted.palette.colors[color]


def test_small_palette() -> None:
Expand Down
2 changes: 1 addition & 1 deletion Tests/test_imagedraw.py
Original file line number Diff line number Diff line change
Expand Up @@ -813,7 +813,7 @@ def test_rounded_rectangle(
tuple[int, int, int, int]
| tuple[list[int]]
| tuple[tuple[int, int], tuple[int, int]]
)
),
) -> None:
# Arrange
im = Image.new("RGB", (200, 200))
Expand Down
Loading

0 comments on commit 9ca85eb

Please sign in to comment.