Convert to use pytest

This commit is contained in:
Hugo 2020-02-18 15:50:34 +02:00
parent 17c67a2cfb
commit d289a5b072
4 changed files with 338 additions and 345 deletions

View File

@ -1,114 +1,115 @@
import pytest
from PIL import Image
from .helper import PillowTestCase, assert_image_equal, assert_image_similar, hopper
from .helper import assert_image_equal, assert_image_similar, hopper
_webp = pytest.importorskip("PIL._webp", reason="WebP support not installed")
class TestFileWebpAlpha(PillowTestCase):
def setUp(self):
if _webp.WebPDecoderBuggyAlpha(self):
self.skipTest(
"Buggy early version of WebP installed, not testing transparency"
)
def setup_module():
if _webp.WebPDecoderBuggyAlpha():
pytest.skip("Buggy early version of WebP installed, not testing transparency")
def test_read_rgba(self):
"""
Can we read an RGBA mode file without error?
Does it have the bits we expect?
"""
# Generated with `cwebp transparent.png -o transparent.webp`
file_path = "Tests/images/transparent.webp"
with Image.open(file_path) as image:
self.assertEqual(image.mode, "RGBA")
self.assertEqual(image.size, (200, 150))
self.assertEqual(image.format, "WEBP")
image.load()
image.getdata()
def test_read_rgba():
"""
Can we read an RGBA mode file without error?
Does it have the bits we expect?
"""
image.tobytes()
# Generated with `cwebp transparent.png -o transparent.webp`
file_path = "Tests/images/transparent.webp"
with Image.open(file_path) as image:
assert image.mode == "RGBA"
assert image.size == (200, 150)
assert image.format == "WEBP"
image.load()
image.getdata()
with Image.open("Tests/images/transparent.png") as target:
assert_image_similar(image, target, 20.0)
image.tobytes()
def test_write_lossless_rgb(self):
"""
Can we write an RGBA mode file with lossless compression without
error? Does it have the bits we expect?
"""
with Image.open("Tests/images/transparent.png") as target:
assert_image_similar(image, target, 20.0)
temp_file = self.tempfile("temp.webp")
# temp_file = "temp.webp"
pil_image = hopper("RGBA")
def test_write_lossless_rgb(tmp_path):
"""
Can we write an RGBA mode file with lossless compression without error?
Does it have the bits we expect?
"""
mask = Image.new("RGBA", (64, 64), (128, 128, 128, 128))
# Add some partially transparent bits:
pil_image.paste(mask, (0, 0), mask)
temp_file = str(tmp_path / "temp.webp")
# temp_file = "temp.webp"
pil_image.save(temp_file, lossless=True)
pil_image = hopper("RGBA")
with Image.open(temp_file) as image:
image.load()
mask = Image.new("RGBA", (64, 64), (128, 128, 128, 128))
# Add some partially transparent bits:
pil_image.paste(mask, (0, 0), mask)
self.assertEqual(image.mode, "RGBA")
self.assertEqual(image.size, pil_image.size)
self.assertEqual(image.format, "WEBP")
image.load()
image.getdata()
pil_image.save(temp_file, lossless=True)
assert_image_equal(image, pil_image)
with Image.open(temp_file) as image:
image.load()
def test_write_rgba(self):
"""
Can we write a RGBA mode file to webp without error.
Does it have the bits we expect?
"""
assert image.mode == "RGBA"
assert image.size == pil_image.size
assert image.format == "WEBP"
image.load()
image.getdata()
temp_file = self.tempfile("temp.webp")
assert_image_equal(image, pil_image)
pil_image = Image.new("RGBA", (10, 10), (255, 0, 0, 20))
pil_image.save(temp_file)
if _webp.WebPDecoderBuggyAlpha(self):
return
def test_write_rgba(tmp_path):
"""
Can we write a RGBA mode file to WebP without error.
Does it have the bits we expect?
"""
with Image.open(temp_file) as image:
image.load()
temp_file = str(tmp_path / "temp.webp")
self.assertEqual(image.mode, "RGBA")
self.assertEqual(image.size, (10, 10))
self.assertEqual(image.format, "WEBP")
image.load()
image.getdata()
pil_image = Image.new("RGBA", (10, 10), (255, 0, 0, 20))
pil_image.save(temp_file)
# early versions of webp are known to produce higher deviations:
# deal with it
if _webp.WebPDecoderVersion(self) <= 0x201:
assert_image_similar(image, pil_image, 3.0)
else:
assert_image_similar(image, pil_image, 1.0)
if _webp.WebPDecoderBuggyAlpha():
return
def test_write_unsupported_mode_PA(self):
"""
Saving a palette-based file with transparency to WebP format
should work, and be similar to the original file.
"""
with Image.open(temp_file) as image:
image.load()
temp_file = self.tempfile("temp.webp")
file_path = "Tests/images/transparent.gif"
assert image.mode == "RGBA"
assert image.size == (10, 10)
assert image.format == "WEBP"
image.load()
image.getdata()
# Early versions of WebP are known to produce higher deviations:
# deal with it
if _webp.WebPDecoderVersion() <= 0x201:
assert_image_similar(image, pil_image, 3.0)
else:
assert_image_similar(image, pil_image, 1.0)
def test_write_unsupported_mode_PA(tmp_path):
"""
Saving a palette-based file with transparency to WebP format
should work, and be similar to the original file.
"""
temp_file = str(tmp_path / "temp.webp")
file_path = "Tests/images/transparent.gif"
with Image.open(file_path) as im:
im.save(temp_file)
with Image.open(temp_file) as image:
assert image.mode == "RGBA"
assert image.size == (200, 150)
assert image.format == "WEBP"
image.load()
image.getdata()
with Image.open(file_path) as im:
im.save(temp_file)
with Image.open(temp_file) as image:
self.assertEqual(image.mode, "RGBA")
self.assertEqual(image.size, (200, 150))
self.assertEqual(image.format, "WEBP")
target = im.convert("RGBA")
image.load()
image.getdata()
with Image.open(file_path) as im:
target = im.convert("RGBA")
assert_image_similar(image, target, 25.0)
assert_image_similar(image, target, 25.0)

