Pillow/Tests/test_imagetk.py
2024-06-22 14:23:01 +02:00

127 lines
3.5 KiB
Python

from __future__ import annotations
import gc
import pytest
import tkinter as tk
from unittest import mock
from PIL import Image
from PIL import ImageTk
from .helper import assert_image_equal, hopper
TK_MODES = ("1", "L", "P", "RGB", "RGBA")
try:
dir(ImageTk)
HAS_TK = True
except (OSError, ImportError):
HAS_TK = False
pytestmark = pytest.mark.skipif(not HAS_TK, reason="Tk not installed")
def setup_module() -> None:
try:
# setup tk
tk.Frame()
except RuntimeError as v:
pytest.skip(f"RuntimeError: {v}")
except tk.TclError as v:
pytest.skip(f"TCL Error: {v}")
def test_kw() -> None:
TEST_JPG = "Tests/images/hopper.jpg"
TEST_PNG = "Tests/images/hopper.png"
with Image.open(TEST_JPG) as im1:
with Image.open(TEST_PNG) as im2:
with open(TEST_PNG, "rb") as fp:
data = fp.read()
kw = {"file": TEST_JPG, "data": data}
# Test "file"
im = ImageTk._get_image_from_kw(kw)
assert_image_equal(im, im1)
# Test "data"
im = ImageTk._get_image_from_kw(kw)
assert_image_equal(im, im2)
# Test no relevant entry
im = ImageTk._get_image_from_kw(kw)
assert im is None
@pytest.mark.parametrize("mode", TK_MODES)
def test_photoimage(mode: str) -> None:
# test as image:
im = hopper(mode)
# this should not crash
im_tk = ImageTk.PhotoImage(im)
assert im_tk.width() == im.width
assert im_tk.height() == im.height
reloaded = ImageTk.getimage(im_tk)
assert_image_equal(reloaded, im.convert("RGBA"))
def test_photoimage_apply_transparency() -> None:
with Image.open("Tests/images/pil123p.png") as im:
im_tk = ImageTk.PhotoImage(im)
reloaded = ImageTk.getimage(im_tk)
assert_image_equal(reloaded, im.convert("RGBA"))
@pytest.mark.parametrize("mode", TK_MODES)
def test_photoimage_blank(mode: str) -> None:
# test a image using mode/size:
im_tk = ImageTk.PhotoImage(mode, (100, 100))
assert im_tk.width() == 100
assert im_tk.height() == 100
im = Image.new(mode, (100, 100))
reloaded = ImageTk.getimage(im_tk)
assert_image_equal(reloaded.convert(mode), im)
def test_bitmapimage() -> None:
im = hopper("1")
# this should not crash
im_tk = ImageTk.BitmapImage(im)
assert im_tk.width() == im.width
assert im_tk.height() == im.height
# reloaded = ImageTk.getimage(im_tk)
# assert_image_equal(reloaded, im)
def test_bitmapimage_del() -> None:
# Set up an image
im = Image.new("1", (10, 10))
# Mock the tkinter PhotoImage to track calls
with mock.patch.object(tk, 'BitmapImage', wraps=tk.BitmapImage) as mock_bitmapimage:
# Create an instance of BitmapImage
bitmap_image = ImageTk.BitmapImage(im)
# Ensure the BitmapImage was created
assert mock_bitmapimage.call_count == 1
# Get the internal Tkinter image object
tk_image = bitmap_image._BitmapImage__photo
# Mock the tk.call method to track the 'image delete' call
with mock.patch.object(tk_image.tk, 'call', wraps=tk_image.tk.call) as mock_tk_call:
# Delete the instance and force garbage collection
del bitmap_image
gc.collect()
# Check that the 'image delete' command was called
mock_tk_call.assert_any_call("image", "delete", tk_image.name)