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 Jan 8, 2025
2 parents 3c3a2e6 + af3b904 commit b135739
Show file tree
Hide file tree
Showing 18 changed files with 181 additions and 101 deletions.
6 changes: 1 addition & 5 deletions .ci/after_success.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,4 @@

# gather the coverage data
python3 -m pip install coverage
if [[ $MATRIX_DOCKER ]]; then
python3 -m coverage xml --ignore-errors
else
python3 -m coverage xml
fi
python3 -m coverage xml
2 changes: 1 addition & 1 deletion .github/workflows/test-cygwin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
persist-credentials: false

- name: Install Cygwin
uses: cygwin/cygwin-install-action@v4
uses: cygwin/cygwin-install-action@v5
with:
packages: >
gcc-g++
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/test-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,15 @@ jobs:
- name: After success
run: |
PATH="$PATH:~/.local/bin"
docker start pillow_container
sudo docker cp pillow_container:/Pillow /Pillow
sudo chown -R runner /Pillow
pil_path=`docker exec pillow_container /vpy3/bin/python -c 'import os, PIL;print(os.path.realpath(os.path.dirname(PIL.__file__)))'`
docker stop pillow_container
sudo mkdir -p $pil_path
sudo cp src/PIL/*.py $pil_path
cd /Pillow
.ci/after_success.sh
env:
MATRIX_DOCKER: ${{ matrix.docker }}
- name: Upload coverage
uses: codecov/codecov-action@v5
Expand Down
17 changes: 5 additions & 12 deletions .github/workflows/wheels-dependencies.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,12 @@ ARCHIVE_SDIR=pillow-depends-main
# Package versions for fresh source builds
FREETYPE_VERSION=2.13.3
HARFBUZZ_VERSION=10.1.0
LIBPNG_VERSION=1.6.44
LIBPNG_VERSION=1.6.45
JPEGTURBO_VERSION=3.1.0
OPENJPEG_VERSION=2.5.3
XZ_VERSION=5.6.3
TIFF_VERSION=4.6.0
LCMS2_VERSION=2.16
GIFLIB_VERSION=5.2.2
ZLIB_NG_VERSION=2.2.3
LIBWEBP_VERSION=1.5.0
BZIP2_VERSION=1.0.8
Expand Down Expand Up @@ -99,7 +98,7 @@ function build_harfbuzz {

function build {
build_xz
if [ -z "$IS_ALPINE" ] && [ -z "$IS_MACOS" ]; then
if [ -z "$IS_ALPINE" ] && [ -z "$SANITIZER" ] && [ -z "$IS_MACOS" ]; then
yum remove -y zlib-devel
fi
build_zlib_ng
Expand Down Expand Up @@ -135,16 +134,10 @@ function build {
CFLAGS="$CFLAGS -O3 -DNDEBUG"
if [[ -n "$IS_MACOS" ]]; then
CFLAGS="$CFLAGS -Wl,-headerpad_max_install_names"
# For giflib 5.2.2
elif [ -n "$IS_ALPINE" ]; then
apk add imagemagick
else
if [[ "$MB_ML_VER" == "_2_28" ]]; then
yum install -y epel-release
fi
yum install -y ImageMagick
fi
build_libwebp
build_simple libwebp $LIBWEBP_VERSION \
https://storage.googleapis.com/downloads.webmproject.org/releases/webp tar.gz \
--enable-libwebpmux --enable-libwebpdemux
CFLAGS=$ORIGINAL_CFLAGS

build_brotli
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ on:
paths:
- ".ci/requirements-cibw.txt"
- ".github/workflows/wheel*"
- "pyproject.toml"
- "setup.py"
- "wheels/*"
- "winbuild/build_prepare.py"
Expand All @@ -23,6 +24,7 @@ on:
paths:
- ".ci/requirements-cibw.txt"
- ".github/workflows/wheel*"
- "pyproject.toml"
- "setup.py"
- "wheels/*"
- "winbuild/build_prepare.py"
Expand Down
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.4
rev: v0.8.6
hooks:
- id: ruff
args: [--exit-non-zero-on-fix]
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.5
rev: v19.1.6
hooks:
- id: clang-format
types: [c]
Expand Down Expand Up @@ -57,7 +57,7 @@ repos:
- id: check-renovate

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

Expand Down
13 changes: 10 additions & 3 deletions Tests/test_file_jpeg.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,10 @@ def test_progressive(self) -> None:
assert not im2.info.get("progressive")
assert im3.info.get("progressive")

assert_image_equal(im1, im3)
if features.check_feature("mozjpeg"):
assert_image_similar(im1, im3, 9.39)
else:
assert_image_equal(im1, im3)
assert im1_bytes >= im3_bytes

def test_progressive_large_buffer(self, tmp_path: Path) -> None:
Expand Down Expand Up @@ -440,8 +443,12 @@ def test_progressive_compat(self) -> None:

im2 = self.roundtrip(hopper(), progressive=1)
im3 = self.roundtrip(hopper(), progression=1) # compatibility
assert_image_equal(im1, im2)
assert_image_equal(im1, im3)
if features.check_feature("mozjpeg"):
assert_image_similar(im1, im2, 9.39)
assert_image_similar(im1, im3, 9.39)
else:
assert_image_equal(im1, im2)
assert_image_equal(im1, im3)
assert im2.info.get("progressive")
assert im2.info.get("progression")
assert im3.info.get("progressive")
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 @@ -1176,7 +1176,7 @@ def test_realloc_overflow(self, monkeypatch: pytest.MonkeyPatch) -> None:
im.load()

# Assert that the error code is IMAGING_CODEC_MEMORY
assert str(e.value) == "-9"
assert str(e.value) == "decoder error -9"

@pytest.mark.parametrize("compression", ("tiff_adobe_deflate", "jpeg"))
def test_save_multistrip(self, compression: str, tmp_path: Path) -> None:
Expand Down
6 changes: 3 additions & 3 deletions Tests/test_file_spider.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import pytest

from PIL import Image, ImageSequence, SpiderImagePlugin
from PIL import Image, SpiderImagePlugin

from .helper import assert_image_equal, hopper, is_pypy

Expand Down Expand Up @@ -154,8 +154,8 @@ def test_nonstack_file() -> None:

def test_nonstack_dos() -> None:
with Image.open(TEST_FILE) as im:
for i, frame in enumerate(ImageSequence.Iterator(im)):
assert i <= 1, "Non-stack DOS file test failed"
with pytest.raises(EOFError):
im.seek(0)


# for issue #4093
Expand Down
48 changes: 43 additions & 5 deletions Tests/test_file_tiff.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,18 @@ def test_bigtiff(self, tmp_path: Path) -> None:

def test_bigtiff_save(self, tmp_path: Path) -> None:
outfile = str(tmp_path / "temp.tif")
hopper().save(outfile, big_tiff=True)
im = hopper()
im.save(outfile, big_tiff=True)

with Image.open(outfile) as im:
assert isinstance(im, TiffImagePlugin.TiffImageFile)
assert im.tag_v2._bigtiff is True
with Image.open(outfile) as reloaded:
assert isinstance(reloaded, TiffImagePlugin.TiffImageFile)
assert reloaded.tag_v2._bigtiff is True

im.save(outfile, save_all=True, append_images=[im], big_tiff=True)

with Image.open(outfile) as reloaded:
assert isinstance(reloaded, TiffImagePlugin.TiffImageFile)
assert reloaded.tag_v2._bigtiff is True

def test_seek_too_large(self) -> None:
with pytest.raises(ValueError, match="Unable to seek to frame"):
Expand Down Expand Up @@ -776,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 @@ -789,6 +796,37 @@ def test_fixoffsets(self) -> None:
with pytest.raises(RuntimeError):
a.fixOffsets(1)

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")
with TiffImagePlugin.AppendingTiffWriter(b) as a:
a.offsetOfNewPage = 2**32

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

b.seek(0)
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"
b = BytesIO(data)
with TiffImagePlugin.AppendingTiffWriter(b) as a:
a.writeLong(2**32 - 1)
assert b.getvalue() == data + 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"
b = BytesIO(data)
with TiffImagePlugin.AppendingTiffWriter(b) as a:
a.rewriteLastShortToLong(2**32 - 1)
assert b.getvalue() == data[:-2] + b"\xff\xff\xff\xff"

def test_saving_icc_profile(self, tmp_path: Path) -> None:
# Tests saving TIFF with icc_profile set.
# At the time of writing this will only work for non-compressed tiffs
Expand Down
10 changes: 3 additions & 7 deletions src/PIL/BlpImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -375,14 +375,10 @@ def _decode_jpeg_stream(self) -> None:
image = JpegImageFile(BytesIO(data))
Image._decompression_bomb_check(image.size)
if image.mode == "CMYK":
decoder_name, extents, offset, args = image.tile[0]
args = image.tile[0].args
assert isinstance(args, tuple)
image.tile = [
ImageFile._Tile(decoder_name, extents, offset, (args[0], "CMYK"))
]
r, g, b = image.convert("RGB").split()
reversed_image = Image.merge("RGB", (b, g, r))
self.set_as_raw(reversed_image.tobytes())
image.tile = [image.tile[0]._replace(args=(args[0], "CMYK"))]
self.set_as_raw(image.convert("RGB").tobytes(), "BGR")


class BLP2Decoder(_BLPBaseDecoder):
Expand Down
Loading

0 comments on commit b135739

Please sign in to comment.