Pillow/Tests/test_pickle.py
2024-09-09 22:34:46 +10:00

155 lines
4.3 KiB
Python

from __future__ import annotations
import pickle
from pathlib import Path
import pytest
from PIL import Image, ImageDraw, ImageFont
from .helper import assert_image_equal, skip_unless_feature
FONT_SIZE = 20
FONT_PATH = "Tests/fonts/DejaVuSans/DejaVuSans.ttf"
def helper_pickle_file(
tmp_path: Path, protocol: int, test_file: str, mode: str | None
) -> None:
# Arrange
im: Image.Image
with Image.open(test_file) as im:
filename = str(tmp_path / "temp.pkl")
if mode:
im = im.convert(mode)
# Act
with open(filename, "wb") as f:
pickle.dump(im, f, protocol)
with open(filename, "rb") as f:
loaded_im = pickle.load(f)
# Assert
assert im == loaded_im
def helper_pickle_string(protocol: int, test_file: str, mode: str | None) -> None:
im: Image.Image
with Image.open(test_file) as im:
if mode:
im = im.convert(mode)
# Act
dumped_string = pickle.dumps(im, protocol)
loaded_im = pickle.loads(dumped_string)
# Assert
assert im == loaded_im
@pytest.mark.parametrize(
"test_file, test_mode",
[
("Tests/images/hopper.jpg", None),
("Tests/images/hopper.jpg", "L"),
("Tests/images/hopper.jpg", "PA"),
pytest.param(
"Tests/images/hopper.webp", None, marks=skip_unless_feature("webp")
),
("Tests/images/hopper.tif", None),
("Tests/images/test-card.png", None),
("Tests/images/zero_bb.png", None),
("Tests/images/zero_bb_scale2.png", None),
("Tests/images/non_zero_bb.png", None),
("Tests/images/non_zero_bb_scale2.png", None),
("Tests/images/p_trns_single.png", None),
("Tests/images/pil123p.png", None),
("Tests/images/itxt_chunks.png", None),
],
)
@pytest.mark.parametrize("protocol", range(0, pickle.HIGHEST_PROTOCOL + 1))
def test_pickle_image(
tmp_path: Path, test_file: str, test_mode: str | None, protocol: int
) -> None:
# Act / Assert
helper_pickle_string(protocol, test_file, test_mode)
helper_pickle_file(tmp_path, protocol, test_file, test_mode)
def test_pickle_la_mode_with_palette(tmp_path: Path) -> None:
# Arrange
filename = str(tmp_path / "temp.pkl")
with Image.open("Tests/images/hopper.jpg") as img:
im = img.convert("PA")
# Act / Assert
for protocol in range(0, pickle.HIGHEST_PROTOCOL + 1):
im._mode = "LA"
with open(filename, "wb") as f:
pickle.dump(im, f, protocol)
with open(filename, "rb") as f:
loaded_im = pickle.load(f)
im._mode = "PA"
assert im == loaded_im
@skip_unless_feature("webp")
def test_pickle_tell() -> None:
# Arrange
with Image.open("Tests/images/hopper.webp") as image:
# Act: roundtrip
unpickled_image = pickle.loads(pickle.dumps(image))
# Assert
assert unpickled_image.tell() == 0
def helper_assert_pickled_font_images(
font1: ImageFont.FreeTypeFont, font2: ImageFont.FreeTypeFont
) -> None:
# Arrange
im1 = Image.new(mode="RGBA", size=(300, 100))
im2 = Image.new(mode="RGBA", size=(300, 100))
draw1 = ImageDraw.Draw(im1)
draw2 = ImageDraw.Draw(im2)
txt = "Hello World!"
# Act
draw1.text((10, 10), txt, font=font1)
draw2.text((10, 10), txt, font=font2)
# Assert
assert_image_equal(im1, im2)
@skip_unless_feature("freetype2")
@pytest.mark.parametrize("protocol", list(range(0, pickle.HIGHEST_PROTOCOL + 1)))
def test_pickle_font_string(protocol: int) -> None:
# Arrange
font = ImageFont.truetype(FONT_PATH, FONT_SIZE)
# Act: roundtrip
pickled_font = pickle.dumps(font, protocol)
unpickled_font = pickle.loads(pickled_font)
# Assert
helper_assert_pickled_font_images(font, unpickled_font)
@skip_unless_feature("freetype2")
@pytest.mark.parametrize("protocol", list(range(0, pickle.HIGHEST_PROTOCOL + 1)))
def test_pickle_font_file(tmp_path: Path, protocol: int) -> None:
# Arrange
font = ImageFont.truetype(FONT_PATH, FONT_SIZE)
filename = str(tmp_path / "temp.pkl")
# Act: roundtrip
with open(filename, "wb") as f:
pickle.dump(font, f, protocol)
with open(filename, "rb") as f:
unpickled_font = pickle.load(f)
# Assert
helper_assert_pickled_font_images(font, unpickled_font)