152 lines
4.7 KiB
Python
152 lines
4.7 KiB
Python
import io
|
|
import os
|
|
import re
|
|
import shutil
|
|
from importlib import import_module
|
|
|
|
import pytest
|
|
from PIL import Image as PIL_Image, ImageDraw as PIL_ImageDraw
|
|
|
|
import toga
|
|
|
|
|
|
def image_probe(app, image):
|
|
module = import_module("tests_backend.images")
|
|
return module.ImageProbe(app, image)
|
|
|
|
|
|
async def test_local_image(app):
|
|
"An image can be specified by filename"
|
|
image = toga.Image("resources/sample.png")
|
|
assert image.width == 144
|
|
assert image.height == 72
|
|
|
|
|
|
async def test_raw_image(app):
|
|
"An image can be created from the platform's raw representation"
|
|
original = toga.Image("resources/sample.png")
|
|
|
|
image = toga.Image(original._impl.native)
|
|
|
|
assert image.width == original.width
|
|
assert image.height == original.height
|
|
|
|
|
|
async def test_bad_image_file(app):
|
|
"If a file isn't a loadable image, an error is raised"
|
|
with pytest.raises(
|
|
ValueError,
|
|
match=rf"Unable to load image from {re.escape(__file__)}",
|
|
):
|
|
toga.Image(__file__)
|
|
|
|
|
|
async def test_buffer_image(app):
|
|
"An image can be constructed from buffer data"
|
|
# Generate an image using pillow
|
|
pil_image = PIL_Image.new("RGBA", size=(110, 30))
|
|
draw_context = PIL_ImageDraw.Draw(pil_image)
|
|
draw_context.text((20, 10), "Hello World", fill="green")
|
|
|
|
buffer = io.BytesIO()
|
|
pil_image.save(buffer, format="png", compress_level=0)
|
|
|
|
# Construct a Toga image from buffer data.
|
|
image = toga.Image(buffer.getvalue())
|
|
|
|
assert image.width == 110
|
|
assert image.height == 30
|
|
|
|
|
|
async def test_pil_raw_and_data_image(app):
|
|
"An image can be created from PIL, platform's raw representation and `toga.Image` data"
|
|
# Generate an image using pillow
|
|
pil_image = PIL_Image.new("RGBA", size=(110, 30))
|
|
draw_context = PIL_ImageDraw.Draw(pil_image)
|
|
draw_context.text((20, 10), "Hello World", fill="green")
|
|
|
|
# Construct a Toga image from PIL image
|
|
image_from_pil = toga.Image(pil_image)
|
|
|
|
assert image_from_pil.width == 110
|
|
assert image_from_pil.height == 30
|
|
|
|
# Construct a Toga image using the native image type
|
|
image_from_native = toga.Image(image_from_pil._impl.native)
|
|
|
|
assert image_from_native.width == 110
|
|
assert image_from_native.height == 30
|
|
|
|
# Construct an image from `image_from_native`'s data
|
|
image_from_data = toga.Image(image_from_native.data)
|
|
|
|
assert image_from_data.width == 110
|
|
assert image_from_data.height == 30
|
|
|
|
|
|
async def test_bad_image_data(app):
|
|
"If data isn't a valid image, an error is raised"
|
|
with pytest.raises(
|
|
ValueError,
|
|
match=r"Unable to load image from data",
|
|
):
|
|
toga.Image(b"Not an image")
|
|
|
|
|
|
async def test_save(app):
|
|
"""An image can be saved."""
|
|
orig_image = toga.Image("resources/sample.png")
|
|
probe = image_probe(app, orig_image)
|
|
assert orig_image.width == 144
|
|
assert orig_image.height == 72
|
|
|
|
try:
|
|
output_folder = app.paths.data / "images"
|
|
output_folder.mkdir(parents=True, exist_ok=True)
|
|
for i, extension in enumerate(
|
|
[
|
|
"", # No extension
|
|
".unknown", # Something that won't exist
|
|
".png",
|
|
".PNG", # Check upper case
|
|
".jpg",
|
|
".jpeg",
|
|
".gif",
|
|
".bmp",
|
|
".tiff",
|
|
]
|
|
):
|
|
filename = output_folder / f"image-{os.getpid()}-{i}{extension}"
|
|
|
|
if probe.supports_extension(extension):
|
|
orig_image.save(filename)
|
|
await probe.redraw(f"Saving {filename}")
|
|
|
|
assert filename.exists()
|
|
new_image = toga.Image(filename)
|
|
assert new_image.width == orig_image.width
|
|
assert new_image.height == orig_image.height
|
|
else:
|
|
with pytest.raises(
|
|
ValueError,
|
|
match=f"Don't know how to save image of type '{extension}'",
|
|
):
|
|
orig_image.save(filename)
|
|
|
|
await probe.redraw(f"Doesn't support files of type {extension!r}")
|
|
|
|
assert not filename.exists()
|
|
|
|
finally:
|
|
if output_folder.exists():
|
|
try:
|
|
shutil.rmtree(output_folder)
|
|
except PermissionError:
|
|
# On Winforms, Python.net has open file references to the
|
|
# `new_image` instances created to validate that the image was
|
|
# successfully saved. These will be garbage collected
|
|
# eventually, but there's non way to force the issue for test
|
|
# cleanup. The files will be cleaned up the next time the test
|
|
# suite is run; and the files have a PID in them to ensure that
|
|
# they're unique across test runs.
|
|
pass
|