View File

@ -1,171 +1,164 @@
import pytest
from PIL import Image
from .helper import (
PillowTestCase,
assert_image_equal,
assert_image_similar,
is_big_endian,
on_ci,
)
from .helper import assert_image_equal, assert_image_similar, is_big_endian, on_ci
_webp = pytest.importorskip("PIL._webp", reason="WebP support not installed")
class TestFileWebpAnimation(PillowTestCase):
def setUp(self):
if not _webp.HAVE_WEBPANIM:
self.skipTest(
"WebP library does not contain animation support, "
"not testing animation"
def setup_module():
if not _webp.HAVE_WEBPANIM:
pytest.skip(
"WebP library does not contain animation support, not testing animation"
)
def test_n_frames():
"""Ensure that WebP format sets n_frames and is_animated attributes correctly."""
with Image.open("Tests/images/hopper.webp") as im:
assert im.n_frames == 1
assert not im.is_animated
with Image.open("Tests/images/iss634.webp") as im:
assert im.n_frames == 42
assert im.is_animated
@pytest.mark.xfail(is_big_endian() and on_ci(), reason="Fails on big-endian")
def test_write_animation_L(tmp_path):
"""
Convert an animated GIF to animated WebP, then compare the frame count, and first
and last frames to ensure they're visually similar.
"""
with Image.open("Tests/images/iss634.gif") as orig:
assert orig.n_frames > 1
temp_file = str(tmp_path / "temp.webp")
orig.save(temp_file, save_all=True)
with Image.open(temp_file) as im:
assert im.n_frames == orig.n_frames
# Compare first and last frames to the original animated GIF
orig.load()
im.load()
assert_image_similar(im, orig.convert("RGBA"), 25.0)
orig.seek(orig.n_frames - 1)
im.seek(im.n_frames - 1)
orig.load()
im.load()
assert_image_similar(im, orig.convert("RGBA"), 25.0)
@pytest.mark.xfail(is_big_endian() and on_ci(), reason="Fails on big-endian")
def test_write_animation_RGB(tmp_path):
"""
Write an animated WebP from RGB frames, and ensure the frames
are visually similar to the originals.
"""
def check(temp_file):
with Image.open(temp_file) as im:
assert im.n_frames == 2
# Compare first frame to original
im.load()
assert_image_equal(im, frame1.convert("RGBA"))
# Compare second frame to original
im.seek(1)
im.load()
assert_image_equal(im, frame2.convert("RGBA"))
with Image.open("Tests/images/anim_frame1.webp") as frame1:
with Image.open("Tests/images/anim_frame2.webp") as frame2:
temp_file1 = str(tmp_path / "temp.webp")
frame1.copy().save(
temp_file1, save_all=True, append_images=[frame2], lossless=True
)
check(temp_file1)
# Tests appending using a generator
def imGenerator(ims):
yield from ims
temp_file2 = str(tmp_path / "temp_generator.webp")
frame1.copy().save(
temp_file2,
save_all=True,
append_images=imGenerator([frame2]),
lossless=True,
)
check(temp_file2)
def test_timestamp_and_duration(tmp_path):
"""
Try passing a list of durations, and make sure the encoded
timestamps and durations are correct.
"""
durations = [0, 10, 20, 30, 40]
temp_file = str(tmp_path / "temp.webp")
with Image.open("Tests/images/anim_frame1.webp") as frame1:
with Image.open("Tests/images/anim_frame2.webp") as frame2:
frame1.save(
temp_file,
save_all=True,
append_images=[frame2, frame1, frame2, frame1],
duration=durations,
)
def test_n_frames(self):
"""
Ensure that WebP format sets n_frames and is_animated
attributes correctly.
"""
with Image.open(temp_file) as im:
assert im.n_frames == 5
assert im.is_animated
with Image.open("Tests/images/hopper.webp") as im:
self.assertEqual(im.n_frames, 1)
self.assertFalse(im.is_animated)
# Check that timestamps and durations match original values specified
ts = 0
for frame in range(im.n_frames):
im.seek(frame)
im.load()
assert im.info["duration"] == durations[frame]
assert im.info["timestamp"] == ts
ts += durations[frame]
with Image.open("Tests/images/iss634.webp") as im:
self.assertEqual(im.n_frames, 42)
self.assertTrue(im.is_animated)
@pytest.mark.xfail(is_big_endian() and on_ci(), reason="Fails on big-endian")
def test_write_animation_L(self):
"""
Convert an animated GIF to animated WebP, then compare the
frame count, and first and last frames to ensure they're
visually similar.
"""
def test_seeking(tmp_path):
"""
Create an animated WebP file, and then try seeking through frames in reverse-order,
verifying the timestamps and durations are correct.
"""
with Image.open("Tests/images/iss634.gif") as orig:
self.assertGreater(orig.n_frames, 1)
dur = 33
temp_file = str(tmp_path / "temp.webp")
with Image.open("Tests/images/anim_frame1.webp") as frame1:
with Image.open("Tests/images/anim_frame2.webp") as frame2:
frame1.save(
temp_file,
save_all=True,
append_images=[frame2, frame1, frame2, frame1],
duration=dur,
)
temp_file = self.tempfile("temp.webp")
orig.save(temp_file, save_all=True)
with Image.open(temp_file) as im:
self.assertEqual(im.n_frames, orig.n_frames)
with Image.open(temp_file) as im:
assert im.n_frames == 5
assert im.is_animated
# Compare first and last frames to the original animated GIF
orig.load()
im.load()
assert_image_similar(im, orig.convert("RGBA"), 25.0)
orig.seek(orig.n_frames - 1)
im.seek(im.n_frames - 1)
orig.load()
im.load()
assert_image_similar(im, orig.convert("RGBA"), 25.0)
# Traverse frames in reverse, checking timestamps and durations
ts = dur * (im.n_frames - 1)
for frame in reversed(range(im.n_frames)):
im.seek(frame)
im.load()
assert im.info["duration"] == dur
assert im.info["timestamp"] == ts
ts -= dur
@pytest.mark.xfail(is_big_endian() and on_ci(), reason="Fails on big-endian")
def test_write_animation_RGB(self):
"""
Write an animated WebP from RGB frames, and ensure the frames
are visually similar to the originals.
"""
def check(temp_file):
with Image.open(temp_file) as im:
self.assertEqual(im.n_frames, 2)
def test_seek_errors():
with Image.open("Tests/images/iss634.webp") as im:
with pytest.raises(EOFError):
im.seek(-1)
# Compare first frame to original
im.load()
assert_image_equal(im, frame1.convert("RGBA"))
# Compare second frame to original
im.seek(1)
im.load()
assert_image_equal(im, frame2.convert("RGBA"))
with Image.open("Tests/images/anim_frame1.webp") as frame1:
with Image.open("Tests/images/anim_frame2.webp") as frame2:
temp_file1 = self.tempfile("temp.webp")
frame1.copy().save(
temp_file1, save_all=True, append_images=[frame2], lossless=True
)
check(temp_file1)
# Tests appending using a generator
def imGenerator(ims):
yield from ims
temp_file2 = self.tempfile("temp_generator.webp")
frame1.copy().save(
temp_file2,
save_all=True,
append_images=imGenerator([frame2]),
lossless=True,
)
check(temp_file2)
def test_timestamp_and_duration(self):
"""
Try passing a list of durations, and make sure the encoded
timestamps and durations are correct.
"""
durations = [0, 10, 20, 30, 40]
temp_file = self.tempfile("temp.webp")
with Image.open("Tests/images/anim_frame1.webp") as frame1:
with Image.open("Tests/images/anim_frame2.webp") as frame2:
frame1.save(
temp_file,
save_all=True,
append_images=[frame2, frame1, frame2, frame1],
duration=durations,
)
with Image.open(temp_file) as im:
self.assertEqual(im.n_frames, 5)
self.assertTrue(im.is_animated)
# Check that timestamps and durations match original values specified
ts = 0
for frame in range(im.n_frames):
im.seek(frame)
im.load()
self.assertEqual(im.info["duration"], durations[frame])
self.assertEqual(im.info["timestamp"], ts)
ts += durations[frame]
def test_seeking(self):
"""
Create an animated WebP file, and then try seeking through
frames in reverse-order, verifying the timestamps and durations
are correct.
"""
dur = 33
temp_file = self.tempfile("temp.webp")
with Image.open("Tests/images/anim_frame1.webp") as frame1:
with Image.open("Tests/images/anim_frame2.webp") as frame2:
frame1.save(
temp_file,
save_all=True,
append_images=[frame2, frame1, frame2, frame1],
duration=dur,
)
with Image.open(temp_file) as im:
self.assertEqual(im.n_frames, 5)
self.assertTrue(im.is_animated)
# Traverse frames in reverse, checking timestamps and durations
ts = dur * (im.n_frames - 1)
for frame in reversed(range(im.n_frames)):
im.seek(frame)
im.load()
self.assertEqual(im.info["duration"], dur)
self.assertEqual(im.info["timestamp"], ts)
ts -= dur
def test_seek_errors(self):
with Image.open("Tests/images/iss634.webp") as im:
with self.assertRaises(EOFError):
im.seek(-1)
with self.assertRaises(EOFError):
im.seek(42)
with pytest.raises(EOFError):
im.seek(42)

View File

@ -1,30 +1,28 @@
import pytest
from PIL import Image
from .helper import PillowTestCase, assert_image_equal, hopper
from .helper import assert_image_equal, hopper
_webp = pytest.importorskip("PIL._webp", reason="WebP support not installed")
RGB_MODE = "RGB"
class TestFileWebpLossless(PillowTestCase):
def setUp(self):
if _webp.WebPDecoderVersion() < 0x0200:
self.skipTest("lossless not included")
self.rgb_mode = "RGB"
def test_write_lossless_rgb(tmp_path):
if _webp.WebPDecoderVersion() < 0x0200:
pytest.skip("lossless not included")
def test_write_lossless_rgb(self):
temp_file = self.tempfile("temp.webp")
temp_file = str(tmp_path / "temp.webp")
hopper(self.rgb_mode).save(temp_file, lossless=True)
hopper(RGB_MODE).save(temp_file, lossless=True)
with Image.open(temp_file) as image:
image.load()
with Image.open(temp_file) as image:
image.load()
self.assertEqual(image.mode, self.rgb_mode)
self.assertEqual(image.size, (128, 128))
self.assertEqual(image.format, "WEBP")
image.load()
image.getdata()
assert image.mode == RGB_MODE
assert image.size == (128, 128)
assert image.format == "WEBP"
image.load()
image.getdata()
assert_image_equal(image, hopper(self.rgb_mode))
assert_image_equal(image, hopper(RGB_MODE))

View File

@ -3,119 +3,120 @@ from io import BytesIO
import pytest
from PIL import Image
from .helper import PillowTestCase
_webp = pytest.importorskip("PIL._webp", reason="WebP support not installed")
class TestFileWebpMetadata(PillowTestCase):
def setUp(self):
if not _webp.HAVE_WEBPMUX:
self.skipTest("WebPMux support not installed")
def setup_module():
if not _webp.HAVE_WEBPMUX:
pytest.skip("WebPMux support not installed")
def test_read_exif_metadata(self):
file_path = "Tests/images/flower.webp"
with Image.open(file_path) as image:
def test_read_exif_metadata():
self.assertEqual(image.format, "WEBP")
exif_data = image.info.get("exif", None)
self.assertTrue(exif_data)
file_path = "Tests/images/flower.webp"
with Image.open(file_path) as image:
exif = image._getexif()
assert image.format == "WEBP"
exif_data = image.info.get("exif", None)
assert exif_data
# camera make
self.assertEqual(exif[271], "Canon")
exif = image._getexif()
with Image.open("Tests/images/flower.jpg") as jpeg_image:
expected_exif = jpeg_image.info["exif"]
# Camera make
assert exif[271] == "Canon"
self.assertEqual(exif_data, expected_exif)
with Image.open("Tests/images/flower.jpg") as jpeg_image:
expected_exif = jpeg_image.info["exif"]
def test_write_exif_metadata(self):
file_path = "Tests/images/flower.jpg"
test_buffer = BytesIO()
with Image.open(file_path) as image:
expected_exif = image.info["exif"]
assert exif_data == expected_exif
image.save(test_buffer, "webp", exif=expected_exif)
test_buffer.seek(0)
with Image.open(test_buffer) as webp_image:
webp_exif = webp_image.info.get("exif", None)
self.assertTrue(webp_exif)
if webp_exif:
self.assertEqual(webp_exif, expected_exif, "WebP EXIF didn't match")
def test_write_exif_metadata():
file_path = "Tests/images/flower.jpg"
test_buffer = BytesIO()
with Image.open(file_path) as image:
expected_exif = image.info["exif"]
def test_read_icc_profile(self):
image.save(test_buffer, "webp", exif=expected_exif)
file_path = "Tests/images/flower2.webp"
with Image.open(file_path) as image:
test_buffer.seek(0)
with Image.open(test_buffer) as webp_image:
webp_exif = webp_image.info.get("exif", None)
assert webp_exif
if webp_exif:
assert webp_exif == expected_exif, "WebP EXIF didn't match"
self.assertEqual(image.format, "WEBP")
self.assertTrue(image.info.get("icc_profile", None))
icc = image.info["icc_profile"]
def test_read_icc_profile():
with Image.open("Tests/images/flower2.jpg") as jpeg_image:
expected_icc = jpeg_image.info["icc_profile"]
file_path = "Tests/images/flower2.webp"
with Image.open(file_path) as image:
self.assertEqual(icc, expected_icc)
assert image.format == "WEBP"
assert image.info.get("icc_profile", None)
def test_write_icc_metadata(self):
file_path = "Tests/images/flower2.jpg"
test_buffer = BytesIO()
with Image.open(file_path) as image:
expected_icc_profile = image.info["icc_profile"]
icc = image.info["icc_profile"]
image.save(test_buffer, "webp", icc_profile=expected_icc_profile)
with Image.open("Tests/images/flower2.jpg") as jpeg_image:
expected_icc = jpeg_image.info["icc_profile"]
test_buffer.seek(0)
with Image.open(test_buffer) as webp_image:
webp_icc_profile = webp_image.info.get("icc_profile", None)
assert icc == expected_icc
self.assertTrue(webp_icc_profile)
if webp_icc_profile:
self.assertEqual(
webp_icc_profile, expected_icc_profile, "Webp ICC didn't match"
def test_write_icc_metadata():
file_path = "Tests/images/flower2.jpg"
test_buffer = BytesIO()
with Image.open(file_path) as image:
expected_icc_profile = image.info["icc_profile"]
image.save(test_buffer, "webp", icc_profile=expected_icc_profile)
test_buffer.seek(0)
with Image.open(test_buffer) as webp_image:
webp_icc_profile = webp_image.info.get("icc_profile", None)
assert webp_icc_profile
if webp_icc_profile:
assert webp_icc_profile == expected_icc_profile, "Webp ICC didn't match"
def test_read_no_exif():
file_path = "Tests/images/flower.jpg"
test_buffer = BytesIO()
with Image.open(file_path) as image:
assert "exif" in image.info
image.save(test_buffer, "webp")
test_buffer.seek(0)
with Image.open(test_buffer) as webp_image:
assert not webp_image._getexif()
def test_write_animated_metadata(tmp_path):
if not _webp.HAVE_WEBPANIM:
pytest.skip("WebP animation support not available")
iccp_data = b"<iccp_data>"
exif_data = b"<exif_data>"
xmp_data = b"<xmp_data>"
temp_file = str(tmp_path / "temp.webp")
with Image.open("Tests/images/anim_frame1.webp") as frame1:
with Image.open("Tests/images/anim_frame2.webp") as frame2:
frame1.save(
temp_file,
save_all=True,
append_images=[frame2, frame1, frame2],
icc_profile=iccp_data,
exif=exif_data,
xmp=xmp_data,
)
def test_read_no_exif(self):
file_path = "Tests/images/flower.jpg"
test_buffer = BytesIO()
with Image.open(file_path) as image:
self.assertIn("exif", image.info)
image.save(test_buffer, "webp")
test_buffer.seek(0)
with Image.open(test_buffer) as webp_image:
self.assertFalse(webp_image._getexif())
def test_write_animated_metadata(self):
if not _webp.HAVE_WEBPANIM:
self.skipTest("WebP animation support not available")
iccp_data = b"<iccp_data>"
exif_data = b"<exif_data>"
xmp_data = b"<xmp_data>"
temp_file = self.tempfile("temp.webp")
with Image.open("Tests/images/anim_frame1.webp") as frame1:
with Image.open("Tests/images/anim_frame2.webp") as frame2:
frame1.save(
temp_file,
save_all=True,
append_images=[frame2, frame1, frame2],
icc_profile=iccp_data,
exif=exif_data,
xmp=xmp_data,
)
with Image.open(temp_file) as image:
self.assertIn("icc_profile", image.info)
self.assertIn("exif", image.info)
self.assertIn("xmp", image.info)
self.assertEqual(iccp_data, image.info.get("icc_profile", None))
self.assertEqual(exif_data, image.info.get("exif", None))
self.assertEqual(xmp_data, image.info.get("xmp", None))
with Image.open(temp_file) as image:
assert "icc_profile" in image.info
assert "exif" in image.info
assert "xmp" in image.info
assert iccp_data == image.info.get("icc_profile", None)
assert exif_data == image.info.get("exif", None)
assert xmp_data == image.info.get("xmp", None)