Convert to use pytest

This commit is contained in:
Hugo 2020-02-22 23:03:01 +02:00
parent 699a9dadf1
commit 44e661f25a
10 changed files with 1310 additions and 1241 deletions

View File

@ -1,10 +1,9 @@
import unittest
from array import array
import pytest
from PIL import Image, ImageFilter
from .helper import PillowTestCase, assert_image_equal
from .helper import assert_image_equal
try:
import numpy
@ -12,7 +11,7 @@ except ImportError:
numpy = None
class TestColorLut3DCoreAPI(PillowTestCase):
class TestColorLut3DCoreAPI:
def generate_identity_table(self, channels, size):
if isinstance(size, tuple):
size1D, size2D, size3D = size
@ -271,7 +270,7 @@ class TestColorLut3DCoreAPI(PillowTestCase):
assert transformed[205, 205] == (255, 255, 0)
class TestColorLut3DFilter(PillowTestCase):
class TestColorLut3DFilter:
def test_wrong_args(self):
with pytest.raises(ValueError, match="should be either an integer"):
ImageFilter.Color3DLUT("small", [1])
@ -317,7 +316,7 @@ class TestColorLut3DFilter(PillowTestCase):
assert tuple(lut.size) == (2, 2, 2)
assert lut.table == list(range(4)) * 8
@unittest.skipIf(numpy is None, "Numpy is not installed")
@pytest.mark.skipif(numpy is None, reason="NumPy not installed")
def test_numpy_sources(self):
table = numpy.ones((5, 6, 7, 3), dtype=numpy.float16)
with pytest.raises(ValueError, match="should have either channels"):
@ -350,7 +349,7 @@ class TestColorLut3DFilter(PillowTestCase):
table[0] = 33
assert lut.table[0] == 33
@unittest.skipIf(numpy is None, "Numpy is not installed")
@pytest.mark.skipif(numpy is None, reason="NumPy not installed")
def test_numpy_formats(self):
g = Image.linear_gradient("L")
im = Image.merge(
@ -402,7 +401,7 @@ class TestColorLut3DFilter(PillowTestCase):
)
class TestGenerateColorLut3D(PillowTestCase):
class TestGenerateColorLut3D:
def test_wrong_channels_count(self):
with pytest.raises(ValueError, match="3 or 4 output channels"):
ImageFilter.Color3DLUT.generate(
@ -450,7 +449,7 @@ class TestGenerateColorLut3D(PillowTestCase):
assert im == im.filter(lut)
class TestTransformColorLut3D(PillowTestCase):
class TestTransformColorLut3D:
def test_wrong_args(self):
source = ImageFilter.Color3DLUT.generate(5, lambda r, g, b: (r, g, b))

View File

@ -1,65 +1,65 @@
import io
import unittest
import pytest
from PIL import EpsImagePlugin, Image, features
from .helper import PillowTestCase, assert_image_similar, hopper, skip_unless_feature
from .helper import assert_image_similar, hopper, skip_unless_feature
HAS_GHOSTSCRIPT = EpsImagePlugin.has_ghostscript()
# Our two EPS test files (they are identical except for their bounding boxes)
file1 = "Tests/images/zero_bb.eps"
file2 = "Tests/images/non_zero_bb.eps"
FILE1 = "Tests/images/zero_bb.eps"
FILE2 = "Tests/images/non_zero_bb.eps"
# Due to palletization, we'll need to convert these to RGB after load
file1_compare = "Tests/images/zero_bb.png"
file1_compare_scale2 = "Tests/images/zero_bb_scale2.png"
FILE1_COMPARE = "Tests/images/zero_bb.png"
FILE1_COMPARE_SCALE2 = "Tests/images/zero_bb_scale2.png"
file2_compare = "Tests/images/non_zero_bb.png"
file2_compare_scale2 = "Tests/images/non_zero_bb_scale2.png"
FILE2_COMPARE = "Tests/images/non_zero_bb.png"
FILE2_COMPARE_SCALE2 = "Tests/images/non_zero_bb_scale2.png"
# EPS test files with binary preview
file3 = "Tests/images/binary_preview_map.eps"
FILE3 = "Tests/images/binary_preview_map.eps"
class TestFileEps(PillowTestCase):
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
def test_sanity(self):
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
def test_sanity():
# Regular scale
with Image.open(file1) as image1:
with Image.open(FILE1) as image1:
image1.load()
assert image1.mode == "RGB"
assert image1.size == (460, 352)
assert image1.format == "EPS"
with Image.open(file2) as image2:
with Image.open(FILE2) as image2:
image2.load()
assert image2.mode == "RGB"
assert image2.size == (360, 252)
assert image2.format == "EPS"
# Double scale
with Image.open(file1) as image1_scale2:
with Image.open(FILE1) as image1_scale2:
image1_scale2.load(scale=2)
assert image1_scale2.mode == "RGB"
assert image1_scale2.size == (920, 704)
assert image1_scale2.format == "EPS"
with Image.open(file2) as image2_scale2:
with Image.open(FILE2) as image2_scale2:
image2_scale2.load(scale=2)
assert image2_scale2.mode == "RGB"
assert image2_scale2.size == (720, 504)
assert image2_scale2.format == "EPS"
def test_invalid_file(self):
def test_invalid_file():
invalid_file = "Tests/images/flower.jpg"
with pytest.raises(SyntaxError):
EpsImagePlugin.EpsImageFile(invalid_file)
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
def test_cmyk(self):
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
def test_cmyk():
with Image.open("Tests/images/pil_sample_cmyk.eps") as cmyk_image:
assert cmyk_image.mode == "CMYK"
@ -73,8 +73,9 @@ class TestFileEps(PillowTestCase):
with Image.open("Tests/images/pil_sample_rgb.jpg") as target:
assert_image_similar(cmyk_image, target, 10)
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
def test_showpage(self):
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
def test_showpage():
# See https://github.com/python-pillow/Pillow/issues/2615
with Image.open("Tests/images/reqd_showpage.eps") as plot_image:
with Image.open("Tests/images/reqd_showpage.png") as target:
@ -83,108 +84,124 @@ class TestFileEps(PillowTestCase):
# fonts could be slightly different
assert_image_similar(plot_image, target, 6)
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
def test_file_object(self):
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
def test_file_object(tmp_path):
# issue 479
with Image.open(file1) as image1:
with open(self.tempfile("temp_file.eps"), "wb") as fh:
with Image.open(FILE1) as image1:
with open(str(tmp_path / "temp.eps"), "wb") as fh:
image1.save(fh, "EPS")
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
def test_iobase_object(self):
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
def test_iobase_object(tmp_path):
# issue 479
with Image.open(file1) as image1:
with open(self.tempfile("temp_iobase.eps"), "wb") as fh:
with Image.open(FILE1) as image1:
with open(str(tmp_path / "temp_iobase.eps"), "wb") as fh:
image1.save(fh, "EPS")
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
def test_bytesio_object(self):
with open(file1, "rb") as f:
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
def test_bytesio_object():
with open(FILE1, "rb") as f:
img_bytes = io.BytesIO(f.read())
with Image.open(img_bytes) as img:
img.load()
with Image.open(file1_compare) as image1_scale1_compare:
with Image.open(FILE1_COMPARE) as image1_scale1_compare:
image1_scale1_compare = image1_scale1_compare.convert("RGB")
image1_scale1_compare.load()
assert_image_similar(img, image1_scale1_compare, 5)
def test_image_mode_not_supported(self):
def test_image_mode_not_supported(tmp_path):
im = hopper("RGBA")
tmpfile = self.tempfile("temp.eps")
tmpfile = str(tmp_path / "temp.eps")
with pytest.raises(ValueError):
im.save(tmpfile)
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
@skip_unless_feature("zlib")
def test_render_scale1(self):
def test_render_scale1():
# We need png support for these render test
# Zero bounding box
with Image.open(file1) as image1_scale1:
with Image.open(FILE1) as image1_scale1:
image1_scale1.load()
with Image.open(file1_compare) as image1_scale1_compare:
with Image.open(FILE1_COMPARE) as image1_scale1_compare:
image1_scale1_compare = image1_scale1_compare.convert("RGB")
image1_scale1_compare.load()
assert_image_similar(image1_scale1, image1_scale1_compare, 5)
# Non-Zero bounding box
with Image.open(file2) as image2_scale1:
with Image.open(FILE2) as image2_scale1:
image2_scale1.load()
with Image.open(file2_compare) as image2_scale1_compare:
with Image.open(FILE2_COMPARE) as image2_scale1_compare:
image2_scale1_compare = image2_scale1_compare.convert("RGB")
image2_scale1_compare.load()
assert_image_similar(image2_scale1, image2_scale1_compare, 10)
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
@skip_unless_feature("zlib")
def test_render_scale2(self):
def test_render_scale2():
# We need png support for these render test
# Zero bounding box
with Image.open(file1) as image1_scale2:
with Image.open(FILE1) as image1_scale2:
image1_scale2.load(scale=2)
with Image.open(file1_compare_scale2) as image1_scale2_compare:
with Image.open(FILE1_COMPARE_SCALE2) as image1_scale2_compare:
image1_scale2_compare = image1_scale2_compare.convert("RGB")
image1_scale2_compare.load()
assert_image_similar(image1_scale2, image1_scale2_compare, 5)
# Non-Zero bounding box
with Image.open(file2) as image2_scale2:
with Image.open(FILE2) as image2_scale2:
image2_scale2.load(scale=2)
with Image.open(file2_compare_scale2) as image2_scale2_compare:
with Image.open(FILE2_COMPARE_SCALE2) as image2_scale2_compare:
image2_scale2_compare = image2_scale2_compare.convert("RGB")
image2_scale2_compare.load()
assert_image_similar(image2_scale2, image2_scale2_compare, 10)
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
def test_resize(self):
files = [file1, file2, "Tests/images/illu10_preview.eps"]
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
def test_resize():
files = [FILE1, FILE2, "Tests/images/illu10_preview.eps"]
for fn in files:
with Image.open(fn) as im:
new_size = (100, 100)
im = im.resize(new_size)
assert im.size == new_size
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
def test_thumbnail(self):
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
def test_thumbnail():
# Issue #619
# Arrange
files = [file1, file2]
files = [FILE1, FILE2]
for fn in files:
with Image.open(file1) as im:
with Image.open(FILE1) as im:
new_size = (100, 100)
im.thumbnail(new_size)
assert max(im.size) == max(new_size)
def test_read_binary_preview(self):
def test_read_binary_preview():
# Issue 302
# open image with binary preview
with Image.open(file3):
with Image.open(FILE3):
pass
def _test_readline(self, t, ending):
def test_readline(tmp_path):
# check all the freaking line endings possible from the spec
# test_string = u'something\r\nelse\n\rbaz\rbif\n'
line_endings = ["\r\n", "\n", "\n\r", "\r"]
strings = ["something", "else", "baz", "bif"]
def _test_readline(t, ending):
ending = "Failure with line ending: %s" % (
"".join("%s" % ord(s) for s in ending)
)
@ -193,32 +210,27 @@ class TestFileEps(PillowTestCase):
assert t.readline().strip("\r\n") == "baz", ending
assert t.readline().strip("\r\n") == "bif", ending
def _test_readline_io_psfile(self, test_string, ending):
def _test_readline_io_psfile(test_string, ending):
f = io.BytesIO(test_string.encode("latin-1"))
t = EpsImagePlugin.PSFile(f)
self._test_readline(t, ending)
_test_readline(t, ending)
def _test_readline_file_psfile(self, test_string, ending):
f = self.tempfile("temp.txt")
def _test_readline_file_psfile(test_string, ending):
f = str(tmp_path / "temp.bufr")
with open(f, "wb") as w:
w.write(test_string.encode("latin-1"))
with open(f, "rb") as r:
t = EpsImagePlugin.PSFile(r)
self._test_readline(t, ending)
def test_readline(self):
# check all the freaking line endings possible from the spec
# test_string = u'something\r\nelse\n\rbaz\rbif\n'
line_endings = ["\r\n", "\n", "\n\r", "\r"]
strings = ["something", "else", "baz", "bif"]
_test_readline(t, ending)
for ending in line_endings:
s = ending.join(strings)
self._test_readline_io_psfile(s, ending)
self._test_readline_file_psfile(s, ending)
_test_readline_io_psfile(s, ending)
_test_readline_file_psfile(s, ending)
def test_open_eps(self):
def test_open_eps():
# https://github.com/python-pillow/Pillow/issues/1104
# Arrange
FILES = [
@ -233,8 +245,9 @@ class TestFileEps(PillowTestCase):
with Image.open(filename) as img:
assert img.mode == "RGB"
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
def test_emptyline(self):
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
def test_emptyline():
# Test file includes an empty line in the header data
emptyline_file = "Tests/images/zero_bb_emptyline.eps"

View File

@ -1,11 +1,9 @@
import unittest
from io import BytesIO
import pytest
from PIL import GifImagePlugin, Image, ImageDraw, ImagePalette, features
from .helper import (
PillowTestCase,
assert_image_equal,
assert_image_similar,
hopper,
@ -20,8 +18,7 @@ with open(TEST_GIF, "rb") as f:
data = f.read()
class TestFileGif(PillowTestCase):
def test_sanity(self):
def test_sanity():
with Image.open(TEST_GIF) as im:
im.load()
assert im.mode == "P"
@ -29,15 +26,17 @@ class TestFileGif(PillowTestCase):
assert im.format == "GIF"
assert im.info["version"] == b"GIF89a"
@unittest.skipIf(is_pypy(), "Requires CPython")
def test_unclosed_file(self):
@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
def test_unclosed_file():
def open():
im = Image.open(TEST_GIF)
im.load()
pytest.warns(ResourceWarning, open)
def test_closed_file(self):
def test_closed_file():
def open():
im = Image.open(TEST_GIF)
im.load()
@ -45,20 +44,23 @@ class TestFileGif(PillowTestCase):
pytest.warns(None, open)
def test_context_manager(self):
def test_context_manager():
def open():
with Image.open(TEST_GIF) as im:
im.load()
pytest.warns(None, open)
def test_invalid_file(self):
def test_invalid_file():
invalid_file = "Tests/images/flower.jpg"
with pytest.raises(SyntaxError):
GifImagePlugin.GifImageFile(invalid_file)
def test_optimize(self):
def test_optimize():
def test_grayscale(optimize):
im = Image.new("L", (1, 1), 0)
filename = BytesIO()
@ -76,7 +78,8 @@ class TestFileGif(PillowTestCase):
assert test_bilevel(0) == 800
assert test_bilevel(1) == 800
def test_optimize_correctness(self):
def test_optimize_correctness():
# 256 color Palette image, posterize to > 128 and < 128 levels
# Size bigger and smaller than 512x512
# Check the palette for number of colors allocated.
@ -92,9 +95,7 @@ class TestFileGif(PillowTestCase):
outfile.seek(0)
with Image.open(outfile) as reloaded:
# check palette length
palette_length = max(
i + 1 for i, v in enumerate(reloaded.histogram()) if v
)
palette_length = max(i + 1 for i, v in enumerate(reloaded.histogram()) if v)
assert expected_palette_length == palette_length
assert_image_equal(im.convert("RGB"), reloaded.convert("RGB"))
@ -109,28 +110,31 @@ class TestFileGif(PillowTestCase):
check(64, 513, 256)
check(4, 513, 256)
# other limits that don't optimize the palette
# Other limits that don't optimize the palette
check(129, 511, 256)
check(255, 511, 256)
check(256, 511, 256)
def test_optimize_full_l(self):
def test_optimize_full_l():
im = Image.frombytes("L", (16, 16), bytes(range(256)))
test_file = BytesIO()
im.save(test_file, "GIF", optimize=True)
assert im.mode == "L"
def test_roundtrip(self):
out = self.tempfile("temp.gif")
def test_roundtrip(tmp_path):
out = str(tmp_path / "temp.gif")
im = hopper()
im.save(out)
with Image.open(out) as reread:
assert_image_similar(reread.convert("RGB"), im, 50)
def test_roundtrip2(self):
def test_roundtrip2(tmp_path):
# see https://github.com/python-pillow/Pillow/issues/403
out = self.tempfile("temp.gif")
out = str(tmp_path / "temp.gif")
with Image.open(TEST_GIF) as im:
im2 = im.copy()
im2.save(out)
@ -138,9 +142,10 @@ class TestFileGif(PillowTestCase):
assert_image_similar(reread.convert("RGB"), hopper(), 50)
def test_roundtrip_save_all(self):
def test_roundtrip_save_all(tmp_path):
# Single frame image
out = self.tempfile("temp.gif")
out = str(tmp_path / "temp.gif")
im = hopper()
im.save(out, save_all=True)
with Image.open(out) as reread:
@ -149,28 +154,29 @@ class TestFileGif(PillowTestCase):
# Multiframe image
with Image.open("Tests/images/dispose_bgnd.gif") as im:
out = self.tempfile("temp.gif")
out = str(tmp_path / "temp.gif")
im.save(out, save_all=True)
with Image.open(out) as reread:
with Image.open(out) as reread:
assert reread.n_frames == 5
def test_headers_saving_for_animated_gifs(self):
def test_headers_saving_for_animated_gifs(tmp_path):
important_headers = ["background", "version", "duration", "loop"]
# Multiframe image
with Image.open("Tests/images/dispose_bgnd.gif") as im:
info = im.info.copy()
out = self.tempfile("temp.gif")
out = str(tmp_path / "temp.gif")
im.save(out, save_all=True)
with Image.open(out) as reread:
for header in important_headers:
assert info[header] == reread.info[header]
def test_palette_handling(self):
def test_palette_handling(tmp_path):
# see https://github.com/python-pillow/Pillow/issues/513
with Image.open(TEST_GIF) as im:
@ -179,18 +185,19 @@ class TestFileGif(PillowTestCase):
im = im.resize((100, 100), Image.LANCZOS)
im2 = im.convert("P", palette=Image.ADAPTIVE, colors=256)
f = self.tempfile("temp.gif")
f = str(tmp_path / "temp.gif")
im2.save(f, optimize=True)
with Image.open(f) as reloaded:
assert_image_similar(im, reloaded.convert("RGB"), 10)
def test_palette_434(self):
def test_palette_434(tmp_path):
# see https://github.com/python-pillow/Pillow/issues/434
def roundtrip(im, *args, **kwargs):
out = self.tempfile("temp.gif")
out = str(tmp_path / "temp.gif")
im.copy().save(out, *args, **kwargs)
reloaded = Image.open(out)
@ -210,37 +217,41 @@ class TestFileGif(PillowTestCase):
reloaded = reloaded.convert("RGB")
assert_image_equal(im, reloaded)
@unittest.skipUnless(netpbm_available(), "netpbm not available")
def test_save_netpbm_bmp_mode(self):
@pytest.mark.skipif(not netpbm_available(), reason="Netpbm not available")
def test_save_netpbm_bmp_mode(tmp_path):
with Image.open(TEST_GIF) as img:
img = img.convert("RGB")
tempfile = self.tempfile("temp.gif")
tempfile = str(tmp_path / "temp.gif")
GifImagePlugin._save_netpbm(img, 0, tempfile)
with Image.open(tempfile) as reloaded:
assert_image_similar(img, reloaded.convert("RGB"), 0)
@unittest.skipUnless(netpbm_available(), "netpbm not available")
def test_save_netpbm_l_mode(self):
@pytest.mark.skipif(not netpbm_available(), reason="Netpbm not available")
def test_save_netpbm_l_mode(tmp_path):
with Image.open(TEST_GIF) as img:
img = img.convert("L")
tempfile = self.tempfile("temp.gif")
tempfile = str(tmp_path / "temp.gif")
GifImagePlugin._save_netpbm(img, 0, tempfile)
with Image.open(tempfile) as reloaded:
assert_image_similar(img, reloaded.convert("L"), 0)
def test_seek(self):
def test_seek():
with Image.open("Tests/images/dispose_none.gif") as img:
framecount = 0
frame_count = 0
try:
while True:
framecount += 1
frame_count += 1
img.seek(img.tell() + 1)
except EOFError:
assert framecount == 5
assert frame_count == 5
def test_seek_info(self):
def test_seek_info():
with Image.open("Tests/images/iss634.gif") as im:
info = im.info.copy()
@ -249,7 +260,8 @@ class TestFileGif(PillowTestCase):
assert im.info == info
def test_seek_rewind(self):
def test_seek_rewind():
with Image.open("Tests/images/iss634.gif") as im:
im.seek(2)
im.seek(1)
@ -258,7 +270,8 @@ class TestFileGif(PillowTestCase):
expected.seek(1)
assert_image_equal(im, expected)
def test_n_frames(self):
def test_n_frames():
for path, n_frames in [[TEST_GIF, 1], ["Tests/images/iss634.gif", 42]]:
# Test is_animated before n_frames
with Image.open(path) as im:
@ -269,7 +282,8 @@ class TestFileGif(PillowTestCase):
assert im.n_frames == n_frames
assert im.is_animated == (n_frames != 1)
def test_eoferror(self):
def test_eoferror():
with Image.open(TEST_GIF) as im:
n_frames = im.n_frames
@ -281,7 +295,8 @@ class TestFileGif(PillowTestCase):
# Test that seeking to the last frame does not raise an error
im.seek(n_frames - 1)
def test_dispose_none(self):
def test_dispose_none():
with Image.open("Tests/images/dispose_none.gif") as img:
try:
while True:
@ -290,7 +305,8 @@ class TestFileGif(PillowTestCase):
except EOFError:
pass
def test_dispose_background(self):
def test_dispose_background():
with Image.open("Tests/images/dispose_bgnd.gif") as img:
try:
while True:
@ -299,7 +315,8 @@ class TestFileGif(PillowTestCase):
except EOFError:
pass
def test_dispose_previous(self):
def test_dispose_previous():
with Image.open("Tests/images/dispose_prev.gif") as img:
try:
while True:
@ -308,23 +325,22 @@ class TestFileGif(PillowTestCase):
except EOFError:
pass
def test_save_dispose(self):
out = self.tempfile("temp.gif")
def test_save_dispose(tmp_path):
out = str(tmp_path / "temp.gif")
im_list = [
Image.new("L", (100, 100), "#000"),
Image.new("L", (100, 100), "#111"),
Image.new("L", (100, 100), "#222"),
]
for method in range(0, 4):
im_list[0].save(
out, save_all=True, append_images=im_list[1:], disposal=method
)
im_list[0].save(out, save_all=True, append_images=im_list[1:], disposal=method)
with Image.open(out) as img:
for _ in range(2):
img.seek(img.tell() + 1)
assert img.disposal_method == method
# check per frame disposal
# Check per frame disposal
im_list[0].save(
out,
save_all=True,
@ -338,8 +354,9 @@ class TestFileGif(PillowTestCase):
img.seek(img.tell() + 1)
assert img.disposal_method == i + 1
def test_dispose2_palette(self):
out = self.tempfile("temp.gif")
def test_dispose2_palette(tmp_path):
out = str(tmp_path / "temp.gif")
# 4 backgrounds: White, Grey, Black, Red
circles = [(255, 255, 255), (153, 153, 153), (0, 0, 0), (255, 0, 0)]
@ -367,8 +384,9 @@ class TestFileGif(PillowTestCase):
# Center remains red every frame
assert rgb_img.getpixel((50, 50)) == circle
def test_dispose2_diff(self):
out = self.tempfile("temp.gif")
def test_dispose2_diff(tmp_path):
out = str(tmp_path / "temp.gif")
# 4 frames: red/blue, red/red, blue/blue, red/blue
circles = [
@ -408,8 +426,9 @@ class TestFileGif(PillowTestCase):
# Check BG is correct colour
assert rgb_img.getpixel((1, 1)) == (255, 255, 255, 0)
def test_dispose2_background(self):
out = self.tempfile("temp.gif")
def test_dispose2_background(tmp_path):
out = str(tmp_path / "temp.gif")
im_list = []
@ -433,18 +452,19 @@ class TestFileGif(PillowTestCase):
im.seek(1)
assert im.getpixel((0, 0)) == 0
def test_iss634(self):
def test_iss634():
with Image.open("Tests/images/iss634.gif") as img:
# seek to the second frame
# Seek to the second frame
img.seek(img.tell() + 1)
# all transparent pixels should be replaced with the color from the
# first frame
# All transparent pixels should be replaced with the color from the first frame
assert img.histogram()[img.info["transparency"]] == 0
def test_duration(self):
def test_duration(tmp_path):
duration = 1000
out = self.tempfile("temp.gif")
out = str(tmp_path / "temp.gif")
im = Image.new("L", (100, 100), "#000")
# Check that the argument has priority over the info settings
@ -454,17 +474,18 @@ class TestFileGif(PillowTestCase):
with Image.open(out) as reread:
assert reread.info["duration"] == duration
def test_multiple_duration(self):
def test_multiple_duration(tmp_path):
duration_list = [1000, 2000, 3000]
out = self.tempfile("temp.gif")
out = str(tmp_path / "temp.gif")
im_list = [
Image.new("L", (100, 100), "#000"),
Image.new("L", (100, 100), "#111"),
Image.new("L", (100, 100), "#222"),
]
# duration as list
# Duration as list
im_list[0].save(
out, save_all=True, append_images=im_list[1:], duration=duration_list
)
@ -477,7 +498,7 @@ class TestFileGif(PillowTestCase):
except EOFError:
pass
# duration as tuple
# Duration as tuple
im_list[0].save(
out, save_all=True, append_images=im_list[1:], duration=tuple(duration_list)
)
@ -490,10 +511,11 @@ class TestFileGif(PillowTestCase):
except EOFError:
pass
def test_identical_frames(self):
def test_identical_frames(tmp_path):
duration_list = [1000, 1500, 2000, 4000]
out = self.tempfile("temp.gif")
out = str(tmp_path / "temp.gif")
im_list = [
Image.new("L", (100, 100), "#000"),
Image.new("L", (100, 100), "#000"),
@ -501,7 +523,7 @@ class TestFileGif(PillowTestCase):
Image.new("L", (100, 100), "#111"),
]
# duration as list
# Duration as list
im_list[0].save(
out, save_all=True, append_images=im_list[1:], duration=duration_list
)
@ -513,9 +535,10 @@ class TestFileGif(PillowTestCase):
# Assert that the new duration is the total of the identical frames
assert reread.info["duration"] == 4500
def test_identical_frames_to_single_frame(self):
def test_identical_frames_to_single_frame(tmp_path):
for duration in ([1000, 1500, 2000, 4000], (1000, 1500, 2000, 4000), 8500):
out = self.tempfile("temp.gif")
out = str(tmp_path / "temp.gif")
im_list = [
Image.new("L", (100, 100), "#000"),
Image.new("L", (100, 100), "#000"),
@ -532,18 +555,20 @@ class TestFileGif(PillowTestCase):
# Assert that the new duration is the total of the identical frames
assert reread.info["duration"] == 8500
def test_number_of_loops(self):
def test_number_of_loops(tmp_path):
number_of_loops = 2
out = self.tempfile("temp.gif")
out = str(tmp_path / "temp.gif")
im = Image.new("L", (100, 100), "#000")
im.save(out, loop=number_of_loops)
with Image.open(out) as reread:
assert reread.info["loop"] == number_of_loops
def test_background(self):
out = self.tempfile("temp.gif")
def test_background(tmp_path):
out = str(tmp_path / "temp.gif")
im = Image.new("L", (100, 100), "#000")
im.info["background"] = 1
im.save(out)
@ -556,11 +581,12 @@ class TestFileGif(PillowTestCase):
assert isinstance(im.info["background"], tuple)
im.save(out)
def test_comment(self):
def test_comment(tmp_path):
with Image.open(TEST_GIF) as im:
assert im.info["comment"] == b"File written by Adobe Photoshop\xa8 4.0"
out = self.tempfile("temp.gif")
out = str(tmp_path / "temp.gif")
im = Image.new("L", (100, 100), "#000")
im.info["comment"] = b"Test comment text"
im.save(out)
@ -572,8 +598,9 @@ class TestFileGif(PillowTestCase):
with Image.open(out) as reread:
assert reread.info["comment"] == im.info["comment"].encode()
def test_comment_over_255(self):
out = self.tempfile("temp.gif")
def test_comment_over_255(tmp_path):
out = str(tmp_path / "temp.gif")
im = Image.new("L", (100, 100), "#000")
comment = b"Test comment text"
while len(comment) < 256:
@ -584,13 +611,15 @@ class TestFileGif(PillowTestCase):
assert reread.info["comment"] == comment
def test_zero_comment_subblocks(self):
def test_zero_comment_subblocks():
with Image.open("Tests/images/hopper_zero_comment_subblocks.gif") as im:
with Image.open(TEST_GIF) as expected:
assert_image_equal(im, expected)
def test_version(self):
out = self.tempfile("temp.gif")
def test_version(tmp_path):
out = str(tmp_path / "temp.gif")
def assertVersionAfterSave(im, version):
im.save(out)
@ -618,8 +647,9 @@ class TestFileGif(PillowTestCase):
im.info["version"] = b"GIF89a"
assertVersionAfterSave(im, b"GIF87a")
def test_append_images(self):
out = self.tempfile("temp.gif")
def test_append_images(tmp_path):
out = str(tmp_path / "temp.gif")
# Test appending single frame images
im = Image.new("RGB", (100, 100), "#f00")
@ -646,12 +676,12 @@ class TestFileGif(PillowTestCase):
with Image.open(out) as reread:
assert reread.n_frames == 10
def test_transparent_optimize(self):
# from issue #2195, if the transparent color is incorrectly
# optimized out, gif loses transparency
# Need a palette that isn't using the 0 color, and one
# that's > 128 items where the transparent color is actually
# the top palette entry to trigger the bug.
def test_transparent_optimize(tmp_path):
# From issue #2195, if the transparent color is incorrectly optimized out, GIF loses
# transparency.
# Need a palette that isn't using the 0 color, and one that's > 128 items where the
# transparent color is actually the top palette entry to trigger the bug.
data = bytes(range(1, 254))
palette = ImagePalette.ImagePalette("RGB", list(range(256)) * 3)
@ -660,14 +690,15 @@ class TestFileGif(PillowTestCase):
im.frombytes(data)
im.putpalette(palette)
out = self.tempfile("temp.gif")
out = str(tmp_path / "temp.gif")
im.save(out, transparency=253)
with Image.open(out) as reloaded:
assert reloaded.info["transparency"] == 253
def test_rgb_transparency(self):
out = self.tempfile("temp.gif")
def test_rgb_transparency(tmp_path):
out = str(tmp_path / "temp.gif")
# Single frame
im = Image.new("RGB", (1, 1))
@ -686,8 +717,9 @@ class TestFileGif(PillowTestCase):
with Image.open(out) as reloaded:
assert "transparency" not in reloaded.info
def test_bbox(self):
out = self.tempfile("temp.gif")
def test_bbox(tmp_path):
out = str(tmp_path / "temp.gif")
im = Image.new("RGB", (100, 100), "#fff")
ims = [Image.new("RGB", (100, 100), "#000")]
@ -696,63 +728,66 @@ class TestFileGif(PillowTestCase):
with Image.open(out) as reread:
assert reread.n_frames == 2
def test_palette_save_L(self):
# generate an L mode image with a separate palette
def test_palette_save_L(tmp_path):
# Generate an L mode image with a separate palette
im = hopper("P")
im_l = Image.frombytes("L", im.size, im.tobytes())
palette = bytes(im.getpalette())
out = self.tempfile("temp.gif")
out = str(tmp_path / "temp.gif")
im_l.save(out, palette=palette)
with Image.open(out) as reloaded:
assert_image_equal(reloaded.convert("RGB"), im.convert("RGB"))
def test_palette_save_P(self):
# pass in a different palette, then construct what the image
# would look like.
def test_palette_save_P(tmp_path):
# Pass in a different palette, then construct what the image would look like.
# Forcing a non-straight grayscale palette.
im = hopper("P")
palette = bytes([255 - i // 3 for i in range(768)])
out = self.tempfile("temp.gif")
out = str(tmp_path / "temp.gif")
im.save(out, palette=palette)
with Image.open(out) as reloaded:
im.putpalette(palette)
assert_image_equal(reloaded, im)
def test_palette_save_ImagePalette(self):
# pass in a different palette, as an ImagePalette.ImagePalette
def test_palette_save_ImagePalette(tmp_path):
# Pass in a different palette, as an ImagePalette.ImagePalette
# effectively the same as test_palette_save_P
im = hopper("P")
palette = ImagePalette.ImagePalette("RGB", list(range(256))[::-1] * 3)
out = self.tempfile("temp.gif")
out = str(tmp_path / "temp.gif")
im.save(out, palette=palette)
with Image.open(out) as reloaded:
im.putpalette(palette)
assert_image_equal(reloaded, im)
def test_save_I(self):
def test_save_I(tmp_path):
# Test saving something that would trigger the auto-convert to 'L'
im = hopper("I")
out = self.tempfile("temp.gif")
out = str(tmp_path / "temp.gif")
im.save(out)
with Image.open(out) as reloaded:
assert_image_equal(reloaded.convert("L"), im.convert("L"))
def test_getdata(self):
# test getheader/getdata against legacy values
# Create a 'P' image with holes in the palette
def test_getdata():
# Test getheader/getdata against legacy values.
# Create a 'P' image with holes in the palette.
im = Image._wedge().resize((16, 16), Image.NEAREST)
im.putpalette(ImagePalette.ImagePalette("RGB"))
im.info = {"background": 0}
@ -777,14 +812,16 @@ class TestFileGif(PillowTestCase):
finally:
GifImagePlugin._FORCE_OPTIMIZE = False
def test_lzw_bits(self):
def test_lzw_bits():
# see https://github.com/python-pillow/Pillow/issues/2811
with Image.open("Tests/images/issue_2811.gif") as im:
assert im.tile[0][3][0] == 11 # LZW bits
# codec error prepatch
im.load()
def test_extents(self):
def test_extents():
with Image.open("Tests/images/test_extents.gif") as im:
assert im.size == (100, 100)
im.seek(1)

View File

@ -1,20 +1,18 @@
import io
import sys
import unittest
import pytest
from PIL import IcnsImagePlugin, Image
from .helper import PillowTestCase, assert_image_equal, assert_image_similar
from .helper import assert_image_equal, assert_image_similar
# sample icon file
TEST_FILE = "Tests/images/pillow.icns"
enable_jpeg2k = hasattr(Image.core, "jp2klib_version")
ENABLE_JPEG2K = hasattr(Image.core, "jp2klib_version")
class TestFileIcns(PillowTestCase):
def test_sanity(self):
def test_sanity():
# Loading this icon by default should result in the largest size
# (512x512@2x) being loaded
with Image.open(TEST_FILE) as im:
@ -26,9 +24,10 @@ class TestFileIcns(PillowTestCase):
assert im.size == (1024, 1024)
assert im.format == "ICNS"
@unittest.skipIf(sys.platform != "darwin", "requires macOS")
def test_save(self):
temp_file = self.tempfile("temp.icns")
@pytest.mark.skipif(sys.platform != "darwin", reason="Requires macOS")
def test_save(tmp_path):
temp_file = str(tmp_path / "temp.icns")
with Image.open(TEST_FILE) as im:
im.save(temp_file)
@ -38,9 +37,10 @@ class TestFileIcns(PillowTestCase):
assert reread.size == (1024, 1024)
assert reread.format == "ICNS"
@unittest.skipIf(sys.platform != "darwin", "requires macOS")
def test_save_append_images(self):
temp_file = self.tempfile("temp.icns")
@pytest.mark.skipif(sys.platform != "darwin", reason="Requires macOS")
def test_save_append_images(tmp_path):
temp_file = str(tmp_path / "temp.icns")
provided_im = Image.new("RGBA", (32, 32), (255, 0, 0, 128))
with Image.open(TEST_FILE) as im:
@ -54,7 +54,8 @@ class TestFileIcns(PillowTestCase):
reread.load()
assert_image_equal(reread, provided_im)
def test_sizes(self):
def test_sizes():
# Check that we can load all of the sizes, and that the final pixel
# dimensions are as expected
with Image.open(TEST_FILE) as im:
@ -70,7 +71,8 @@ class TestFileIcns(PillowTestCase):
with pytest.raises(ValueError):
im.size = (1, 1)
def test_older_icon(self):
def test_older_icon():
# This icon was made with Icon Composer rather than iconutil; it still
# uses PNG rather than JP2, however (since it was made on 10.9).
with Image.open("Tests/images/pillow2.icns") as im:
@ -83,7 +85,8 @@ class TestFileIcns(PillowTestCase):
assert im2.mode == "RGBA"
assert im2.size == (wr, hr)
def test_jp2_icon(self):
def test_jp2_icon():
# This icon was made by using Uli Kusterer's oldiconutil to replace
# the PNG images with JPEG 2000 ones. The advantage of doing this is
# that OS X 10.5 supports JPEG 2000 but not PNG; some commercial
@ -91,7 +94,7 @@ class TestFileIcns(PillowTestCase):
# (oldiconutil is here: https://github.com/uliwitness/oldiconutil)
if not enable_jpeg2k:
if not ENABLE_JPEG2K:
return
with Image.open("Tests/images/pillow3.icns") as im:
@ -104,7 +107,8 @@ class TestFileIcns(PillowTestCase):
assert im2.mode == "RGBA"
assert im2.size == (wr, hr)
def test_getimage(self):
def test_getimage():
with open(TEST_FILE, "rb") as fp:
icns_file = IcnsImagePlugin.IcnsFile(fp)
@ -116,7 +120,8 @@ class TestFileIcns(PillowTestCase):
assert im.mode == "RGBA"
assert im.size == (512, 512)
def test_not_an_icns_file(self):
def test_not_an_icns_file():
with io.BytesIO(b"invalid\n") as fp:
with pytest.raises(SyntaxError):
IcnsImagePlugin.IcnsFile(fp)

View File

@ -3,13 +3,12 @@ import io
import pytest
from PIL import IcoImagePlugin, Image, ImageDraw
from .helper import PillowTestCase, assert_image_equal, hopper
from .helper import assert_image_equal, hopper
TEST_ICO_FILE = "Tests/images/hopper.ico"
class TestFileIco(PillowTestCase):
def test_sanity(self):
def test_sanity():
with Image.open(TEST_ICO_FILE) as im:
im.load()
assert im.mode == "RGBA"
@ -17,17 +16,19 @@ class TestFileIco(PillowTestCase):
assert im.format == "ICO"
assert im.get_format_mimetype() == "image/x-icon"
def test_invalid_file(self):
def test_invalid_file():
with open("Tests/images/flower.jpg", "rb") as fp:
with pytest.raises(SyntaxError):
IcoImagePlugin.IcoImageFile(fp)
def test_save_to_bytes(self):
def test_save_to_bytes():
output = io.BytesIO()
im = hopper()
im.save(output, "ico", sizes=[(32, 32), (64, 64)])
# the default image
# The default image
output.seek(0)
with Image.open(output) as reloaded:
assert reloaded.info["sizes"] == {(32, 32), (64, 64)}
@ -37,7 +38,7 @@ class TestFileIco(PillowTestCase):
assert reloaded.format == "ICO"
assert_image_equal(reloaded, hopper().resize((64, 64), Image.LANCZOS))
# the other one
# The other one
output.seek(0)
with Image.open(output) as reloaded:
reloaded.size = (32, 32)
@ -47,16 +48,18 @@ class TestFileIco(PillowTestCase):
assert reloaded.format == "ICO"
assert_image_equal(reloaded, hopper().resize((32, 32), Image.LANCZOS))
def test_incorrect_size(self):
def test_incorrect_size():
with Image.open(TEST_ICO_FILE) as im:
with pytest.raises(ValueError):
im.size = (1, 1)
def test_save_256x256(self):
def test_save_256x256(tmp_path):
"""Issue #2264 https://github.com/python-pillow/Pillow/issues/2264"""
# Arrange
with Image.open("Tests/images/hopper_256x256.ico") as im:
outfile = self.tempfile("temp_saved_hopper_256x256.ico")
outfile = str(tmp_path / "temp_saved_hopper_256x256.ico")
# Act
im.save(outfile)
@ -65,14 +68,15 @@ class TestFileIco(PillowTestCase):
# Assert
assert im_saved.size == (256, 256)
def test_only_save_relevant_sizes(self):
def test_only_save_relevant_sizes(tmp_path):
"""Issue #2266 https://github.com/python-pillow/Pillow/issues/2266
Should save in 16x16, 24x24, 32x32, 48x48 sizes
and not in 16x16, 24x24, 32x32, 48x48, 48x48, 48x48, 48x48 sizes
"""
# Arrange
with Image.open("Tests/images/python.ico") as im: # 16x16, 32x32, 48x48
outfile = self.tempfile("temp_saved_python.ico")
outfile = str(tmp_path / "temp_saved_python.ico")
# Act
im.save(outfile)
@ -80,7 +84,8 @@ class TestFileIco(PillowTestCase):
# Assert
assert im_saved.info["sizes"] == {(16, 16), (24, 24), (32, 32), (48, 48)}
def test_unexpected_size(self):
def test_unexpected_size():
# This image has been manually hexedited to state that it is 16x32
# while the image within is still 16x16
def open():
@ -89,9 +94,10 @@ class TestFileIco(PillowTestCase):
pytest.warns(UserWarning, open)
def test_draw_reloaded(self):
def test_draw_reloaded(tmp_path):
with Image.open(TEST_ICO_FILE) as im:
outfile = self.tempfile("temp_saved_hopper_draw.ico")
outfile = str(tmp_path / "temp_saved_hopper_draw.ico")
draw = ImageDraw.Draw(im)
draw.line((0, 0) + im.size, "#f00")

View File

@ -1,19 +1,17 @@
import os
import unittest
import pytest
from PIL import Image, MspImagePlugin
from .helper import PillowTestCase, assert_image_equal, hopper
from .helper import assert_image_equal, hopper
TEST_FILE = "Tests/images/hopper.msp"
EXTRA_DIR = "Tests/images/picins"
YA_EXTRA_DIR = "Tests/images/msp"
class TestFileMsp(PillowTestCase):
def test_sanity(self):
test_file = self.tempfile("temp.msp")
def test_sanity(tmp_path):
test_file = str(tmp_path / "temp.msp")
hopper("1").save(test_file)
@ -23,13 +21,15 @@ class TestFileMsp(PillowTestCase):
assert im.size == (128, 128)
assert im.format == "MSP"
def test_invalid_file(self):
def test_invalid_file():
invalid_file = "Tests/images/flower.jpg"
with pytest.raises(SyntaxError):
MspImagePlugin.MspImageFile(invalid_file)
def test_bad_checksum(self):
def test_bad_checksum():
# Arrange
# This was created by forcing Pillow to save with checksum=0
bad_checksum = "Tests/images/hopper_bad_checksum.msp"
@ -38,7 +38,8 @@ class TestFileMsp(PillowTestCase):
with pytest.raises(SyntaxError):
MspImagePlugin.MspImageFile(bad_checksum)
def test_open_windows_v1(self):
def test_open_windows_v1():
# Arrange
# Act
with Image.open(TEST_FILE) as im:
@ -47,13 +48,17 @@ class TestFileMsp(PillowTestCase):
assert_image_equal(im, hopper("1"))
assert isinstance(im, MspImagePlugin.MspImageFile)
def _assert_file_image_equal(self, source_path, target_path):
def _assert_file_image_equal(source_path, target_path):
with Image.open(source_path) as im:
with Image.open(target_path) as target:
assert_image_equal(im, target)
@unittest.skipUnless(os.path.exists(EXTRA_DIR), "Extra image files not installed")
def test_open_windows_v2(self):
@pytest.mark.skipif(
not os.path.exists(EXTRA_DIR), reason="Extra image files not installed"
)
def test_open_windows_v2():
files = (
os.path.join(EXTRA_DIR, f)
@ -61,22 +66,24 @@ class TestFileMsp(PillowTestCase):
if os.path.splitext(f)[1] == ".msp"
)
for path in files:
self._assert_file_image_equal(path, path.replace(".msp", ".png"))
_assert_file_image_equal(path, path.replace(".msp", ".png"))
@unittest.skipIf(
not os.path.exists(YA_EXTRA_DIR), "Even More Extra image files not installed"
@pytest.mark.skipif(
not os.path.exists(YA_EXTRA_DIR), reason="Even More Extra image files not installed"
)
def test_msp_v2(self):
def test_msp_v2():
for f in os.listdir(YA_EXTRA_DIR):
if ".MSP" not in f:
continue
path = os.path.join(YA_EXTRA_DIR, f)
self._assert_file_image_equal(path, path.replace(".MSP", ".png"))
_assert_file_image_equal(path, path.replace(".MSP", ".png"))
def test_cannot_save_wrong_mode(self):
def test_cannot_save_wrong_mode(tmp_path):
# Arrange
im = hopper()
filename = self.tempfile("temp.msp")
filename = str(tmp_path / "temp.msp")
# Act/Assert
with pytest.raises(IOError):

View File

@ -1,32 +1,32 @@
import tempfile
import unittest
from io import BytesIO
import pytest
from PIL import Image, ImageSequence, SpiderImagePlugin
from .helper import PillowTestCase, assert_image_equal, hopper, is_pypy
from .helper import assert_image_equal, hopper, is_pypy
TEST_FILE = "Tests/images/hopper.spider"
class TestImageSpider(PillowTestCase):
def test_sanity(self):
def test_sanity():
with Image.open(TEST_FILE) as im:
im.load()
assert im.mode == "F"
assert im.size == (128, 128)
assert im.format == "SPIDER"
@unittest.skipIf(is_pypy(), "Requires CPython")
def test_unclosed_file(self):
@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
def test_unclosed_file():
def open():
im = Image.open(TEST_FILE)
im.load()
pytest.warns(ResourceWarning, open)
def test_closed_file(self):
def test_closed_file():
def open():
im = Image.open(TEST_FILE)
im.load()
@ -34,16 +34,18 @@ class TestImageSpider(PillowTestCase):
pytest.warns(None, open)
def test_context_manager(self):
def test_context_manager():
def open():
with Image.open(TEST_FILE) as im:
im.load()
pytest.warns(None, open)
def test_save(self):
def test_save(tmp_path):
# Arrange
temp = self.tempfile("temp.spider")
temp = str(tmp_path / "temp.spider")
im = hopper()
# Act
@ -55,7 +57,8 @@ class TestImageSpider(PillowTestCase):
assert im2.size == (128, 128)
assert im2.format == "SPIDER"
def test_tempfile(self):
def test_tempfile():
# Arrange
im = hopper()
@ -70,10 +73,12 @@ class TestImageSpider(PillowTestCase):
assert reloaded.size == (128, 128)
assert reloaded.format == "SPIDER"
def test_isSpiderImage(self):
def test_is_spider_image():
assert SpiderImagePlugin.isSpiderImage(TEST_FILE)
def test_tell(self):
def test_tell():
# Arrange
with Image.open(TEST_FILE) as im:
@ -83,12 +88,14 @@ class TestImageSpider(PillowTestCase):
# Assert
assert index == 0
def test_n_frames(self):
def test_n_frames():
with Image.open(TEST_FILE) as im:
assert im.n_frames == 1
assert not im.is_animated
def test_loadImageSeries(self):
def test_load_image_series():
# Arrange
not_spider_file = "Tests/images/hopper.ppm"
file_list = [TEST_FILE, not_spider_file, "path/not_found.ext"]
@ -101,7 +108,8 @@ class TestImageSpider(PillowTestCase):
assert isinstance(img_list[0], Image.Image)
assert img_list[0].size == (128, 128)
def test_loadImageSeries_no_input(self):
def test_load_image_series_no_input():
# Arrange
file_list = None
@ -111,7 +119,8 @@ class TestImageSpider(PillowTestCase):
# Assert
assert img_list is None
def test_isInt_not_a_number(self):
def test_is_int_not_a_number():
# Arrange
not_a_number = "a"
@ -121,24 +130,28 @@ class TestImageSpider(PillowTestCase):
# Assert
assert ret == 0
def test_invalid_file(self):
def test_invalid_file():
invalid_file = "Tests/images/invalid.spider"
with pytest.raises(IOError):
Image.open(invalid_file)
def test_nonstack_file(self):
def test_nonstack_file():
with Image.open(TEST_FILE) as im:
with pytest.raises(EOFError):
im.seek(0)
def test_nonstack_dos(self):
def test_nonstack_dos():
with Image.open(TEST_FILE) as im:
for i, frame in enumerate(ImageSequence.Iterator(im)):
assert i <= 1, "Non-stack DOS file test failed"
# for issue #4093
def test_odd_size(self):
def test_odd_size():
data = BytesIO()
width = 100
im = Image.new("F", (width, 64))

View File

@ -2,13 +2,11 @@ import io
import os
import shutil
import tempfile
import unittest
import pytest
from PIL import Image, ImageDraw, ImagePalette, UnidentifiedImageError
from .helper import (
PillowTestCase,
assert_image_equal,
assert_image_similar,
assert_not_all_same,
@ -17,7 +15,7 @@ from .helper import (
)
class TestImage(PillowTestCase):
class TestImage:
def test_image_modes_success(self):
for mode in [
"1",
@ -109,7 +107,7 @@ class TestImage(PillowTestCase):
with pytest.raises(ValueError):
Image.open(io.StringIO())
def test_pathlib(self):
def test_pathlib(self, tmp_path):
from PIL.Image import Path
with Image.open(Path("Tests/images/multipage-mmap.tiff")) as im:
@ -120,13 +118,13 @@ class TestImage(PillowTestCase):
assert im.mode == "RGB"
assert im.size == (128, 128)
temp_file = self.tempfile("temp.jpg")
temp_file = str(tmp_path / "temp.jpg")
if os.path.exists(temp_file):
os.remove(temp_file)
im.save(Path(temp_file))
def test_fp_name(self):
temp_file = self.tempfile("temp.jpg")
def test_fp_name(self, tmp_path):
temp_file = str(tmp_path / "temp.jpg")
class FP:
def write(a, b):
@ -148,9 +146,9 @@ class TestImage(PillowTestCase):
with Image.open(fp) as reloaded:
assert_image_similar(im, reloaded, 20)
def test_unknown_extension(self):
def test_unknown_extension(self, tmp_path):
im = hopper()
temp_file = self.tempfile("temp.unknown")
temp_file = str(tmp_path / "temp.unknown")
with pytest.raises(ValueError):
im.save(temp_file)
@ -164,25 +162,25 @@ class TestImage(PillowTestCase):
im.paste(0, (0, 0, 100, 100))
assert not im.readonly
@unittest.skipIf(is_win32(), "Test requires opening tempfile twice")
def test_readonly_save(self):
temp_file = self.tempfile("temp.bmp")
@pytest.mark.skipif(is_win32(), reason="Test requires opening tempfile twice")
def test_readonly_save(self, tmp_path):
temp_file = str(tmp_path / "temp.bmp")
shutil.copy("Tests/images/rgb32bf-rgba.bmp", temp_file)
with Image.open(temp_file) as im:
assert im.readonly
im.save(temp_file)
def test_dump(self):
def test_dump(self, tmp_path):
im = Image.new("L", (10, 10))
im._dump(self.tempfile("temp_L.ppm"))
im._dump(str(tmp_path / "temp_L.ppm"))
im = Image.new("RGB", (10, 10))
im._dump(self.tempfile("temp_RGB.ppm"))
im._dump(str(tmp_path / "temp_RGB.ppm"))
im = Image.new("HSV", (10, 10))
with pytest.raises(ValueError):
im._dump(self.tempfile("temp_HSV.ppm"))
im._dump(str(tmp_path / "temp_HSV.ppm"))
def test_comparison_with_other_type(self):
# Arrange
@ -434,8 +432,7 @@ class TestImage(PillowTestCase):
assert_image_similar(im2, im3, 110)
def test_check_size(self):
# Checking that the _check_size function throws value errors
# when we want it to.
# Checking that the _check_size function throws value errors when we want it to
with pytest.raises(ValueError):
Image.new("RGB", 0) # not a tuple
with pytest.raises(ValueError):
@ -587,11 +584,11 @@ class TestImage(PillowTestCase):
expected = Image.new(mode, (100, 100), color)
assert_image_equal(im.convert(mode), expected)
def test_no_resource_warning_on_save(self):
def test_no_resource_warning_on_save(self, tmp_path):
# https://github.com/python-pillow/Pillow/issues/835
# Arrange
test_file = "Tests/images/hopper.png"
temp_file = self.tempfile("temp.jpg")
temp_file = str(tmp_path / "temp.jpg")
# Act/Assert
with Image.open(test_file) as im:
@ -623,14 +620,14 @@ class TestImage(PillowTestCase):
with Image.open(os.path.join("Tests/images", file)) as im:
try:
im.load()
self.assertFail()
assert False
except OSError as e:
assert str(e) == "buffer overrun when reading image file"
with Image.open("Tests/images/fli_overrun2.bin") as im:
try:
im.seek(1)
self.assertFail()
assert False
except OSError as e:
assert str(e) == "buffer overrun when reading image file"
@ -645,7 +642,7 @@ def mock_encode(*args):
return encoder
class TestRegistry(PillowTestCase):
class TestRegistry:
def test_encode_registry(self):
Image.register_encoder("MOCK", mock_encode)

View File

@ -1,13 +1,12 @@
import unittest
from contextlib import contextmanager
import pytest
from PIL import Image, ImageDraw
from .helper import PillowTestCase, assert_image_equal, assert_image_similar, hopper
from .helper import assert_image_equal, assert_image_similar, hopper
class TestImagingResampleVulnerability(PillowTestCase):
class TestImagingResampleVulnerability:
# see https://github.com/python-pillow/Pillow/issues/1710
def test_overflow(self):
im = hopper("L")
@ -43,7 +42,7 @@ class TestImagingResampleVulnerability(PillowTestCase):
assert im.tobytes() != copy.tobytes()
class TestImagingCoreResampleAccuracy(PillowTestCase):
class TestImagingCoreResampleAccuracy:
def make_case(self, mode, size, color):
"""Makes a sample image with two dark and two bright squares.
For example:
@ -219,7 +218,7 @@ class TestImagingCoreResampleAccuracy(PillowTestCase):
assert_image_equal(im, ref)
class CoreResampleConsistencyTest(PillowTestCase):
class CoreResampleConsistencyTest:
def make_case(self, mode, fill):
im = Image.new(mode, (512, 9), fill)
return im.resize((9, 512), Image.LANCZOS), im.load()[0, 0]
@ -254,7 +253,7 @@ class CoreResampleConsistencyTest(PillowTestCase):
self.run_case(self.make_case("F", 1.192093e-07))
class CoreResampleAlphaCorrectTest(PillowTestCase):
class CoreResampleAlphaCorrectTest:
def make_levels_case(self, mode):
i = Image.new(mode, (256, 16))
px = i.load()
@ -275,7 +274,7 @@ class CoreResampleAlphaCorrectTest(PillowTestCase):
len(used_colors), y
)
@unittest.skip("current implementation isn't precise enough")
@pytest.mark.skip("Current implementation isn't precise enough")
def test_levels_rgba(self):
case = self.make_levels_case("RGBA")
self.run_levels_case(case.resize((512, 32), Image.BOX))
@ -284,7 +283,7 @@ class CoreResampleAlphaCorrectTest(PillowTestCase):
self.run_levels_case(case.resize((512, 32), Image.BICUBIC))
self.run_levels_case(case.resize((512, 32), Image.LANCZOS))
@unittest.skip("current implementation isn't precise enough")
@pytest.mark.skip("Current implementation isn't precise enough")
def test_levels_la(self):
case = self.make_levels_case("LA")
self.run_levels_case(case.resize((512, 32), Image.BOX))
@ -330,7 +329,7 @@ class CoreResampleAlphaCorrectTest(PillowTestCase):
self.run_dirty_case(case.resize((20, 20), Image.LANCZOS), (255,))
class CoreResamplePassesTest(PillowTestCase):
class CoreResamplePassesTest:
@contextmanager
def count(self, diff):
count = Image.core.get_stats()["new_count"]
@ -373,7 +372,7 @@ class CoreResamplePassesTest(PillowTestCase):
assert_image_similar(with_box, cropped, 0.1)
class CoreResampleCoefficientsTest(PillowTestCase):
class CoreResampleCoefficientsTest:
def test_reduce(self):
test_color = 254
@ -402,7 +401,7 @@ class CoreResampleCoefficientsTest(PillowTestCase):
assert histogram[0x100 * 3 + 0xFF] == 0x10000
class CoreResampleBoxTest(PillowTestCase):
class CoreResampleBoxTest:
def test_wrong_arguments(self):
im = hopper()
for resample in (

View File

@ -1,8 +1,7 @@
import unittest
import pytest
from PIL import Image, ImageDraw, ImageFont
from .helper import PillowTestCase, assert_image_similar
from .helper import assert_image_similar
image_font_installed = True
try:
@ -11,14 +10,11 @@ except ImportError:
image_font_installed = False
@unittest.skipUnless(image_font_installed, "image font not installed")
class TestImageFontBitmap(PillowTestCase):
def test_similar(self):
@pytest.mark.skipif(not image_font_installed, reason="Image font not installed")
def test_similar():
text = "EmbeddedBitmap"
font_outline = ImageFont.truetype(font="Tests/fonts/DejaVuSans.ttf", size=24)
font_bitmap = ImageFont.truetype(
font="Tests/fonts/DejaVuSans-bitmap.ttf", size=24
)
font_bitmap = ImageFont.truetype(font="Tests/fonts/DejaVuSans-bitmap.ttf", size=24)
size_outline = font_outline.getsize(text)
size_bitmap = font_bitmap.getsize(text)
size_final = (
@ -30,16 +26,13 @@ class TestImageFontBitmap(PillowTestCase):
draw_bitmap = ImageDraw.Draw(im_bitmap)
draw_outline = ImageDraw.Draw(im_outline)
# Metrics are different on the bitmap and ttf fonts,
# more so on some platforms and versions of freetype than others.
# Mac has a 1px difference, linux doesn't.
# Metrics are different on the bitmap and TTF fonts,
# more so on some platforms and versions of FreeType than others.
# Mac has a 1px difference, Linux doesn't.
draw_bitmap.text(
(0, size_final[1] - size_bitmap[1]), text, fill=(0, 0, 0), font=font_bitmap
)
draw_outline.text(
(0, size_final[1] - size_outline[1]),
text,
fill=(0, 0, 0),
font=font_outline,
(0, size_final[1] - size_outline[1]), text, fill=(0, 0, 0), font=font_outline,
)
assert_image_similar(im_bitmap, im_outline, 20)