Autotype tests (#7756)

* autotyping: --none-return
* autotyping: --scalar-return
* autotyping: --int-param
* autotyping: --float-param
* autotyping: --str-param
* autotyping: --annotate-named-param tmp_path:pathlib.Path
This commit is contained in:
Hugo van Kemenade 2024-01-31 11:12:58 +02:00 committed by GitHub
parent db437386eb
commit 4a4b90c365
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
108 changed files with 1866 additions and 1798 deletions

View File

@ -9,21 +9,21 @@ from .helper import hopper
# Not running this test by default. No DOS against CI.
def iterate_get(size, access):
def iterate_get(size, access) -> None:
(w, h) = size
for x in range(w):
for y in range(h):
access[(x, y)]
def iterate_set(size, access):
def iterate_set(size, access) -> None:
(w, h) = size
for x in range(w):
for y in range(h):
access[(x, y)] = (x % 256, y % 256, 0)
def timer(func, label, *args):
def timer(func, label, *args) -> None:
iterations = 5000
starttime = time.time()
for x in range(iterations):
@ -38,7 +38,7 @@ def timer(func, label, *args):
)
def test_direct():
def test_direct() -> None:
im = hopper()
im.load()
# im = Image.new("RGB", (2000, 2000), (1, 3, 2))

View File

@ -10,13 +10,13 @@ from .helper import assert_image_similar
base = os.path.join("Tests", "images", "bmp")
def get_files(d, ext=".bmp"):
def get_files(d, ext: str = ".bmp"):
return [
os.path.join(base, d, f) for f in os.listdir(os.path.join(base, d)) if ext in f
]
def test_bad():
def test_bad() -> None:
"""These shouldn't crash/dos, but they shouldn't return anything
either"""
for f in get_files("b"):
@ -56,7 +56,7 @@ def test_questionable():
raise
def test_good():
def test_good() -> None:
"""These should all work. There's a set of target files in the
html directory that we can compare against."""

View File

@ -16,18 +16,18 @@ sample.putdata(sum([
# fmt: on
def test_imageops_box_blur():
def test_imageops_box_blur() -> None:
i = sample.filter(ImageFilter.BoxBlur(1))
assert i.mode == sample.mode
assert i.size == sample.size
assert isinstance(i, Image.Image)
def box_blur(image, radius=1, n=1):
def box_blur(image, radius: int = 1, n: int = 1):
return image._new(image.im.box_blur((radius, radius), n))
def assert_image(im, data, delta=0):
def assert_image(im, data, delta: int = 0) -> None:
it = iter(im.getdata())
for data_row in data:
im_row = [next(it) for _ in range(im.size[0])]
@ -37,7 +37,7 @@ def assert_image(im, data, delta=0):
next(it)
def assert_blur(im, radius, data, passes=1, delta=0):
def assert_blur(im, radius, data, passes: int = 1, delta: int = 0) -> None:
# check grayscale image
assert_image(box_blur(im, radius, passes), data, delta)
rgba = Image.merge("RGBA", (im, im, im, im))
@ -45,7 +45,7 @@ def assert_blur(im, radius, data, passes=1, delta=0):
assert_image(band, data, delta)
def test_color_modes():
def test_color_modes() -> None:
with pytest.raises(ValueError):
box_blur(sample.convert("1"))
with pytest.raises(ValueError):
@ -65,7 +65,7 @@ def test_color_modes():
box_blur(sample.convert("YCbCr"))
def test_radius_0():
def test_radius_0() -> None:
assert_blur(
sample,
0,
@ -81,7 +81,7 @@ def test_radius_0():
)
def test_radius_0_02():
def test_radius_0_02() -> None:
assert_blur(
sample,
0.02,
@ -98,7 +98,7 @@ def test_radius_0_02():
)
def test_radius_0_05():
def test_radius_0_05() -> None:
assert_blur(
sample,
0.05,
@ -115,7 +115,7 @@ def test_radius_0_05():
)
def test_radius_0_1():
def test_radius_0_1() -> None:
assert_blur(
sample,
0.1,
@ -132,7 +132,7 @@ def test_radius_0_1():
)
def test_radius_0_5():
def test_radius_0_5() -> None:
assert_blur(
sample,
0.5,
@ -149,7 +149,7 @@ def test_radius_0_5():
)
def test_radius_1():
def test_radius_1() -> None:
assert_blur(
sample,
1,
@ -166,7 +166,7 @@ def test_radius_1():
)
def test_radius_1_5():
def test_radius_1_5() -> None:
assert_blur(
sample,
1.5,
@ -183,7 +183,7 @@ def test_radius_1_5():
)
def test_radius_bigger_then_half():
def test_radius_bigger_then_half() -> None:
assert_blur(
sample,
3,
@ -200,7 +200,7 @@ def test_radius_bigger_then_half():
)
def test_radius_bigger_then_width():
def test_radius_bigger_then_width() -> None:
assert_blur(
sample,
10,
@ -215,7 +215,7 @@ def test_radius_bigger_then_width():
)
def test_extreme_large_radius():
def test_extreme_large_radius() -> None:
assert_blur(
sample,
600,
@ -230,7 +230,7 @@ def test_extreme_large_radius():
)
def test_two_passes():
def test_two_passes() -> None:
assert_blur(
sample,
1,
@ -248,7 +248,7 @@ def test_two_passes():
)
def test_three_passes():
def test_three_passes() -> None:
assert_blur(
sample,
1,

View File

@ -41,7 +41,7 @@ class TestColorLut3DCoreAPI:
[item for sublist in table for item in sublist],
)
def test_wrong_args(self):
def test_wrong_args(self) -> None:
im = Image.new("RGB", (10, 10), 0)
with pytest.raises(ValueError, match="filter"):
@ -101,7 +101,7 @@ class TestColorLut3DCoreAPI:
with pytest.raises(TypeError):
im.im.color_lut_3d("RGB", Image.Resampling.BILINEAR, 3, 2, 2, 2, 16)
def test_correct_args(self):
def test_correct_args(self) -> None:
im = Image.new("RGB", (10, 10), 0)
im.im.color_lut_3d(
@ -136,7 +136,7 @@ class TestColorLut3DCoreAPI:
*self.generate_identity_table(3, (3, 3, 65)),
)
def test_wrong_mode(self):
def test_wrong_mode(self) -> None:
with pytest.raises(ValueError, match="wrong mode"):
im = Image.new("L", (10, 10), 0)
im.im.color_lut_3d(
@ -167,7 +167,7 @@ class TestColorLut3DCoreAPI:
"RGB", Image.Resampling.BILINEAR, *self.generate_identity_table(4, 3)
)
def test_correct_mode(self):
def test_correct_mode(self) -> None:
im = Image.new("RGBA", (10, 10), 0)
im.im.color_lut_3d(
"RGBA", Image.Resampling.BILINEAR, *self.generate_identity_table(3, 3)
@ -188,7 +188,7 @@ class TestColorLut3DCoreAPI:
"RGBA", Image.Resampling.BILINEAR, *self.generate_identity_table(4, 3)
)
def test_identities(self):
def test_identities(self) -> None:
g = Image.linear_gradient("L")
im = Image.merge(
"RGB",
@ -224,7 +224,7 @@ class TestColorLut3DCoreAPI:
),
)
def test_identities_4_channels(self):
def test_identities_4_channels(self) -> None:
g = Image.linear_gradient("L")
im = Image.merge(
"RGB",
@ -247,7 +247,7 @@ class TestColorLut3DCoreAPI:
),
)
def test_copy_alpha_channel(self):
def test_copy_alpha_channel(self) -> None:
g = Image.linear_gradient("L")
im = Image.merge(
"RGBA",
@ -270,7 +270,7 @@ class TestColorLut3DCoreAPI:
),
)
def test_channels_order(self):
def test_channels_order(self) -> None:
g = Image.linear_gradient("L")
im = Image.merge(
"RGB",
@ -295,7 +295,7 @@ class TestColorLut3DCoreAPI:
])))
# fmt: on
def test_overflow(self):
def test_overflow(self) -> None:
g = Image.linear_gradient("L")
im = Image.merge(
"RGB",
@ -348,7 +348,7 @@ class TestColorLut3DCoreAPI:
class TestColorLut3DFilter:
def test_wrong_args(self):
def test_wrong_args(self) -> None:
with pytest.raises(ValueError, match="should be either an integer"):
ImageFilter.Color3DLUT("small", [1])
@ -376,7 +376,7 @@ class TestColorLut3DFilter:
with pytest.raises(ValueError, match="Only 3 or 4 output"):
ImageFilter.Color3DLUT((2, 2, 2), [[1, 1]] * 8, channels=2)
def test_convert_table(self):
def test_convert_table(self) -> None:
lut = ImageFilter.Color3DLUT(2, [0, 1, 2] * 8)
assert tuple(lut.size) == (2, 2, 2)
assert lut.name == "Color 3D LUT"
@ -394,7 +394,7 @@ class TestColorLut3DFilter:
assert lut.table == list(range(4)) * 8
@pytest.mark.skipif(numpy is None, reason="NumPy not installed")
def test_numpy_sources(self):
def test_numpy_sources(self) -> None:
table = numpy.ones((5, 6, 7, 3), dtype=numpy.float16)
with pytest.raises(ValueError, match="should have either channels"):
lut = ImageFilter.Color3DLUT((5, 6, 7), table)
@ -427,7 +427,7 @@ class TestColorLut3DFilter:
assert lut.table[0] == 33
@pytest.mark.skipif(numpy is None, reason="NumPy not installed")
def test_numpy_formats(self):
def test_numpy_formats(self) -> None:
g = Image.linear_gradient("L")
im = Image.merge(
"RGB",
@ -466,7 +466,7 @@ class TestColorLut3DFilter:
lut.table = numpy.array(lut.table, dtype=numpy.int8)
im.filter(lut)
def test_repr(self):
def test_repr(self) -> None:
lut = ImageFilter.Color3DLUT(2, [0, 1, 2] * 8)
assert repr(lut) == "<Color3DLUT from list size=2x2x2 channels=3>"
@ -484,7 +484,7 @@ class TestColorLut3DFilter:
class TestGenerateColorLut3D:
def test_wrong_channels_count(self):
def test_wrong_channels_count(self) -> None:
with pytest.raises(ValueError, match="3 or 4 output channels"):
ImageFilter.Color3DLUT.generate(
5, channels=2, callback=lambda r, g, b: (r, g, b)
@ -498,7 +498,7 @@ class TestGenerateColorLut3D:
5, channels=4, callback=lambda r, g, b: (r, g, b)
)
def test_3_channels(self):
def test_3_channels(self) -> None:
lut = ImageFilter.Color3DLUT.generate(5, lambda r, g, b: (r, g, b))
assert tuple(lut.size) == (5, 5, 5)
assert lut.name == "Color 3D LUT"
@ -508,7 +508,7 @@ class TestGenerateColorLut3D:
1.0, 0.0, 0.0, 0.0, 0.25, 0.0, 0.25, 0.25, 0.0, 0.5, 0.25, 0.0]
# fmt: on
def test_4_channels(self):
def test_4_channels(self) -> None:
lut = ImageFilter.Color3DLUT.generate(
5, channels=4, callback=lambda r, g, b: (b, r, g, (r + g + b) / 2)
)
@ -521,7 +521,7 @@ class TestGenerateColorLut3D:
]
# fmt: on
def test_apply(self):
def test_apply(self) -> None:
lut = ImageFilter.Color3DLUT.generate(5, lambda r, g, b: (r, g, b))
g = Image.linear_gradient("L")
@ -537,7 +537,7 @@ class TestGenerateColorLut3D:
class TestTransformColorLut3D:
def test_wrong_args(self):
def test_wrong_args(self) -> None:
source = ImageFilter.Color3DLUT.generate(5, lambda r, g, b: (r, g, b))
with pytest.raises(ValueError, match="Only 3 or 4 output"):
@ -552,7 +552,7 @@ class TestTransformColorLut3D:
with pytest.raises(TypeError):
source.transform(lambda r, g, b, a: (r, g, b))
def test_target_mode(self):
def test_target_mode(self) -> None:
source = ImageFilter.Color3DLUT.generate(
2, lambda r, g, b: (r, g, b), target_mode="HSV"
)
@ -563,7 +563,7 @@ class TestTransformColorLut3D:
lut = source.transform(lambda r, g, b: (r, g, b), target_mode="RGB")
assert lut.mode == "RGB"
def test_3_to_3_channels(self):
def test_3_to_3_channels(self) -> None:
source = ImageFilter.Color3DLUT.generate((3, 4, 5), lambda r, g, b: (r, g, b))
lut = source.transform(lambda r, g, b: (r * r, g * g, b * b))
assert tuple(lut.size) == tuple(source.size)
@ -571,7 +571,7 @@ class TestTransformColorLut3D:
assert lut.table != source.table
assert lut.table[:10] == [0.0, 0.0, 0.0, 0.25, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0]
def test_3_to_4_channels(self):
def test_3_to_4_channels(self) -> None:
source = ImageFilter.Color3DLUT.generate((6, 5, 4), lambda r, g, b: (r, g, b))
lut = source.transform(lambda r, g, b: (r * r, g * g, b * b, 1), channels=4)
assert tuple(lut.size) == tuple(source.size)
@ -583,7 +583,7 @@ class TestTransformColorLut3D:
0.4**2, 0.0, 0.0, 1, 0.6**2, 0.0, 0.0, 1]
# fmt: on
def test_4_to_3_channels(self):
def test_4_to_3_channels(self) -> None:
source = ImageFilter.Color3DLUT.generate(
(3, 6, 5), lambda r, g, b: (r, g, b, 1), channels=4
)
@ -599,7 +599,7 @@ class TestTransformColorLut3D:
1.0, 0.96, 1.0, 0.75, 0.96, 1.0, 0.0, 0.96, 1.0]
# fmt: on
def test_4_to_4_channels(self):
def test_4_to_4_channels(self) -> None:
source = ImageFilter.Color3DLUT.generate(
(6, 5, 4), lambda r, g, b: (r, g, b, 1), channels=4
)
@ -613,7 +613,7 @@ class TestTransformColorLut3D:
0.4**2, 0.0, 0.0, 0.5, 0.6**2, 0.0, 0.0, 0.5]
# fmt: on
def test_with_normals_3_channels(self):
def test_with_normals_3_channels(self) -> None:
source = ImageFilter.Color3DLUT.generate(
(6, 5, 4), lambda r, g, b: (r * r, g * g, b * b)
)
@ -629,7 +629,7 @@ class TestTransformColorLut3D:
0.24, 0.0, 0.0, 0.8 - (0.8**2), 0, 0, 0, 0, 0]
# fmt: on
def test_with_normals_4_channels(self):
def test_with_normals_4_channels(self) -> None:
source = ImageFilter.Color3DLUT.generate(
(3, 6, 5), lambda r, g, b: (r * r, g * g, b * b, 1), channels=4
)

View File

@ -9,7 +9,7 @@ from PIL import Image
from .helper import is_pypy
def test_get_stats():
def test_get_stats() -> None:
# Create at least one image
Image.new("RGB", (10, 10))
@ -22,7 +22,7 @@ def test_get_stats():
assert "blocks_cached" in stats
def test_reset_stats():
def test_reset_stats() -> None:
Image.core.reset_stats()
stats = Image.core.get_stats()
@ -35,19 +35,19 @@ def test_reset_stats():
class TestCoreMemory:
def teardown_method(self):
def teardown_method(self) -> None:
# Restore default values
Image.core.set_alignment(1)
Image.core.set_block_size(1024 * 1024)
Image.core.set_blocks_max(0)
Image.core.clear_cache()
def test_get_alignment(self):
def test_get_alignment(self) -> None:
alignment = Image.core.get_alignment()
assert alignment > 0
def test_set_alignment(self):
def test_set_alignment(self) -> None:
for i in [1, 2, 4, 8, 16, 32]:
Image.core.set_alignment(i)
alignment = Image.core.get_alignment()
@ -63,12 +63,12 @@ class TestCoreMemory:
with pytest.raises(ValueError):
Image.core.set_alignment(3)
def test_get_block_size(self):
def test_get_block_size(self) -> None:
block_size = Image.core.get_block_size()
assert block_size >= 4096
def test_set_block_size(self):
def test_set_block_size(self) -> None:
for i in [4096, 2 * 4096, 3 * 4096]:
Image.core.set_block_size(i)
block_size = Image.core.get_block_size()
@ -84,7 +84,7 @@ class TestCoreMemory:
with pytest.raises(ValueError):
Image.core.set_block_size(4000)
def test_set_block_size_stats(self):
def test_set_block_size_stats(self) -> None:
Image.core.reset_stats()
Image.core.set_blocks_max(0)
Image.core.set_block_size(4096)
@ -96,12 +96,12 @@ class TestCoreMemory:
if not is_pypy():
assert stats["freed_blocks"] >= 64
def test_get_blocks_max(self):
def test_get_blocks_max(self) -> None:
blocks_max = Image.core.get_blocks_max()
assert blocks_max >= 0
def test_set_blocks_max(self):
def test_set_blocks_max(self) -> None:
for i in [0, 1, 10]:
Image.core.set_blocks_max(i)
blocks_max = Image.core.get_blocks_max()
@ -117,7 +117,7 @@ class TestCoreMemory:
Image.core.set_blocks_max(2**29)
@pytest.mark.skipif(is_pypy(), reason="Images not collected")
def test_set_blocks_max_stats(self):
def test_set_blocks_max_stats(self) -> None:
Image.core.reset_stats()
Image.core.set_blocks_max(128)
Image.core.set_block_size(4096)
@ -132,7 +132,7 @@ class TestCoreMemory:
assert stats["blocks_cached"] == 64
@pytest.mark.skipif(is_pypy(), reason="Images not collected")
def test_clear_cache_stats(self):
def test_clear_cache_stats(self) -> None:
Image.core.reset_stats()
Image.core.clear_cache()
Image.core.set_blocks_max(128)
@ -149,7 +149,7 @@ class TestCoreMemory:
assert stats["freed_blocks"] >= 48
assert stats["blocks_cached"] == 16
def test_large_images(self):
def test_large_images(self) -> None:
Image.core.reset_stats()
Image.core.set_blocks_max(0)
Image.core.set_block_size(4096)
@ -166,14 +166,14 @@ class TestCoreMemory:
class TestEnvVars:
def teardown_method(self):
def teardown_method(self) -> None:
# Restore default values
Image.core.set_alignment(1)
Image.core.set_block_size(1024 * 1024)
Image.core.set_blocks_max(0)
Image.core.clear_cache()
def test_units(self):
def test_units(self) -> None:
Image._apply_env_variables({"PILLOW_BLOCKS_MAX": "2K"})
assert Image.core.get_blocks_max() == 2 * 1024
Image._apply_env_variables({"PILLOW_BLOCK_SIZE": "2m"})
@ -187,6 +187,6 @@ class TestEnvVars:
{"PILLOW_BLOCKS_MAX": "wat"},
),
)
def test_warnings(self, var):
def test_warnings(self, var) -> None:
with pytest.warns(UserWarning):
Image._apply_env_variables(var)

View File

@ -12,16 +12,16 @@ ORIGINAL_LIMIT = Image.MAX_IMAGE_PIXELS
class TestDecompressionBomb:
def teardown_method(self, method):
def teardown_method(self, method) -> None:
Image.MAX_IMAGE_PIXELS = ORIGINAL_LIMIT
def test_no_warning_small_file(self):
def test_no_warning_small_file(self) -> None:
# Implicit assert: no warning.
# A warning would cause a failure.
with Image.open(TEST_FILE):
pass
def test_no_warning_no_limit(self):
def test_no_warning_no_limit(self) -> None:
# Arrange
# Turn limit off
Image.MAX_IMAGE_PIXELS = None
@ -33,7 +33,7 @@ class TestDecompressionBomb:
with Image.open(TEST_FILE):
pass
def test_warning(self):
def test_warning(self) -> None:
# Set limit to trigger warning on the test file
Image.MAX_IMAGE_PIXELS = 128 * 128 - 1
assert Image.MAX_IMAGE_PIXELS == 128 * 128 - 1
@ -42,7 +42,7 @@ class TestDecompressionBomb:
with Image.open(TEST_FILE):
pass
def test_exception(self):
def test_exception(self) -> None:
# Set limit to trigger exception on the test file
Image.MAX_IMAGE_PIXELS = 64 * 128 - 1
assert Image.MAX_IMAGE_PIXELS == 64 * 128 - 1
@ -51,22 +51,22 @@ class TestDecompressionBomb:
with Image.open(TEST_FILE):
pass
def test_exception_ico(self):
def test_exception_ico(self) -> None:
with pytest.raises(Image.DecompressionBombError):
with Image.open("Tests/images/decompression_bomb.ico"):
pass
def test_exception_gif(self):
def test_exception_gif(self) -> None:
with pytest.raises(Image.DecompressionBombError):
with Image.open("Tests/images/decompression_bomb.gif"):
pass
def test_exception_gif_extents(self):
def test_exception_gif_extents(self) -> None:
with Image.open("Tests/images/decompression_bomb_extents.gif") as im:
with pytest.raises(Image.DecompressionBombError):
im.seek(1)
def test_exception_gif_zero_width(self):
def test_exception_gif_zero_width(self) -> None:
# Set limit to trigger exception on the test file
Image.MAX_IMAGE_PIXELS = 4 * 64 * 128
assert Image.MAX_IMAGE_PIXELS == 4 * 64 * 128
@ -75,7 +75,7 @@ class TestDecompressionBomb:
with Image.open("Tests/images/zero_width.gif"):
pass
def test_exception_bmp(self):
def test_exception_bmp(self) -> None:
with pytest.raises(Image.DecompressionBombError):
with Image.open("Tests/images/bmp/b/reallybig.bmp"):
pass
@ -83,15 +83,15 @@ class TestDecompressionBomb:
class TestDecompressionCrop:
@classmethod
def setup_class(cls):
def setup_class(cls) -> None:
width, height = 128, 128
Image.MAX_IMAGE_PIXELS = height * width * 4 - 1
@classmethod
def teardown_class(cls):
def teardown_class(cls) -> None:
Image.MAX_IMAGE_PIXELS = ORIGINAL_LIMIT
def test_enlarge_crop(self):
def test_enlarge_crop(self) -> None:
# Crops can extend the extents, therefore we should have the
# same decompression bomb warnings on them.
with hopper() as src:
@ -99,7 +99,7 @@ class TestDecompressionCrop:
with pytest.warns(Image.DecompressionBombWarning):
src.crop(box)
def test_crop_decompression_checks(self):
def test_crop_decompression_checks(self) -> None:
im = Image.new("RGB", (100, 100))
for value in ((-9999, -9999, -9990, -9990), (-999, -999, -990, -990)):

View File

@ -20,12 +20,12 @@ from PIL import _deprecate
),
],
)
def test_version(version, expected):
def test_version(version, expected) -> None:
with pytest.warns(DeprecationWarning, match=expected):
_deprecate.deprecate("Old thing", version, "new thing")
def test_unknown_version():
def test_unknown_version() -> None:
expected = r"Unknown removal version: 12345. Update PIL\._deprecate\?"
with pytest.raises(ValueError, match=expected):
_deprecate.deprecate("Old thing", 12345, "new thing")
@ -46,13 +46,13 @@ def test_unknown_version():
),
],
)
def test_old_version(deprecated, plural, expected):
def test_old_version(deprecated, plural, expected) -> None:
expected = r""
with pytest.raises(RuntimeError, match=expected):
_deprecate.deprecate(deprecated, 1, plural=plural)
def test_plural():
def test_plural() -> None:
expected = (
r"Old things are deprecated and will be removed in Pillow 11 \(2024-10-15\)\. "
r"Use new thing instead\."
@ -61,7 +61,7 @@ def test_plural():
_deprecate.deprecate("Old things", 11, "new thing", plural=True)
def test_replacement_and_action():
def test_replacement_and_action() -> None:
expected = "Use only one of 'replacement' and 'action'"
with pytest.raises(ValueError, match=expected):
_deprecate.deprecate(
@ -76,7 +76,7 @@ def test_replacement_and_action():
"Upgrade to new thing.",
],
)
def test_action(action):
def test_action(action) -> None:
expected = (
r"Old thing is deprecated and will be removed in Pillow 11 \(2024-10-15\)\. "
r"Upgrade to new thing\."
@ -85,7 +85,7 @@ def test_action(action):
_deprecate.deprecate("Old thing", 11, action=action)
def test_no_replacement_or_action():
def test_no_replacement_or_action() -> None:
expected = (
r"Old thing is deprecated and will be removed in Pillow 11 \(2024-10-15\)"
)

View File

@ -15,7 +15,7 @@ except ImportError:
pass
def test_check():
def test_check() -> None:
# Check the correctness of the convenience function
for module in features.modules:
assert features.check_module(module) == features.check(module)
@ -25,11 +25,11 @@ def test_check():
assert features.check_feature(feature) == features.check(feature)
def test_version():
def test_version() -> None:
# Check the correctness of the convenience function
# and the format of version numbers
def test(name, function):
def test(name, function) -> None:
version = features.version(name)
if not features.check(name):
assert version is None
@ -47,56 +47,56 @@ def test_version():
@skip_unless_feature("webp")
def test_webp_transparency():
def test_webp_transparency() -> None:
assert features.check("transp_webp") != _webp.WebPDecoderBuggyAlpha()
assert features.check("transp_webp") == _webp.HAVE_TRANSPARENCY
@skip_unless_feature("webp")
def test_webp_mux():
def test_webp_mux() -> None:
assert features.check("webp_mux") == _webp.HAVE_WEBPMUX
@skip_unless_feature("webp")
def test_webp_anim():
def test_webp_anim() -> None:
assert features.check("webp_anim") == _webp.HAVE_WEBPANIM
@skip_unless_feature("libjpeg_turbo")
def test_libjpeg_turbo_version():
def test_libjpeg_turbo_version() -> None:
assert re.search(r"\d+\.\d+\.\d+$", features.version("libjpeg_turbo"))
@skip_unless_feature("libimagequant")
def test_libimagequant_version():
def test_libimagequant_version() -> None:
assert re.search(r"\d+\.\d+\.\d+$", features.version("libimagequant"))
@pytest.mark.parametrize("feature", features.modules)
def test_check_modules(feature):
def test_check_modules(feature) -> None:
assert features.check_module(feature) in [True, False]
@pytest.mark.parametrize("feature", features.codecs)
def test_check_codecs(feature):
def test_check_codecs(feature) -> None:
assert features.check_codec(feature) in [True, False]
def test_check_warns_on_nonexistent():
def test_check_warns_on_nonexistent() -> None:
with pytest.warns(UserWarning) as cm:
has_feature = features.check("typo")
assert has_feature is False
assert str(cm[-1].message) == "Unknown feature 'typo'."
def test_supported_modules():
def test_supported_modules() -> None:
assert isinstance(features.get_supported_modules(), list)
assert isinstance(features.get_supported_codecs(), list)
assert isinstance(features.get_supported_features(), list)
assert isinstance(features.get_supported(), list)
def test_unsupported_codec():
def test_unsupported_codec() -> None:
# Arrange
codec = "unsupported_codec"
# Act / Assert
@ -106,7 +106,7 @@ def test_unsupported_codec():
features.version_codec(codec)
def test_unsupported_module():
def test_unsupported_module() -> None:
# Arrange
module = "unsupported_module"
# Act / Assert
@ -116,7 +116,7 @@ def test_unsupported_module():
features.version_module(module)
def test_pilinfo():
def test_pilinfo() -> None:
buf = io.StringIO()
features.pilinfo(buf)
out = buf.getvalue()

View File

@ -1,5 +1,7 @@
from __future__ import annotations
from pathlib import Path
import pytest
from PIL import Image, ImageSequence, PngImagePlugin
@ -8,7 +10,7 @@ from PIL import Image, ImageSequence, PngImagePlugin
# APNG browser support tests and fixtures via:
# https://philip.html5.org/tests/apng/tests.html
# (referenced from https://wiki.mozilla.org/APNG_Specification)
def test_apng_basic():
def test_apng_basic() -> None:
with Image.open("Tests/images/apng/single_frame.png") as im:
assert not im.is_animated
assert im.n_frames == 1
@ -45,14 +47,14 @@ def test_apng_basic():
"filename",
("Tests/images/apng/split_fdat.png", "Tests/images/apng/split_fdat_zero_chunk.png"),
)
def test_apng_fdat(filename):
def test_apng_fdat(filename) -> None:
with Image.open(filename) as im:
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (0, 255, 0, 255)
assert im.getpixel((64, 32)) == (0, 255, 0, 255)
def test_apng_dispose():
def test_apng_dispose() -> None:
with Image.open("Tests/images/apng/dispose_op_none.png") as im:
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (0, 255, 0, 255)
@ -84,7 +86,7 @@ def test_apng_dispose():
assert im.getpixel((64, 32)) == (0, 0, 0, 0)
def test_apng_dispose_region():
def test_apng_dispose_region() -> None:
with Image.open("Tests/images/apng/dispose_op_none_region.png") as im:
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (0, 255, 0, 255)
@ -106,7 +108,7 @@ def test_apng_dispose_region():
assert im.getpixel((64, 32)) == (0, 255, 0, 255)
def test_apng_dispose_op_previous_frame():
def test_apng_dispose_op_previous_frame() -> None:
# Test that the dispose settings being used are from the previous frame
#
# Image created with:
@ -131,14 +133,14 @@ def test_apng_dispose_op_previous_frame():
assert im.getpixel((0, 0)) == (255, 0, 0, 255)
def test_apng_dispose_op_background_p_mode():
def test_apng_dispose_op_background_p_mode() -> None:
with Image.open("Tests/images/apng/dispose_op_background_p_mode.png") as im:
im.seek(1)
im.load()
assert im.size == (128, 64)
def test_apng_blend():
def test_apng_blend() -> None:
with Image.open("Tests/images/apng/blend_op_source_solid.png") as im:
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (0, 255, 0, 255)
@ -165,20 +167,20 @@ def test_apng_blend():
assert im.getpixel((64, 32)) == (0, 255, 0, 255)
def test_apng_blend_transparency():
def test_apng_blend_transparency() -> None:
with Image.open("Tests/images/blend_transparency.png") as im:
im.seek(1)
assert im.getpixel((0, 0)) == (255, 0, 0)
def test_apng_chunk_order():
def test_apng_chunk_order() -> None:
with Image.open("Tests/images/apng/fctl_actl.png") as im:
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (0, 255, 0, 255)
assert im.getpixel((64, 32)) == (0, 255, 0, 255)
def test_apng_delay():
def test_apng_delay() -> None:
with Image.open("Tests/images/apng/delay.png") as im:
im.seek(1)
assert im.info.get("duration") == 500.0
@ -218,7 +220,7 @@ def test_apng_delay():
assert im.info.get("duration") == 1000.0
def test_apng_num_plays():
def test_apng_num_plays() -> None:
with Image.open("Tests/images/apng/num_plays.png") as im:
assert im.info.get("loop") == 0
@ -226,7 +228,7 @@ def test_apng_num_plays():
assert im.info.get("loop") == 1
def test_apng_mode():
def test_apng_mode() -> None:
with Image.open("Tests/images/apng/mode_16bit.png") as im:
assert im.mode == "RGBA"
im.seek(im.n_frames - 1)
@ -267,7 +269,7 @@ def test_apng_mode():
assert im.getpixel((64, 32)) == (0, 0, 255, 128)
def test_apng_chunk_errors():
def test_apng_chunk_errors() -> None:
with Image.open("Tests/images/apng/chunk_no_actl.png") as im:
assert not im.is_animated
@ -292,7 +294,7 @@ def test_apng_chunk_errors():
im.seek(im.n_frames - 1)
def test_apng_syntax_errors():
def test_apng_syntax_errors() -> None:
with pytest.warns(UserWarning):
with Image.open("Tests/images/apng/syntax_num_frames_zero.png") as im:
assert not im.is_animated
@ -336,14 +338,14 @@ def test_apng_syntax_errors():
"sequence_fdat_fctl.png",
),
)
def test_apng_sequence_errors(test_file):
def test_apng_sequence_errors(test_file) -> None:
with pytest.raises(SyntaxError):
with Image.open(f"Tests/images/apng/{test_file}") as im:
im.seek(im.n_frames - 1)
im.load()
def test_apng_save(tmp_path):
def test_apng_save(tmp_path: Path) -> None:
with Image.open("Tests/images/apng/single_frame.png") as im:
test_file = str(tmp_path / "temp.png")
im.save(test_file, save_all=True)
@ -374,7 +376,7 @@ def test_apng_save(tmp_path):
assert im.getpixel((64, 32)) == (0, 255, 0, 255)
def test_apng_save_alpha(tmp_path):
def test_apng_save_alpha(tmp_path: Path) -> None:
test_file = str(tmp_path / "temp.png")
im = Image.new("RGBA", (1, 1), (255, 0, 0, 255))
@ -388,7 +390,7 @@ def test_apng_save_alpha(tmp_path):
assert reloaded.getpixel((0, 0)) == (255, 0, 0, 127)
def test_apng_save_split_fdat(tmp_path):
def test_apng_save_split_fdat(tmp_path: Path) -> None:
# test to make sure we do not generate sequence errors when writing
# frames with image data spanning multiple fdAT chunks (in this case
# both the default image and first animation frame will span multiple
@ -412,7 +414,7 @@ def test_apng_save_split_fdat(tmp_path):
assert exception is None
def test_apng_save_duration_loop(tmp_path):
def test_apng_save_duration_loop(tmp_path: Path) -> None:
test_file = str(tmp_path / "temp.png")
with Image.open("Tests/images/apng/delay.png") as im:
frames = []
@ -475,7 +477,7 @@ def test_apng_save_duration_loop(tmp_path):
assert im.info["duration"] == 600
def test_apng_save_disposal(tmp_path):
def test_apng_save_disposal(tmp_path: Path) -> None:
test_file = str(tmp_path / "temp.png")
size = (128, 64)
red = Image.new("RGBA", size, (255, 0, 0, 255))
@ -576,7 +578,7 @@ def test_apng_save_disposal(tmp_path):
assert im.getpixel((64, 32)) == (0, 0, 0, 0)
def test_apng_save_disposal_previous(tmp_path):
def test_apng_save_disposal_previous(tmp_path: Path) -> None:
test_file = str(tmp_path / "temp.png")
size = (128, 64)
blue = Image.new("RGBA", size, (0, 0, 255, 255))
@ -598,7 +600,7 @@ def test_apng_save_disposal_previous(tmp_path):
assert im.getpixel((64, 32)) == (0, 255, 0, 255)
def test_apng_save_blend(tmp_path):
def test_apng_save_blend(tmp_path: Path) -> None:
test_file = str(tmp_path / "temp.png")
size = (128, 64)
red = Image.new("RGBA", size, (255, 0, 0, 255))
@ -666,7 +668,7 @@ def test_apng_save_blend(tmp_path):
assert im.getpixel((0, 0)) == (0, 255, 0, 255)
def test_seek_after_close():
def test_seek_after_close() -> None:
im = Image.open("Tests/images/apng/delay.png")
im.seek(1)
im.close()
@ -678,7 +680,9 @@ def test_seek_after_close():
@pytest.mark.parametrize("mode", ("RGBA", "RGB", "P"))
@pytest.mark.parametrize("default_image", (True, False))
@pytest.mark.parametrize("duplicate", (True, False))
def test_different_modes_in_later_frames(mode, default_image, duplicate, tmp_path):
def test_different_modes_in_later_frames(
mode, default_image, duplicate, tmp_path: Path
) -> None:
test_file = str(tmp_path / "temp.png")
im = Image.new("L", (1, 1))

View File

@ -1,5 +1,7 @@
from __future__ import annotations
from pathlib import Path
import pytest
from PIL import Image
@ -12,7 +14,7 @@ from .helper import (
)
def test_load_blp1():
def test_load_blp1() -> None:
with Image.open("Tests/images/blp/blp1_jpeg.blp") as im:
assert_image_equal_tofile(im, "Tests/images/blp/blp1_jpeg.png")
@ -20,22 +22,22 @@ def test_load_blp1():
im.load()
def test_load_blp2_raw():
def test_load_blp2_raw() -> None:
with Image.open("Tests/images/blp/blp2_raw.blp") as im:
assert_image_equal_tofile(im, "Tests/images/blp/blp2_raw.png")
def test_load_blp2_dxt1():
def test_load_blp2_dxt1() -> None:
with Image.open("Tests/images/blp/blp2_dxt1.blp") as im:
assert_image_equal_tofile(im, "Tests/images/blp/blp2_dxt1.png")
def test_load_blp2_dxt1a():
def test_load_blp2_dxt1a() -> None:
with Image.open("Tests/images/blp/blp2_dxt1a.blp") as im:
assert_image_equal_tofile(im, "Tests/images/blp/blp2_dxt1a.png")
def test_save(tmp_path):
def test_save(tmp_path: Path) -> None:
f = str(tmp_path / "temp.blp")
for version in ("BLP1", "BLP2"):
@ -69,7 +71,7 @@ def test_save(tmp_path):
"Tests/images/timeout-ef9112a065e7183fa7faa2e18929b03e44ee16bf.blp",
],
)
def test_crashes(test_file):
def test_crashes(test_file) -> None:
with open(test_file, "rb") as f:
with Image.open(f) as im:
with pytest.raises(OSError):

View File

@ -1,6 +1,7 @@
from __future__ import annotations
import io
from pathlib import Path
import pytest
@ -14,8 +15,8 @@ from .helper import (
)
def test_sanity(tmp_path):
def roundtrip(im):
def test_sanity(tmp_path: Path) -> None:
def roundtrip(im) -> None:
outfile = str(tmp_path / "temp.bmp")
im.save(outfile, "BMP")
@ -35,20 +36,20 @@ def test_sanity(tmp_path):
roundtrip(hopper("RGB"))
def test_invalid_file():
def test_invalid_file() -> None:
with open("Tests/images/flower.jpg", "rb") as fp:
with pytest.raises(SyntaxError):
BmpImagePlugin.BmpImageFile(fp)
def test_fallback_if_mmap_errors():
def test_fallback_if_mmap_errors() -> None:
# This image has been truncated,
# so that the buffer is not large enough when using mmap
with Image.open("Tests/images/mmap_error.bmp") as im:
assert_image_equal_tofile(im, "Tests/images/pal8_offset.bmp")
def test_save_to_bytes():
def test_save_to_bytes() -> None:
output = io.BytesIO()
im = hopper()
im.save(output, "BMP")
@ -60,7 +61,7 @@ def test_save_to_bytes():
assert reloaded.format == "BMP"
def test_small_palette(tmp_path):
def test_small_palette(tmp_path: Path) -> None:
im = Image.new("P", (1, 1))
colors = [0, 0, 0, 125, 125, 125, 255, 255, 255]
im.putpalette(colors)
@ -72,7 +73,7 @@ def test_small_palette(tmp_path):
assert reloaded.getpalette() == colors
def test_save_too_large(tmp_path):
def test_save_too_large(tmp_path: Path) -> None:
outfile = str(tmp_path / "temp.bmp")
with Image.new("RGB", (1, 1)) as im:
im._size = (37838, 37838)
@ -80,7 +81,7 @@ def test_save_too_large(tmp_path):
im.save(outfile)
def test_dpi():
def test_dpi() -> None:
dpi = (72, 72)
output = io.BytesIO()
@ -92,7 +93,7 @@ def test_dpi():
assert reloaded.info["dpi"] == (72.008961115161, 72.008961115161)
def test_save_bmp_with_dpi(tmp_path):
def test_save_bmp_with_dpi(tmp_path: Path) -> None:
# Test for #1301
# Arrange
outfile = str(tmp_path / "temp.jpg")
@ -110,7 +111,7 @@ def test_save_bmp_with_dpi(tmp_path):
assert reloaded.format == "JPEG"
def test_save_float_dpi(tmp_path):
def test_save_float_dpi(tmp_path: Path) -> None:
outfile = str(tmp_path / "temp.bmp")
with Image.open("Tests/images/hopper.bmp") as im:
im.save(outfile, dpi=(72.21216100543306, 72.21216100543306))
@ -118,7 +119,7 @@ def test_save_float_dpi(tmp_path):
assert reloaded.info["dpi"] == (72.21216100543306, 72.21216100543306)
def test_load_dib():
def test_load_dib() -> None:
# test for #1293, Imagegrab returning Unsupported Bitfields Format
with Image.open("Tests/images/clipboard.dib") as im:
assert im.format == "DIB"
@ -127,7 +128,7 @@ def test_load_dib():
assert_image_equal_tofile(im, "Tests/images/clipboard_target.png")
def test_save_dib(tmp_path):
def test_save_dib(tmp_path: Path) -> None:
outfile = str(tmp_path / "temp.dib")
with Image.open("Tests/images/clipboard.dib") as im:
@ -139,7 +140,7 @@ def test_save_dib(tmp_path):
assert_image_equal(im, reloaded)
def test_rgba_bitfields():
def test_rgba_bitfields() -> None:
# This test image has been manually hexedited
# to change the bitfield compression in the header from XBGR to RGBA
with Image.open("Tests/images/rgb32bf-rgba.bmp") as im:
@ -157,7 +158,7 @@ def test_rgba_bitfields():
)
def test_rle8():
def test_rle8() -> None:
with Image.open("Tests/images/hopper_rle8.bmp") as im:
assert_image_similar_tofile(im.convert("RGB"), "Tests/images/hopper.bmp", 12)
@ -177,7 +178,7 @@ def test_rle8():
im.load()
def test_rle4():
def test_rle4() -> None:
with Image.open("Tests/images/bmp/g/pal4rle.bmp") as im:
assert_image_similar_tofile(im, "Tests/images/bmp/g/pal4.bmp", 12)
@ -193,7 +194,7 @@ def test_rle4():
("Tests/images/bmp/g/pal8rle.bmp", 1064),
),
)
def test_rle8_eof(file_name, length):
def test_rle8_eof(file_name, length) -> None:
with open(file_name, "rb") as fp:
data = fp.read(length)
with Image.open(io.BytesIO(data)) as im:
@ -201,7 +202,7 @@ def test_rle8_eof(file_name, length):
im.load()
def test_offset():
def test_offset() -> None:
# This image has been hexedited
# to exclude the palette size from the pixel data offset
with Image.open("Tests/images/pal8_offset.bmp") as im:

View File

@ -1,5 +1,7 @@
from __future__ import annotations
from pathlib import Path
import pytest
from PIL import BufrStubImagePlugin, Image
@ -9,7 +11,7 @@ from .helper import hopper
TEST_FILE = "Tests/images/gfs.t06z.rassda.tm00.bufr_d"
def test_open():
def test_open() -> None:
# Act
with Image.open(TEST_FILE) as im:
# Assert
@ -20,7 +22,7 @@ def test_open():
assert im.size == (1, 1)
def test_invalid_file():
def test_invalid_file() -> None:
# Arrange
invalid_file = "Tests/images/flower.jpg"
@ -29,7 +31,7 @@ def test_invalid_file():
BufrStubImagePlugin.BufrStubImageFile(invalid_file)
def test_load():
def test_load() -> None:
# Arrange
with Image.open(TEST_FILE) as im:
# Act / Assert: stub cannot load without an implemented handler
@ -37,7 +39,7 @@ def test_load():
im.load()
def test_save(tmp_path):
def test_save(tmp_path: Path) -> None:
# Arrange
im = hopper()
tmpfile = str(tmp_path / "temp.bufr")
@ -47,13 +49,13 @@ def test_save(tmp_path):
im.save(tmpfile)
def test_handler(tmp_path):
def test_handler(tmp_path: Path) -> None:
class TestHandler:
opened = False
loaded = False
saved = False
def open(self, im):
def open(self, im) -> None:
self.opened = True
def load(self, im):
@ -61,7 +63,7 @@ def test_handler(tmp_path):
im.fp.close()
return Image.new("RGB", (1, 1))
def save(self, im, fp, filename):
def save(self, im, fp, filename) -> None:
self.saved = True
handler = TestHandler()

View File

@ -9,19 +9,19 @@ from .helper import hopper
TEST_FILE = "Tests/images/dummy.container"
def test_sanity():
def test_sanity() -> None:
dir(Image)
dir(ContainerIO)
def test_isatty():
def test_isatty() -> None:
with hopper() as im:
container = ContainerIO.ContainerIO(im, 0, 0)
assert container.isatty() is False
def test_seek_mode_0():
def test_seek_mode_0() -> None:
# Arrange
mode = 0
with open(TEST_FILE, "rb") as fh:
@ -35,7 +35,7 @@ def test_seek_mode_0():
assert container.tell() == 33
def test_seek_mode_1():
def test_seek_mode_1() -> None:
# Arrange
mode = 1
with open(TEST_FILE, "rb") as fh:
@ -49,7 +49,7 @@ def test_seek_mode_1():
assert container.tell() == 66
def test_seek_mode_2():
def test_seek_mode_2() -> None:
# Arrange
mode = 2
with open(TEST_FILE, "rb") as fh:
@ -64,7 +64,7 @@ def test_seek_mode_2():
@pytest.mark.parametrize("bytesmode", (True, False))
def test_read_n0(bytesmode):
def test_read_n0(bytesmode) -> None:
# Arrange
with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
container = ContainerIO.ContainerIO(fh, 22, 100)
@ -80,7 +80,7 @@ def test_read_n0(bytesmode):
@pytest.mark.parametrize("bytesmode", (True, False))
def test_read_n(bytesmode):
def test_read_n(bytesmode) -> None:
# Arrange
with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
container = ContainerIO.ContainerIO(fh, 22, 100)
@ -96,7 +96,7 @@ def test_read_n(bytesmode):
@pytest.mark.parametrize("bytesmode", (True, False))
def test_read_eof(bytesmode):
def test_read_eof(bytesmode) -> None:
# Arrange
with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
container = ContainerIO.ContainerIO(fh, 22, 100)
@ -112,7 +112,7 @@ def test_read_eof(bytesmode):
@pytest.mark.parametrize("bytesmode", (True, False))
def test_readline(bytesmode):
def test_readline(bytesmode) -> None:
# Arrange
with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
container = ContainerIO.ContainerIO(fh, 0, 120)
@ -127,7 +127,7 @@ def test_readline(bytesmode):
@pytest.mark.parametrize("bytesmode", (True, False))
def test_readlines(bytesmode):
def test_readlines(bytesmode) -> None:
# Arrange
expected = [
"This is line 1\n",

View File

@ -12,7 +12,7 @@ from .helper import assert_image_equal, hopper, is_pypy
TEST_FILE = "Tests/images/hopper.dcx"
def test_sanity():
def test_sanity() -> None:
# Arrange
# Act
@ -25,8 +25,8 @@ def test_sanity():
@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
def test_unclosed_file():
def open():
def test_unclosed_file() -> None:
def open() -> None:
im = Image.open(TEST_FILE)
im.load()
@ -34,26 +34,26 @@ def test_unclosed_file():
open()
def test_closed_file():
def test_closed_file() -> None:
with warnings.catch_warnings():
im = Image.open(TEST_FILE)
im.load()
im.close()
def test_context_manager():
def test_context_manager() -> None:
with warnings.catch_warnings():
with Image.open(TEST_FILE) as im:
im.load()
def test_invalid_file():
def test_invalid_file() -> None:
with open("Tests/images/flower.jpg", "rb") as fp:
with pytest.raises(SyntaxError):
DcxImagePlugin.DcxImageFile(fp)
def test_tell():
def test_tell() -> None:
# Arrange
with Image.open(TEST_FILE) as im:
# Act
@ -63,13 +63,13 @@ def test_tell():
assert frame == 0
def test_n_frames():
def test_n_frames() -> None:
with Image.open(TEST_FILE) as im:
assert im.n_frames == 1
assert not im.is_animated
def test_eoferror():
def test_eoferror() -> None:
with Image.open(TEST_FILE) as im:
n_frames = im.n_frames
@ -82,7 +82,7 @@ def test_eoferror():
im.seek(n_frames - 1)
def test_seek_too_far():
def test_seek_too_far() -> None:
# Arrange
with Image.open(TEST_FILE) as im:
frame = 999 # too big on purpose

View File

@ -2,6 +2,7 @@
from __future__ import annotations
from io import BytesIO
from pathlib import Path
import pytest
@ -46,7 +47,7 @@ TEST_FILE_UNCOMPRESSED_RGB_WITH_ALPHA = "Tests/images/uncompressed_rgb.dds"
TEST_FILE_DX10_BC1_TYPELESS,
),
)
def test_sanity_dxt1_bc1(image_path):
def test_sanity_dxt1_bc1(image_path) -> None:
"""Check DXT1 and BC1 images can be opened"""
with Image.open(TEST_FILE_DXT1.replace(".dds", ".png")) as target:
target = target.convert("RGBA")
@ -60,7 +61,7 @@ def test_sanity_dxt1_bc1(image_path):
assert_image_equal(im, target)
def test_sanity_dxt3():
def test_sanity_dxt3() -> None:
"""Check DXT3 images can be opened"""
with Image.open(TEST_FILE_DXT3) as im:
@ -73,7 +74,7 @@ def test_sanity_dxt3():
assert_image_equal_tofile(im, TEST_FILE_DXT3.replace(".dds", ".png"))
def test_sanity_dxt5():
def test_sanity_dxt5() -> None:
"""Check DXT5 images can be opened"""
with Image.open(TEST_FILE_DXT5) as im:
@ -94,7 +95,7 @@ def test_sanity_dxt5():
TEST_FILE_BC4U,
),
)
def test_sanity_ati1_bc4u(image_path):
def test_sanity_ati1_bc4u(image_path) -> None:
"""Check ATI1 and BC4U images can be opened"""
with Image.open(image_path) as im:
@ -115,7 +116,7 @@ def test_sanity_ati1_bc4u(image_path):
TEST_FILE_DX10_BC4_TYPELESS,
),
)
def test_dx10_bc4(image_path):
def test_dx10_bc4(image_path) -> None:
"""Check DX10 BC4 images can be opened"""
with Image.open(image_path) as im:
@ -136,7 +137,7 @@ def test_dx10_bc4(image_path):
TEST_FILE_BC5U,
),
)
def test_sanity_ati2_bc5u(image_path):
def test_sanity_ati2_bc5u(image_path) -> None:
"""Check ATI2 and BC5U images can be opened"""
with Image.open(image_path) as im:
@ -160,7 +161,7 @@ def test_sanity_ati2_bc5u(image_path):
(TEST_FILE_BC5S, TEST_FILE_BC5S),
),
)
def test_dx10_bc5(image_path, expected_path):
def test_dx10_bc5(image_path, expected_path) -> None:
"""Check DX10 BC5 images can be opened"""
with Image.open(image_path) as im:
@ -174,7 +175,7 @@ def test_dx10_bc5(image_path, expected_path):
@pytest.mark.parametrize("image_path", (TEST_FILE_BC6H, TEST_FILE_BC6HS))
def test_dx10_bc6h(image_path):
def test_dx10_bc6h(image_path) -> None:
"""Check DX10 BC6H/BC6HS images can be opened"""
with Image.open(image_path) as im:
@ -187,7 +188,7 @@ def test_dx10_bc6h(image_path):
assert_image_equal_tofile(im, image_path.replace(".dds", ".png"))
def test_dx10_bc7():
def test_dx10_bc7() -> None:
"""Check DX10 images can be opened"""
with Image.open(TEST_FILE_DX10_BC7) as im:
@ -200,7 +201,7 @@ def test_dx10_bc7():
assert_image_equal_tofile(im, TEST_FILE_DX10_BC7.replace(".dds", ".png"))
def test_dx10_bc7_unorm_srgb():
def test_dx10_bc7_unorm_srgb() -> None:
"""Check DX10 unsigned normalized integer images can be opened"""
with Image.open(TEST_FILE_DX10_BC7_UNORM_SRGB) as im:
@ -216,7 +217,7 @@ def test_dx10_bc7_unorm_srgb():
)
def test_dx10_r8g8b8a8():
def test_dx10_r8g8b8a8() -> None:
"""Check DX10 images can be opened"""
with Image.open(TEST_FILE_DX10_R8G8B8A8) as im:
@ -229,7 +230,7 @@ def test_dx10_r8g8b8a8():
assert_image_equal_tofile(im, TEST_FILE_DX10_R8G8B8A8.replace(".dds", ".png"))
def test_dx10_r8g8b8a8_unorm_srgb():
def test_dx10_r8g8b8a8_unorm_srgb() -> None:
"""Check DX10 unsigned normalized integer images can be opened"""
with Image.open(TEST_FILE_DX10_R8G8B8A8_UNORM_SRGB) as im:
@ -255,7 +256,7 @@ def test_dx10_r8g8b8a8_unorm_srgb():
("RGBA", (800, 600), TEST_FILE_UNCOMPRESSED_RGB_WITH_ALPHA),
],
)
def test_uncompressed(mode, size, test_file):
def test_uncompressed(mode, size, test_file) -> None:
"""Check uncompressed images can be opened"""
with Image.open(test_file) as im:
@ -266,7 +267,7 @@ def test_uncompressed(mode, size, test_file):
assert_image_equal_tofile(im, test_file.replace(".dds", ".png"))
def test__accept_true():
def test__accept_true() -> None:
"""Check valid prefix"""
# Arrange
prefix = b"DDS etc"
@ -278,7 +279,7 @@ def test__accept_true():
assert output
def test__accept_false():
def test__accept_false() -> None:
"""Check invalid prefix"""
# Arrange
prefix = b"something invalid"
@ -290,19 +291,19 @@ def test__accept_false():
assert not output
def test_invalid_file():
def test_invalid_file() -> None:
invalid_file = "Tests/images/flower.jpg"
with pytest.raises(SyntaxError):
DdsImagePlugin.DdsImageFile(invalid_file)
def test_short_header():
def test_short_header() -> None:
"""Check a short header"""
with open(TEST_FILE_DXT5, "rb") as f:
img_file = f.read()
def short_header():
def short_header() -> None:
with Image.open(BytesIO(img_file[:119])):
pass # pragma: no cover
@ -310,13 +311,13 @@ def test_short_header():
short_header()
def test_short_file():
def test_short_file() -> None:
"""Check that the appropriate error is thrown for a short file"""
with open(TEST_FILE_DXT5, "rb") as f:
img_file = f.read()
def short_file():
def short_file() -> None:
with Image.open(BytesIO(img_file[:-100])) as im:
im.load()
@ -324,7 +325,7 @@ def test_short_file():
short_file()
def test_dxt5_colorblock_alpha_issue_4142():
def test_dxt5_colorblock_alpha_issue_4142() -> None:
"""Check that colorblocks are decoded correctly in DXT5"""
with Image.open("Tests/images/dxt5-colorblock-alpha-issue-4142.dds") as im:
@ -339,12 +340,12 @@ def test_dxt5_colorblock_alpha_issue_4142():
assert px[2] != 0
def test_palette():
def test_palette() -> None:
with Image.open("Tests/images/palette.dds") as im:
assert_image_equal_tofile(im, "Tests/images/transparent.gif")
def test_unsupported_bitcount():
def test_unsupported_bitcount() -> None:
with pytest.raises(OSError):
with Image.open("Tests/images/unsupported_bitcount.dds"):
pass
@ -357,13 +358,13 @@ def test_unsupported_bitcount():
"Tests/images/unimplemented_pfflags.dds",
),
)
def test_not_implemented(test_file):
def test_not_implemented(test_file) -> None:
with pytest.raises(NotImplementedError):
with Image.open(test_file):
pass
def test_save_unsupported_mode(tmp_path):
def test_save_unsupported_mode(tmp_path: Path) -> None:
out = str(tmp_path / "temp.dds")
im = hopper("HSV")
with pytest.raises(OSError):
@ -379,7 +380,7 @@ def test_save_unsupported_mode(tmp_path):
("RGBA", "Tests/images/pil123rgba.png"),
],
)
def test_save(mode, test_file, tmp_path):
def test_save(mode, test_file, tmp_path: Path) -> None:
out = str(tmp_path / "temp.dds")
with Image.open(test_file) as im:
assert im.mode == mode

View File

@ -1,6 +1,7 @@
from __future__ import annotations
import io
from pathlib import Path
import pytest
@ -83,7 +84,7 @@ simple_eps_file_with_long_binary_data = (
("filename", "size"), ((FILE1, (460, 352)), (FILE2, (360, 252)))
)
@pytest.mark.parametrize("scale", (1, 2))
def test_sanity(filename, size, scale):
def test_sanity(filename, size, scale) -> None:
expected_size = tuple(s * scale for s in size)
with Image.open(filename) as image:
image.load(scale=scale)
@ -93,7 +94,7 @@ def test_sanity(filename, size, scale):
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
def test_load():
def test_load() -> None:
with Image.open(FILE1) as im:
assert im.load()[0, 0] == (255, 255, 255)
@ -101,7 +102,7 @@ def test_load():
assert im.load()[0, 0] == (255, 255, 255)
def test_binary():
def test_binary() -> None:
if HAS_GHOSTSCRIPT:
assert EpsImagePlugin.gs_binary is not None
else:
@ -115,41 +116,41 @@ def test_binary():
assert EpsImagePlugin.gs_windows_binary is not None
def test_invalid_file():
def test_invalid_file() -> None:
invalid_file = "Tests/images/flower.jpg"
with pytest.raises(SyntaxError):
EpsImagePlugin.EpsImageFile(invalid_file)
def test_binary_header_only():
def test_binary_header_only() -> None:
data = io.BytesIO(simple_binary_header)
with pytest.raises(SyntaxError, match='EPS header missing "%!PS-Adobe" comment'):
EpsImagePlugin.EpsImageFile(data)
@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
def test_missing_version_comment(prefix):
def test_missing_version_comment(prefix) -> None:
data = io.BytesIO(prefix + b"\n".join(simple_eps_file_without_version))
with pytest.raises(SyntaxError):
EpsImagePlugin.EpsImageFile(data)
@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
def test_missing_boundingbox_comment(prefix):
def test_missing_boundingbox_comment(prefix) -> None:
data = io.BytesIO(prefix + b"\n".join(simple_eps_file_without_boundingbox))
with pytest.raises(SyntaxError, match='EPS header missing "%%BoundingBox" comment'):
EpsImagePlugin.EpsImageFile(data)
@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
def test_invalid_boundingbox_comment(prefix):
def test_invalid_boundingbox_comment(prefix) -> None:
data = io.BytesIO(prefix + b"\n".join(simple_eps_file_with_invalid_boundingbox))
with pytest.raises(OSError, match="cannot determine EPS bounding box"):
EpsImagePlugin.EpsImageFile(data)
@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
def test_invalid_boundingbox_comment_valid_imagedata_comment(prefix):
def test_invalid_boundingbox_comment_valid_imagedata_comment(prefix) -> None:
data = io.BytesIO(
prefix + b"\n".join(simple_eps_file_with_invalid_boundingbox_valid_imagedata)
)
@ -160,21 +161,21 @@ def test_invalid_boundingbox_comment_valid_imagedata_comment(prefix):
@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
def test_ascii_comment_too_long(prefix):
def test_ascii_comment_too_long(prefix) -> None:
data = io.BytesIO(prefix + b"\n".join(simple_eps_file_with_long_ascii_comment))
with pytest.raises(SyntaxError, match="not an EPS file"):
EpsImagePlugin.EpsImageFile(data)
@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
def test_long_binary_data(prefix):
def test_long_binary_data(prefix) -> None:
data = io.BytesIO(prefix + b"\n".join(simple_eps_file_with_long_binary_data))
EpsImagePlugin.EpsImageFile(data)
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
def test_load_long_binary_data(prefix):
def test_load_long_binary_data(prefix) -> None:
data = io.BytesIO(prefix + b"\n".join(simple_eps_file_with_long_binary_data))
with Image.open(data) as img:
img.load()
@ -187,7 +188,7 @@ def test_load_long_binary_data(prefix):
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
)
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
def test_cmyk():
def test_cmyk() -> None:
with Image.open("Tests/images/pil_sample_cmyk.eps") as cmyk_image:
assert cmyk_image.mode == "CMYK"
assert cmyk_image.size == (100, 100)
@ -203,7 +204,7 @@ def test_cmyk():
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
def test_showpage():
def test_showpage() -> None:
# 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:
@ -214,7 +215,7 @@ def test_showpage():
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
def test_transparency():
def test_transparency() -> None:
with Image.open("Tests/images/reqd_showpage.eps") as plot_image:
plot_image.load(transparency=True)
assert plot_image.mode == "RGBA"
@ -225,7 +226,7 @@ def test_transparency():
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
def test_file_object(tmp_path):
def test_file_object(tmp_path: Path) -> None:
# issue 479
with Image.open(FILE1) as image1:
with open(str(tmp_path / "temp.eps"), "wb") as fh:
@ -233,7 +234,7 @@ def test_file_object(tmp_path):
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
def test_bytesio_object():
def test_bytesio_object() -> None:
with open(FILE1, "rb") as f:
img_bytes = io.BytesIO(f.read())
@ -246,12 +247,12 @@ def test_bytesio_object():
assert_image_similar(img, image1_scale1_compare, 5)
def test_1_mode():
def test_1_mode() -> None:
with Image.open("Tests/images/1.eps") as im:
assert im.mode == "1"
def test_image_mode_not_supported(tmp_path):
def test_image_mode_not_supported(tmp_path: Path) -> None:
im = hopper("RGBA")
tmpfile = str(tmp_path / "temp.eps")
with pytest.raises(ValueError):
@ -260,7 +261,7 @@ def test_image_mode_not_supported(tmp_path):
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
@skip_unless_feature("zlib")
def test_render_scale1():
def test_render_scale1() -> None:
# We need png support for these render test
# Zero bounding box
@ -282,7 +283,7 @@ def test_render_scale1():
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
@skip_unless_feature("zlib")
def test_render_scale2():
def test_render_scale2() -> None:
# We need png support for these render test
# Zero bounding box
@ -304,7 +305,7 @@ def test_render_scale2():
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
@pytest.mark.parametrize("filename", (FILE1, FILE2, "Tests/images/illu10_preview.eps"))
def test_resize(filename):
def test_resize(filename) -> None:
with Image.open(filename) as im:
new_size = (100, 100)
im = im.resize(new_size)
@ -313,7 +314,7 @@ def test_resize(filename):
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
@pytest.mark.parametrize("filename", (FILE1, FILE2))
def test_thumbnail(filename):
def test_thumbnail(filename) -> None:
# Issue #619
with Image.open(filename) as im:
new_size = (100, 100)
@ -321,20 +322,20 @@ def test_thumbnail(filename):
assert max(im.size) == max(new_size)
def test_read_binary_preview():
def test_read_binary_preview() -> None:
# Issue 302
# open image with binary preview
with Image.open(FILE3):
pass
def test_readline_psfile(tmp_path):
def test_readline_psfile(tmp_path: Path) -> None:
# 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):
def _test_readline(t, ending) -> None:
ending = "Failure with line ending: %s" % (
"".join("%s" % ord(s) for s in ending)
)
@ -343,13 +344,13 @@ def test_readline_psfile(tmp_path):
assert t.readline().strip("\r\n") == "baz", ending
assert t.readline().strip("\r\n") == "bif", ending
def _test_readline_io_psfile(test_string, ending):
def _test_readline_io_psfile(test_string, ending) -> None:
f = io.BytesIO(test_string.encode("latin-1"))
with pytest.warns(DeprecationWarning):
t = EpsImagePlugin.PSFile(f)
_test_readline(t, ending)
def _test_readline_file_psfile(test_string, ending):
def _test_readline_file_psfile(test_string, ending) -> None:
f = str(tmp_path / "temp.txt")
with open(f, "wb") as w:
w.write(test_string.encode("latin-1"))
@ -365,7 +366,7 @@ def test_readline_psfile(tmp_path):
_test_readline_file_psfile(s, ending)
def test_psfile_deprecation():
def test_psfile_deprecation() -> None:
with pytest.warns(DeprecationWarning):
EpsImagePlugin.PSFile(None)
@ -375,7 +376,7 @@ def test_psfile_deprecation():
"line_ending",
(b"\r\n", b"\n", b"\n\r", b"\r"),
)
def test_readline(prefix, line_ending):
def test_readline(prefix, line_ending) -> None:
simple_file = prefix + line_ending.join(simple_eps_file_with_comments)
data = io.BytesIO(simple_file)
test_file = EpsImagePlugin.EpsImageFile(data)
@ -393,14 +394,14 @@ def test_readline(prefix, line_ending):
"Tests/images/illuCS6_preview.eps",
),
)
def test_open_eps(filename):
def test_open_eps(filename) -> None:
# https://github.com/python-pillow/Pillow/issues/1104
with Image.open(filename) as img:
assert img.mode == "RGB"
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
def test_emptyline():
def test_emptyline() -> None:
# Test file includes an empty line in the header data
emptyline_file = "Tests/images/zero_bb_emptyline.eps"
@ -416,14 +417,14 @@ def test_emptyline():
"test_file",
["Tests/images/timeout-d675703545fee17acab56e5fec644c19979175de.eps"],
)
def test_timeout(test_file):
def test_timeout(test_file) -> None:
with open(test_file, "rb") as f:
with pytest.raises(Image.UnidentifiedImageError):
with Image.open(f):
pass
def test_bounding_box_in_trailer():
def test_bounding_box_in_trailer() -> None:
# Check bounding boxes are parsed in the same way
# when specified in the header and the trailer
with Image.open("Tests/images/zero_bb_trailer.eps") as trailer_image, Image.open(
@ -432,7 +433,7 @@ def test_bounding_box_in_trailer():
assert trailer_image.size == header_image.size
def test_eof_before_bounding_box():
def test_eof_before_bounding_box() -> None:
with pytest.raises(OSError):
with Image.open("Tests/images/zero_bb_eof_before_boundingbox.eps"):
pass

View File

@ -11,7 +11,7 @@ from .helper import assert_image_equal, hopper
TEST_FILE = "Tests/images/hopper.fits"
def test_open():
def test_open() -> None:
# Act
with Image.open(TEST_FILE) as im:
# Assert
@ -22,7 +22,7 @@ def test_open():
assert_image_equal(im, hopper("L"))
def test_invalid_file():
def test_invalid_file() -> None:
# Arrange
invalid_file = "Tests/images/flower.jpg"
@ -31,14 +31,14 @@ def test_invalid_file():
FitsImagePlugin.FitsImageFile(invalid_file)
def test_truncated_fits():
def test_truncated_fits() -> None:
# No END to headers
image_data = b"SIMPLE = T" + b" " * 50 + b"TRUNCATE"
with pytest.raises(OSError):
FitsImagePlugin.FitsImageFile(BytesIO(image_data))
def test_naxis_zero():
def test_naxis_zero() -> None:
# This test image has been manually hexedited
# to set the number of data axes to zero
with pytest.raises(ValueError):
@ -46,7 +46,7 @@ def test_naxis_zero():
pass
def test_comment():
def test_comment() -> None:
image_data = b"SIMPLE = T / comment string"
with pytest.raises(OSError):
FitsImagePlugin.FitsImageFile(BytesIO(image_data))

View File

@ -16,7 +16,7 @@ static_test_file = "Tests/images/hopper.fli"
animated_test_file = "Tests/images/a.fli"
def test_sanity():
def test_sanity() -> None:
with Image.open(static_test_file) as im:
im.load()
assert im.mode == "P"
@ -33,8 +33,8 @@ def test_sanity():
@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
def test_unclosed_file():
def open():
def test_unclosed_file() -> None:
def open() -> None:
im = Image.open(static_test_file)
im.load()
@ -42,14 +42,14 @@ def test_unclosed_file():
open()
def test_closed_file():
def test_closed_file() -> None:
with warnings.catch_warnings():
im = Image.open(static_test_file)
im.load()
im.close()
def test_seek_after_close():
def test_seek_after_close() -> None:
im = Image.open(animated_test_file)
im.seek(1)
im.close()
@ -58,13 +58,13 @@ def test_seek_after_close():
im.seek(0)
def test_context_manager():
def test_context_manager() -> None:
with warnings.catch_warnings():
with Image.open(static_test_file) as im:
im.load()
def test_tell():
def test_tell() -> None:
# Arrange
with Image.open(static_test_file) as im:
# Act
@ -74,20 +74,20 @@ def test_tell():
assert frame == 0
def test_invalid_file():
def test_invalid_file() -> None:
invalid_file = "Tests/images/flower.jpg"
with pytest.raises(SyntaxError):
FliImagePlugin.FliImageFile(invalid_file)
def test_palette_chunk_second():
def test_palette_chunk_second() -> None:
with Image.open("Tests/images/hopper_palette_chunk_second.fli") as im:
with Image.open(static_test_file) as expected:
assert_image_equal(im.convert("RGB"), expected.convert("RGB"))
def test_n_frames():
def test_n_frames() -> None:
with Image.open(static_test_file) as im:
assert im.n_frames == 1
assert not im.is_animated
@ -97,7 +97,7 @@ def test_n_frames():
assert im.is_animated
def test_eoferror():
def test_eoferror() -> None:
with Image.open(animated_test_file) as im:
n_frames = im.n_frames
@ -110,7 +110,7 @@ def test_eoferror():
im.seek(n_frames - 1)
def test_seek_tell():
def test_seek_tell() -> None:
with Image.open(animated_test_file) as im:
layer_number = im.tell()
assert layer_number == 0
@ -132,7 +132,7 @@ def test_seek_tell():
assert layer_number == 1
def test_seek():
def test_seek() -> None:
with Image.open(animated_test_file) as im:
im.seek(50)
@ -147,7 +147,7 @@ def test_seek():
],
)
@pytest.mark.timeout(timeout=3)
def test_timeouts(test_file):
def test_timeouts(test_file) -> None:
with open(test_file, "rb") as f:
with Image.open(f) as im:
with pytest.raises(OSError):
@ -160,7 +160,7 @@ def test_timeouts(test_file):
"Tests/images/crash-5762152299364352.fli",
],
)
def test_crash(test_file):
def test_crash(test_file) -> None:
with open(test_file, "rb") as f:
with Image.open(f) as im:
with pytest.raises(OSError):

View File

@ -11,7 +11,7 @@ FpxImagePlugin = pytest.importorskip(
)
def test_sanity():
def test_sanity() -> None:
with Image.open("Tests/images/input_bw_one_band.fpx") as im:
assert im.mode == "L"
assert im.size == (70, 46)
@ -20,7 +20,7 @@ def test_sanity():
assert_image_equal_tofile(im, "Tests/images/input_bw_one_band.png")
def test_close():
def test_close() -> None:
with Image.open("Tests/images/input_bw_one_band.fpx") as im:
pass
assert im.ole.fp.closed
@ -30,7 +30,7 @@ def test_close():
assert im.ole.fp.closed
def test_invalid_file():
def test_invalid_file() -> None:
# Test an invalid OLE file
invalid_file = "Tests/images/flower.jpg"
with pytest.raises(SyntaxError):
@ -42,7 +42,7 @@ def test_invalid_file():
FpxImagePlugin.FpxImageFile(ole_file)
def test_fpx_invalid_number_of_bands():
def test_fpx_invalid_number_of_bands() -> None:
with pytest.raises(OSError, match="Invalid number of bands"):
with Image.open("Tests/images/input_bw_five_bands.fpx"):
pass

View File

@ -2,6 +2,7 @@ from __future__ import annotations
import warnings
from io import BytesIO
from pathlib import Path
import pytest
@ -23,7 +24,7 @@ with open(TEST_GIF, "rb") as f:
data = f.read()
def test_sanity():
def test_sanity() -> None:
with Image.open(TEST_GIF) as im:
im.load()
assert im.mode == "P"
@ -33,8 +34,8 @@ def test_sanity():
@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
def test_unclosed_file():
def open():
def test_unclosed_file() -> None:
def open() -> None:
im = Image.open(TEST_GIF)
im.load()
@ -42,14 +43,14 @@ def test_unclosed_file():
open()
def test_closed_file():
def test_closed_file() -> None:
with warnings.catch_warnings():
im = Image.open(TEST_GIF)
im.load()
im.close()
def test_seek_after_close():
def test_seek_after_close() -> None:
im = Image.open("Tests/images/iss634.gif")
im.load()
im.close()
@ -62,20 +63,20 @@ def test_seek_after_close():
im.seek(1)
def test_context_manager():
def test_context_manager() -> None:
with warnings.catch_warnings():
with Image.open(TEST_GIF) as im:
im.load()
def test_invalid_file():
def test_invalid_file() -> None:
invalid_file = "Tests/images/flower.jpg"
with pytest.raises(SyntaxError):
GifImagePlugin.GifImageFile(invalid_file)
def test_l_mode_transparency():
def test_l_mode_transparency() -> None:
with Image.open("Tests/images/no_palette_with_transparency.gif") as im:
assert im.mode == "L"
assert im.load()[0, 0] == 128
@ -86,7 +87,7 @@ def test_l_mode_transparency():
assert im.load()[0, 0] == 128
def test_l_mode_after_rgb():
def test_l_mode_after_rgb() -> None:
with Image.open("Tests/images/no_palette_after_rgb.gif") as im:
im.seek(1)
assert im.mode == "RGB"
@ -95,13 +96,13 @@ def test_l_mode_after_rgb():
assert im.mode == "RGB"
def test_palette_not_needed_for_second_frame():
def test_palette_not_needed_for_second_frame() -> None:
with Image.open("Tests/images/palette_not_needed_for_second_frame.gif") as im:
im.seek(1)
assert_image_similar(im, hopper("L").convert("RGB"), 8)
def test_strategy():
def test_strategy() -> None:
with Image.open("Tests/images/iss634.gif") as im:
expected_rgb_always = im.convert("RGB")
@ -142,7 +143,7 @@ def test_strategy():
GifImagePlugin.LOADING_STRATEGY = GifImagePlugin.LoadingStrategy.RGB_AFTER_FIRST
def test_optimize():
def test_optimize() -> None:
def test_grayscale(optimize):
im = Image.new("L", (1, 1), 0)
filename = BytesIO()
@ -177,7 +178,7 @@ def test_optimize():
(4, 513, 256),
),
)
def test_optimize_correctness(colors, size, expected_palette_length):
def test_optimize_correctness(colors, size, expected_palette_length) -> None:
# 256 color Palette image, posterize to > 128 and < 128 levels.
# Size bigger and smaller than 512x512.
# Check the palette for number of colors allocated.
@ -199,14 +200,14 @@ def test_optimize_correctness(colors, size, expected_palette_length):
assert_image_equal(im.convert("RGB"), reloaded.convert("RGB"))
def test_optimize_full_l():
def test_optimize_full_l() -> None:
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_optimize_if_palette_can_be_reduced_by_half():
def test_optimize_if_palette_can_be_reduced_by_half() -> None:
im = Image.new("P", (8, 1))
im.palette = ImagePalette.raw("RGB", bytes((0, 0, 0) * 150))
for i in range(8):
@ -219,7 +220,7 @@ def test_optimize_if_palette_can_be_reduced_by_half():
assert len(reloaded.palette.palette) // 3 == colors
def test_full_palette_second_frame(tmp_path):
def test_full_palette_second_frame(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
im = Image.new("P", (1, 256))
@ -240,7 +241,7 @@ def test_full_palette_second_frame(tmp_path):
reloaded.getpixel((0, i)) == i
def test_roundtrip(tmp_path):
def test_roundtrip(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
im = hopper()
im.save(out)
@ -248,7 +249,7 @@ def test_roundtrip(tmp_path):
assert_image_similar(reread.convert("RGB"), im, 50)
def test_roundtrip2(tmp_path):
def test_roundtrip2(tmp_path: Path) -> None:
# see https://github.com/python-pillow/Pillow/issues/403
out = str(tmp_path / "temp.gif")
with Image.open(TEST_GIF) as im:
@ -258,7 +259,7 @@ def test_roundtrip2(tmp_path):
assert_image_similar(reread.convert("RGB"), hopper(), 50)
def test_roundtrip_save_all(tmp_path):
def test_roundtrip_save_all(tmp_path: Path) -> None:
# Single frame image
out = str(tmp_path / "temp.gif")
im = hopper()
@ -275,7 +276,7 @@ def test_roundtrip_save_all(tmp_path):
assert reread.n_frames == 5
def test_roundtrip_save_all_1(tmp_path):
def test_roundtrip_save_all_1(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
im = Image.new("1", (1, 1))
im2 = Image.new("1", (1, 1), 1)
@ -296,7 +297,7 @@ def test_roundtrip_save_all_1(tmp_path):
("Tests/images/dispose_bgnd_rgba.gif", "RGBA"),
),
)
def test_loading_multiple_palettes(path, mode):
def test_loading_multiple_palettes(path, mode) -> None:
with Image.open(path) as im:
assert im.mode == "P"
first_frame_colors = im.palette.colors.keys()
@ -314,7 +315,7 @@ def test_loading_multiple_palettes(path, mode):
assert im.load()[24, 24] not in first_frame_colors
def test_headers_saving_for_animated_gifs(tmp_path):
def test_headers_saving_for_animated_gifs(tmp_path: Path) -> None:
important_headers = ["background", "version", "duration", "loop"]
# Multiframe image
with Image.open("Tests/images/dispose_bgnd.gif") as im:
@ -327,7 +328,7 @@ def test_headers_saving_for_animated_gifs(tmp_path):
assert info[header] == reread.info[header]
def test_palette_handling(tmp_path):
def test_palette_handling(tmp_path: Path) -> None:
# see https://github.com/python-pillow/Pillow/issues/513
with Image.open(TEST_GIF) as im:
@ -343,7 +344,7 @@ def test_palette_handling(tmp_path):
assert_image_similar(im, reloaded.convert("RGB"), 10)
def test_palette_434(tmp_path):
def test_palette_434(tmp_path: Path) -> None:
# see https://github.com/python-pillow/Pillow/issues/434
def roundtrip(im, *args, **kwargs):
@ -368,7 +369,7 @@ def test_palette_434(tmp_path):
@pytest.mark.skipif(not netpbm_available(), reason="Netpbm not available")
def test_save_netpbm_bmp_mode(tmp_path):
def test_save_netpbm_bmp_mode(tmp_path: Path) -> None:
with Image.open(TEST_GIF) as img:
img = img.convert("RGB")
@ -379,7 +380,7 @@ def test_save_netpbm_bmp_mode(tmp_path):
@pytest.mark.skipif(not netpbm_available(), reason="Netpbm not available")
def test_save_netpbm_l_mode(tmp_path):
def test_save_netpbm_l_mode(tmp_path: Path) -> None:
with Image.open(TEST_GIF) as img:
img = img.convert("L")
@ -389,7 +390,7 @@ def test_save_netpbm_l_mode(tmp_path):
assert_image_similar(img, reloaded.convert("L"), 0)
def test_seek():
def test_seek() -> None:
with Image.open("Tests/images/dispose_none.gif") as img:
frame_count = 0
try:
@ -400,7 +401,7 @@ def test_seek():
assert frame_count == 5
def test_seek_info():
def test_seek_info() -> None:
with Image.open("Tests/images/iss634.gif") as im:
info = im.info.copy()
@ -410,7 +411,7 @@ def test_seek_info():
assert im.info == info
def test_seek_rewind():
def test_seek_rewind() -> None:
with Image.open("Tests/images/iss634.gif") as im:
im.seek(2)
im.seek(1)
@ -428,7 +429,7 @@ def test_seek_rewind():
("Tests/images/iss634.gif", 42),
),
)
def test_n_frames(path, n_frames):
def test_n_frames(path, n_frames) -> None:
# Test is_animated before n_frames
with Image.open(path) as im:
assert im.is_animated == (n_frames != 1)
@ -439,7 +440,7 @@ def test_n_frames(path, n_frames):
assert im.is_animated == (n_frames != 1)
def test_no_change():
def test_no_change() -> None:
# Test n_frames does not change the image
with Image.open("Tests/images/dispose_bgnd.gif") as im:
im.seek(1)
@ -460,7 +461,7 @@ def test_no_change():
assert_image_equal(im, expected)
def test_eoferror():
def test_eoferror() -> None:
with Image.open(TEST_GIF) as im:
n_frames = im.n_frames
@ -473,13 +474,13 @@ def test_eoferror():
im.seek(n_frames - 1)
def test_first_frame_transparency():
def test_first_frame_transparency() -> None:
with Image.open("Tests/images/first_frame_transparency.gif") as im:
px = im.load()
assert px[0, 0] == im.info["transparency"]
def test_dispose_none():
def test_dispose_none() -> None:
with Image.open("Tests/images/dispose_none.gif") as img:
try:
while True:
@ -489,7 +490,7 @@ def test_dispose_none():
pass
def test_dispose_none_load_end():
def test_dispose_none_load_end() -> None:
# Test image created with:
#
# im = Image.open("transparent.gif")
@ -502,7 +503,7 @@ def test_dispose_none_load_end():
assert_image_equal_tofile(img, "Tests/images/dispose_none_load_end_second.png")
def test_dispose_background():
def test_dispose_background() -> None:
with Image.open("Tests/images/dispose_bgnd.gif") as img:
try:
while True:
@ -512,7 +513,7 @@ def test_dispose_background():
pass
def test_dispose_background_transparency():
def test_dispose_background_transparency() -> None:
with Image.open("Tests/images/dispose_bgnd_transparency.gif") as img:
img.seek(2)
px = img.load()
@ -540,7 +541,7 @@ def test_dispose_background_transparency():
),
),
)
def test_transparent_dispose(loading_strategy, expected_colors):
def test_transparent_dispose(loading_strategy, expected_colors) -> None:
GifImagePlugin.LOADING_STRATEGY = loading_strategy
try:
with Image.open("Tests/images/transparent_dispose.gif") as img:
@ -553,7 +554,7 @@ def test_transparent_dispose(loading_strategy, expected_colors):
GifImagePlugin.LOADING_STRATEGY = GifImagePlugin.LoadingStrategy.RGB_AFTER_FIRST
def test_dispose_previous():
def test_dispose_previous() -> None:
with Image.open("Tests/images/dispose_prev.gif") as img:
try:
while True:
@ -563,7 +564,7 @@ def test_dispose_previous():
pass
def test_dispose_previous_first_frame():
def test_dispose_previous_first_frame() -> None:
with Image.open("Tests/images/dispose_prev_first_frame.gif") as im:
im.seek(1)
assert_image_equal_tofile(
@ -571,7 +572,7 @@ def test_dispose_previous_first_frame():
)
def test_previous_frame_loaded():
def test_previous_frame_loaded() -> None:
with Image.open("Tests/images/dispose_none.gif") as img:
img.load()
img.seek(1)
@ -582,7 +583,7 @@ def test_previous_frame_loaded():
assert_image_equal(img_skipped, img)
def test_save_dispose(tmp_path):
def test_save_dispose(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
im_list = [
Image.new("L", (100, 100), "#000"),
@ -610,7 +611,7 @@ def test_save_dispose(tmp_path):
assert img.disposal_method == i + 1
def test_dispose2_palette(tmp_path):
def test_dispose2_palette(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
# Four colors: white, gray, black, red
@ -641,7 +642,7 @@ def test_dispose2_palette(tmp_path):
assert rgb_img.getpixel((50, 50)) == circle
def test_dispose2_diff(tmp_path):
def test_dispose2_diff(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
# 4 frames: red/blue, red/red, blue/blue, red/blue
@ -683,7 +684,7 @@ def test_dispose2_diff(tmp_path):
assert rgb_img.getpixel((1, 1)) == (255, 255, 255, 0)
def test_dispose2_background(tmp_path):
def test_dispose2_background(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
im_list = []
@ -709,7 +710,7 @@ def test_dispose2_background(tmp_path):
assert im.getpixel((0, 0)) == (255, 0, 0)
def test_dispose2_background_frame(tmp_path):
def test_dispose2_background_frame(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
im_list = [Image.new("RGBA", (1, 20))]
@ -727,7 +728,7 @@ def test_dispose2_background_frame(tmp_path):
assert im.n_frames == 3
def test_transparency_in_second_frame(tmp_path):
def test_transparency_in_second_frame(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
with Image.open("Tests/images/different_transparency.gif") as im:
assert im.info["transparency"] == 0
@ -747,7 +748,7 @@ def test_transparency_in_second_frame(tmp_path):
)
def test_no_transparency_in_second_frame():
def test_no_transparency_in_second_frame() -> None:
with Image.open("Tests/images/iss634.gif") as img:
# Seek to the second frame
img.seek(img.tell() + 1)
@ -757,7 +758,7 @@ def test_no_transparency_in_second_frame():
assert img.histogram()[255] == 0
def test_remapped_transparency(tmp_path):
def test_remapped_transparency(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
im = Image.new("P", (1, 2))
@ -773,7 +774,7 @@ def test_remapped_transparency(tmp_path):
assert reloaded.info["transparency"] == reloaded.getpixel((0, 1))
def test_duration(tmp_path):
def test_duration(tmp_path: Path) -> None:
duration = 1000
out = str(tmp_path / "temp.gif")
@ -787,7 +788,7 @@ def test_duration(tmp_path):
assert reread.info["duration"] == duration
def test_multiple_duration(tmp_path):
def test_multiple_duration(tmp_path: Path) -> None:
duration_list = [1000, 2000, 3000]
out = str(tmp_path / "temp.gif")
@ -822,7 +823,7 @@ def test_multiple_duration(tmp_path):
pass
def test_roundtrip_info_duration(tmp_path):
def test_roundtrip_info_duration(tmp_path: Path) -> None:
duration_list = [100, 500, 500]
out = str(tmp_path / "temp.gif")
@ -839,7 +840,7 @@ def test_roundtrip_info_duration(tmp_path):
] == duration_list
def test_roundtrip_info_duration_combined(tmp_path):
def test_roundtrip_info_duration_combined(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
with Image.open("Tests/images/duplicate_frame.gif") as im:
assert [frame.info["duration"] for frame in ImageSequence.Iterator(im)] == [
@ -855,7 +856,7 @@ def test_roundtrip_info_duration_combined(tmp_path):
] == [1000, 2000]
def test_identical_frames(tmp_path):
def test_identical_frames(tmp_path: Path) -> None:
duration_list = [1000, 1500, 2000, 4000]
out = str(tmp_path / "temp.gif")
@ -888,7 +889,7 @@ def test_identical_frames(tmp_path):
1500,
),
)
def test_identical_frames_to_single_frame(duration, tmp_path):
def test_identical_frames_to_single_frame(duration, tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
im_list = [
Image.new("L", (100, 100), "#000"),
@ -905,7 +906,7 @@ def test_identical_frames_to_single_frame(duration, tmp_path):
assert reread.info["duration"] == 4500
def test_loop_none(tmp_path):
def test_loop_none(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
im = Image.new("L", (100, 100), "#000")
im.save(out, loop=None)
@ -913,7 +914,7 @@ def test_loop_none(tmp_path):
assert "loop" not in reread.info
def test_number_of_loops(tmp_path):
def test_number_of_loops(tmp_path: Path) -> None:
number_of_loops = 2
out = str(tmp_path / "temp.gif")
@ -931,7 +932,7 @@ def test_number_of_loops(tmp_path):
assert im.info["loop"] == 2
def test_background(tmp_path):
def test_background(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
im = Image.new("L", (100, 100), "#000")
im.info["background"] = 1
@ -940,7 +941,7 @@ def test_background(tmp_path):
assert reread.info["background"] == im.info["background"]
def test_webp_background(tmp_path):
def test_webp_background(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
# Test opaque WebP background
@ -955,7 +956,7 @@ def test_webp_background(tmp_path):
im.save(out)
def test_comment(tmp_path):
def test_comment(tmp_path: Path) -> None:
with Image.open(TEST_GIF) as im:
assert im.info["comment"] == b"File written by Adobe Photoshop\xa8 4.0"
@ -975,7 +976,7 @@ def test_comment(tmp_path):
assert reread.info["version"] == b"GIF89a"
def test_comment_over_255(tmp_path):
def test_comment_over_255(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
im = Image.new("L", (100, 100), "#000")
comment = b"Test comment text"
@ -990,18 +991,18 @@ def test_comment_over_255(tmp_path):
assert reread.info["version"] == b"GIF89a"
def test_zero_comment_subblocks():
def test_zero_comment_subblocks() -> None:
with Image.open("Tests/images/hopper_zero_comment_subblocks.gif") as im:
assert_image_equal_tofile(im, TEST_GIF)
def test_read_multiple_comment_blocks():
def test_read_multiple_comment_blocks() -> None:
with Image.open("Tests/images/multiple_comments.gif") as im:
# Multiple comment blocks in a frame are separated not concatenated
assert im.info["comment"] == b"Test comment 1\nTest comment 2"
def test_empty_string_comment(tmp_path):
def test_empty_string_comment(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
with Image.open("Tests/images/chi.gif") as im:
assert "comment" in im.info
@ -1014,7 +1015,7 @@ def test_empty_string_comment(tmp_path):
assert "comment" not in frame.info
def test_retain_comment_in_subsequent_frames(tmp_path):
def test_retain_comment_in_subsequent_frames(tmp_path: Path) -> None:
# Test that a comment block at the beginning is kept
with Image.open("Tests/images/chi.gif") as im:
for frame in ImageSequence.Iterator(im):
@ -1045,10 +1046,10 @@ def test_retain_comment_in_subsequent_frames(tmp_path):
assert frame.info["comment"] == b"Test"
def test_version(tmp_path):
def test_version(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
def assert_version_after_save(im, version):
def assert_version_after_save(im, version) -> None:
im.save(out)
with Image.open(out) as reread:
assert reread.info["version"] == version
@ -1075,7 +1076,7 @@ def test_version(tmp_path):
assert_version_after_save(im, b"GIF87a")
def test_append_images(tmp_path):
def test_append_images(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
# Test appending single frame images
@ -1104,7 +1105,7 @@ def test_append_images(tmp_path):
assert reread.n_frames == 10
def test_transparent_optimize(tmp_path):
def test_transparent_optimize(tmp_path: Path) -> None:
# From issue #2195, if the transparent color is incorrectly optimized out, GIF loses
# transparency.
# Need a palette that isn't using the 0 color,
@ -1124,7 +1125,7 @@ def test_transparent_optimize(tmp_path):
assert reloaded.info["transparency"] == reloaded.getpixel((252, 0))
def test_removed_transparency(tmp_path):
def test_removed_transparency(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
im = Image.new("RGB", (256, 1))
@ -1139,7 +1140,7 @@ def test_removed_transparency(tmp_path):
assert "transparency" not in reloaded.info
def test_rgb_transparency(tmp_path):
def test_rgb_transparency(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
# Single frame
@ -1161,7 +1162,7 @@ def test_rgb_transparency(tmp_path):
assert "transparency" not in reloaded.info
def test_rgba_transparency(tmp_path):
def test_rgba_transparency(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
im = hopper("P")
@ -1172,13 +1173,13 @@ def test_rgba_transparency(tmp_path):
assert_image_equal(hopper("P").convert("RGB"), reloaded)
def test_background_outside_palettte(tmp_path):
def test_background_outside_palettte(tmp_path: Path) -> None:
with Image.open("Tests/images/background_outside_palette.gif") as im:
im.seek(1)
assert im.info["background"] == 255
def test_bbox(tmp_path):
def test_bbox(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
im = Image.new("RGB", (100, 100), "#fff")
@ -1189,7 +1190,7 @@ def test_bbox(tmp_path):
assert reread.n_frames == 2
def test_bbox_alpha(tmp_path):
def test_bbox_alpha(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
im = Image.new("RGBA", (1, 2), (255, 0, 0, 255))
@ -1201,7 +1202,7 @@ def test_bbox_alpha(tmp_path):
assert reread.n_frames == 2
def test_palette_save_L(tmp_path):
def test_palette_save_L(tmp_path: Path) -> None:
# Generate an L mode image with a separate palette
im = hopper("P")
@ -1215,7 +1216,7 @@ def test_palette_save_L(tmp_path):
assert_image_equal(reloaded.convert("RGB"), im.convert("RGB"))
def test_palette_save_P(tmp_path):
def test_palette_save_P(tmp_path: Path) -> None:
im = Image.new("P", (1, 2))
im.putpixel((0, 1), 1)
@ -1229,7 +1230,7 @@ def test_palette_save_P(tmp_path):
assert reloaded_rgb.getpixel((0, 1)) == (4, 5, 6)
def test_palette_save_duplicate_entries(tmp_path):
def test_palette_save_duplicate_entries(tmp_path: Path) -> None:
im = Image.new("P", (1, 2))
im.putpixel((0, 1), 1)
@ -1242,7 +1243,7 @@ def test_palette_save_duplicate_entries(tmp_path):
assert reloaded.convert("RGB").getpixel((0, 1)) == (0, 0, 0)
def test_palette_save_all_P(tmp_path):
def test_palette_save_all_P(tmp_path: Path) -> None:
frames = []
colors = ((255, 0, 0), (0, 255, 0))
for color in colors:
@ -1265,7 +1266,7 @@ def test_palette_save_all_P(tmp_path):
assert im.palette.palette == im.global_palette.palette
def test_palette_save_ImagePalette(tmp_path):
def test_palette_save_ImagePalette(tmp_path: Path) -> None:
# Pass in a different palette, as an ImagePalette.ImagePalette
# effectively the same as test_palette_save_P
@ -1280,7 +1281,7 @@ def test_palette_save_ImagePalette(tmp_path):
assert_image_equal(reloaded.convert("RGB"), im.convert("RGB"))
def test_save_I(tmp_path):
def test_save_I(tmp_path: Path) -> None:
# Test saving something that would trigger the auto-convert to 'L'
im = hopper("I")
@ -1292,7 +1293,7 @@ def test_save_I(tmp_path):
assert_image_equal(reloaded.convert("L"), im.convert("L"))
def test_getdata():
def test_getdata() -> None:
# Test getheader/getdata against legacy values.
# Create a 'P' image with holes in the palette.
im = Image._wedge().resize((16, 16), Image.Resampling.NEAREST)
@ -1320,7 +1321,7 @@ def test_getdata():
GifImagePlugin._FORCE_OPTIMIZE = False
def test_lzw_bits():
def test_lzw_bits() -> None:
# 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
@ -1328,7 +1329,7 @@ def test_lzw_bits():
im.load()
def test_extents():
def test_extents() -> None:
with Image.open("Tests/images/test_extents.gif") as im:
assert im.size == (100, 100)
@ -1340,7 +1341,7 @@ def test_extents():
assert im.size == (150, 150)
def test_missing_background():
def test_missing_background() -> None:
# The Global Color Table Flag isn't set, so there is no background color index,
# but the disposal method is "Restore to background color"
with Image.open("Tests/images/missing_background.gif") as im:
@ -1348,7 +1349,7 @@ def test_missing_background():
assert_image_equal_tofile(im, "Tests/images/missing_background_first_frame.png")
def test_saving_rgba(tmp_path):
def test_saving_rgba(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
with Image.open("Tests/images/transparent.png") as im:
im.save(out)

View File

@ -3,7 +3,7 @@ from __future__ import annotations
from PIL import GimpGradientFile, ImagePalette
def test_linear_pos_le_middle():
def test_linear_pos_le_middle() -> None:
# Arrange
middle = 0.5
pos = 0.25
@ -15,7 +15,7 @@ def test_linear_pos_le_middle():
assert ret == 0.25
def test_linear_pos_le_small_middle():
def test_linear_pos_le_small_middle() -> None:
# Arrange
middle = 1e-11
pos = 1e-12
@ -27,7 +27,7 @@ def test_linear_pos_le_small_middle():
assert ret == 0.0
def test_linear_pos_gt_middle():
def test_linear_pos_gt_middle() -> None:
# Arrange
middle = 0.5
pos = 0.75
@ -39,7 +39,7 @@ def test_linear_pos_gt_middle():
assert ret == 0.75
def test_linear_pos_gt_small_middle():
def test_linear_pos_gt_small_middle() -> None:
# Arrange
middle = 1 - 1e-11
pos = 1 - 1e-12
@ -51,7 +51,7 @@ def test_linear_pos_gt_small_middle():
assert ret == 1.0
def test_curved():
def test_curved() -> None:
# Arrange
middle = 0.5
pos = 0.75
@ -63,7 +63,7 @@ def test_curved():
assert ret == 0.75
def test_sine():
def test_sine() -> None:
# Arrange
middle = 0.5
pos = 0.75
@ -75,7 +75,7 @@ def test_sine():
assert ret == 0.8535533905932737
def test_sphere_increasing():
def test_sphere_increasing() -> None:
# Arrange
middle = 0.5
pos = 0.75
@ -87,7 +87,7 @@ def test_sphere_increasing():
assert round(abs(ret - 0.9682458365518543), 7) == 0
def test_sphere_decreasing():
def test_sphere_decreasing() -> None:
# Arrange
middle = 0.5
pos = 0.75
@ -99,7 +99,7 @@ def test_sphere_decreasing():
assert ret == 0.3385621722338523
def test_load_via_imagepalette():
def test_load_via_imagepalette() -> None:
# Arrange
test_file = "Tests/images/gimp_gradient.ggr"
@ -112,7 +112,7 @@ def test_load_via_imagepalette():
assert palette[1] == "RGBA"
def test_load_1_3_via_imagepalette():
def test_load_1_3_via_imagepalette() -> None:
# Arrange
# GIMP 1.3 gradient files contain a name field
test_file = "Tests/images/gimp_gradient_with_name.ggr"

View File

@ -1,5 +1,7 @@
from __future__ import annotations
from pathlib import Path
import pytest
from PIL import GribStubImagePlugin, Image
@ -9,7 +11,7 @@ from .helper import hopper
TEST_FILE = "Tests/images/WAlaska.wind.7days.grb"
def test_open():
def test_open() -> None:
# Act
with Image.open(TEST_FILE) as im:
# Assert
@ -20,7 +22,7 @@ def test_open():
assert im.size == (1, 1)
def test_invalid_file():
def test_invalid_file() -> None:
# Arrange
invalid_file = "Tests/images/flower.jpg"
@ -29,7 +31,7 @@ def test_invalid_file():
GribStubImagePlugin.GribStubImageFile(invalid_file)
def test_load():
def test_load() -> None:
# Arrange
with Image.open(TEST_FILE) as im:
# Act / Assert: stub cannot load without an implemented handler
@ -37,7 +39,7 @@ def test_load():
im.load()
def test_save(tmp_path):
def test_save(tmp_path: Path) -> None:
# Arrange
im = hopper()
tmpfile = str(tmp_path / "temp.grib")
@ -47,13 +49,13 @@ def test_save(tmp_path):
im.save(tmpfile)
def test_handler(tmp_path):
def test_handler(tmp_path: Path) -> None:
class TestHandler:
opened = False
loaded = False
saved = False
def open(self, im):
def open(self, im) -> None:
self.opened = True
def load(self, im):
@ -61,7 +63,7 @@ def test_handler(tmp_path):
im.fp.close()
return Image.new("RGB", (1, 1))
def save(self, im, fp, filename):
def save(self, im, fp, filename) -> None:
self.saved = True
handler = TestHandler()

View File

@ -1,5 +1,7 @@
from __future__ import annotations
from pathlib import Path
import pytest
from PIL import Hdf5StubImagePlugin, Image
@ -7,7 +9,7 @@ from PIL import Hdf5StubImagePlugin, Image
TEST_FILE = "Tests/images/hdf5.h5"
def test_open():
def test_open() -> None:
# Act
with Image.open(TEST_FILE) as im:
# Assert
@ -18,7 +20,7 @@ def test_open():
assert im.size == (1, 1)
def test_invalid_file():
def test_invalid_file() -> None:
# Arrange
invalid_file = "Tests/images/flower.jpg"
@ -27,7 +29,7 @@ def test_invalid_file():
Hdf5StubImagePlugin.HDF5StubImageFile(invalid_file)
def test_load():
def test_load() -> None:
# Arrange
with Image.open(TEST_FILE) as im:
# Act / Assert: stub cannot load without an implemented handler
@ -35,7 +37,7 @@ def test_load():
im.load()
def test_save():
def test_save() -> None:
# Arrange
with Image.open(TEST_FILE) as im:
dummy_fp = None
@ -48,13 +50,13 @@ def test_save():
Hdf5StubImagePlugin._save(im, dummy_fp, dummy_filename)
def test_handler(tmp_path):
def test_handler(tmp_path: Path) -> None:
class TestHandler:
opened = False
loaded = False
saved = False
def open(self, im):
def open(self, im) -> None:
self.opened = True
def load(self, im):
@ -62,7 +64,7 @@ def test_handler(tmp_path):
im.fp.close()
return Image.new("RGB", (1, 1))
def save(self, im, fp, filename):
def save(self, im, fp, filename) -> None:
self.saved = True
handler = TestHandler()

View File

@ -3,6 +3,7 @@ from __future__ import annotations
import io
import os
import warnings
from pathlib import Path
import pytest
@ -14,7 +15,7 @@ from .helper import assert_image_equal, assert_image_similar_tofile, skip_unless
TEST_FILE = "Tests/images/pillow.icns"
def test_sanity():
def test_sanity() -> None:
# Loading this icon by default should result in the largest size
# (512x512@2x) being loaded
with Image.open(TEST_FILE) as im:
@ -27,7 +28,7 @@ def test_sanity():
assert im.format == "ICNS"
def test_load():
def test_load() -> None:
with Image.open(TEST_FILE) as im:
assert im.load()[0, 0] == (0, 0, 0, 0)
@ -35,7 +36,7 @@ def test_load():
assert im.load()[0, 0] == (0, 0, 0, 0)
def test_save(tmp_path):
def test_save(tmp_path: Path) -> None:
temp_file = str(tmp_path / "temp.icns")
with Image.open(TEST_FILE) as im:
@ -52,7 +53,7 @@ def test_save(tmp_path):
assert _binary.i32be(fp.read(4)) == file_length
def test_save_append_images(tmp_path):
def test_save_append_images(tmp_path: Path) -> None:
temp_file = str(tmp_path / "temp.icns")
provided_im = Image.new("RGBA", (32, 32), (255, 0, 0, 128))
@ -67,7 +68,7 @@ def test_save_append_images(tmp_path):
assert_image_equal(reread, provided_im)
def test_save_fp():
def test_save_fp() -> None:
fp = io.BytesIO()
with Image.open(TEST_FILE) as im:
@ -79,7 +80,7 @@ def test_save_fp():
assert reread.format == "ICNS"
def test_sizes():
def test_sizes() -> None:
# 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:
@ -96,7 +97,7 @@ def test_sizes():
im.size = (1, 1)
def test_older_icon():
def test_older_icon() -> None:
# 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:
@ -111,7 +112,7 @@ def test_older_icon():
@skip_unless_feature("jpg_2000")
def test_jp2_icon():
def test_jp2_icon() -> None:
# This icon uses JPEG 2000 images instead of the PNG images.
# The advantage of doing this is that OS X 10.5 supports JPEG 2000
# but not PNG; some commercial software therefore does just this.
@ -127,7 +128,7 @@ def test_jp2_icon():
assert im2.size == (wr, hr)
def test_getimage():
def test_getimage() -> None:
with open(TEST_FILE, "rb") as fp:
icns_file = IcnsImagePlugin.IcnsFile(fp)
@ -140,14 +141,14 @@ def test_getimage():
assert im.size == (512, 512)
def test_not_an_icns_file():
def test_not_an_icns_file() -> None:
with io.BytesIO(b"invalid\n") as fp:
with pytest.raises(SyntaxError):
IcnsImagePlugin.IcnsFile(fp)
@skip_unless_feature("jpg_2000")
def test_icns_decompression_bomb():
def test_icns_decompression_bomb() -> None:
with Image.open(
"Tests/images/oom-8ed3316a4109213ca96fb8a256a0bfefdece1461.icns"
) as im:

View File

@ -2,6 +2,7 @@ from __future__ import annotations
import io
import os
from pathlib import Path
import pytest
@ -12,7 +13,7 @@ from .helper import assert_image_equal, assert_image_equal_tofile, hopper
TEST_ICO_FILE = "Tests/images/hopper.ico"
def test_sanity():
def test_sanity() -> None:
with Image.open(TEST_ICO_FILE) as im:
im.load()
assert im.mode == "RGBA"
@ -21,29 +22,29 @@ def test_sanity():
assert im.get_format_mimetype() == "image/x-icon"
def test_load():
def test_load() -> None:
with Image.open(TEST_ICO_FILE) as im:
assert im.load()[0, 0] == (1, 1, 9, 255)
def test_mask():
def test_mask() -> None:
with Image.open("Tests/images/hopper_mask.ico") as im:
assert_image_equal_tofile(im, "Tests/images/hopper_mask.png")
def test_black_and_white():
def test_black_and_white() -> None:
with Image.open("Tests/images/black_and_white.ico") as im:
assert im.mode == "RGBA"
assert im.size == (16, 16)
def test_invalid_file():
def test_invalid_file() -> None:
with open("Tests/images/flower.jpg", "rb") as fp:
with pytest.raises(SyntaxError):
IcoImagePlugin.IcoImageFile(fp)
def test_save_to_bytes():
def test_save_to_bytes() -> None:
output = io.BytesIO()
im = hopper()
im.save(output, "ico", sizes=[(32, 32), (64, 64)])
@ -73,7 +74,7 @@ def test_save_to_bytes():
)
def test_getpixel(tmp_path):
def test_getpixel(tmp_path: Path) -> None:
temp_file = str(tmp_path / "temp.ico")
im = hopper()
@ -86,7 +87,7 @@ def test_getpixel(tmp_path):
assert reloaded.getpixel((0, 0)) == (18, 20, 62)
def test_no_duplicates(tmp_path):
def test_no_duplicates(tmp_path: Path) -> None:
temp_file = str(tmp_path / "temp.ico")
temp_file2 = str(tmp_path / "temp2.ico")
@ -100,7 +101,7 @@ def test_no_duplicates(tmp_path):
assert os.path.getsize(temp_file) == os.path.getsize(temp_file2)
def test_different_bit_depths(tmp_path):
def test_different_bit_depths(tmp_path: Path) -> None:
temp_file = str(tmp_path / "temp.ico")
temp_file2 = str(tmp_path / "temp2.ico")
@ -134,7 +135,7 @@ def test_different_bit_depths(tmp_path):
@pytest.mark.parametrize("mode", ("1", "L", "P", "RGB", "RGBA"))
def test_save_to_bytes_bmp(mode):
def test_save_to_bytes_bmp(mode) -> None:
output = io.BytesIO()
im = hopper(mode)
im.save(output, "ico", bitmap_format="bmp", sizes=[(32, 32), (64, 64)])
@ -162,13 +163,13 @@ def test_save_to_bytes_bmp(mode):
assert_image_equal(reloaded, im)
def test_incorrect_size():
def test_incorrect_size() -> None:
with Image.open(TEST_ICO_FILE) as im:
with pytest.raises(ValueError):
im.size = (1, 1)
def test_save_256x256(tmp_path):
def test_save_256x256(tmp_path: Path) -> None:
"""Issue #2264 https://github.com/python-pillow/Pillow/issues/2264"""
# Arrange
with Image.open("Tests/images/hopper_256x256.ico") as im:
@ -181,7 +182,7 @@ def test_save_256x256(tmp_path):
assert im_saved.size == (256, 256)
def test_only_save_relevant_sizes(tmp_path):
def test_only_save_relevant_sizes(tmp_path: Path) -> None:
"""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
@ -197,7 +198,7 @@ def test_only_save_relevant_sizes(tmp_path):
assert im_saved.info["sizes"] == {(16, 16), (24, 24), (32, 32), (48, 48)}
def test_save_append_images(tmp_path):
def test_save_append_images(tmp_path: Path) -> None:
# append_images should be used for scaled down versions of the image
im = hopper("RGBA")
provided_im = Image.new("RGBA", (32, 32), (255, 0, 0))
@ -211,7 +212,7 @@ def test_save_append_images(tmp_path):
assert_image_equal(reread, provided_im)
def test_unexpected_size():
def test_unexpected_size() -> None:
# This image has been manually hexedited to state that it is 16x32
# while the image within is still 16x16
with pytest.warns(UserWarning):
@ -219,7 +220,7 @@ def test_unexpected_size():
assert im.size == (16, 16)
def test_draw_reloaded(tmp_path):
def test_draw_reloaded(tmp_path: Path) -> None:
with Image.open(TEST_ICO_FILE) as im:
outfile = str(tmp_path / "temp_saved_hopper_draw.ico")

View File

@ -2,6 +2,7 @@ from __future__ import annotations
import filecmp
import warnings
from pathlib import Path
import pytest
@ -13,7 +14,7 @@ from .helper import assert_image_equal_tofile, hopper, is_pypy
TEST_IM = "Tests/images/hopper.im"
def test_sanity():
def test_sanity() -> None:
with Image.open(TEST_IM) as im:
im.load()
assert im.mode == "RGB"
@ -21,7 +22,7 @@ def test_sanity():
assert im.format == "IM"
def test_name_limit(tmp_path):
def test_name_limit(tmp_path: Path) -> None:
out = str(tmp_path / ("name_limit_test" * 7 + ".im"))
with Image.open(TEST_IM) as im:
im.save(out)
@ -29,8 +30,8 @@ def test_name_limit(tmp_path):
@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
def test_unclosed_file():
def open():
def test_unclosed_file() -> None:
def open() -> None:
im = Image.open(TEST_IM)
im.load()
@ -38,20 +39,20 @@ def test_unclosed_file():
open()
def test_closed_file():
def test_closed_file() -> None:
with warnings.catch_warnings():
im = Image.open(TEST_IM)
im.load()
im.close()
def test_context_manager():
def test_context_manager() -> None:
with warnings.catch_warnings():
with Image.open(TEST_IM) as im:
im.load()
def test_tell():
def test_tell() -> None:
# Arrange
with Image.open(TEST_IM) as im:
# Act
@ -61,13 +62,13 @@ def test_tell():
assert frame == 0
def test_n_frames():
def test_n_frames() -> None:
with Image.open(TEST_IM) as im:
assert im.n_frames == 1
assert not im.is_animated
def test_eoferror():
def test_eoferror() -> None:
with Image.open(TEST_IM) as im:
n_frames = im.n_frames
@ -81,14 +82,14 @@ def test_eoferror():
@pytest.mark.parametrize("mode", ("RGB", "P", "PA"))
def test_roundtrip(mode, tmp_path):
def test_roundtrip(mode, tmp_path: Path) -> None:
out = str(tmp_path / "temp.im")
im = hopper(mode)
im.save(out)
assert_image_equal_tofile(im, out)
def test_small_palette(tmp_path):
def test_small_palette(tmp_path: Path) -> None:
im = Image.new("P", (1, 1))
colors = [0, 1, 2]
im.putpalette(colors)
@ -100,19 +101,19 @@ def test_small_palette(tmp_path):
assert reloaded.getpalette() == colors + [0] * 765
def test_save_unsupported_mode(tmp_path):
def test_save_unsupported_mode(tmp_path: Path) -> None:
out = str(tmp_path / "temp.im")
im = hopper("HSV")
with pytest.raises(ValueError):
im.save(out)
def test_invalid_file():
def test_invalid_file() -> None:
invalid_file = "Tests/images/flower.jpg"
with pytest.raises(SyntaxError):
ImImagePlugin.ImImageFile(invalid_file)
def test_number():
def test_number() -> None:
assert ImImagePlugin.number("1.2") == 1.2

View File

@ -12,7 +12,7 @@ from .helper import assert_image_equal, hopper
TEST_FILE = "Tests/images/iptc.jpg"
def test_open():
def test_open() -> None:
expected = Image.new("L", (1, 1))
f = BytesIO(
@ -24,7 +24,7 @@ def test_open():
assert_image_equal(im, expected)
def test_getiptcinfo_jpg_none():
def test_getiptcinfo_jpg_none() -> None:
# Arrange
with hopper() as im:
# Act
@ -34,7 +34,7 @@ def test_getiptcinfo_jpg_none():
assert iptc is None
def test_getiptcinfo_jpg_found():
def test_getiptcinfo_jpg_found() -> None:
# Arrange
with Image.open(TEST_FILE) as im:
# Act
@ -46,7 +46,7 @@ def test_getiptcinfo_jpg_found():
assert iptc[(2, 101)] == b"Hungary"
def test_getiptcinfo_fotostation():
def test_getiptcinfo_fotostation() -> None:
# Arrange
with open(TEST_FILE, "rb") as fp:
data = bytearray(fp.read())
@ -63,7 +63,7 @@ def test_getiptcinfo_fotostation():
pytest.fail("FotoStation tag not found")
def test_getiptcinfo_zero_padding():
def test_getiptcinfo_zero_padding() -> None:
# Arrange
with Image.open(TEST_FILE) as im:
im.info["photoshop"][0x0404] += b"\x00\x00\x00"
@ -76,7 +76,7 @@ def test_getiptcinfo_zero_padding():
assert len(iptc) == 3
def test_getiptcinfo_tiff_none():
def test_getiptcinfo_tiff_none() -> None:
# Arrange
with Image.open("Tests/images/hopper.tif") as im:
# Act
@ -86,7 +86,7 @@ def test_getiptcinfo_tiff_none():
assert iptc is None
def test_i():
def test_i() -> None:
# Arrange
c = b"a"
@ -98,7 +98,7 @@ def test_i():
assert ret == 97
def test_dump(monkeypatch):
def test_dump(monkeypatch) -> None:
# Arrange
c = b"abc"
# Temporarily redirect stdout
@ -113,6 +113,6 @@ def test_dump(monkeypatch):
assert mystdout.getvalue() == "61 62 63 \n"
def test_pad_deprecation():
def test_pad_deprecation() -> None:
with pytest.warns(DeprecationWarning):
assert IptcImagePlugin.PAD == b"\0\0\0\0"

View File

@ -4,6 +4,7 @@ import os
import re
import warnings
from io import BytesIO
from pathlib import Path
import pytest
@ -50,7 +51,7 @@ class TestFileJpeg:
im.bytes = test_bytes # for testing only
return im
def gen_random_image(self, size, mode="RGB"):
def gen_random_image(self, size, mode: str = "RGB"):
"""Generates a very hard to compress file
:param size: tuple
:param mode: optional image mode
@ -58,7 +59,7 @@ class TestFileJpeg:
"""
return Image.frombytes(mode, size, os.urandom(size[0] * size[1] * len(mode)))
def test_sanity(self):
def test_sanity(self) -> None:
# internal version number
assert re.search(r"\d+\.\d+$", features.version_codec("jpg"))
@ -70,13 +71,13 @@ class TestFileJpeg:
assert im.get_format_mimetype() == "image/jpeg"
@pytest.mark.parametrize("size", ((1, 0), (0, 1), (0, 0)))
def test_zero(self, size, tmp_path):
def test_zero(self, size, tmp_path: Path) -> None:
f = str(tmp_path / "temp.jpg")
im = Image.new("RGB", size)
with pytest.raises(ValueError):
im.save(f)
def test_app(self):
def test_app(self) -> None:
# Test APP/COM reader (@PIL135)
with Image.open(TEST_FILE) as im:
assert im.applist[0] == ("APP0", b"JFIF\x00\x01\x01\x01\x00`\x00`\x00\x00")
@ -89,7 +90,7 @@ class TestFileJpeg:
assert im.info["comment"] == b"File written by Adobe Photoshop\xa8 4.0\x00"
assert im.app["COM"] == im.info["comment"]
def test_comment_write(self):
def test_comment_write(self) -> None:
with Image.open(TEST_FILE) as im:
assert im.info["comment"] == b"File written by Adobe Photoshop\xa8 4.0\x00"
@ -115,7 +116,7 @@ class TestFileJpeg:
comment = comment.encode()
assert reloaded.info["comment"] == comment
def test_cmyk(self):
def test_cmyk(self) -> None:
# Test CMYK handling. Thanks to Tim and Charlie for test data,
# Michael for getting me to look one more time.
f = "Tests/images/pil_sample_cmyk.jpg"
@ -143,7 +144,7 @@ class TestFileJpeg:
)
assert k > 0.9
def test_rgb(self):
def test_rgb(self) -> None:
def getchannels(im):
return tuple(v[0] for v in im.layer)
@ -160,7 +161,7 @@ class TestFileJpeg:
"test_image_path",
[TEST_FILE, "Tests/images/pil_sample_cmyk.jpg"],
)
def test_dpi(self, test_image_path):
def test_dpi(self, test_image_path) -> None:
def test(xdpi, ydpi=None):
with Image.open(test_image_path) as im:
im = self.roundtrip(im, dpi=(xdpi, ydpi or xdpi))
@ -174,7 +175,7 @@ class TestFileJpeg:
@mark_if_feature_version(
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
)
def test_icc(self, tmp_path):
def test_icc(self, tmp_path: Path) -> None:
# Test ICC support
with Image.open("Tests/images/rgb.jpg") as im1:
icc_profile = im1.info["icc_profile"]
@ -206,7 +207,7 @@ class TestFileJpeg:
ImageFile.MAXBLOCK * 4 + 3, # large block
),
)
def test_icc_big(self, n):
def test_icc_big(self, n) -> None:
# Make sure that the "extra" support handles large blocks
# The ICC APP marker can store 65519 bytes per marker, so
# using a 4-byte test code should allow us to detect out of
@ -219,7 +220,7 @@ class TestFileJpeg:
@mark_if_feature_version(
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
)
def test_large_icc_meta(self, tmp_path):
def test_large_icc_meta(self, tmp_path: Path) -> None:
# https://github.com/python-pillow/Pillow/issues/148
# Sometimes the meta data on the icc_profile block is bigger than
# Image.MAXBLOCK or the image size.
@ -243,7 +244,7 @@ class TestFileJpeg:
f = str(tmp_path / "temp3.jpg")
im.save(f, progressive=True, quality=94, exif=b" " * 43668)
def test_optimize(self):
def test_optimize(self) -> None:
im1 = self.roundtrip(hopper())
im2 = self.roundtrip(hopper(), optimize=0)
im3 = self.roundtrip(hopper(), optimize=1)
@ -252,14 +253,14 @@ class TestFileJpeg:
assert im1.bytes >= im2.bytes
assert im1.bytes >= im3.bytes
def test_optimize_large_buffer(self, tmp_path):
def test_optimize_large_buffer(self, tmp_path: Path) -> None:
# https://github.com/python-pillow/Pillow/issues/148
f = str(tmp_path / "temp.jpg")
# this requires ~ 1.5x Image.MAXBLOCK
im = Image.new("RGB", (4096, 4096), 0xFF3333)
im.save(f, format="JPEG", optimize=True)
def test_progressive(self):
def test_progressive(self) -> None:
im1 = self.roundtrip(hopper())
im2 = self.roundtrip(hopper(), progressive=False)
im3 = self.roundtrip(hopper(), progressive=True)
@ -270,25 +271,25 @@ class TestFileJpeg:
assert_image_equal(im1, im3)
assert im1.bytes >= im3.bytes
def test_progressive_large_buffer(self, tmp_path):
def test_progressive_large_buffer(self, tmp_path: Path) -> None:
f = str(tmp_path / "temp.jpg")
# this requires ~ 1.5x Image.MAXBLOCK
im = Image.new("RGB", (4096, 4096), 0xFF3333)
im.save(f, format="JPEG", progressive=True)
def test_progressive_large_buffer_highest_quality(self, tmp_path):
def test_progressive_large_buffer_highest_quality(self, tmp_path: Path) -> None:
f = str(tmp_path / "temp.jpg")
im = self.gen_random_image((255, 255))
# this requires more bytes than pixels in the image
im.save(f, format="JPEG", progressive=True, quality=100)
def test_progressive_cmyk_buffer(self):
def test_progressive_cmyk_buffer(self) -> None:
# Issue 2272, quality 90 cmyk image is tripping the large buffer bug.
f = BytesIO()
im = self.gen_random_image((256, 256), "CMYK")
im.save(f, format="JPEG", progressive=True, quality=94)
def test_large_exif(self, tmp_path):
def test_large_exif(self, tmp_path: Path) -> None:
# https://github.com/python-pillow/Pillow/issues/148
f = str(tmp_path / "temp.jpg")
im = hopper()
@ -297,12 +298,12 @@ class TestFileJpeg:
with pytest.raises(ValueError):
im.save(f, "JPEG", quality=90, exif=b"1" * 65534)
def test_exif_typeerror(self):
def test_exif_typeerror(self) -> None:
with Image.open("Tests/images/exif_typeerror.jpg") as im:
# Should not raise a TypeError
im._getexif()
def test_exif_gps(self, tmp_path):
def test_exif_gps(self, tmp_path: Path) -> None:
expected_exif_gps = {
0: b"\x00\x00\x00\x01",
2: 4294967295,
@ -327,7 +328,7 @@ class TestFileJpeg:
exif = reloaded._getexif()
assert exif[gps_index] == expected_exif_gps
def test_empty_exif_gps(self):
def test_empty_exif_gps(self) -> None:
with Image.open("Tests/images/empty_gps_ifd.jpg") as im:
exif = im.getexif()
del exif[0x8769]
@ -345,7 +346,7 @@ class TestFileJpeg:
# Assert that it was transposed
assert 0x0112 not in exif
def test_exif_equality(self):
def test_exif_equality(self) -> None:
# In 7.2.0, Exif rationals were changed to be read as
# TiffImagePlugin.IFDRational. This class had a bug in __eq__,
# breaking the self-equality of Exif data
@ -355,7 +356,7 @@ class TestFileJpeg:
exifs.append(im._getexif())
assert exifs[0] == exifs[1]
def test_exif_rollback(self):
def test_exif_rollback(self) -> None:
# rolling back exif support in 3.1 to pre-3.0 formatting.
# expected from 2.9, with b/u qualifiers switched for 3.2 compatibility
# this test passes on 2.9 and 3.1, but not 3.0
@ -390,12 +391,12 @@ class TestFileJpeg:
for tag, value in expected_exif.items():
assert value == exif[tag]
def test_exif_gps_typeerror(self):
def test_exif_gps_typeerror(self) -> None:
with Image.open("Tests/images/exif_gps_typeerror.jpg") as im:
# Should not raise a TypeError
im._getexif()
def test_progressive_compat(self):
def test_progressive_compat(self) -> None:
im1 = self.roundtrip(hopper())
assert not im1.info.get("progressive")
assert not im1.info.get("progression")
@ -416,7 +417,7 @@ class TestFileJpeg:
assert im3.info.get("progressive")
assert im3.info.get("progression")
def test_quality(self):
def test_quality(self) -> None:
im1 = self.roundtrip(hopper())
im2 = self.roundtrip(hopper(), quality=50)
assert_image(im1, im2.mode, im2.size)
@ -426,12 +427,12 @@ class TestFileJpeg:
assert_image(im1, im3.mode, im3.size)
assert im2.bytes > im3.bytes
def test_smooth(self):
def test_smooth(self) -> None:
im1 = self.roundtrip(hopper())
im2 = self.roundtrip(hopper(), smooth=100)
assert_image(im1, im2.mode, im2.size)
def test_subsampling(self):
def test_subsampling(self) -> None:
def getsampling(im):
layer = im.layer
return layer[0][1:3] + layer[1][1:3] + layer[2][1:3]
@ -463,23 +464,23 @@ class TestFileJpeg:
with pytest.raises(TypeError):
self.roundtrip(hopper(), subsampling="1:1:1")
def test_exif(self):
def test_exif(self) -> None:
with Image.open("Tests/images/pil_sample_rgb.jpg") as im:
info = im._getexif()
assert info[305] == "Adobe Photoshop CS Macintosh"
def test_get_child_images(self):
def test_get_child_images(self) -> None:
with Image.open("Tests/images/flower.jpg") as im:
ims = im.get_child_images()
assert len(ims) == 1
assert_image_similar_tofile(ims[0], "Tests/images/flower_thumbnail.png", 2.1)
def test_mp(self):
def test_mp(self) -> None:
with Image.open("Tests/images/pil_sample_rgb.jpg") as im:
assert im._getmp() is None
def test_quality_keep(self, tmp_path):
def test_quality_keep(self, tmp_path: Path) -> None:
# RGB
with Image.open("Tests/images/hopper.jpg") as im:
f = str(tmp_path / "temp.jpg")
@ -493,13 +494,13 @@ class TestFileJpeg:
f = str(tmp_path / "temp.jpg")
im.save(f, quality="keep")
def test_junk_jpeg_header(self):
def test_junk_jpeg_header(self) -> None:
# https://github.com/python-pillow/Pillow/issues/630
filename = "Tests/images/junk_jpeg_header.jpg"
with Image.open(filename):
pass
def test_ff00_jpeg_header(self):
def test_ff00_jpeg_header(self) -> None:
filename = "Tests/images/jpeg_ff00_header.jpg"
with Image.open(filename):
pass
@ -507,7 +508,7 @@ class TestFileJpeg:
@mark_if_feature_version(
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
)
def test_truncated_jpeg_should_read_all_the_data(self):
def test_truncated_jpeg_should_read_all_the_data(self) -> None:
filename = "Tests/images/truncated_jpeg.jpg"
ImageFile.LOAD_TRUNCATED_IMAGES = True
with Image.open(filename) as im:
@ -515,7 +516,7 @@ class TestFileJpeg:
ImageFile.LOAD_TRUNCATED_IMAGES = False
assert im.getbbox() is not None
def test_truncated_jpeg_throws_oserror(self):
def test_truncated_jpeg_throws_oserror(self) -> None:
filename = "Tests/images/truncated_jpeg.jpg"
with Image.open(filename) as im:
with pytest.raises(OSError):
@ -528,8 +529,8 @@ class TestFileJpeg:
@mark_if_feature_version(
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
)
def test_qtables(self, tmp_path):
def _n_qtables_helper(n, test_file):
def test_qtables(self, tmp_path: Path) -> None:
def _n_qtables_helper(n, test_file) -> None:
with Image.open(test_file) as im:
f = str(tmp_path / "temp.jpg")
im.save(f, qtables=[[n] * 64] * n)
@ -637,24 +638,24 @@ class TestFileJpeg:
with pytest.raises(ValueError):
self.roundtrip(im, qtables=[[1, 2, 3, 4]])
def test_load_16bit_qtables(self):
def test_load_16bit_qtables(self) -> None:
with Image.open("Tests/images/hopper_16bit_qtables.jpg") as im:
assert len(im.quantization) == 2
assert len(im.quantization[0]) == 64
assert max(im.quantization[0]) > 255
def test_save_multiple_16bit_qtables(self):
def test_save_multiple_16bit_qtables(self) -> None:
with Image.open("Tests/images/hopper_16bit_qtables.jpg") as im:
im2 = self.roundtrip(im, qtables="keep")
assert im.quantization == im2.quantization
def test_save_single_16bit_qtable(self):
def test_save_single_16bit_qtable(self) -> None:
with Image.open("Tests/images/hopper_16bit_qtables.jpg") as im:
im2 = self.roundtrip(im, qtables={0: im.quantization[0]})
assert len(im2.quantization) == 1
assert im2.quantization[0] == im.quantization[0]
def test_save_low_quality_baseline_qtables(self):
def test_save_low_quality_baseline_qtables(self) -> None:
with Image.open(TEST_FILE) as im:
im2 = self.roundtrip(im, quality=10)
assert len(im2.quantization) == 2
@ -665,7 +666,7 @@ class TestFileJpeg:
"blocks, rows, markers",
((0, 0, 0), (1, 0, 15), (3, 0, 5), (8, 0, 1), (0, 1, 3), (0, 2, 1)),
)
def test_restart_markers(self, blocks, rows, markers):
def test_restart_markers(self, blocks, rows, markers) -> None:
im = Image.new("RGB", (32, 32)) # 16 MCUs
out = BytesIO()
im.save(
@ -679,20 +680,20 @@ class TestFileJpeg:
assert len(re.findall(b"\xff[\xd0-\xd7]", out.getvalue())) == markers
@pytest.mark.skipif(not djpeg_available(), reason="djpeg not available")
def test_load_djpeg(self):
def test_load_djpeg(self) -> None:
with Image.open(TEST_FILE) as img:
img.load_djpeg()
assert_image_similar_tofile(img, TEST_FILE, 5)
@pytest.mark.skipif(not cjpeg_available(), reason="cjpeg not available")
def test_save_cjpeg(self, tmp_path):
def test_save_cjpeg(self, tmp_path: Path) -> None:
with Image.open(TEST_FILE) as img:
tempfile = str(tmp_path / "temp.jpg")
JpegImagePlugin._save_cjpeg(img, 0, tempfile)
# Default save quality is 75%, so a tiny bit of difference is alright
assert_image_similar_tofile(img, tempfile, 17)
def test_no_duplicate_0x1001_tag(self):
def test_no_duplicate_0x1001_tag(self) -> None:
# Arrange
tag_ids = {v: k for k, v in ExifTags.TAGS.items()}
@ -700,7 +701,7 @@ class TestFileJpeg:
assert tag_ids["RelatedImageWidth"] == 0x1001
assert tag_ids["RelatedImageLength"] == 0x1002
def test_MAXBLOCK_scaling(self, tmp_path):
def test_MAXBLOCK_scaling(self, tmp_path: Path) -> None:
im = self.gen_random_image((512, 512))
f = str(tmp_path / "temp.jpeg")
im.save(f, quality=100, optimize=True)
@ -711,7 +712,7 @@ class TestFileJpeg:
reloaded.save(f, quality="keep", progressive=True)
reloaded.save(f, quality="keep", optimize=True)
def test_bad_mpo_header(self):
def test_bad_mpo_header(self) -> None:
"""Treat unknown MPO as JPEG"""
# Arrange
@ -723,20 +724,20 @@ class TestFileJpeg:
assert im.format == "JPEG"
@pytest.mark.parametrize("mode", ("1", "L", "RGB", "RGBX", "CMYK", "YCbCr"))
def test_save_correct_modes(self, mode):
def test_save_correct_modes(self, mode) -> None:
out = BytesIO()
img = Image.new(mode, (20, 20))
img.save(out, "JPEG")
@pytest.mark.parametrize("mode", ("LA", "La", "RGBA", "RGBa", "P"))
def test_save_wrong_modes(self, mode):
def test_save_wrong_modes(self, mode) -> None:
# ref https://github.com/python-pillow/Pillow/issues/2005
out = BytesIO()
img = Image.new(mode, (20, 20))
with pytest.raises(OSError):
img.save(out, "JPEG")
def test_save_tiff_with_dpi(self, tmp_path):
def test_save_tiff_with_dpi(self, tmp_path: Path) -> None:
# Arrange
outfile = str(tmp_path / "temp.tif")
with Image.open("Tests/images/hopper.tif") as im:
@ -748,7 +749,7 @@ class TestFileJpeg:
reloaded.load()
assert im.info["dpi"] == reloaded.info["dpi"]
def test_save_dpi_rounding(self, tmp_path):
def test_save_dpi_rounding(self, tmp_path: Path) -> None:
outfile = str(tmp_path / "temp.jpg")
with Image.open("Tests/images/hopper.jpg") as im:
im.save(outfile, dpi=(72.2, 72.2))
@ -761,7 +762,7 @@ class TestFileJpeg:
with Image.open(outfile) as reloaded:
assert reloaded.info["dpi"] == (73, 73)
def test_dpi_tuple_from_exif(self):
def test_dpi_tuple_from_exif(self) -> None:
# Arrange
# This Photoshop CC 2017 image has DPI in EXIF not metadata
# EXIF XResolution is (2000000, 10000)
@ -769,7 +770,7 @@ class TestFileJpeg:
# Act / Assert
assert im.info.get("dpi") == (200, 200)
def test_dpi_int_from_exif(self):
def test_dpi_int_from_exif(self) -> None:
# Arrange
# This image has DPI in EXIF not metadata
# EXIF XResolution is 72
@ -777,7 +778,7 @@ class TestFileJpeg:
# Act / Assert
assert im.info.get("dpi") == (72, 72)
def test_dpi_from_dpcm_exif(self):
def test_dpi_from_dpcm_exif(self) -> None:
# Arrange
# This is photoshop-200dpi.jpg with EXIF resolution unit set to cm:
# exiftool -exif:ResolutionUnit=cm photoshop-200dpi.jpg
@ -785,7 +786,7 @@ class TestFileJpeg:
# Act / Assert
assert im.info.get("dpi") == (508, 508)
def test_dpi_exif_zero_division(self):
def test_dpi_exif_zero_division(self) -> None:
# Arrange
# This is photoshop-200dpi.jpg with EXIF resolution set to 0/0:
# exiftool -XResolution=0/0 -YResolution=0/0 photoshop-200dpi.jpg
@ -794,7 +795,7 @@ class TestFileJpeg:
# This should return the default, and not raise a ZeroDivisionError
assert im.info.get("dpi") == (72, 72)
def test_dpi_exif_string(self):
def test_dpi_exif_string(self) -> None:
# Arrange
# 0x011A tag in this exif contains string '300300\x02'
with Image.open("Tests/images/broken_exif_dpi.jpg") as im:
@ -802,14 +803,14 @@ class TestFileJpeg:
# This should return the default
assert im.info.get("dpi") == (72, 72)
def test_dpi_exif_truncated(self):
def test_dpi_exif_truncated(self) -> None:
# Arrange
with Image.open("Tests/images/truncated_exif_dpi.jpg") as im:
# Act / Assert
# This should return the default
assert im.info.get("dpi") == (72, 72)
def test_no_dpi_in_exif(self):
def test_no_dpi_in_exif(self) -> None:
# Arrange
# This is photoshop-200dpi.jpg with resolution removed from EXIF:
# exiftool "-*resolution*"= photoshop-200dpi.jpg
@ -819,7 +820,7 @@ class TestFileJpeg:
# https://exiv2.org/tags.html
assert im.info.get("dpi") == (72, 72)
def test_invalid_exif(self):
def test_invalid_exif(self) -> None:
# This is no-dpi-in-exif with the tiff header of the exif block
# hexedited from MM * to FF FF FF FF
with Image.open("Tests/images/invalid-exif.jpg") as im:
@ -830,7 +831,7 @@ class TestFileJpeg:
@mark_if_feature_version(
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
)
def test_exif_x_resolution(self, tmp_path):
def test_exif_x_resolution(self, tmp_path: Path) -> None:
with Image.open("Tests/images/flower.jpg") as im:
exif = im.getexif()
assert exif[282] == 180
@ -842,14 +843,14 @@ class TestFileJpeg:
with Image.open(out) as reloaded:
assert reloaded.getexif()[282] == 180
def test_invalid_exif_x_resolution(self):
def test_invalid_exif_x_resolution(self) -> None:
# When no x or y resolution is defined in EXIF
with Image.open("Tests/images/invalid-exif-without-x-resolution.jpg") as im:
# This should return the default, and not a ValueError or
# OSError for an unidentified image.
assert im.info.get("dpi") == (72, 72)
def test_ifd_offset_exif(self):
def test_ifd_offset_exif(self) -> None:
# Arrange
# This image has been manually hexedited to have an IFD offset of 10,
# in contrast to normal 8
@ -857,14 +858,14 @@ class TestFileJpeg:
# Act / Assert
assert im._getexif()[306] == "2017:03:13 23:03:09"
def test_multiple_exif(self):
def test_multiple_exif(self) -> None:
with Image.open("Tests/images/multiple_exif.jpg") as im:
assert im.info["exif"] == b"Exif\x00\x00firstsecond"
@mark_if_feature_version(
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
)
def test_photoshop(self):
def test_photoshop(self) -> None:
with Image.open("Tests/images/photoshop-200dpi.jpg") as im:
assert im.info["photoshop"][0x03ED] == {
"XResolution": 200.0,
@ -881,14 +882,14 @@ class TestFileJpeg:
with Image.open("Tests/images/app13.jpg") as im:
assert "photoshop" not in im.info
def test_photoshop_malformed_and_multiple(self):
def test_photoshop_malformed_and_multiple(self) -> None:
with Image.open("Tests/images/app13-multiple.jpg") as im:
assert "photoshop" in im.info
assert 24 == len(im.info["photoshop"])
apps_13_lengths = [len(v) for k, v in im.applist if k == "APP13"]
assert [65504, 24] == apps_13_lengths
def test_adobe_transform(self):
def test_adobe_transform(self) -> None:
with Image.open("Tests/images/pil_sample_rgb.jpg") as im:
assert im.info["adobe_transform"] == 1
@ -902,11 +903,11 @@ class TestFileJpeg:
assert "adobe" in im.info
assert "adobe_transform" not in im.info
def test_icc_after_SOF(self):
def test_icc_after_SOF(self) -> None:
with Image.open("Tests/images/icc-after-SOF.jpg") as im:
assert im.info["icc_profile"] == b"profile"
def test_jpeg_magic_number(self):
def test_jpeg_magic_number(self) -> None:
size = 4097
buffer = BytesIO(b"\xFF" * size) # Many xFF bytes
buffer.max_pos = 0
@ -925,7 +926,7 @@ class TestFileJpeg:
# Assert the entire file has not been read
assert 0 < buffer.max_pos < size
def test_getxmp(self):
def test_getxmp(self) -> None:
with Image.open("Tests/images/xmp_test.jpg") as im:
if ElementTree is None:
with pytest.warns(
@ -954,7 +955,7 @@ class TestFileJpeg:
with Image.open("Tests/images/hopper.jpg") as im:
assert im.getxmp() == {}
def test_getxmp_no_prefix(self):
def test_getxmp_no_prefix(self) -> None:
with Image.open("Tests/images/xmp_no_prefix.jpg") as im:
if ElementTree is None:
with pytest.warns(
@ -965,7 +966,7 @@ class TestFileJpeg:
else:
assert im.getxmp() == {"xmpmeta": {"key": "value"}}
def test_getxmp_padded(self):
def test_getxmp_padded(self) -> None:
with Image.open("Tests/images/xmp_padded.jpg") as im:
if ElementTree is None:
with pytest.warns(
@ -977,7 +978,7 @@ class TestFileJpeg:
assert im.getxmp() == {"xmpmeta": None}
@pytest.mark.timeout(timeout=1)
def test_eof(self):
def test_eof(self) -> None:
# Even though this decoder never says that it is finished
# the image should still end when there is no new data
class InfiniteMockPyDecoder(ImageFile.PyDecoder):
@ -1000,7 +1001,7 @@ class TestFileJpeg:
im.load()
ImageFile.LOAD_TRUNCATED_IMAGES = False
def test_separate_tables(self):
def test_separate_tables(self) -> None:
im = hopper()
data = [] # [interchange, tables-only, image-only]
for streamtype in range(3):
@ -1022,14 +1023,14 @@ class TestFileJpeg:
with Image.open(BytesIO(data[1] + data[2])) as combined_im:
assert_image_equal(interchange_im, combined_im)
def test_repr_jpeg(self):
def test_repr_jpeg(self) -> None:
im = hopper()
with Image.open(BytesIO(im._repr_jpeg_())) as repr_jpeg:
assert repr_jpeg.format == "JPEG"
assert_image_similar(im, repr_jpeg, 17)
def test_repr_jpeg_error_returns_none(self):
def test_repr_jpeg_error_returns_none(self) -> None:
im = hopper("F")
assert im._repr_jpeg_() is None
@ -1038,7 +1039,7 @@ class TestFileJpeg:
@pytest.mark.skipif(not is_win32(), reason="Windows only")
@skip_unless_feature("jpg")
class TestFileCloseW32:
def test_fd_leak(self, tmp_path):
def test_fd_leak(self, tmp_path: Path) -> None:
tmpfile = str(tmp_path / "temp.jpg")
with Image.open("Tests/images/hopper.jpg") as im:

View File

@ -3,6 +3,7 @@ from __future__ import annotations
import os
import re
from io import BytesIO
from pathlib import Path
import pytest
@ -46,7 +47,7 @@ def roundtrip(im, **options):
return im
def test_sanity():
def test_sanity() -> None:
# Internal version number
assert re.search(r"\d+\.\d+\.\d+$", features.version_codec("jpg_2000"))
@ -59,20 +60,20 @@ def test_sanity():
assert im.get_format_mimetype() == "image/jp2"
def test_jpf():
def test_jpf() -> None:
with Image.open("Tests/images/balloon.jpf") as im:
assert im.format == "JPEG2000"
assert im.get_format_mimetype() == "image/jpx"
def test_invalid_file():
def test_invalid_file() -> None:
invalid_file = "Tests/images/flower.jpg"
with pytest.raises(SyntaxError):
Jpeg2KImagePlugin.Jpeg2KImageFile(invalid_file)
def test_bytesio():
def test_bytesio() -> None:
with open("Tests/images/test-card-lossless.jp2", "rb") as f:
data = BytesIO(f.read())
assert_image_similar_tofile(test_card, data, 1.0e-3)
@ -82,7 +83,7 @@ def test_bytesio():
# PIL (they were made using Adobe Photoshop)
def test_lossless(tmp_path):
def test_lossless(tmp_path: Path) -> None:
with Image.open("Tests/images/test-card-lossless.jp2") as im:
im.load()
outfile = str(tmp_path / "temp_test-card.png")
@ -90,54 +91,54 @@ def test_lossless(tmp_path):
assert_image_similar(im, test_card, 1.0e-3)
def test_lossy_tiled():
def test_lossy_tiled() -> None:
assert_image_similar_tofile(
test_card, "Tests/images/test-card-lossy-tiled.jp2", 2.0
)
def test_lossless_rt():
def test_lossless_rt() -> None:
im = roundtrip(test_card)
assert_image_equal(im, test_card)
def test_lossy_rt():
def test_lossy_rt() -> None:
im = roundtrip(test_card, quality_layers=[20])
assert_image_similar(im, test_card, 2.0)
def test_tiled_rt():
def test_tiled_rt() -> None:
im = roundtrip(test_card, tile_size=(128, 128))
assert_image_equal(im, test_card)
def test_tiled_offset_rt():
def test_tiled_offset_rt() -> None:
im = roundtrip(test_card, tile_size=(128, 128), tile_offset=(0, 0), offset=(32, 32))
assert_image_equal(im, test_card)
def test_tiled_offset_too_small():
def test_tiled_offset_too_small() -> None:
with pytest.raises(ValueError):
roundtrip(test_card, tile_size=(128, 128), tile_offset=(0, 0), offset=(128, 32))
def test_irreversible_rt():
def test_irreversible_rt() -> None:
im = roundtrip(test_card, irreversible=True, quality_layers=[20])
assert_image_similar(im, test_card, 2.0)
def test_prog_qual_rt():
def test_prog_qual_rt() -> None:
im = roundtrip(test_card, quality_layers=[60, 40, 20], progression="LRCP")
assert_image_similar(im, test_card, 2.0)
def test_prog_res_rt():
def test_prog_res_rt() -> None:
im = roundtrip(test_card, num_resolutions=8, progression="RLCP")
assert_image_equal(im, test_card)
@pytest.mark.parametrize("num_resolutions", range(2, 6))
def test_default_num_resolutions(num_resolutions):
def test_default_num_resolutions(num_resolutions) -> None:
d = 1 << (num_resolutions - 1)
im = test_card.resize((d - 1, d - 1))
with pytest.raises(OSError):
@ -146,7 +147,7 @@ def test_default_num_resolutions(num_resolutions):
assert_image_equal(im, reloaded)
def test_reduce():
def test_reduce() -> None:
with Image.open("Tests/images/test-card-lossless.jp2") as im:
assert callable(im.reduce)
@ -160,7 +161,7 @@ def test_reduce():
assert im.size == (40, 30)
def test_load_dpi():
def test_load_dpi() -> None:
with Image.open("Tests/images/test-card-lossless.jp2") as im:
assert im.info["dpi"] == (71.9836, 71.9836)
@ -168,7 +169,7 @@ def test_load_dpi():
assert "dpi" not in im.info
def test_restricted_icc_profile():
def test_restricted_icc_profile() -> None:
ImageFile.LOAD_TRUNCATED_IMAGES = True
try:
# JPEG2000 image with a restricted ICC profile and a known colorspace
@ -178,7 +179,7 @@ def test_restricted_icc_profile():
ImageFile.LOAD_TRUNCATED_IMAGES = False
def test_header_errors():
def test_header_errors() -> None:
for path in (
"Tests/images/invalid_header_length.jp2",
"Tests/images/not_enough_data.jp2",
@ -192,7 +193,7 @@ def test_header_errors():
pass
def test_layers_type(tmp_path):
def test_layers_type(tmp_path: Path) -> None:
outfile = str(tmp_path / "temp_layers.jp2")
for quality_layers in [[100, 50, 10], (100, 50, 10), None]:
test_card.save(outfile, quality_layers=quality_layers)
@ -202,7 +203,7 @@ def test_layers_type(tmp_path):
test_card.save(outfile, quality_layers=quality_layers)
def test_layers():
def test_layers() -> None:
out = BytesIO()
test_card.save(out, "JPEG2000", quality_layers=[100, 50, 10], progression="LRCP")
out.seek(0)
@ -232,7 +233,7 @@ def test_layers():
("foo.jp2", {"no_jp2": False}, 4, b"jP"),
),
)
def test_no_jp2(name, args, offset, data):
def test_no_jp2(name, args, offset, data) -> None:
out = BytesIO()
if name:
out.name = name
@ -241,7 +242,7 @@ def test_no_jp2(name, args, offset, data):
assert out.read(2) == data
def test_mct():
def test_mct() -> None:
# Three component
for val in (0, 1):
out = BytesIO()
@ -262,7 +263,7 @@ def test_mct():
assert_image_similar(im, jp2, 1.0e-3)
def test_sgnd(tmp_path):
def test_sgnd(tmp_path: Path) -> None:
outfile = str(tmp_path / "temp.jp2")
im = Image.new("L", (1, 1))
@ -277,7 +278,7 @@ def test_sgnd(tmp_path):
@pytest.mark.parametrize("ext", (".j2k", ".jp2"))
def test_rgba(ext):
def test_rgba(ext) -> None:
# Arrange
with Image.open("Tests/images/rgb_trns_ycbc" + ext) as im:
# Act
@ -288,47 +289,47 @@ def test_rgba(ext):
@pytest.mark.parametrize("ext", (".j2k", ".jp2"))
def test_16bit_monochrome_has_correct_mode(ext):
def test_16bit_monochrome_has_correct_mode(ext) -> None:
with Image.open("Tests/images/16bit.cropped" + ext) as im:
im.load()
assert im.mode == "I;16"
def test_16bit_monochrome_jp2_like_tiff():
def test_16bit_monochrome_jp2_like_tiff() -> None:
with Image.open("Tests/images/16bit.cropped.tif") as tiff_16bit:
assert_image_similar_tofile(tiff_16bit, "Tests/images/16bit.cropped.jp2", 1e-3)
def test_16bit_monochrome_j2k_like_tiff():
def test_16bit_monochrome_j2k_like_tiff() -> None:
with Image.open("Tests/images/16bit.cropped.tif") as tiff_16bit:
assert_image_similar_tofile(tiff_16bit, "Tests/images/16bit.cropped.j2k", 1e-3)
def test_16bit_j2k_roundtrips():
def test_16bit_j2k_roundtrips() -> None:
with Image.open("Tests/images/16bit.cropped.j2k") as j2k:
im = roundtrip(j2k)
assert_image_equal(im, j2k)
def test_16bit_jp2_roundtrips():
def test_16bit_jp2_roundtrips() -> None:
with Image.open("Tests/images/16bit.cropped.jp2") as jp2:
im = roundtrip(jp2)
assert_image_equal(im, jp2)
def test_issue_6194():
def test_issue_6194() -> None:
with Image.open("Tests/images/issue_6194.j2k") as im:
assert im.getpixel((5, 5)) == 31
def test_unbound_local():
def test_unbound_local() -> None:
# prepatch, a malformed jp2 file could cause an UnboundLocalError exception.
with pytest.raises(OSError):
with Image.open("Tests/images/unbound_variable.jp2"):
pass
def test_parser_feed():
def test_parser_feed() -> None:
# Arrange
with open("Tests/images/test-card-lossless.jp2", "rb") as f:
data = f.read()
@ -345,7 +346,7 @@ def test_parser_feed():
not os.path.exists(EXTRA_DIR), reason="Extra image files not installed"
)
@pytest.mark.parametrize("name", ("subsampling_1", "subsampling_2", "zoo1", "zoo2"))
def test_subsampling_decode(name):
def test_subsampling_decode(name) -> None:
test = f"{EXTRA_DIR}/{name}.jp2"
reference = f"{EXTRA_DIR}/{name}.ppm"
@ -361,7 +362,7 @@ def test_subsampling_decode(name):
assert_image_similar(im, expected, epsilon)
def test_comment():
def test_comment() -> None:
with Image.open("Tests/images/comment.jp2") as im:
assert im.info["comment"] == b"Created by OpenJPEG version 2.5.0"
@ -372,7 +373,7 @@ def test_comment():
pass
def test_save_comment():
def test_save_comment() -> None:
for comment in ("Created by Pillow", b"Created by Pillow"):
out = BytesIO()
test_card.save(out, "JPEG2000", comment=comment)
@ -399,7 +400,7 @@ def test_save_comment():
"Tests/images/crash-d2c93af851d3ab9a19e34503626368b2ecde9c03.j2k",
],
)
def test_crashes(test_file):
def test_crashes(test_file) -> None:
with open(test_file, "rb") as f:
with Image.open(f) as im:
# Valgrind should not complain here
@ -410,7 +411,7 @@ def test_crashes(test_file):
@skip_unless_feature_version("jpg_2000", "2.4.0")
def test_plt_marker():
def test_plt_marker() -> None:
# Search the start of the codesteam for PLT
out = BytesIO()
test_card.save(out, "JPEG2000", no_jp2=True, plt=True)

View File

@ -7,6 +7,7 @@ import os
import re
import sys
from collections import namedtuple
from pathlib import Path
import pytest
@ -26,7 +27,7 @@ from .helper import (
@skip_unless_feature("libtiff")
class LibTiffTestCase:
def _assert_noerr(self, tmp_path, im):
def _assert_noerr(self, tmp_path: Path, im) -> None:
"""Helper tests that assert basic sanity about the g4 tiff reading"""
# 1 bit
assert im.mode == "1"
@ -50,10 +51,10 @@ class LibTiffTestCase:
class TestFileLibTiff(LibTiffTestCase):
def test_version(self):
def test_version(self) -> None:
assert re.search(r"\d+\.\d+\.\d+$", features.version_codec("libtiff"))
def test_g4_tiff(self, tmp_path):
def test_g4_tiff(self, tmp_path: Path) -> None:
"""Test the ordinary file path load path"""
test_file = "Tests/images/hopper_g4_500.tif"
@ -61,12 +62,12 @@ class TestFileLibTiff(LibTiffTestCase):
assert im.size == (500, 500)
self._assert_noerr(tmp_path, im)
def test_g4_large(self, tmp_path):
def test_g4_large(self, tmp_path: Path) -> None:
test_file = "Tests/images/pport_g4.tif"
with Image.open(test_file) as im:
self._assert_noerr(tmp_path, im)
def test_g4_tiff_file(self, tmp_path):
def test_g4_tiff_file(self, tmp_path: Path) -> None:
"""Testing the string load path"""
test_file = "Tests/images/hopper_g4_500.tif"
@ -75,7 +76,7 @@ class TestFileLibTiff(LibTiffTestCase):
assert im.size == (500, 500)
self._assert_noerr(tmp_path, im)
def test_g4_tiff_bytesio(self, tmp_path):
def test_g4_tiff_bytesio(self, tmp_path: Path) -> None:
"""Testing the stringio loading code path"""
test_file = "Tests/images/hopper_g4_500.tif"
s = io.BytesIO()
@ -86,7 +87,7 @@ class TestFileLibTiff(LibTiffTestCase):
assert im.size == (500, 500)
self._assert_noerr(tmp_path, im)
def test_g4_non_disk_file_object(self, tmp_path):
def test_g4_non_disk_file_object(self, tmp_path: Path) -> None:
"""Testing loading from non-disk non-BytesIO file object"""
test_file = "Tests/images/hopper_g4_500.tif"
s = io.BytesIO()
@ -98,18 +99,18 @@ class TestFileLibTiff(LibTiffTestCase):
assert im.size == (500, 500)
self._assert_noerr(tmp_path, im)
def test_g4_eq_png(self):
def test_g4_eq_png(self) -> None:
"""Checking that we're actually getting the data that we expect"""
with Image.open("Tests/images/hopper_bw_500.png") as png:
assert_image_equal_tofile(png, "Tests/images/hopper_g4_500.tif")
# see https://github.com/python-pillow/Pillow/issues/279
def test_g4_fillorder_eq_png(self):
def test_g4_fillorder_eq_png(self) -> None:
"""Checking that we're actually getting the data that we expect"""
with Image.open("Tests/images/g4-fillorder-test.tif") as g4:
assert_image_equal_tofile(g4, "Tests/images/g4-fillorder-test.png")
def test_g4_write(self, tmp_path):
def test_g4_write(self, tmp_path: Path) -> None:
"""Checking to see that the saved image is the same as what we wrote"""
test_file = "Tests/images/hopper_g4_500.tif"
with Image.open(test_file) as orig:
@ -128,7 +129,7 @@ class TestFileLibTiff(LibTiffTestCase):
assert orig.tobytes() != reread.tobytes()
def test_adobe_deflate_tiff(self):
def test_adobe_deflate_tiff(self) -> None:
test_file = "Tests/images/tiff_adobe_deflate.tif"
with Image.open(test_file) as im:
assert im.mode == "RGB"
@ -139,7 +140,7 @@ class TestFileLibTiff(LibTiffTestCase):
assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png")
@pytest.mark.parametrize("legacy_api", (False, True))
def test_write_metadata(self, legacy_api, tmp_path):
def test_write_metadata(self, legacy_api, tmp_path: Path) -> None:
"""Test metadata writing through libtiff"""
f = str(tmp_path / "temp.tiff")
with Image.open("Tests/images/hopper_g4.tif") as img:
@ -184,7 +185,7 @@ class TestFileLibTiff(LibTiffTestCase):
assert field in reloaded, f"{field} not in metadata"
@pytest.mark.valgrind_known_error(reason="Known invalid metadata")
def test_additional_metadata(self, tmp_path):
def test_additional_metadata(self, tmp_path: Path) -> None:
# these should not crash. Seriously dummy data, most of it doesn't make
# any sense, so we're running up against limits where we're asking
# libtiff to do stupid things.
@ -241,7 +242,7 @@ class TestFileLibTiff(LibTiffTestCase):
TiffImagePlugin.WRITE_LIBTIFF = False
def test_custom_metadata(self, tmp_path):
def test_custom_metadata(self, tmp_path: Path) -> None:
tc = namedtuple("test_case", "value,type,supported_by_default")
custom = {
37000 + k: v
@ -283,7 +284,7 @@ class TestFileLibTiff(LibTiffTestCase):
for libtiff in libtiffs:
TiffImagePlugin.WRITE_LIBTIFF = libtiff
def check_tags(tiffinfo):
def check_tags(tiffinfo) -> None:
im = hopper()
out = str(tmp_path / "temp.tif")
@ -322,7 +323,7 @@ class TestFileLibTiff(LibTiffTestCase):
)
TiffImagePlugin.WRITE_LIBTIFF = False
def test_subifd(self, tmp_path):
def test_subifd(self, tmp_path: Path) -> None:
outfile = str(tmp_path / "temp.tif")
with Image.open("Tests/images/g4_orientation_6.tif") as im:
im.tag_v2[SUBIFD] = 10000
@ -330,7 +331,7 @@ class TestFileLibTiff(LibTiffTestCase):
# Should not segfault
im.save(outfile)
def test_xmlpacket_tag(self, tmp_path):
def test_xmlpacket_tag(self, tmp_path: Path) -> None:
TiffImagePlugin.WRITE_LIBTIFF = True
out = str(tmp_path / "temp.tif")
@ -341,7 +342,7 @@ class TestFileLibTiff(LibTiffTestCase):
if 700 in reloaded.tag_v2:
assert reloaded.tag_v2[700] == b"xmlpacket tag"
def test_int_dpi(self, tmp_path):
def test_int_dpi(self, tmp_path: Path) -> None:
# issue #1765
im = hopper("RGB")
out = str(tmp_path / "temp.tif")
@ -351,7 +352,7 @@ class TestFileLibTiff(LibTiffTestCase):
with Image.open(out) as reloaded:
assert reloaded.info["dpi"] == (72.0, 72.0)
def test_g3_compression(self, tmp_path):
def test_g3_compression(self, tmp_path: Path) -> None:
with Image.open("Tests/images/hopper_g4_500.tif") as i:
out = str(tmp_path / "temp.tif")
i.save(out, compression="group3")
@ -360,7 +361,7 @@ class TestFileLibTiff(LibTiffTestCase):
assert reread.info["compression"] == "group3"
assert_image_equal(reread, i)
def test_little_endian(self, tmp_path):
def test_little_endian(self, tmp_path: Path) -> None:
with Image.open("Tests/images/16bit.deflate.tif") as im:
assert im.getpixel((0, 0)) == 480
assert im.mode == "I;16"
@ -379,7 +380,7 @@ class TestFileLibTiff(LibTiffTestCase):
# UNDONE - libtiff defaults to writing in native endian, so
# on big endian, we'll get back mode = 'I;16B' here.
def test_big_endian(self, tmp_path):
def test_big_endian(self, tmp_path: Path) -> None:
with Image.open("Tests/images/16bit.MM.deflate.tif") as im:
assert im.getpixel((0, 0)) == 480
assert im.mode == "I;16B"
@ -396,7 +397,7 @@ class TestFileLibTiff(LibTiffTestCase):
assert reread.info["compression"] == im.info["compression"]
assert reread.getpixel((0, 0)) == 480
def test_g4_string_info(self, tmp_path):
def test_g4_string_info(self, tmp_path: Path) -> None:
"""Tests String data in info directory"""
test_file = "Tests/images/hopper_g4_500.tif"
with Image.open(test_file) as orig:
@ -409,7 +410,7 @@ class TestFileLibTiff(LibTiffTestCase):
assert "temp.tif" == reread.tag_v2[269]
assert "temp.tif" == reread.tag[269][0]
def test_12bit_rawmode(self):
def test_12bit_rawmode(self) -> None:
"""Are we generating the same interpretation
of the image as Imagemagick is?"""
TiffImagePlugin.READ_LIBTIFF = True
@ -424,7 +425,7 @@ class TestFileLibTiff(LibTiffTestCase):
assert_image_equal_tofile(im, "Tests/images/12in16bit.tif")
def test_blur(self, tmp_path):
def test_blur(self, tmp_path: Path) -> None:
# test case from irc, how to do blur on b/w image
# and save to compressed tif.
out = str(tmp_path / "temp.tif")
@ -436,7 +437,7 @@ class TestFileLibTiff(LibTiffTestCase):
assert_image_equal_tofile(im, out)
def test_compressions(self, tmp_path):
def test_compressions(self, tmp_path: Path) -> None:
# Test various tiff compressions and assert similar image content but reduced
# file sizes.
im = hopper("RGB")
@ -462,7 +463,7 @@ class TestFileLibTiff(LibTiffTestCase):
assert size_compressed > size_jpeg
assert size_jpeg > size_jpeg_30
def test_tiff_jpeg_compression(self, tmp_path):
def test_tiff_jpeg_compression(self, tmp_path: Path) -> None:
im = hopper("RGB")
out = str(tmp_path / "temp.tif")
im.save(out, compression="tiff_jpeg")
@ -470,7 +471,7 @@ class TestFileLibTiff(LibTiffTestCase):
with Image.open(out) as reloaded:
assert reloaded.info["compression"] == "jpeg"
def test_tiff_deflate_compression(self, tmp_path):
def test_tiff_deflate_compression(self, tmp_path: Path) -> None:
im = hopper("RGB")
out = str(tmp_path / "temp.tif")
im.save(out, compression="tiff_deflate")
@ -478,7 +479,7 @@ class TestFileLibTiff(LibTiffTestCase):
with Image.open(out) as reloaded:
assert reloaded.info["compression"] == "tiff_adobe_deflate"
def test_quality(self, tmp_path):
def test_quality(self, tmp_path: Path) -> None:
im = hopper("RGB")
out = str(tmp_path / "temp.tif")
@ -493,7 +494,7 @@ class TestFileLibTiff(LibTiffTestCase):
im.save(out, compression="jpeg", quality=0)
im.save(out, compression="jpeg", quality=100)
def test_cmyk_save(self, tmp_path):
def test_cmyk_save(self, tmp_path: Path) -> None:
im = hopper("CMYK")
out = str(tmp_path / "temp.tif")
@ -501,7 +502,7 @@ class TestFileLibTiff(LibTiffTestCase):
assert_image_equal_tofile(im, out)
@pytest.mark.parametrize("im", (hopper("P"), Image.new("P", (1, 1), "#000")))
def test_palette_save(self, im, tmp_path):
def test_palette_save(self, im, tmp_path: Path) -> None:
out = str(tmp_path / "temp.tif")
TiffImagePlugin.WRITE_LIBTIFF = True
@ -513,14 +514,14 @@ class TestFileLibTiff(LibTiffTestCase):
assert len(reloaded.tag_v2[320]) == 768
@pytest.mark.parametrize("compression", ("tiff_ccitt", "group3", "group4"))
def test_bw_compression_w_rgb(self, compression, tmp_path):
def test_bw_compression_w_rgb(self, compression, tmp_path: Path) -> None:
im = hopper("RGB")
out = str(tmp_path / "temp.tif")
with pytest.raises(OSError):
im.save(out, compression=compression)
def test_fp_leak(self):
def test_fp_leak(self) -> None:
im = Image.open("Tests/images/hopper_g4_500.tif")
fn = im.fp.fileno()
@ -534,7 +535,7 @@ class TestFileLibTiff(LibTiffTestCase):
with pytest.raises(OSError):
os.close(fn)
def test_multipage(self):
def test_multipage(self) -> None:
# issue #862
TiffImagePlugin.READ_LIBTIFF = True
with Image.open("Tests/images/multipage.tiff") as im:
@ -557,7 +558,7 @@ class TestFileLibTiff(LibTiffTestCase):
TiffImagePlugin.READ_LIBTIFF = False
def test_multipage_nframes(self):
def test_multipage_nframes(self) -> None:
# issue #862
TiffImagePlugin.READ_LIBTIFF = True
with Image.open("Tests/images/multipage.tiff") as im:
@ -570,7 +571,7 @@ class TestFileLibTiff(LibTiffTestCase):
TiffImagePlugin.READ_LIBTIFF = False
def test_multipage_seek_backwards(self):
def test_multipage_seek_backwards(self) -> None:
TiffImagePlugin.READ_LIBTIFF = True
with Image.open("Tests/images/multipage.tiff") as im:
im.seek(1)
@ -581,14 +582,14 @@ class TestFileLibTiff(LibTiffTestCase):
TiffImagePlugin.READ_LIBTIFF = False
def test__next(self):
def test__next(self) -> None:
TiffImagePlugin.READ_LIBTIFF = True
with Image.open("Tests/images/hopper.tif") as im:
assert not im.tag.next
im.load()
assert not im.tag.next
def test_4bit(self):
def test_4bit(self) -> None:
# Arrange
test_file = "Tests/images/hopper_gray_4bpp.tif"
original = hopper("L")
@ -603,7 +604,7 @@ class TestFileLibTiff(LibTiffTestCase):
assert im.mode == "L"
assert_image_similar(im, original, 7.3)
def test_gray_semibyte_per_pixel(self):
def test_gray_semibyte_per_pixel(self) -> None:
test_files = (
(
24.8, # epsilon
@ -636,7 +637,7 @@ class TestFileLibTiff(LibTiffTestCase):
assert im2.mode == "L"
assert_image_equal(im, im2)
def test_save_bytesio(self):
def test_save_bytesio(self) -> None:
# PR 1011
# Test TIFF saving to io.BytesIO() object.
@ -646,7 +647,7 @@ class TestFileLibTiff(LibTiffTestCase):
# Generate test image
pilim = hopper()
def save_bytesio(compression=None):
def save_bytesio(compression=None) -> None:
buffer_io = io.BytesIO()
pilim.save(buffer_io, format="tiff", compression=compression)
buffer_io.seek(0)
@ -661,7 +662,7 @@ class TestFileLibTiff(LibTiffTestCase):
TiffImagePlugin.WRITE_LIBTIFF = False
TiffImagePlugin.READ_LIBTIFF = False
def test_save_ycbcr(self, tmp_path):
def test_save_ycbcr(self, tmp_path: Path) -> None:
im = hopper("YCbCr")
outfile = str(tmp_path / "temp.tif")
im.save(outfile, compression="jpeg")
@ -670,7 +671,7 @@ class TestFileLibTiff(LibTiffTestCase):
assert reloaded.tag_v2[530] == (1, 1)
assert reloaded.tag_v2[532] == (0, 255, 128, 255, 128, 255)
def test_exif_ifd(self, tmp_path):
def test_exif_ifd(self, tmp_path: Path) -> None:
outfile = str(tmp_path / "temp.tif")
with Image.open("Tests/images/tiff_adobe_deflate.tif") as im:
assert im.tag_v2[34665] == 125456
@ -680,7 +681,7 @@ class TestFileLibTiff(LibTiffTestCase):
if Image.core.libtiff_support_custom_tags:
assert reloaded.tag_v2[34665] == 125456
def test_crashing_metadata(self, tmp_path):
def test_crashing_metadata(self, tmp_path: Path) -> None:
# issue 1597
with Image.open("Tests/images/rdf.tif") as im:
out = str(tmp_path / "temp.tif")
@ -690,7 +691,7 @@ class TestFileLibTiff(LibTiffTestCase):
im.save(out, format="TIFF")
TiffImagePlugin.WRITE_LIBTIFF = False
def test_page_number_x_0(self, tmp_path):
def test_page_number_x_0(self, tmp_path: Path) -> None:
# Issue 973
# Test TIFF with tag 297 (Page Number) having value of 0 0.
# The first number is the current page number.
@ -704,7 +705,7 @@ class TestFileLibTiff(LibTiffTestCase):
# Should not divide by zero
im.save(outfile)
def test_fd_duplication(self, tmp_path):
def test_fd_duplication(self, tmp_path: Path) -> None:
# https://github.com/python-pillow/Pillow/issues/1651
tmpfile = str(tmp_path / "temp.tif")
@ -718,7 +719,7 @@ class TestFileLibTiff(LibTiffTestCase):
# Should not raise PermissionError.
os.remove(tmpfile)
def test_read_icc(self):
def test_read_icc(self) -> None:
with Image.open("Tests/images/hopper.iccprofile.tif") as img:
icc = img.info.get("icc_profile")
assert icc is not None
@ -729,8 +730,8 @@ class TestFileLibTiff(LibTiffTestCase):
TiffImagePlugin.READ_LIBTIFF = False
assert icc == icc_libtiff
def test_write_icc(self, tmp_path):
def check_write(libtiff):
def test_write_icc(self, tmp_path: Path) -> None:
def check_write(libtiff) -> None:
TiffImagePlugin.WRITE_LIBTIFF = libtiff
with Image.open("Tests/images/hopper.iccprofile.tif") as img:
@ -749,7 +750,7 @@ class TestFileLibTiff(LibTiffTestCase):
for libtiff in libtiffs:
check_write(libtiff)
def test_multipage_compression(self):
def test_multipage_compression(self) -> None:
with Image.open("Tests/images/compression.tif") as im:
im.seek(0)
assert im._compression == "tiff_ccitt"
@ -765,7 +766,7 @@ class TestFileLibTiff(LibTiffTestCase):
assert im.size == (10, 10)
im.load()
def test_save_tiff_with_jpegtables(self, tmp_path):
def test_save_tiff_with_jpegtables(self, tmp_path: Path) -> None:
# Arrange
outfile = str(tmp_path / "temp.tif")
@ -777,7 +778,7 @@ class TestFileLibTiff(LibTiffTestCase):
# Should not raise UnicodeDecodeError or anything else
im.save(outfile)
def test_16bit_RGB_tiff(self):
def test_16bit_RGB_tiff(self) -> None:
with Image.open("Tests/images/tiff_16bit_RGB.tiff") as im:
assert im.mode == "RGB"
assert im.size == (100, 40)
@ -793,7 +794,7 @@ class TestFileLibTiff(LibTiffTestCase):
assert_image_equal_tofile(im, "Tests/images/tiff_16bit_RGB_target.png")
def test_16bit_RGBa_tiff(self):
def test_16bit_RGBa_tiff(self) -> None:
with Image.open("Tests/images/tiff_16bit_RGBa.tiff") as im:
assert im.mode == "RGBA"
assert im.size == (100, 40)
@ -805,7 +806,7 @@ class TestFileLibTiff(LibTiffTestCase):
assert_image_equal_tofile(im, "Tests/images/tiff_16bit_RGBa_target.png")
@skip_unless_feature("jpg")
def test_gimp_tiff(self):
def test_gimp_tiff(self) -> None:
# Read TIFF JPEG images from GIMP [@PIL168]
filename = "Tests/images/pil168.tif"
with Image.open(filename) as im:
@ -818,14 +819,14 @@ class TestFileLibTiff(LibTiffTestCase):
assert_image_equal_tofile(im, "Tests/images/pil168.png")
def test_sampleformat(self):
def test_sampleformat(self) -> None:
# https://github.com/python-pillow/Pillow/issues/1466
with Image.open("Tests/images/copyleft.tiff") as im:
assert im.mode == "RGB"
assert_image_equal_tofile(im, "Tests/images/copyleft.png", mode="RGB")
def test_sampleformat_write(self, tmp_path):
def test_sampleformat_write(self, tmp_path: Path) -> None:
im = Image.new("F", (1, 1))
out = str(tmp_path / "temp.tif")
TiffImagePlugin.WRITE_LIBTIFF = True
@ -874,7 +875,7 @@ class TestFileLibTiff(LibTiffTestCase):
sys.stderr.write(captured.err)
raise
def test_lzw(self):
def test_lzw(self) -> None:
with Image.open("Tests/images/hopper_lzw.tif") as im:
assert im.mode == "RGB"
assert im.size == (128, 128)
@ -882,12 +883,12 @@ class TestFileLibTiff(LibTiffTestCase):
im2 = hopper()
assert_image_similar(im, im2, 5)
def test_strip_cmyk_jpeg(self):
def test_strip_cmyk_jpeg(self) -> None:
infile = "Tests/images/tiff_strip_cmyk_jpeg.tif"
with Image.open(infile) as im:
assert_image_similar_tofile(im, "Tests/images/pil_sample_cmyk.jpg", 0.5)
def test_strip_cmyk_16l_jpeg(self):
def test_strip_cmyk_16l_jpeg(self) -> None:
infile = "Tests/images/tiff_strip_cmyk_16l_jpeg.tif"
with Image.open(infile) as im:
assert_image_similar_tofile(im, "Tests/images/pil_sample_cmyk.jpg", 0.5)
@ -895,7 +896,7 @@ class TestFileLibTiff(LibTiffTestCase):
@mark_if_feature_version(
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
)
def test_strip_ycbcr_jpeg_2x2_sampling(self):
def test_strip_ycbcr_jpeg_2x2_sampling(self) -> None:
infile = "Tests/images/tiff_strip_ycbcr_jpeg_2x2_sampling.tif"
with Image.open(infile) as im:
assert_image_similar_tofile(im, "Tests/images/flower.jpg", 1.2)
@ -903,12 +904,12 @@ class TestFileLibTiff(LibTiffTestCase):
@mark_if_feature_version(
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
)
def test_strip_ycbcr_jpeg_1x1_sampling(self):
def test_strip_ycbcr_jpeg_1x1_sampling(self) -> None:
infile = "Tests/images/tiff_strip_ycbcr_jpeg_1x1_sampling.tif"
with Image.open(infile) as im:
assert_image_similar_tofile(im, "Tests/images/flower2.jpg", 0.01)
def test_tiled_cmyk_jpeg(self):
def test_tiled_cmyk_jpeg(self) -> None:
infile = "Tests/images/tiff_tiled_cmyk_jpeg.tif"
with Image.open(infile) as im:
assert_image_similar_tofile(im, "Tests/images/pil_sample_cmyk.jpg", 0.5)
@ -916,7 +917,7 @@ class TestFileLibTiff(LibTiffTestCase):
@mark_if_feature_version(
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
)
def test_tiled_ycbcr_jpeg_1x1_sampling(self):
def test_tiled_ycbcr_jpeg_1x1_sampling(self) -> None:
infile = "Tests/images/tiff_tiled_ycbcr_jpeg_1x1_sampling.tif"
with Image.open(infile) as im:
assert_image_similar_tofile(im, "Tests/images/flower2.jpg", 0.01)
@ -924,45 +925,45 @@ class TestFileLibTiff(LibTiffTestCase):
@mark_if_feature_version(
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
)
def test_tiled_ycbcr_jpeg_2x2_sampling(self):
def test_tiled_ycbcr_jpeg_2x2_sampling(self) -> None:
infile = "Tests/images/tiff_tiled_ycbcr_jpeg_2x2_sampling.tif"
with Image.open(infile) as im:
assert_image_similar_tofile(im, "Tests/images/flower.jpg", 1.5)
def test_strip_planar_rgb(self):
def test_strip_planar_rgb(self) -> None:
# gdal_translate -co TILED=no -co INTERLEAVE=BAND -co COMPRESS=LZW \
# tiff_strip_raw.tif tiff_strip_planar_lzw.tiff
infile = "Tests/images/tiff_strip_planar_lzw.tiff"
with Image.open(infile) as im:
assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png")
def test_tiled_planar_rgb(self):
def test_tiled_planar_rgb(self) -> None:
# gdal_translate -co TILED=yes -co INTERLEAVE=BAND -co COMPRESS=LZW \
# tiff_tiled_raw.tif tiff_tiled_planar_lzw.tiff
infile = "Tests/images/tiff_tiled_planar_lzw.tiff"
with Image.open(infile) as im:
assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png")
def test_tiled_planar_16bit_RGB(self):
def test_tiled_planar_16bit_RGB(self) -> None:
# gdal_translate -co TILED=yes -co INTERLEAVE=BAND -co COMPRESS=LZW \
# tiff_16bit_RGB.tiff tiff_tiled_planar_16bit_RGB.tiff
with Image.open("Tests/images/tiff_tiled_planar_16bit_RGB.tiff") as im:
assert_image_equal_tofile(im, "Tests/images/tiff_16bit_RGB_target.png")
def test_strip_planar_16bit_RGB(self):
def test_strip_planar_16bit_RGB(self) -> None:
# gdal_translate -co TILED=no -co INTERLEAVE=BAND -co COMPRESS=LZW \
# tiff_16bit_RGB.tiff tiff_strip_planar_16bit_RGB.tiff
with Image.open("Tests/images/tiff_strip_planar_16bit_RGB.tiff") as im:
assert_image_equal_tofile(im, "Tests/images/tiff_16bit_RGB_target.png")
def test_tiled_planar_16bit_RGBa(self):
def test_tiled_planar_16bit_RGBa(self) -> None:
# gdal_translate -co TILED=yes \
# -co INTERLEAVE=BAND -co COMPRESS=LZW -co ALPHA=PREMULTIPLIED \
# tiff_16bit_RGBa.tiff tiff_tiled_planar_16bit_RGBa.tiff
with Image.open("Tests/images/tiff_tiled_planar_16bit_RGBa.tiff") as im:
assert_image_equal_tofile(im, "Tests/images/tiff_16bit_RGBa_target.png")
def test_strip_planar_16bit_RGBa(self):
def test_strip_planar_16bit_RGBa(self) -> None:
# gdal_translate -co TILED=no \
# -co INTERLEAVE=BAND -co COMPRESS=LZW -co ALPHA=PREMULTIPLIED \
# tiff_16bit_RGBa.tiff tiff_strip_planar_16bit_RGBa.tiff
@ -970,7 +971,7 @@ class TestFileLibTiff(LibTiffTestCase):
assert_image_equal_tofile(im, "Tests/images/tiff_16bit_RGBa_target.png")
@pytest.mark.parametrize("compression", (None, "jpeg"))
def test_block_tile_tags(self, compression, tmp_path):
def test_block_tile_tags(self, compression, tmp_path: Path) -> None:
im = hopper()
out = str(tmp_path / "temp.tif")
@ -986,11 +987,11 @@ class TestFileLibTiff(LibTiffTestCase):
for tag in tags:
assert tag not in reloaded.getexif()
def test_old_style_jpeg(self):
def test_old_style_jpeg(self) -> None:
with Image.open("Tests/images/old-style-jpeg-compression.tif") as im:
assert_image_equal_tofile(im, "Tests/images/old-style-jpeg-compression.png")
def test_open_missing_samplesperpixel(self):
def test_open_missing_samplesperpixel(self) -> None:
with Image.open(
"Tests/images/old-style-jpeg-compression-no-samplesperpixel.tif"
) as im:
@ -1019,21 +1020,21 @@ class TestFileLibTiff(LibTiffTestCase):
),
],
)
def test_wrong_bits_per_sample(self, file_name, mode, size, tile):
def test_wrong_bits_per_sample(self, file_name, mode, size, tile) -> None:
with Image.open("Tests/images/" + file_name) as im:
assert im.mode == mode
assert im.size == size
assert im.tile == tile
im.load()
def test_no_rows_per_strip(self):
def test_no_rows_per_strip(self) -> None:
# This image does not have a RowsPerStrip TIFF tag
infile = "Tests/images/no_rows_per_strip.tif"
with Image.open(infile) as im:
im.load()
assert im.size == (950, 975)
def test_orientation(self):
def test_orientation(self) -> None:
with Image.open("Tests/images/g4_orientation_1.tif") as base_im:
for i in range(2, 9):
with Image.open("Tests/images/g4_orientation_" + str(i) + ".tif") as im:
@ -1044,7 +1045,7 @@ class TestFileLibTiff(LibTiffTestCase):
assert_image_similar(base_im, im, 0.7)
def test_exif_transpose(self):
def test_exif_transpose(self) -> None:
with Image.open("Tests/images/g4_orientation_1.tif") as base_im:
for i in range(2, 9):
with Image.open("Tests/images/g4_orientation_" + str(i) + ".tif") as im:
@ -1053,7 +1054,7 @@ class TestFileLibTiff(LibTiffTestCase):
assert_image_similar(base_im, im, 0.7)
@pytest.mark.valgrind_known_error(reason="Backtrace in Python Core")
def test_sampleformat_not_corrupted(self):
def test_sampleformat_not_corrupted(self) -> None:
# Assert that a TIFF image with SampleFormat=UINT tag is not corrupted
# when saving to a new file.
# Pillow 6.0 fails with "OSError: cannot identify image file".
@ -1074,7 +1075,7 @@ class TestFileLibTiff(LibTiffTestCase):
with Image.open(out) as im:
im.load()
def test_realloc_overflow(self):
def test_realloc_overflow(self) -> None:
TiffImagePlugin.READ_LIBTIFF = True
with Image.open("Tests/images/tiff_overflow_rows_per_strip.tif") as im:
with pytest.raises(OSError) as e:
@ -1085,7 +1086,7 @@ class TestFileLibTiff(LibTiffTestCase):
TiffImagePlugin.READ_LIBTIFF = False
@pytest.mark.parametrize("compression", ("tiff_adobe_deflate", "jpeg"))
def test_save_multistrip(self, compression, tmp_path):
def test_save_multistrip(self, compression, tmp_path: Path) -> None:
im = hopper("RGB").resize((256, 256))
out = str(tmp_path / "temp.tif")
im.save(out, compression=compression)
@ -1095,7 +1096,7 @@ class TestFileLibTiff(LibTiffTestCase):
assert len(im.tag_v2[STRIPOFFSETS]) > 1
@pytest.mark.parametrize("argument", (True, False))
def test_save_single_strip(self, argument, tmp_path):
def test_save_single_strip(self, argument, tmp_path: Path) -> None:
im = hopper("RGB").resize((256, 256))
out = str(tmp_path / "temp.tif")
@ -1113,13 +1114,13 @@ class TestFileLibTiff(LibTiffTestCase):
TiffImagePlugin.STRIP_SIZE = 65536
@pytest.mark.parametrize("compression", ("tiff_adobe_deflate", None))
def test_save_zero(self, compression, tmp_path):
def test_save_zero(self, compression, tmp_path: Path) -> None:
im = Image.new("RGB", (0, 0))
out = str(tmp_path / "temp.tif")
with pytest.raises(SystemError):
im.save(out, compression=compression)
def test_save_many_compressed(self, tmp_path):
def test_save_many_compressed(self, tmp_path: Path) -> None:
im = hopper()
out = str(tmp_path / "temp.tif")
for _ in range(10000):
@ -1133,7 +1134,7 @@ class TestFileLibTiff(LibTiffTestCase):
("Tests/images/child_ifd_jpeg.tiff", (20,)),
),
)
def test_get_child_images(self, path, sizes):
def test_get_child_images(self, path, sizes) -> None:
with Image.open(path) as im:
ims = im.get_child_images()

View File

@ -1,6 +1,7 @@
from __future__ import annotations
from io import BytesIO
from pathlib import Path
from PIL import Image
@ -17,7 +18,7 @@ class TestFileLibTiffSmall(LibTiffTestCase):
file just before reading in libtiff. These tests remain
to ensure that it stays fixed."""
def test_g4_hopper_file(self, tmp_path):
def test_g4_hopper_file(self, tmp_path: Path) -> None:
"""Testing the open file load path"""
test_file = "Tests/images/hopper_g4.tif"
@ -26,7 +27,7 @@ class TestFileLibTiffSmall(LibTiffTestCase):
assert im.size == (128, 128)
self._assert_noerr(tmp_path, im)
def test_g4_hopper_bytesio(self, tmp_path):
def test_g4_hopper_bytesio(self, tmp_path: Path) -> None:
"""Testing the bytesio loading code path"""
test_file = "Tests/images/hopper_g4.tif"
s = BytesIO()
@ -37,7 +38,7 @@ class TestFileLibTiffSmall(LibTiffTestCase):
assert im.size == (128, 128)
self._assert_noerr(tmp_path, im)
def test_g4_hopper(self, tmp_path):
def test_g4_hopper(self, tmp_path: Path) -> None:
"""The 128x128 lena image failed for some reason."""
test_file = "Tests/images/hopper_g4.tif"

View File

@ -13,7 +13,7 @@ pytestmark = skip_unless_feature("libtiff")
TEST_FILE = "Tests/images/hopper.mic"
def test_sanity():
def test_sanity() -> None:
with Image.open(TEST_FILE) as im:
im.load()
assert im.mode == "RGBA"
@ -28,22 +28,22 @@ def test_sanity():
assert_image_similar(im, im2, 10)
def test_n_frames():
def test_n_frames() -> None:
with Image.open(TEST_FILE) as im:
assert im.n_frames == 1
def test_is_animated():
def test_is_animated() -> None:
with Image.open(TEST_FILE) as im:
assert not im.is_animated
def test_tell():
def test_tell() -> None:
with Image.open(TEST_FILE) as im:
assert im.tell() == 0
def test_seek():
def test_seek() -> None:
with Image.open(TEST_FILE) as im:
im.seek(0)
assert im.tell() == 0
@ -53,7 +53,7 @@ def test_seek():
assert im.tell() == 0
def test_close():
def test_close() -> None:
with Image.open(TEST_FILE) as im:
pass
assert im.ole.fp.closed
@ -63,7 +63,7 @@ def test_close():
assert im.ole.fp.closed
def test_invalid_file():
def test_invalid_file() -> None:
# Test an invalid OLE file
invalid_file = "Tests/images/flower.jpg"
with pytest.raises(SyntaxError):

View File

@ -30,7 +30,7 @@ def roundtrip(im, **options):
@pytest.mark.parametrize("test_file", test_files)
def test_sanity(test_file):
def test_sanity(test_file) -> None:
with Image.open(test_file) as im:
im.load()
assert im.mode == "RGB"
@ -39,8 +39,8 @@ def test_sanity(test_file):
@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
def test_unclosed_file():
def open():
def test_unclosed_file() -> None:
def open() -> None:
im = Image.open(test_files[0])
im.load()
@ -48,14 +48,14 @@ def test_unclosed_file():
open()
def test_closed_file():
def test_closed_file() -> None:
with warnings.catch_warnings():
im = Image.open(test_files[0])
im.load()
im.close()
def test_seek_after_close():
def test_seek_after_close() -> None:
im = Image.open(test_files[0])
im.close()
@ -63,14 +63,14 @@ def test_seek_after_close():
im.seek(1)
def test_context_manager():
def test_context_manager() -> None:
with warnings.catch_warnings():
with Image.open(test_files[0]) as im:
im.load()
@pytest.mark.parametrize("test_file", test_files)
def test_app(test_file):
def test_app(test_file) -> None:
# Test APP/COM reader (@PIL135)
with Image.open(test_file) as im:
assert im.applist[0][0] == "APP1"
@ -82,7 +82,7 @@ def test_app(test_file):
@pytest.mark.parametrize("test_file", test_files)
def test_exif(test_file):
def test_exif(test_file) -> None:
with Image.open(test_file) as im_original:
im_reloaded = roundtrip(im_original, save_all=True, exif=im_original.getexif())
@ -93,7 +93,7 @@ def test_exif(test_file):
assert info[34665] == 188
def test_frame_size():
def test_frame_size() -> None:
# This image has been hexedited to contain a different size
# in the EXIF data of the second frame
with Image.open("Tests/images/sugarshack_frame_size.mpo") as im:
@ -106,7 +106,7 @@ def test_frame_size():
assert im.size == (640, 480)
def test_ignore_frame_size():
def test_ignore_frame_size() -> None:
# Ignore the different size of the second frame
# since this is not a "Large Thumbnail" image
with Image.open("Tests/images/ignore_frame_size.mpo") as im:
@ -120,7 +120,7 @@ def test_ignore_frame_size():
assert im.size == (64, 64)
def test_parallax():
def test_parallax() -> None:
# Nintendo
with Image.open("Tests/images/sugarshack.mpo") as im:
exif = im.getexif()
@ -133,7 +133,7 @@ def test_parallax():
assert exif.get_ifd(0x927C)[0xB211] == -3.125
def test_reload_exif_after_seek():
def test_reload_exif_after_seek() -> None:
with Image.open("Tests/images/sugarshack.mpo") as im:
exif = im.getexif()
del exif[296]
@ -143,14 +143,14 @@ def test_reload_exif_after_seek():
@pytest.mark.parametrize("test_file", test_files)
def test_mp(test_file):
def test_mp(test_file) -> None:
with Image.open(test_file) as im:
mpinfo = im._getmp()
assert mpinfo[45056] == b"0100"
assert mpinfo[45057] == 2
def test_mp_offset():
def test_mp_offset() -> None:
# This image has been manually hexedited to have an IFD offset of 10
# in APP2 data, in contrast to normal 8
with Image.open("Tests/images/sugarshack_ifd_offset.mpo") as im:
@ -159,7 +159,7 @@ def test_mp_offset():
assert mpinfo[45057] == 2
def test_mp_no_data():
def test_mp_no_data() -> None:
# This image has been manually hexedited to have the second frame
# beyond the end of the file
with Image.open("Tests/images/sugarshack_no_data.mpo") as im:
@ -168,7 +168,7 @@ def test_mp_no_data():
@pytest.mark.parametrize("test_file", test_files)
def test_mp_attribute(test_file):
def test_mp_attribute(test_file) -> None:
with Image.open(test_file) as im:
mpinfo = im._getmp()
for frame_number, mpentry in enumerate(mpinfo[0xB002]):
@ -185,7 +185,7 @@ def test_mp_attribute(test_file):
@pytest.mark.parametrize("test_file", test_files)
def test_seek(test_file):
def test_seek(test_file) -> None:
with Image.open(test_file) as im:
assert im.tell() == 0
# prior to first image raises an error, both blatant and borderline
@ -209,13 +209,13 @@ def test_seek(test_file):
assert im.tell() == 0
def test_n_frames():
def test_n_frames() -> None:
with Image.open("Tests/images/sugarshack.mpo") as im:
assert im.n_frames == 2
assert im.is_animated
def test_eoferror():
def test_eoferror() -> None:
with Image.open("Tests/images/sugarshack.mpo") as im:
n_frames = im.n_frames
@ -229,7 +229,7 @@ def test_eoferror():
@pytest.mark.parametrize("test_file", test_files)
def test_image_grab(test_file):
def test_image_grab(test_file) -> None:
with Image.open(test_file) as im:
assert im.tell() == 0
im0 = im.tobytes()
@ -244,7 +244,7 @@ def test_image_grab(test_file):
@pytest.mark.parametrize("test_file", test_files)
def test_save(test_file):
def test_save(test_file) -> None:
with Image.open(test_file) as im:
assert im.tell() == 0
jpg0 = roundtrip(im)
@ -255,7 +255,7 @@ def test_save(test_file):
assert_image_similar(im, jpg1, 30)
def test_save_all():
def test_save_all() -> None:
for test_file in test_files:
with Image.open(test_file) as im:
im_reloaded = roundtrip(im, save_all=True)

View File

@ -1,6 +1,7 @@
from __future__ import annotations
import os
from pathlib import Path
import pytest
@ -13,7 +14,7 @@ EXTRA_DIR = "Tests/images/picins"
YA_EXTRA_DIR = "Tests/images/msp"
def test_sanity(tmp_path):
def test_sanity(tmp_path: Path) -> None:
test_file = str(tmp_path / "temp.msp")
hopper("1").save(test_file)
@ -25,14 +26,14 @@ def test_sanity(tmp_path):
assert im.format == "MSP"
def test_invalid_file():
def test_invalid_file() -> None:
invalid_file = "Tests/images/flower.jpg"
with pytest.raises(SyntaxError):
MspImagePlugin.MspImageFile(invalid_file)
def test_bad_checksum():
def test_bad_checksum() -> None:
# Arrange
# This was created by forcing Pillow to save with checksum=0
bad_checksum = "Tests/images/hopper_bad_checksum.msp"
@ -42,7 +43,7 @@ def test_bad_checksum():
MspImagePlugin.MspImageFile(bad_checksum)
def test_open_windows_v1():
def test_open_windows_v1() -> None:
# Arrange
# Act
with Image.open(TEST_FILE) as im:
@ -51,7 +52,7 @@ def test_open_windows_v1():
assert isinstance(im, MspImagePlugin.MspImageFile)
def _assert_file_image_equal(source_path, target_path):
def _assert_file_image_equal(source_path, target_path) -> None:
with Image.open(source_path) as im:
assert_image_equal_tofile(im, target_path)
@ -59,7 +60,7 @@ def _assert_file_image_equal(source_path, target_path):
@pytest.mark.skipif(
not os.path.exists(EXTRA_DIR), reason="Extra image files not installed"
)
def test_open_windows_v2():
def test_open_windows_v2() -> None:
files = (
os.path.join(EXTRA_DIR, f)
for f in os.listdir(EXTRA_DIR)
@ -72,7 +73,7 @@ def test_open_windows_v2():
@pytest.mark.skipif(
not os.path.exists(YA_EXTRA_DIR), reason="Even More Extra image files not installed"
)
def test_msp_v2():
def test_msp_v2() -> None:
for f in os.listdir(YA_EXTRA_DIR):
if ".MSP" not in f:
continue
@ -80,7 +81,7 @@ def test_msp_v2():
_assert_file_image_equal(path, path.replace(".MSP", ".png"))
def test_cannot_save_wrong_mode(tmp_path):
def test_cannot_save_wrong_mode(tmp_path: Path) -> None:
# Arrange
im = hopper()
filename = str(tmp_path / "temp.msp")

View File

@ -2,6 +2,7 @@ from __future__ import annotations
import os.path
import subprocess
from pathlib import Path
import pytest
@ -10,7 +11,7 @@ from PIL import Image
from .helper import assert_image_equal, hopper, magick_command
def helper_save_as_palm(tmp_path, mode):
def helper_save_as_palm(tmp_path: Path, mode) -> None:
# Arrange
im = hopper(mode)
outfile = str(tmp_path / ("temp_" + mode + ".palm"))
@ -23,7 +24,7 @@ def helper_save_as_palm(tmp_path, mode):
assert os.path.getsize(outfile) > 0
def open_with_magick(magick, tmp_path, f):
def open_with_magick(magick, tmp_path: Path, f):
outfile = str(tmp_path / "temp.png")
rc = subprocess.call(
magick + [f, outfile], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT
@ -32,7 +33,7 @@ def open_with_magick(magick, tmp_path, f):
return Image.open(outfile)
def roundtrip(tmp_path, mode):
def roundtrip(tmp_path: Path, mode) -> None:
magick = magick_command()
if not magick:
return
@ -45,7 +46,7 @@ def roundtrip(tmp_path, mode):
assert_image_equal(converted, im)
def test_monochrome(tmp_path):
def test_monochrome(tmp_path: Path) -> None:
# Arrange
mode = "1"
@ -55,7 +56,7 @@ def test_monochrome(tmp_path):
@pytest.mark.xfail(reason="Palm P image is wrong")
def test_p_mode(tmp_path):
def test_p_mode(tmp_path: Path) -> None:
# Arrange
mode = "P"
@ -65,6 +66,6 @@ def test_p_mode(tmp_path):
@pytest.mark.parametrize("mode", ("L", "RGB"))
def test_oserror(tmp_path, mode):
def test_oserror(tmp_path: Path, mode) -> None:
with pytest.raises(OSError):
helper_save_as_palm(tmp_path, mode)

View File

@ -1,5 +1,7 @@
from __future__ import annotations
from pathlib import Path
import pytest
from PIL import Image, ImageFile, PcxImagePlugin
@ -7,7 +9,7 @@ from PIL import Image, ImageFile, PcxImagePlugin
from .helper import assert_image_equal, hopper
def _roundtrip(tmp_path, im):
def _roundtrip(tmp_path: Path, im) -> None:
f = str(tmp_path / "temp.pcx")
im.save(f)
with Image.open(f) as im2:
@ -18,7 +20,7 @@ def _roundtrip(tmp_path, im):
assert_image_equal(im2, im)
def test_sanity(tmp_path):
def test_sanity(tmp_path: Path) -> None:
for mode in ("1", "L", "P", "RGB"):
_roundtrip(tmp_path, hopper(mode))
@ -34,7 +36,7 @@ def test_sanity(tmp_path):
im.save(f)
def test_invalid_file():
def test_invalid_file() -> None:
invalid_file = "Tests/images/flower.jpg"
with pytest.raises(SyntaxError):
@ -42,7 +44,7 @@ def test_invalid_file():
@pytest.mark.parametrize("mode", ("1", "L", "P", "RGB"))
def test_odd(tmp_path, mode):
def test_odd(tmp_path: Path, mode) -> None:
# See issue #523, odd sized images should have a stride that's even.
# Not that ImageMagick or GIMP write PCX that way.
# We were not handling properly.
@ -51,7 +53,7 @@ def test_odd(tmp_path, mode):
_roundtrip(tmp_path, hopper(mode).resize((511, 511)))
def test_odd_read():
def test_odd_read() -> None:
# Reading an image with an odd stride, making it malformed
with Image.open("Tests/images/odd_stride.pcx") as im:
im.load()
@ -59,7 +61,7 @@ def test_odd_read():
assert im.size == (371, 150)
def test_pil184():
def test_pil184() -> None:
# Check reading of files where xmin/xmax is not zero.
test_file = "Tests/images/pil184.pcx"
@ -71,7 +73,7 @@ def test_pil184():
assert im.histogram()[0] + im.histogram()[255] == 447 * 144
def test_1px_width(tmp_path):
def test_1px_width(tmp_path: Path) -> None:
im = Image.new("L", (1, 256))
px = im.load()
for y in range(256):
@ -79,7 +81,7 @@ def test_1px_width(tmp_path):
_roundtrip(tmp_path, im)
def test_large_count(tmp_path):
def test_large_count(tmp_path: Path) -> None:
im = Image.new("L", (256, 1))
px = im.load()
for x in range(256):
@ -87,7 +89,7 @@ def test_large_count(tmp_path):
_roundtrip(tmp_path, im)
def _test_buffer_overflow(tmp_path, im, size=1024):
def _test_buffer_overflow(tmp_path: Path, im, size: int = 1024) -> None:
_last = ImageFile.MAXBLOCK
ImageFile.MAXBLOCK = size
try:
@ -96,7 +98,7 @@ def _test_buffer_overflow(tmp_path, im, size=1024):
ImageFile.MAXBLOCK = _last
def test_break_in_count_overflow(tmp_path):
def test_break_in_count_overflow(tmp_path: Path) -> None:
im = Image.new("L", (256, 5))
px = im.load()
for y in range(4):
@ -105,7 +107,7 @@ def test_break_in_count_overflow(tmp_path):
_test_buffer_overflow(tmp_path, im)
def test_break_one_in_loop(tmp_path):
def test_break_one_in_loop(tmp_path: Path) -> None:
im = Image.new("L", (256, 5))
px = im.load()
for y in range(5):
@ -114,7 +116,7 @@ def test_break_one_in_loop(tmp_path):
_test_buffer_overflow(tmp_path, im)
def test_break_many_in_loop(tmp_path):
def test_break_many_in_loop(tmp_path: Path) -> None:
im = Image.new("L", (256, 5))
px = im.load()
for y in range(4):
@ -125,7 +127,7 @@ def test_break_many_in_loop(tmp_path):
_test_buffer_overflow(tmp_path, im)
def test_break_one_at_end(tmp_path):
def test_break_one_at_end(tmp_path: Path) -> None:
im = Image.new("L", (256, 5))
px = im.load()
for y in range(5):
@ -135,7 +137,7 @@ def test_break_one_at_end(tmp_path):
_test_buffer_overflow(tmp_path, im)
def test_break_many_at_end(tmp_path):
def test_break_many_at_end(tmp_path: Path) -> None:
im = Image.new("L", (256, 5))
px = im.load()
for y in range(5):
@ -147,7 +149,7 @@ def test_break_many_at_end(tmp_path):
_test_buffer_overflow(tmp_path, im)
def test_break_padding(tmp_path):
def test_break_padding(tmp_path: Path) -> None:
im = Image.new("L", (257, 5))
px = im.load()
for y in range(5):

View File

@ -5,6 +5,7 @@ import os
import os.path
import tempfile
import time
from pathlib import Path
import pytest
@ -13,7 +14,7 @@ from PIL import Image, PdfParser, features
from .helper import hopper, mark_if_feature_version, skip_unless_feature
def helper_save_as_pdf(tmp_path, mode, **kwargs):
def helper_save_as_pdf(tmp_path: Path, mode, **kwargs):
# Arrange
im = hopper(mode)
outfile = str(tmp_path / ("temp_" + mode + ".pdf"))
@ -40,17 +41,17 @@ def helper_save_as_pdf(tmp_path, mode, **kwargs):
@pytest.mark.parametrize("mode", ("L", "P", "RGB", "CMYK"))
def test_save(tmp_path, mode):
def test_save(tmp_path: Path, mode) -> None:
helper_save_as_pdf(tmp_path, mode)
@skip_unless_feature("jpg_2000")
@pytest.mark.parametrize("mode", ("LA", "RGBA"))
def test_save_alpha(tmp_path, mode):
def test_save_alpha(tmp_path: Path, mode) -> None:
helper_save_as_pdf(tmp_path, mode)
def test_p_alpha(tmp_path):
def test_p_alpha(tmp_path: Path) -> None:
# Arrange
outfile = str(tmp_path / "temp.pdf")
with Image.open("Tests/images/pil123p.png") as im:
@ -66,7 +67,7 @@ def test_p_alpha(tmp_path):
assert b"\n/SMask " in contents
def test_monochrome(tmp_path):
def test_monochrome(tmp_path: Path) -> None:
# Arrange
mode = "1"
@ -75,7 +76,7 @@ def test_monochrome(tmp_path):
assert os.path.getsize(outfile) < (5000 if features.check("libtiff") else 15000)
def test_unsupported_mode(tmp_path):
def test_unsupported_mode(tmp_path: Path) -> None:
im = hopper("PA")
outfile = str(tmp_path / "temp_PA.pdf")
@ -83,7 +84,7 @@ def test_unsupported_mode(tmp_path):
im.save(outfile)
def test_resolution(tmp_path):
def test_resolution(tmp_path: Path) -> None:
im = hopper()
outfile = str(tmp_path / "temp.pdf")
@ -111,7 +112,7 @@ def test_resolution(tmp_path):
{"dpi": (75, 150), "resolution": 200},
),
)
def test_dpi(params, tmp_path):
def test_dpi(params, tmp_path: Path) -> None:
im = hopper()
outfile = str(tmp_path / "temp.pdf")
@ -135,7 +136,7 @@ def test_dpi(params, tmp_path):
@mark_if_feature_version(
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
)
def test_save_all(tmp_path):
def test_save_all(tmp_path: Path) -> None:
# Single frame image
helper_save_as_pdf(tmp_path, "RGB", save_all=True)
@ -171,7 +172,7 @@ def test_save_all(tmp_path):
assert os.path.getsize(outfile) > 0
def test_multiframe_normal_save(tmp_path):
def test_multiframe_normal_save(tmp_path: Path) -> None:
# Test saving a multiframe image without save_all
with Image.open("Tests/images/dispose_bgnd.gif") as im:
outfile = str(tmp_path / "temp.pdf")
@ -181,7 +182,7 @@ def test_multiframe_normal_save(tmp_path):
assert os.path.getsize(outfile) > 0
def test_pdf_open(tmp_path):
def test_pdf_open(tmp_path: Path) -> None:
# fail on a buffer full of null bytes
with pytest.raises(PdfParser.PdfFormatError):
PdfParser.PdfParser(buf=bytearray(65536))
@ -218,14 +219,14 @@ def test_pdf_open(tmp_path):
assert not hopper_pdf.should_close_file
def test_pdf_append_fails_on_nonexistent_file():
def test_pdf_append_fails_on_nonexistent_file() -> None:
im = hopper("RGB")
with tempfile.TemporaryDirectory() as temp_dir:
with pytest.raises(OSError):
im.save(os.path.join(temp_dir, "nonexistent.pdf"), append=True)
def check_pdf_pages_consistency(pdf):
def check_pdf_pages_consistency(pdf) -> None:
pages_info = pdf.read_indirect(pdf.pages_ref)
assert b"Parent" not in pages_info
assert b"Kids" in pages_info
@ -243,7 +244,7 @@ def check_pdf_pages_consistency(pdf):
assert kids_not_used == []
def test_pdf_append(tmp_path):
def test_pdf_append(tmp_path: Path) -> None:
# make a PDF file
pdf_filename = helper_save_as_pdf(tmp_path, "RGB", producer="PdfParser")
@ -294,7 +295,7 @@ def test_pdf_append(tmp_path):
check_pdf_pages_consistency(pdf)
def test_pdf_info(tmp_path):
def test_pdf_info(tmp_path: Path) -> None:
# make a PDF file
pdf_filename = helper_save_as_pdf(
tmp_path,
@ -323,7 +324,7 @@ def test_pdf_info(tmp_path):
check_pdf_pages_consistency(pdf)
def test_pdf_append_to_bytesio():
def test_pdf_append_to_bytesio() -> None:
im = hopper("RGB")
f = io.BytesIO()
im.save(f, format="PDF")
@ -338,7 +339,7 @@ def test_pdf_append_to_bytesio():
@pytest.mark.timeout(1)
@pytest.mark.skipif("PILLOW_VALGRIND_TEST" in os.environ, reason="Valgrind is slower")
@pytest.mark.parametrize("newline", (b"\r", b"\n"))
def test_redos(newline):
def test_redos(newline) -> None:
malicious = b" trailer<<>>" + newline * 3456
# This particular exception isn't relevant here.

View File

@ -5,6 +5,7 @@ import sys
import warnings
import zlib
from io import BytesIO
from pathlib import Path
import pytest
@ -79,7 +80,7 @@ class TestFilePng:
png.crc(cid, s)
return chunks
def test_sanity(self, tmp_path):
def test_sanity(self, tmp_path: Path) -> None:
# internal version number
assert re.search(r"\d+(\.\d+){1,3}$", features.version_codec("zlib"))
@ -102,13 +103,13 @@ class TestFilePng:
reloaded = reloaded.convert(mode)
assert_image_equal(reloaded, im)
def test_invalid_file(self):
def test_invalid_file(self) -> None:
invalid_file = "Tests/images/flower.jpg"
with pytest.raises(SyntaxError):
PngImagePlugin.PngImageFile(invalid_file)
def test_broken(self):
def test_broken(self) -> None:
# Check reading of totally broken files. In this case, the test
# file was checked into Subversion as a text file.
@ -117,7 +118,7 @@ class TestFilePng:
with Image.open(test_file):
pass
def test_bad_text(self):
def test_bad_text(self) -> None:
# Make sure PIL can read malformed tEXt chunks (@PIL152)
im = load(HEAD + chunk(b"tEXt") + TAIL)
@ -135,7 +136,7 @@ class TestFilePng:
im = load(HEAD + chunk(b"tEXt", b"spam\0egg\0") + TAIL)
assert im.info == {"spam": "egg\x00"}
def test_bad_ztxt(self):
def test_bad_ztxt(self) -> None:
# Test reading malformed zTXt chunks (python-pillow/Pillow#318)
im = load(HEAD + chunk(b"zTXt") + TAIL)
@ -156,7 +157,7 @@ class TestFilePng:
im = load(HEAD + chunk(b"zTXt", b"spam\0\0" + zlib.compress(b"egg")) + TAIL)
assert im.info == {"spam": "egg"}
def test_bad_itxt(self):
def test_bad_itxt(self) -> None:
im = load(HEAD + chunk(b"iTXt") + TAIL)
assert im.info == {}
@ -200,7 +201,7 @@ class TestFilePng:
assert im.info["spam"].lang == "en"
assert im.info["spam"].tkey == "Spam"
def test_interlace(self):
def test_interlace(self) -> None:
test_file = "Tests/images/pil123p.png"
with Image.open(test_file) as im:
assert_image(im, "P", (162, 150))
@ -215,7 +216,7 @@ class TestFilePng:
im.load()
def test_load_transparent_p(self):
def test_load_transparent_p(self) -> None:
test_file = "Tests/images/pil123p.png"
with Image.open(test_file) as im:
assert_image(im, "P", (162, 150))
@ -225,7 +226,7 @@ class TestFilePng:
# image has 124 unique alpha values
assert len(im.getchannel("A").getcolors()) == 124
def test_load_transparent_rgb(self):
def test_load_transparent_rgb(self) -> None:
test_file = "Tests/images/rgb_trns.png"
with Image.open(test_file) as im:
assert im.info["transparency"] == (0, 255, 52)
@ -237,7 +238,7 @@ class TestFilePng:
# image has 876 transparent pixels
assert im.getchannel("A").getcolors()[0][0] == 876
def test_save_p_transparent_palette(self, tmp_path):
def test_save_p_transparent_palette(self, tmp_path: Path) -> None:
in_file = "Tests/images/pil123p.png"
with Image.open(in_file) as im:
# 'transparency' contains a byte string with the opacity for
@ -258,7 +259,7 @@ class TestFilePng:
# image has 124 unique alpha values
assert len(im.getchannel("A").getcolors()) == 124
def test_save_p_single_transparency(self, tmp_path):
def test_save_p_single_transparency(self, tmp_path: Path) -> None:
in_file = "Tests/images/p_trns_single.png"
with Image.open(in_file) as im:
# pixel value 164 is full transparent
@ -281,7 +282,7 @@ class TestFilePng:
# image has 876 transparent pixels
assert im.getchannel("A").getcolors()[0][0] == 876
def test_save_p_transparent_black(self, tmp_path):
def test_save_p_transparent_black(self, tmp_path: Path) -> None:
# check if solid black image with full transparency
# is supported (check for #1838)
im = Image.new("RGBA", (10, 10), (0, 0, 0, 0))
@ -299,7 +300,7 @@ class TestFilePng:
assert_image(im, "RGBA", (10, 10))
assert im.getcolors() == [(100, (0, 0, 0, 0))]
def test_save_grayscale_transparency(self, tmp_path):
def test_save_grayscale_transparency(self, tmp_path: Path) -> None:
for mode, num_transparent in {"1": 1994, "L": 559, "I": 559}.items():
in_file = "Tests/images/" + mode.lower() + "_trns.png"
with Image.open(in_file) as im:
@ -320,13 +321,13 @@ class TestFilePng:
test_im_rgba = test_im.convert("RGBA")
assert test_im_rgba.getchannel("A").getcolors()[0][0] == num_transparent
def test_save_rgb_single_transparency(self, tmp_path):
def test_save_rgb_single_transparency(self, tmp_path: Path) -> None:
in_file = "Tests/images/caption_6_33_22.png"
with Image.open(in_file) as im:
test_file = str(tmp_path / "temp.png")
im.save(test_file)
def test_load_verify(self):
def test_load_verify(self) -> None:
# Check open/load/verify exception (@PIL150)
with Image.open(TEST_PNG_FILE) as im:
@ -339,7 +340,7 @@ class TestFilePng:
with pytest.raises(RuntimeError):
im.verify()
def test_verify_struct_error(self):
def test_verify_struct_error(self) -> None:
# Check open/load/verify exception (#1755)
# offsets to test, -10: breaks in i32() in read. (OSError)
@ -355,7 +356,7 @@ class TestFilePng:
with pytest.raises((OSError, SyntaxError)):
im.verify()
def test_verify_ignores_crc_error(self):
def test_verify_ignores_crc_error(self) -> None:
# check ignores crc errors in ancillary chunks
chunk_data = chunk(b"tEXt", b"spam")
@ -372,7 +373,7 @@ class TestFilePng:
finally:
ImageFile.LOAD_TRUNCATED_IMAGES = False
def test_verify_not_ignores_crc_error_in_required_chunk(self):
def test_verify_not_ignores_crc_error_in_required_chunk(self) -> None:
# check does not ignore crc errors in required chunks
image_data = MAGIC + IHDR[:-1] + b"q" + TAIL
@ -384,18 +385,18 @@ class TestFilePng:
finally:
ImageFile.LOAD_TRUNCATED_IMAGES = False
def test_roundtrip_dpi(self):
def test_roundtrip_dpi(self) -> None:
# Check dpi roundtripping
with Image.open(TEST_PNG_FILE) as im:
im = roundtrip(im, dpi=(100.33, 100.33))
assert im.info["dpi"] == (100.33, 100.33)
def test_load_float_dpi(self):
def test_load_float_dpi(self) -> None:
with Image.open(TEST_PNG_FILE) as im:
assert im.info["dpi"] == (95.9866, 95.9866)
def test_roundtrip_text(self):
def test_roundtrip_text(self) -> None:
# Check text roundtripping
with Image.open(TEST_PNG_FILE) as im:
@ -407,7 +408,7 @@ class TestFilePng:
assert im.info == {"TXT": "VALUE", "ZIP": "VALUE"}
assert im.text == {"TXT": "VALUE", "ZIP": "VALUE"}
def test_roundtrip_itxt(self):
def test_roundtrip_itxt(self) -> None:
# Check iTXt roundtripping
im = Image.new("RGB", (32, 32))
@ -423,7 +424,7 @@ class TestFilePng:
assert im.text["eggs"].lang == "en"
assert im.text["eggs"].tkey == "Eggs"
def test_nonunicode_text(self):
def test_nonunicode_text(self) -> None:
# Check so that non-Unicode text is saved as a tEXt rather than iTXt
im = Image.new("RGB", (32, 32))
@ -432,10 +433,10 @@ class TestFilePng:
im = roundtrip(im, pnginfo=info)
assert isinstance(im.info["Text"], str)
def test_unicode_text(self):
def test_unicode_text(self) -> None:
# Check preservation of non-ASCII characters
def rt_text(value):
def rt_text(value) -> None:
im = Image.new("RGB", (32, 32))
info = PngImagePlugin.PngInfo()
info.add_text("Text", value)
@ -448,7 +449,7 @@ class TestFilePng:
rt_text(chr(0x4E00) + chr(0x66F0) + chr(0x9FBA) + chr(0x3042) + chr(0xAC00))
rt_text("A" + chr(0xC4) + chr(0x472) + chr(0x3042)) # Combined
def test_scary(self):
def test_scary(self) -> None:
# Check reading of evil PNG file. For information, see:
# http://scary.beasts.org/security/CESA-2004-001.txt
# The first byte is removed from pngtest_bad.png
@ -462,7 +463,7 @@ class TestFilePng:
with Image.open(pngfile):
pass
def test_trns_rgb(self):
def test_trns_rgb(self) -> None:
# Check writing and reading of tRNS chunks for RGB images.
# Independent file sample provided by Sebastian Spaeth.
@ -477,7 +478,7 @@ class TestFilePng:
im = roundtrip(im, transparency=(0, 1, 2))
assert im.info["transparency"] == (0, 1, 2)
def test_trns_p(self, tmp_path):
def test_trns_p(self, tmp_path: Path) -> None:
# Check writing a transparency of 0, issue #528
im = hopper("P")
im.info["transparency"] = 0
@ -490,13 +491,13 @@ class TestFilePng:
assert_image_equal(im2.convert("RGBA"), im.convert("RGBA"))
def test_trns_null(self):
def test_trns_null(self) -> None:
# Check reading images with null tRNS value, issue #1239
test_file = "Tests/images/tRNS_null_1x1.png"
with Image.open(test_file) as im:
assert im.info["transparency"] == 0
def test_save_icc_profile(self):
def test_save_icc_profile(self) -> None:
with Image.open("Tests/images/icc_profile_none.png") as im:
assert im.info["icc_profile"] is None
@ -506,40 +507,40 @@ class TestFilePng:
im = roundtrip(im, icc_profile=expected_icc)
assert im.info["icc_profile"] == expected_icc
def test_discard_icc_profile(self):
def test_discard_icc_profile(self) -> None:
with Image.open("Tests/images/icc_profile.png") as im:
assert "icc_profile" in im.info
im = roundtrip(im, icc_profile=None)
assert "icc_profile" not in im.info
def test_roundtrip_icc_profile(self):
def test_roundtrip_icc_profile(self) -> None:
with Image.open("Tests/images/icc_profile.png") as im:
expected_icc = im.info["icc_profile"]
im = roundtrip(im)
assert im.info["icc_profile"] == expected_icc
def test_roundtrip_no_icc_profile(self):
def test_roundtrip_no_icc_profile(self) -> None:
with Image.open("Tests/images/icc_profile_none.png") as im:
assert im.info["icc_profile"] is None
im = roundtrip(im)
assert "icc_profile" not in im.info
def test_repr_png(self):
def test_repr_png(self) -> None:
im = hopper()
with Image.open(BytesIO(im._repr_png_())) as repr_png:
assert repr_png.format == "PNG"
assert_image_equal(im, repr_png)
def test_repr_png_error_returns_none(self):
def test_repr_png_error_returns_none(self) -> None:
im = hopper("F")
assert im._repr_png_() is None
def test_chunk_order(self, tmp_path):
def test_chunk_order(self, tmp_path: Path) -> None:
with Image.open("Tests/images/icc_profile.png") as im:
test_file = str(tmp_path / "temp.png")
im.convert("P").save(test_file, dpi=(100, 100))
@ -560,17 +561,17 @@ class TestFilePng:
# pHYs - before IDAT
assert chunks.index(b"pHYs") < chunks.index(b"IDAT")
def test_getchunks(self):
def test_getchunks(self) -> None:
im = hopper()
chunks = PngImagePlugin.getchunks(im)
assert len(chunks) == 3
def test_read_private_chunks(self):
def test_read_private_chunks(self) -> None:
with Image.open("Tests/images/exif.png") as im:
assert im.private_chunks == [(b"orNT", b"\x01")]
def test_roundtrip_private_chunk(self):
def test_roundtrip_private_chunk(self) -> None:
# Check private chunk roundtripping
with Image.open(TEST_PNG_FILE) as im:
@ -588,7 +589,7 @@ class TestFilePng:
(b"prIV", b"VALUE3", True),
]
def test_textual_chunks_after_idat(self):
def test_textual_chunks_after_idat(self) -> None:
with Image.open("Tests/images/hopper.png") as im:
assert "comment" in im.text
for k, v in {
@ -615,7 +616,7 @@ class TestFilePng:
with Image.open("Tests/images/hopper_idat_after_image_end.png") as im:
assert im.text == {"TXT": "VALUE", "ZIP": "VALUE"}
def test_padded_idat(self):
def test_padded_idat(self) -> None:
# This image has been manually hexedited
# so that the IDAT chunk has padding at the end
# Set MAXBLOCK to the length of the actual data
@ -635,7 +636,7 @@ class TestFilePng:
@pytest.mark.parametrize(
"cid", (b"IHDR", b"sRGB", b"pHYs", b"acTL", b"fcTL", b"fdAT")
)
def test_truncated_chunks(self, cid):
def test_truncated_chunks(self, cid) -> None:
fp = BytesIO()
with PngImagePlugin.PngStream(fp) as png:
with pytest.raises(ValueError):
@ -645,7 +646,7 @@ class TestFilePng:
png.call(cid, 0, 0)
ImageFile.LOAD_TRUNCATED_IMAGES = False
def test_specify_bits(self, tmp_path):
def test_specify_bits(self, tmp_path: Path) -> None:
im = hopper("P")
out = str(tmp_path / "temp.png")
@ -654,7 +655,7 @@ class TestFilePng:
with Image.open(out) as reloaded:
assert len(reloaded.png.im_palette[1]) == 48
def test_plte_length(self, tmp_path):
def test_plte_length(self, tmp_path: Path) -> None:
im = Image.new("P", (1, 1))
im.putpalette((1, 1, 1))
@ -664,7 +665,7 @@ class TestFilePng:
with Image.open(out) as reloaded:
assert len(reloaded.png.im_palette[1]) == 3
def test_getxmp(self):
def test_getxmp(self) -> None:
with Image.open("Tests/images/color_snakes.png") as im:
if ElementTree is None:
with pytest.warns(
@ -679,7 +680,7 @@ class TestFilePng:
assert description["PixelXDimension"] == "10"
assert description["subject"]["Seq"] is None
def test_exif(self):
def test_exif(self) -> None:
# With an EXIF chunk
with Image.open("Tests/images/exif.png") as im:
exif = im._getexif()
@ -705,7 +706,7 @@ class TestFilePng:
exif = im.getexif()
assert exif[274] == 3
def test_exif_save(self, tmp_path):
def test_exif_save(self, tmp_path: Path) -> None:
# Test exif is not saved from info
test_file = str(tmp_path / "temp.png")
with Image.open("Tests/images/exif.png") as im:
@ -725,7 +726,7 @@ class TestFilePng:
@mark_if_feature_version(
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
)
def test_exif_from_jpg(self, tmp_path):
def test_exif_from_jpg(self, tmp_path: Path) -> None:
with Image.open("Tests/images/pil_sample_rgb.jpg") as im:
test_file = str(tmp_path / "temp.png")
im.save(test_file, exif=im.getexif())
@ -734,7 +735,7 @@ class TestFilePng:
exif = reloaded._getexif()
assert exif[305] == "Adobe Photoshop CS Macintosh"
def test_exif_argument(self, tmp_path):
def test_exif_argument(self, tmp_path: Path) -> None:
with Image.open(TEST_PNG_FILE) as im:
test_file = str(tmp_path / "temp.png")
im.save(test_file, exif=b"exifstring")
@ -742,11 +743,11 @@ class TestFilePng:
with Image.open(test_file) as reloaded:
assert reloaded.info["exif"] == b"Exif\x00\x00exifstring"
def test_tell(self):
def test_tell(self) -> None:
with Image.open(TEST_PNG_FILE) as im:
assert im.tell() == 0
def test_seek(self):
def test_seek(self) -> None:
with Image.open(TEST_PNG_FILE) as im:
im.seek(0)
@ -754,7 +755,7 @@ class TestFilePng:
im.seek(1)
@pytest.mark.parametrize("buffer", (True, False))
def test_save_stdout(self, buffer):
def test_save_stdout(self, buffer) -> None:
old_stdout = sys.stdout
if buffer:
@ -786,7 +787,7 @@ class TestTruncatedPngPLeaks(PillowLeakTestCase):
mem_limit = 2 * 1024 # max increase in K
iterations = 100 # Leak is 56k/iteration, this will leak 5.6megs
def test_leak_load(self):
def test_leak_load(self) -> None:
with open("Tests/images/hopper.png", "rb") as f:
DATA = BytesIO(f.read(16 * 1024))
@ -794,7 +795,7 @@ class TestTruncatedPngPLeaks(PillowLeakTestCase):
with Image.open(DATA) as im:
im.load()
def core():
def core() -> None:
with Image.open(DATA) as im:
im.load()

View File

@ -2,6 +2,7 @@ from __future__ import annotations
import sys
from io import BytesIO
from pathlib import Path
import pytest
@ -18,7 +19,7 @@ from .helper import (
TEST_FILE = "Tests/images/hopper.ppm"
def test_sanity():
def test_sanity() -> None:
with Image.open(TEST_FILE) as im:
assert im.mode == "RGB"
assert im.size == (128, 128)
@ -69,7 +70,7 @@ def test_sanity():
),
),
)
def test_arbitrary_maxval(data, mode, pixels):
def test_arbitrary_maxval(data, mode, pixels) -> None:
fp = BytesIO(data)
with Image.open(fp) as im:
assert im.size == (3, 1)
@ -79,7 +80,7 @@ def test_arbitrary_maxval(data, mode, pixels):
assert tuple(px[x, 0] for x in range(3)) == pixels
def test_16bit_pgm():
def test_16bit_pgm() -> None:
with Image.open("Tests/images/16_bit_binary.pgm") as im:
assert im.mode == "I"
assert im.size == (20, 100)
@ -88,7 +89,7 @@ def test_16bit_pgm():
assert_image_equal_tofile(im, "Tests/images/16_bit_binary_pgm.png")
def test_16bit_pgm_write(tmp_path):
def test_16bit_pgm_write(tmp_path: Path) -> None:
with Image.open("Tests/images/16_bit_binary.pgm") as im:
filename = str(tmp_path / "temp.pgm")
im.save(filename, "PPM")
@ -96,7 +97,7 @@ def test_16bit_pgm_write(tmp_path):
assert_image_equal_tofile(im, filename)
def test_pnm(tmp_path):
def test_pnm(tmp_path: Path) -> None:
with Image.open("Tests/images/hopper.pnm") as im:
assert_image_similar(im, hopper(), 0.0001)
@ -106,7 +107,7 @@ def test_pnm(tmp_path):
assert_image_equal_tofile(im, filename)
def test_pfm(tmp_path):
def test_pfm(tmp_path: Path) -> None:
with Image.open("Tests/images/hopper.pfm") as im:
assert im.info["scale"] == 1.0
assert_image_equal(im, hopper("F"))
@ -117,7 +118,7 @@ def test_pfm(tmp_path):
assert_image_equal_tofile(im, filename)
def test_pfm_big_endian(tmp_path):
def test_pfm_big_endian(tmp_path: Path) -> None:
with Image.open("Tests/images/hopper_be.pfm") as im:
assert im.info["scale"] == 2.5
assert_image_equal(im, hopper("F"))
@ -138,7 +139,7 @@ def test_pfm_big_endian(tmp_path):
b"Pf 1 1 -0.0 \0\0\0\0",
],
)
def test_pfm_invalid(data):
def test_pfm_invalid(data) -> None:
with pytest.raises(ValueError):
with Image.open(BytesIO(data)):
pass
@ -161,12 +162,12 @@ def test_pfm_invalid(data):
),
),
)
def test_plain(plain_path, raw_path):
def test_plain(plain_path, raw_path) -> None:
with Image.open(plain_path) as im:
assert_image_equal_tofile(im, raw_path)
def test_16bit_plain_pgm():
def test_16bit_plain_pgm() -> None:
# P2 with maxval 2 ** 16 - 1
with Image.open("Tests/images/hopper_16bit_plain.pgm") as im:
assert im.mode == "I"
@ -185,7 +186,7 @@ def test_16bit_plain_pgm():
(b"P3\n2 2\n255", b"0 0 0 001 1 1 2 2 2 255 255 255", 10**6),
),
)
def test_plain_data_with_comment(tmp_path, header, data, comment_count):
def test_plain_data_with_comment(tmp_path: Path, header, data, comment_count) -> None:
path1 = str(tmp_path / "temp1.ppm")
path2 = str(tmp_path / "temp2.ppm")
comment = b"# comment" * comment_count
@ -198,7 +199,7 @@ def test_plain_data_with_comment(tmp_path, header, data, comment_count):
@pytest.mark.parametrize("data", (b"P1\n128 128\n", b"P3\n128 128\n255\n"))
def test_plain_truncated_data(tmp_path, data):
def test_plain_truncated_data(tmp_path: Path, data) -> None:
path = str(tmp_path / "temp.ppm")
with open(path, "wb") as f:
f.write(data)
@ -209,7 +210,7 @@ def test_plain_truncated_data(tmp_path, data):
@pytest.mark.parametrize("data", (b"P1\n128 128\n1009", b"P3\n128 128\n255\n100A"))
def test_plain_invalid_data(tmp_path, data):
def test_plain_invalid_data(tmp_path: Path, data) -> None:
path = str(tmp_path / "temp.ppm")
with open(path, "wb") as f:
f.write(data)
@ -226,7 +227,7 @@ def test_plain_invalid_data(tmp_path, data):
b"P3\n128 128\n255\n012345678910 0", # token too long
),
)
def test_plain_ppm_token_too_long(tmp_path, data):
def test_plain_ppm_token_too_long(tmp_path: Path, data) -> None:
path = str(tmp_path / "temp.ppm")
with open(path, "wb") as f:
f.write(data)
@ -236,7 +237,7 @@ def test_plain_ppm_token_too_long(tmp_path, data):
im.load()
def test_plain_ppm_value_too_large(tmp_path):
def test_plain_ppm_value_too_large(tmp_path: Path) -> None:
path = str(tmp_path / "temp.ppm")
with open(path, "wb") as f:
f.write(b"P3\n128 128\n255\n256")
@ -246,12 +247,12 @@ def test_plain_ppm_value_too_large(tmp_path):
im.load()
def test_magic():
def test_magic() -> None:
with pytest.raises(SyntaxError):
PpmImagePlugin.PpmImageFile(fp=BytesIO(b"PyInvalid"))
def test_header_with_comments(tmp_path):
def test_header_with_comments(tmp_path: Path) -> None:
path = str(tmp_path / "temp.ppm")
with open(path, "wb") as f:
f.write(b"P6 #comment\n#comment\r12#comment\r8\n128 #comment\n255\n")
@ -260,7 +261,7 @@ def test_header_with_comments(tmp_path):
assert im.size == (128, 128)
def test_non_integer_token(tmp_path):
def test_non_integer_token(tmp_path: Path) -> None:
path = str(tmp_path / "temp.ppm")
with open(path, "wb") as f:
f.write(b"P6\nTEST")
@ -270,7 +271,7 @@ def test_non_integer_token(tmp_path):
pass
def test_header_token_too_long(tmp_path):
def test_header_token_too_long(tmp_path: Path) -> None:
path = str(tmp_path / "temp.ppm")
with open(path, "wb") as f:
f.write(b"P6\n 01234567890")
@ -282,7 +283,7 @@ def test_header_token_too_long(tmp_path):
assert str(e.value) == "Token too long in file header: 01234567890"
def test_truncated_file(tmp_path):
def test_truncated_file(tmp_path: Path) -> None:
# Test EOF in header
path = str(tmp_path / "temp.pgm")
with open(path, "wb") as f:
@ -301,7 +302,7 @@ def test_truncated_file(tmp_path):
im.load()
def test_not_enough_image_data(tmp_path):
def test_not_enough_image_data(tmp_path: Path) -> None:
path = str(tmp_path / "temp.ppm")
with open(path, "wb") as f:
f.write(b"P2 1 2 255 255")
@ -312,7 +313,7 @@ def test_not_enough_image_data(tmp_path):
@pytest.mark.parametrize("maxval", (b"0", b"65536"))
def test_invalid_maxval(maxval, tmp_path):
def test_invalid_maxval(maxval, tmp_path: Path) -> None:
path = str(tmp_path / "temp.ppm")
with open(path, "wb") as f:
f.write(b"P6\n3 1 " + maxval)
@ -324,7 +325,7 @@ def test_invalid_maxval(maxval, tmp_path):
assert str(e.value) == "maxval must be greater than 0 and less than 65536"
def test_neg_ppm():
def test_neg_ppm() -> None:
# Storage.c accepted negative values for xsize, ysize. the
# internal open_ppm function didn't check for sanity but it
# has been removed. The default opener doesn't accept negative
@ -335,7 +336,7 @@ def test_neg_ppm():
pass
def test_mimetypes(tmp_path):
def test_mimetypes(tmp_path: Path) -> None:
path = str(tmp_path / "temp.pgm")
with open(path, "wb") as f:
@ -350,7 +351,7 @@ def test_mimetypes(tmp_path):
@pytest.mark.parametrize("buffer", (True, False))
def test_save_stdout(buffer):
def test_save_stdout(buffer) -> None:
old_stdout = sys.stdout
if buffer:

View File

@ -11,7 +11,7 @@ from .helper import assert_image_equal_tofile, assert_image_similar, hopper, is_
test_file = "Tests/images/hopper.psd"
def test_sanity():
def test_sanity() -> None:
with Image.open(test_file) as im:
im.load()
assert im.mode == "RGB"
@ -24,8 +24,8 @@ def test_sanity():
@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
def test_unclosed_file():
def open():
def test_unclosed_file() -> None:
def open() -> None:
im = Image.open(test_file)
im.load()
@ -33,27 +33,27 @@ def test_unclosed_file():
open()
def test_closed_file():
def test_closed_file() -> None:
with warnings.catch_warnings():
im = Image.open(test_file)
im.load()
im.close()
def test_context_manager():
def test_context_manager() -> None:
with warnings.catch_warnings():
with Image.open(test_file) as im:
im.load()
def test_invalid_file():
def test_invalid_file() -> None:
invalid_file = "Tests/images/flower.jpg"
with pytest.raises(SyntaxError):
PsdImagePlugin.PsdImageFile(invalid_file)
def test_n_frames():
def test_n_frames() -> None:
with Image.open("Tests/images/hopper_merged.psd") as im:
assert im.n_frames == 1
assert not im.is_animated
@ -64,7 +64,7 @@ def test_n_frames():
assert im.is_animated
def test_eoferror():
def test_eoferror() -> None:
with Image.open(test_file) as im:
# PSD seek index starts at 1 rather than 0
n_frames = im.n_frames + 1
@ -78,7 +78,7 @@ def test_eoferror():
im.seek(n_frames - 1)
def test_seek_tell():
def test_seek_tell() -> None:
with Image.open(test_file) as im:
layer_number = im.tell()
assert layer_number == 1
@ -95,30 +95,30 @@ def test_seek_tell():
assert layer_number == 2
def test_seek_eoferror():
def test_seek_eoferror() -> None:
with Image.open(test_file) as im:
with pytest.raises(EOFError):
im.seek(-1)
def test_open_after_exclusive_load():
def test_open_after_exclusive_load() -> None:
with Image.open(test_file) as im:
im.load()
im.seek(im.tell() + 1)
im.load()
def test_rgba():
def test_rgba() -> None:
with Image.open("Tests/images/rgba.psd") as im:
assert_image_equal_tofile(im, "Tests/images/imagedraw_square.png")
def test_layer_skip():
def test_layer_skip() -> None:
with Image.open("Tests/images/five_channels.psd") as im:
assert im.n_frames == 1
def test_icc_profile():
def test_icc_profile() -> None:
with Image.open(test_file) as im:
assert "icc_profile" in im.info
@ -126,12 +126,12 @@ def test_icc_profile():
assert len(icc_profile) == 3144
def test_no_icc_profile():
def test_no_icc_profile() -> None:
with Image.open("Tests/images/hopper_merged.psd") as im:
assert "icc_profile" not in im.info
def test_combined_larger_than_size():
def test_combined_larger_than_size() -> None:
# The combined size of the individual parts is larger than the
# declared 'size' of the extra data field, resulting in a backwards seek.
@ -157,7 +157,7 @@ def test_combined_larger_than_size():
("Tests/images/timeout-dedc7a4ebd856d79b4359bbcc79e8ef231ce38f6.psd", OSError),
],
)
def test_crashes(test_file, raises):
def test_crashes(test_file, raises) -> None:
with open(test_file, "rb") as f:
with pytest.raises(raises):
with Image.open(f):

View File

@ -1,5 +1,7 @@
from __future__ import annotations
from pathlib import Path
import pytest
from PIL import Image, SgiImagePlugin
@ -12,7 +14,7 @@ from .helper import (
)
def test_rgb():
def test_rgb() -> None:
# Created with ImageMagick then renamed:
# convert hopper.ppm -compress None sgi:hopper.rgb
test_file = "Tests/images/hopper.rgb"
@ -22,11 +24,11 @@ def test_rgb():
assert im.get_format_mimetype() == "image/rgb"
def test_rgb16():
def test_rgb16() -> None:
assert_image_equal_tofile(hopper(), "Tests/images/hopper16.rgb")
def test_l():
def test_l() -> None:
# Created with ImageMagick
# convert hopper.ppm -monochrome -compress None sgi:hopper.bw
test_file = "Tests/images/hopper.bw"
@ -36,7 +38,7 @@ def test_l():
assert im.get_format_mimetype() == "image/sgi"
def test_rgba():
def test_rgba() -> None:
# Created with ImageMagick:
# convert transparent.png -compress None transparent.sgi
test_file = "Tests/images/transparent.sgi"
@ -46,7 +48,7 @@ def test_rgba():
assert im.get_format_mimetype() == "image/sgi"
def test_rle():
def test_rle() -> None:
# Created with ImageMagick:
# convert hopper.ppm hopper.sgi
test_file = "Tests/images/hopper.sgi"
@ -55,22 +57,22 @@ def test_rle():
assert_image_equal_tofile(im, "Tests/images/hopper.rgb")
def test_rle16():
def test_rle16() -> None:
test_file = "Tests/images/tv16.sgi"
with Image.open(test_file) as im:
assert_image_equal_tofile(im, "Tests/images/tv.rgb")
def test_invalid_file():
def test_invalid_file() -> None:
invalid_file = "Tests/images/flower.jpg"
with pytest.raises(ValueError):
SgiImagePlugin.SgiImageFile(invalid_file)
def test_write(tmp_path):
def roundtrip(img):
def test_write(tmp_path: Path) -> None:
def roundtrip(img) -> None:
out = str(tmp_path / "temp.sgi")
img.save(out, format="sgi")
assert_image_equal_tofile(img, out)
@ -89,7 +91,7 @@ def test_write(tmp_path):
roundtrip(Image.new("L", (10, 1)))
def test_write16(tmp_path):
def test_write16(tmp_path: Path) -> None:
test_file = "Tests/images/hopper16.rgb"
with Image.open(test_file) as im:
@ -99,7 +101,7 @@ def test_write16(tmp_path):
assert_image_equal_tofile(im, out)
def test_unsupported_mode(tmp_path):
def test_unsupported_mode(tmp_path: Path) -> None:
im = hopper("LA")
out = str(tmp_path / "temp.sgi")

View File

@ -3,6 +3,7 @@ from __future__ import annotations
import tempfile
import warnings
from io import BytesIO
from pathlib import Path
import pytest
@ -13,7 +14,7 @@ from .helper import assert_image_equal_tofile, hopper, is_pypy
TEST_FILE = "Tests/images/hopper.spider"
def test_sanity():
def test_sanity() -> None:
with Image.open(TEST_FILE) as im:
im.load()
assert im.mode == "F"
@ -22,8 +23,8 @@ def test_sanity():
@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
def test_unclosed_file():
def open():
def test_unclosed_file() -> None:
def open() -> None:
im = Image.open(TEST_FILE)
im.load()
@ -31,20 +32,20 @@ def test_unclosed_file():
open()
def test_closed_file():
def test_closed_file() -> None:
with warnings.catch_warnings():
im = Image.open(TEST_FILE)
im.load()
im.close()
def test_context_manager():
def test_context_manager() -> None:
with warnings.catch_warnings():
with Image.open(TEST_FILE) as im:
im.load()
def test_save(tmp_path):
def test_save(tmp_path: Path) -> None:
# Arrange
temp = str(tmp_path / "temp.spider")
im = hopper()
@ -59,7 +60,7 @@ def test_save(tmp_path):
assert im2.format == "SPIDER"
def test_tempfile():
def test_tempfile() -> None:
# Arrange
im = hopper()
@ -75,11 +76,11 @@ def test_tempfile():
assert reloaded.format == "SPIDER"
def test_is_spider_image():
def test_is_spider_image() -> None:
assert SpiderImagePlugin.isSpiderImage(TEST_FILE)
def test_tell():
def test_tell() -> None:
# Arrange
with Image.open(TEST_FILE) as im:
# Act
@ -89,13 +90,13 @@ def test_tell():
assert index == 0
def test_n_frames():
def test_n_frames() -> None:
with Image.open(TEST_FILE) as im:
assert im.n_frames == 1
assert not im.is_animated
def test_load_image_series():
def test_load_image_series() -> None:
# Arrange
not_spider_file = "Tests/images/hopper.ppm"
file_list = [TEST_FILE, not_spider_file, "path/not_found.ext"]
@ -109,7 +110,7 @@ def test_load_image_series():
assert img_list[0].size == (128, 128)
def test_load_image_series_no_input():
def test_load_image_series_no_input() -> None:
# Arrange
file_list = None
@ -120,7 +121,7 @@ def test_load_image_series_no_input():
assert img_list is None
def test_is_int_not_a_number():
def test_is_int_not_a_number() -> None:
# Arrange
not_a_number = "a"
@ -131,7 +132,7 @@ def test_is_int_not_a_number():
assert ret == 0
def test_invalid_file():
def test_invalid_file() -> None:
invalid_file = "Tests/images/invalid.spider"
with pytest.raises(OSError):
@ -139,20 +140,20 @@ def test_invalid_file():
pass
def test_nonstack_file():
def test_nonstack_file() -> None:
with Image.open(TEST_FILE) as im:
with pytest.raises(EOFError):
im.seek(0)
def test_nonstack_dos():
def test_nonstack_dos() -> None:
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():
def test_odd_size() -> None:
data = BytesIO()
width = 100
im = Image.new("F", (width, 64))

View File

@ -11,7 +11,7 @@ from .helper import assert_image_equal_tofile, assert_image_similar, hopper
EXTRA_DIR = "Tests/images/sunraster"
def test_sanity():
def test_sanity() -> None:
# Arrange
# Created with ImageMagick: convert hopper.jpg hopper.ras
test_file = "Tests/images/hopper.ras"
@ -28,7 +28,7 @@ def test_sanity():
SunImagePlugin.SunImageFile(invalid_file)
def test_im1():
def test_im1() -> None:
with Image.open("Tests/images/sunraster.im1") as im:
assert_image_equal_tofile(im, "Tests/images/sunraster.im1.png")
@ -36,7 +36,7 @@ def test_im1():
@pytest.mark.skipif(
not os.path.exists(EXTRA_DIR), reason="Extra image files not installed"
)
def test_others():
def test_others() -> None:
files = (
os.path.join(EXTRA_DIR, f)
for f in os.listdir(EXTRA_DIR)

View File

@ -19,7 +19,7 @@ TEST_TAR_FILE = "Tests/images/hopper.tar"
("jpg", "hopper.jpg", "JPEG"),
),
)
def test_sanity(codec, test_path, format):
def test_sanity(codec, test_path, format) -> None:
if features.check(codec):
with TarIO.TarIO(TEST_TAR_FILE, test_path) as tar:
with Image.open(tar) as im:
@ -30,18 +30,18 @@ def test_sanity(codec, test_path, format):
@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
def test_unclosed_file():
def test_unclosed_file() -> None:
with pytest.warns(ResourceWarning):
TarIO.TarIO(TEST_TAR_FILE, "hopper.jpg")
def test_close():
def test_close() -> None:
with warnings.catch_warnings():
tar = TarIO.TarIO(TEST_TAR_FILE, "hopper.jpg")
tar.close()
def test_contextmanager():
def test_contextmanager() -> None:
with warnings.catch_warnings():
with TarIO.TarIO(TEST_TAR_FILE, "hopper.jpg"):
pass

View File

@ -3,6 +3,7 @@ from __future__ import annotations
import os
from glob import glob
from itertools import product
from pathlib import Path
import pytest
@ -21,8 +22,8 @@ _ORIGIN_TO_ORIENTATION = {"tl": 1, "bl": -1}
@pytest.mark.parametrize("mode", _MODES)
def test_sanity(mode, tmp_path):
def roundtrip(original_im):
def test_sanity(mode, tmp_path: Path) -> None:
def roundtrip(original_im) -> None:
out = str(tmp_path / "temp.tga")
original_im.save(out, rle=rle)
@ -64,7 +65,7 @@ def test_sanity(mode, tmp_path):
roundtrip(original_im)
def test_palette_depth_16(tmp_path):
def test_palette_depth_16(tmp_path: Path) -> None:
with Image.open("Tests/images/p_16.tga") as im:
assert_image_equal_tofile(im.convert("RGB"), "Tests/images/p_16.png")
@ -74,7 +75,7 @@ def test_palette_depth_16(tmp_path):
assert_image_equal_tofile(reloaded.convert("RGB"), "Tests/images/p_16.png")
def test_id_field():
def test_id_field() -> None:
# tga file with id field
test_file = "Tests/images/tga_id_field.tga"
@ -84,7 +85,7 @@ def test_id_field():
assert im.size == (100, 100)
def test_id_field_rle():
def test_id_field_rle() -> None:
# tga file with id field
test_file = "Tests/images/rgb32rle.tga"
@ -94,7 +95,7 @@ def test_id_field_rle():
assert im.size == (199, 199)
def test_cross_scan_line():
def test_cross_scan_line() -> None:
with Image.open("Tests/images/cross_scan_line.tga") as im:
assert_image_equal_tofile(im, "Tests/images/cross_scan_line.png")
@ -103,7 +104,7 @@ def test_cross_scan_line():
im.load()
def test_save(tmp_path):
def test_save(tmp_path: Path) -> None:
test_file = "Tests/images/tga_id_field.tga"
with Image.open(test_file) as im:
out = str(tmp_path / "temp.tga")
@ -120,7 +121,7 @@ def test_save(tmp_path):
assert test_im.size == (100, 100)
def test_small_palette(tmp_path):
def test_small_palette(tmp_path: Path) -> None:
im = Image.new("P", (1, 1))
colors = [0, 0, 0]
im.putpalette(colors)
@ -132,7 +133,7 @@ def test_small_palette(tmp_path):
assert reloaded.getpalette() == colors
def test_save_wrong_mode(tmp_path):
def test_save_wrong_mode(tmp_path: Path) -> None:
im = hopper("PA")
out = str(tmp_path / "temp.tga")
@ -140,7 +141,7 @@ def test_save_wrong_mode(tmp_path):
im.save(out)
def test_save_mapdepth():
def test_save_mapdepth() -> None:
# This image has been manually hexedited from 200x32_p_bl_raw.tga
# to include an origin
test_file = "Tests/images/200x32_p_bl_raw_origin.tga"
@ -148,7 +149,7 @@ def test_save_mapdepth():
assert_image_equal_tofile(im, "Tests/images/tga/common/200x32_p.png")
def test_save_id_section(tmp_path):
def test_save_id_section(tmp_path: Path) -> None:
test_file = "Tests/images/rgb32rle.tga"
with Image.open(test_file) as im:
out = str(tmp_path / "temp.tga")
@ -179,7 +180,7 @@ def test_save_id_section(tmp_path):
assert "id_section" not in test_im.info
def test_save_orientation(tmp_path):
def test_save_orientation(tmp_path: Path) -> None:
test_file = "Tests/images/rgb32rle.tga"
out = str(tmp_path / "temp.tga")
with Image.open(test_file) as im:
@ -190,7 +191,7 @@ def test_save_orientation(tmp_path):
assert test_im.info["orientation"] == 1
def test_horizontal_orientations():
def test_horizontal_orientations() -> None:
# These images have been manually hexedited to have the relevant orientations
with Image.open("Tests/images/rgb32rle_top_right.tga") as im:
assert im.load()[90, 90][:3] == (0, 0, 0)
@ -199,7 +200,7 @@ def test_horizontal_orientations():
assert im.load()[90, 90][:3] == (0, 255, 0)
def test_save_rle(tmp_path):
def test_save_rle(tmp_path: Path) -> None:
test_file = "Tests/images/rgb32rle.tga"
with Image.open(test_file) as im:
assert im.info["compression"] == "tga_rle"
@ -232,7 +233,7 @@ def test_save_rle(tmp_path):
assert test_im.info["compression"] == "tga_rle"
def test_save_l_transparency(tmp_path):
def test_save_l_transparency(tmp_path: Path) -> None:
# There are 559 transparent pixels in la.tga.
num_transparent = 559

View File

@ -3,6 +3,7 @@ from __future__ import annotations
import os
import warnings
from io import BytesIO
from pathlib import Path
import pytest
@ -26,7 +27,7 @@ except ImportError:
class TestFileTiff:
def test_sanity(self, tmp_path):
def test_sanity(self, tmp_path: Path) -> None:
filename = str(tmp_path / "temp.tif")
hopper("RGB").save(filename)
@ -58,21 +59,21 @@ class TestFileTiff:
pass
@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
def test_unclosed_file(self):
def open():
def test_unclosed_file(self) -> None:
def open() -> None:
im = Image.open("Tests/images/multipage.tiff")
im.load()
with pytest.warns(ResourceWarning):
open()
def test_closed_file(self):
def test_closed_file(self) -> None:
with warnings.catch_warnings():
im = Image.open("Tests/images/multipage.tiff")
im.load()
im.close()
def test_seek_after_close(self):
def test_seek_after_close(self) -> None:
im = Image.open("Tests/images/multipage.tiff")
im.close()
@ -81,12 +82,12 @@ class TestFileTiff:
with pytest.raises(ValueError):
im.seek(1)
def test_context_manager(self):
def test_context_manager(self) -> None:
with warnings.catch_warnings():
with Image.open("Tests/images/multipage.tiff") as im:
im.load()
def test_mac_tiff(self):
def test_mac_tiff(self) -> None:
# Read RGBa images from macOS [@PIL136]
filename = "Tests/images/pil136.tiff"
@ -98,7 +99,7 @@ class TestFileTiff:
assert_image_similar_tofile(im, "Tests/images/pil136.png", 1)
def test_bigtiff(self, tmp_path):
def test_bigtiff(self, tmp_path: Path) -> None:
with Image.open("Tests/images/hopper_bigtiff.tif") as im:
assert_image_equal_tofile(im, "Tests/images/hopper.tif")
@ -109,13 +110,13 @@ class TestFileTiff:
outfile = str(tmp_path / "temp.tif")
im.save(outfile, save_all=True, append_images=[im], tiffinfo=im.tag_v2)
def test_set_legacy_api(self):
def test_set_legacy_api(self) -> None:
ifd = TiffImagePlugin.ImageFileDirectory_v2()
with pytest.raises(Exception) as e:
ifd.legacy_api = None
assert str(e.value) == "Not allowing setting of legacy api"
def test_xyres_tiff(self):
def test_xyres_tiff(self) -> None:
filename = "Tests/images/pil168.tif"
with Image.open(filename) as im:
# legacy api
@ -128,7 +129,7 @@ class TestFileTiff:
assert im.info["dpi"] == (72.0, 72.0)
def test_xyres_fallback_tiff(self):
def test_xyres_fallback_tiff(self) -> None:
filename = "Tests/images/compression.tif"
with Image.open(filename) as im:
# v2 api
@ -142,7 +143,7 @@ class TestFileTiff:
# Fallback "inch".
assert im.info["dpi"] == (100.0, 100.0)
def test_int_resolution(self):
def test_int_resolution(self) -> None:
filename = "Tests/images/pil168.tif"
with Image.open(filename) as im:
# Try to read a file where X,Y_RESOLUTION are ints
@ -155,14 +156,14 @@ class TestFileTiff:
"resolution_unit, dpi",
[(None, 72.8), (2, 72.8), (3, 184.912)],
)
def test_load_float_dpi(self, resolution_unit, dpi):
def test_load_float_dpi(self, resolution_unit, dpi) -> None:
with Image.open(
"Tests/images/hopper_float_dpi_" + str(resolution_unit) + ".tif"
) as im:
assert im.tag_v2.get(RESOLUTION_UNIT) == resolution_unit
assert im.info["dpi"] == (dpi, dpi)
def test_save_float_dpi(self, tmp_path):
def test_save_float_dpi(self, tmp_path: Path) -> None:
outfile = str(tmp_path / "temp.tif")
with Image.open("Tests/images/hopper.tif") as im:
dpi = (72.2, 72.2)
@ -171,7 +172,7 @@ class TestFileTiff:
with Image.open(outfile) as reloaded:
assert reloaded.info["dpi"] == dpi
def test_save_setting_missing_resolution(self):
def test_save_setting_missing_resolution(self) -> None:
b = BytesIO()
with Image.open("Tests/images/10ct_32bit_128.tiff") as im:
im.save(b, format="tiff", resolution=123.45)
@ -179,7 +180,7 @@ class TestFileTiff:
assert im.tag_v2[X_RESOLUTION] == 123.45
assert im.tag_v2[Y_RESOLUTION] == 123.45
def test_invalid_file(self):
def test_invalid_file(self) -> None:
invalid_file = "Tests/images/flower.jpg"
with pytest.raises(SyntaxError):
@ -190,30 +191,30 @@ class TestFileTiff:
TiffImagePlugin.TiffImageFile(invalid_file)
TiffImagePlugin.PREFIXES.pop()
def test_bad_exif(self):
def test_bad_exif(self) -> None:
with Image.open("Tests/images/hopper_bad_exif.jpg") as i:
# Should not raise struct.error.
with pytest.warns(UserWarning):
i._getexif()
def test_save_rgba(self, tmp_path):
def test_save_rgba(self, tmp_path: Path) -> None:
im = hopper("RGBA")
outfile = str(tmp_path / "temp.tif")
im.save(outfile)
def test_save_unsupported_mode(self, tmp_path):
def test_save_unsupported_mode(self, tmp_path: Path) -> None:
im = hopper("HSV")
outfile = str(tmp_path / "temp.tif")
with pytest.raises(OSError):
im.save(outfile)
def test_8bit_s(self):
def test_8bit_s(self) -> None:
with Image.open("Tests/images/8bit.s.tif") as im:
im.load()
assert im.mode == "L"
assert im.getpixel((50, 50)) == 184
def test_little_endian(self):
def test_little_endian(self) -> None:
with Image.open("Tests/images/16bit.cropped.tif") as im:
assert im.getpixel((0, 0)) == 480
assert im.mode == "I;16"
@ -223,7 +224,7 @@ class TestFileTiff:
assert b[0] == ord(b"\xe0")
assert b[1] == ord(b"\x01")
def test_big_endian(self):
def test_big_endian(self) -> None:
with Image.open("Tests/images/16bit.MM.cropped.tif") as im:
assert im.getpixel((0, 0)) == 480
assert im.mode == "I;16B"
@ -233,7 +234,7 @@ class TestFileTiff:
assert b[0] == ord(b"\x01")
assert b[1] == ord(b"\xe0")
def test_16bit_r(self):
def test_16bit_r(self) -> None:
with Image.open("Tests/images/16bit.r.tif") as im:
assert im.getpixel((0, 0)) == 480
assert im.mode == "I;16"
@ -242,14 +243,14 @@ class TestFileTiff:
assert b[0] == ord(b"\xe0")
assert b[1] == ord(b"\x01")
def test_16bit_s(self):
def test_16bit_s(self) -> None:
with Image.open("Tests/images/16bit.s.tif") as im:
im.load()
assert im.mode == "I"
assert im.getpixel((0, 0)) == 32767
assert im.getpixel((0, 1)) == 0
def test_12bit_rawmode(self):
def test_12bit_rawmode(self) -> None:
"""Are we generating the same interpretation
of the image as Imagemagick is?"""
@ -262,7 +263,7 @@ class TestFileTiff:
assert_image_equal_tofile(im, "Tests/images/12in16bit.tif")
def test_32bit_float(self):
def test_32bit_float(self) -> None:
# Issue 614, specific 32-bit float format
path = "Tests/images/10ct_32bit_128.tiff"
with Image.open(path) as im:
@ -271,7 +272,7 @@ class TestFileTiff:
assert im.getpixel((0, 0)) == -0.4526388943195343
assert im.getextrema() == (-3.140936851501465, 3.140684127807617)
def test_unknown_pixel_mode(self):
def test_unknown_pixel_mode(self) -> None:
with pytest.raises(OSError):
with Image.open("Tests/images/hopper_unknown_pixel_mode.tif"):
pass
@ -283,12 +284,12 @@ class TestFileTiff:
("Tests/images/multipage.tiff", 3),
),
)
def test_n_frames(self, path, n_frames):
def test_n_frames(self, path, n_frames) -> None:
with Image.open(path) as im:
assert im.n_frames == n_frames
assert im.is_animated == (n_frames != 1)
def test_eoferror(self):
def test_eoferror(self) -> None:
with Image.open("Tests/images/multipage-lastframe.tif") as im:
n_frames = im.n_frames
@ -300,7 +301,7 @@ class TestFileTiff:
# Test that seeking to the last frame does not raise an error
im.seek(n_frames - 1)
def test_multipage(self):
def test_multipage(self) -> None:
# issue #862
with Image.open("Tests/images/multipage.tiff") as im:
# file is a multipage tiff: 10x10 green, 10x10 red, 20x20 blue
@ -324,13 +325,13 @@ class TestFileTiff:
assert im.size == (20, 20)
assert im.convert("RGB").getpixel((0, 0)) == (0, 0, 255)
def test_multipage_last_frame(self):
def test_multipage_last_frame(self) -> None:
with Image.open("Tests/images/multipage-lastframe.tif") as im:
im.load()
assert im.size == (20, 20)
assert im.convert("RGB").getpixel((0, 0)) == (0, 0, 255)
def test_frame_order(self):
def test_frame_order(self) -> None:
# A frame can't progress to itself after reading
with Image.open("Tests/images/multipage_single_frame_loop.tiff") as im:
assert im.n_frames == 1
@ -343,7 +344,7 @@ class TestFileTiff:
with Image.open("Tests/images/multipage_out_of_order.tiff") as im:
assert im.n_frames == 3
def test___str__(self):
def test___str__(self) -> None:
filename = "Tests/images/pil136.tiff"
with Image.open(filename) as im:
# Act
@ -352,7 +353,7 @@ class TestFileTiff:
# Assert
assert isinstance(ret, str)
def test_dict(self):
def test_dict(self) -> None:
# Arrange
filename = "Tests/images/pil136.tiff"
with Image.open(filename) as im:
@ -392,7 +393,7 @@ class TestFileTiff:
}
assert dict(im.tag) == legacy_tags
def test__delitem__(self):
def test__delitem__(self) -> None:
filename = "Tests/images/pil136.tiff"
with Image.open(filename) as im:
len_before = len(dict(im.ifd))
@ -401,36 +402,36 @@ class TestFileTiff:
assert len_before == len_after + 1
@pytest.mark.parametrize("legacy_api", (False, True))
def test_load_byte(self, legacy_api):
def test_load_byte(self, legacy_api) -> None:
ifd = TiffImagePlugin.ImageFileDirectory_v2()
data = b"abc"
ret = ifd.load_byte(data, legacy_api)
assert ret == b"abc"
def test_load_string(self):
def test_load_string(self) -> None:
ifd = TiffImagePlugin.ImageFileDirectory_v2()
data = b"abc\0"
ret = ifd.load_string(data, False)
assert ret == "abc"
def test_load_float(self):
def test_load_float(self) -> None:
ifd = TiffImagePlugin.ImageFileDirectory_v2()
data = b"abcdabcd"
ret = ifd.load_float(data, False)
assert ret == (1.6777999408082104e22, 1.6777999408082104e22)
def test_load_double(self):
def test_load_double(self) -> None:
ifd = TiffImagePlugin.ImageFileDirectory_v2()
data = b"abcdefghabcdefgh"
ret = ifd.load_double(data, False)
assert ret == (8.540883223036124e194, 8.540883223036124e194)
def test_ifd_tag_type(self):
def test_ifd_tag_type(self) -> None:
with Image.open("Tests/images/ifd_tag_type.tiff") as im:
assert 0x8825 in im.tag_v2
def test_exif(self, tmp_path):
def check_exif(exif):
def test_exif(self, tmp_path: Path) -> None:
def check_exif(exif) -> None:
assert sorted(exif.keys()) == [
256,
257,
@ -481,7 +482,7 @@ class TestFileTiff:
exif = im.getexif()
check_exif(exif)
def test_modify_exif(self, tmp_path):
def test_modify_exif(self, tmp_path: Path) -> None:
outfile = str(tmp_path / "temp.tif")
with Image.open("Tests/images/ifd_tag_type.tiff") as im:
exif = im.getexif()
@ -493,7 +494,7 @@ class TestFileTiff:
exif = im.getexif()
assert exif[264] == 100
def test_reload_exif_after_seek(self):
def test_reload_exif_after_seek(self) -> None:
with Image.open("Tests/images/multipage.tiff") as im:
exif = im.getexif()
del exif[256]
@ -501,7 +502,7 @@ class TestFileTiff:
assert 256 in exif
def test_exif_frames(self):
def test_exif_frames(self) -> None:
# Test that EXIF data can change across frames
with Image.open("Tests/images/g4-multi.tiff") as im:
assert im.getexif()[273] == (328, 815)
@ -510,7 +511,7 @@ class TestFileTiff:
assert im.getexif()[273] == (1408, 1907)
@pytest.mark.parametrize("mode", ("1", "L"))
def test_photometric(self, mode, tmp_path):
def test_photometric(self, mode, tmp_path: Path) -> None:
filename = str(tmp_path / "temp.tif")
im = hopper(mode)
im.save(filename, tiffinfo={262: 0})
@ -518,13 +519,13 @@ class TestFileTiff:
assert reloaded.tag_v2[262] == 0
assert_image_equal(im, reloaded)
def test_seek(self):
def test_seek(self) -> None:
filename = "Tests/images/pil136.tiff"
with Image.open(filename) as im:
im.seek(0)
assert im.tell() == 0
def test_seek_eof(self):
def test_seek_eof(self) -> None:
filename = "Tests/images/pil136.tiff"
with Image.open(filename) as im:
assert im.tell() == 0
@ -533,21 +534,21 @@ class TestFileTiff:
with pytest.raises(EOFError):
im.seek(1)
def test__limit_rational_int(self):
def test__limit_rational_int(self) -> None:
from PIL.TiffImagePlugin import _limit_rational
value = 34
ret = _limit_rational(value, 65536)
assert ret == (34, 1)
def test__limit_rational_float(self):
def test__limit_rational_float(self) -> None:
from PIL.TiffImagePlugin import _limit_rational
value = 22.3
ret = _limit_rational(value, 65536)
assert ret == (223, 10)
def test_4bit(self):
def test_4bit(self) -> None:
test_file = "Tests/images/hopper_gray_4bpp.tif"
original = hopper("L")
with Image.open(test_file) as im:
@ -555,7 +556,7 @@ class TestFileTiff:
assert im.mode == "L"
assert_image_similar(im, original, 7.3)
def test_gray_semibyte_per_pixel(self):
def test_gray_semibyte_per_pixel(self) -> None:
test_files = (
(
24.8, # epsilon
@ -588,7 +589,7 @@ class TestFileTiff:
assert im2.mode == "L"
assert_image_equal(im, im2)
def test_with_underscores(self, tmp_path):
def test_with_underscores(self, tmp_path: Path) -> None:
kwargs = {"resolution_unit": "inch", "x_resolution": 72, "y_resolution": 36}
filename = str(tmp_path / "temp.tif")
hopper("RGB").save(filename, **kwargs)
@ -601,7 +602,7 @@ class TestFileTiff:
assert im.tag_v2[X_RESOLUTION] == 72
assert im.tag_v2[Y_RESOLUTION] == 36
def test_roundtrip_tiff_uint16(self, tmp_path):
def test_roundtrip_tiff_uint16(self, tmp_path: Path) -> None:
# Test an image of all '0' values
pixel_value = 0x1234
infile = "Tests/images/uint16_1_4660.tif"
@ -613,7 +614,7 @@ class TestFileTiff:
assert_image_equal_tofile(im, tmpfile)
def test_rowsperstrip(self, tmp_path):
def test_rowsperstrip(self, tmp_path: Path) -> None:
outfile = str(tmp_path / "temp.tif")
im = hopper()
im.save(outfile, tiffinfo={278: 256})
@ -621,25 +622,25 @@ class TestFileTiff:
with Image.open(outfile) as im:
assert im.tag_v2[278] == 256
def test_strip_raw(self):
def test_strip_raw(self) -> None:
infile = "Tests/images/tiff_strip_raw.tif"
with Image.open(infile) as im:
assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png")
def test_strip_planar_raw(self):
def test_strip_planar_raw(self) -> None:
# gdal_translate -of GTiff -co INTERLEAVE=BAND \
# tiff_strip_raw.tif tiff_strip_planar_raw.tiff
infile = "Tests/images/tiff_strip_planar_raw.tif"
with Image.open(infile) as im:
assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png")
def test_strip_planar_raw_with_overviews(self):
def test_strip_planar_raw_with_overviews(self) -> None:
# gdaladdo tiff_strip_planar_raw2.tif 2 4 8 16
infile = "Tests/images/tiff_strip_planar_raw_with_overviews.tif"
with Image.open(infile) as im:
assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png")
def test_tiled_planar_raw(self):
def test_tiled_planar_raw(self) -> None:
# gdal_translate -of GTiff -co TILED=YES -co BLOCKXSIZE=32 \
# -co BLOCKYSIZE=32 -co INTERLEAVE=BAND \
# tiff_tiled_raw.tif tiff_tiled_planar_raw.tiff
@ -647,7 +648,7 @@ class TestFileTiff:
with Image.open(infile) as im:
assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png")
def test_planar_configuration_save(self, tmp_path):
def test_planar_configuration_save(self, tmp_path: Path) -> None:
infile = "Tests/images/tiff_tiled_planar_raw.tif"
with Image.open(infile) as im:
assert im._planar_configuration == 2
@ -659,7 +660,7 @@ class TestFileTiff:
assert_image_equal_tofile(reloaded, infile)
@pytest.mark.parametrize("mode", ("P", "PA"))
def test_palette(self, mode, tmp_path):
def test_palette(self, mode, tmp_path: Path) -> None:
outfile = str(tmp_path / "temp.tif")
im = hopper(mode)
@ -668,7 +669,7 @@ class TestFileTiff:
with Image.open(outfile) as reloaded:
assert_image_equal(im.convert("RGB"), reloaded.convert("RGB"))
def test_tiff_save_all(self):
def test_tiff_save_all(self) -> None:
mp = BytesIO()
with Image.open("Tests/images/multipage.tiff") as im:
im.save(mp, format="tiff", save_all=True)
@ -698,7 +699,7 @@ class TestFileTiff:
with Image.open(mp) as reread:
assert reread.n_frames == 3
def test_saving_icc_profile(self, tmp_path):
def test_saving_icc_profile(self, tmp_path: Path) -> None:
# Tests saving TIFF with icc_profile set.
# At the time of writing this will only work for non-compressed tiffs
# as libtiff does not support embedded ICC profiles,
@ -712,7 +713,7 @@ class TestFileTiff:
with Image.open(tmpfile) as reloaded:
assert b"Dummy value" == reloaded.info["icc_profile"]
def test_save_icc_profile(self, tmp_path):
def test_save_icc_profile(self, tmp_path: Path) -> None:
im = hopper()
assert "icc_profile" not in im.info
@ -723,14 +724,14 @@ class TestFileTiff:
with Image.open(outfile) as reloaded:
assert reloaded.info["icc_profile"] == icc_profile
def test_save_bmp_compression(self, tmp_path):
def test_save_bmp_compression(self, tmp_path: Path) -> None:
with Image.open("Tests/images/hopper.bmp") as im:
assert im.info["compression"] == 0
outfile = str(tmp_path / "temp.tif")
im.save(outfile)
def test_discard_icc_profile(self, tmp_path):
def test_discard_icc_profile(self, tmp_path: Path) -> None:
outfile = str(tmp_path / "temp.tif")
with Image.open("Tests/images/icc_profile.png") as im:
@ -741,7 +742,7 @@ class TestFileTiff:
with Image.open(outfile) as reloaded:
assert "icc_profile" not in reloaded.info
def test_getxmp(self):
def test_getxmp(self) -> None:
with Image.open("Tests/images/lab.tif") as im:
if ElementTree is None:
with pytest.warns(
@ -756,7 +757,7 @@ class TestFileTiff:
assert description[0]["format"] == "image/tiff"
assert description[3]["BitsPerSample"]["Seq"]["li"] == ["8", "8", "8"]
def test_get_photoshop_blocks(self):
def test_get_photoshop_blocks(self) -> None:
with Image.open("Tests/images/lab.tif") as im:
assert list(im.get_photoshop_blocks().keys()) == [
1061,
@ -782,7 +783,7 @@ class TestFileTiff:
4001,
]
def test_tiff_chunks(self, tmp_path):
def test_tiff_chunks(self, tmp_path: Path) -> None:
tmpfile = str(tmp_path / "temp.tif")
im = hopper()
@ -803,7 +804,7 @@ class TestFileTiff:
assert_image_equal_tofile(im, tmpfile)
def test_close_on_load_exclusive(self, tmp_path):
def test_close_on_load_exclusive(self, tmp_path: Path) -> None:
# similar to test_fd_leak, but runs on unixlike os
tmpfile = str(tmp_path / "temp.tif")
@ -816,7 +817,7 @@ class TestFileTiff:
im.load()
assert fp.closed
def test_close_on_load_nonexclusive(self, tmp_path):
def test_close_on_load_nonexclusive(self, tmp_path: Path) -> None:
tmpfile = str(tmp_path / "temp.tif")
with Image.open("Tests/images/uint16_1_4660.tif") as im:
@ -838,7 +839,7 @@ class TestFileTiff:
not os.path.exists("Tests/images/string_dimension.tiff"),
reason="Extra image files not installed",
)
def test_string_dimension(self):
def test_string_dimension(self) -> None:
# Assert that an error is raised if one of the dimensions is a string
with Image.open("Tests/images/string_dimension.tiff") as im:
with pytest.raises(OSError):
@ -846,7 +847,7 @@ class TestFileTiff:
@pytest.mark.timeout(6)
@pytest.mark.filterwarnings("ignore:Truncated File Read")
def test_timeout(self):
def test_timeout(self) -> None:
with Image.open("Tests/images/timeout-6646305047838720") as im:
ImageFile.LOAD_TRUNCATED_IMAGES = True
im.load()
@ -859,7 +860,7 @@ class TestFileTiff:
],
)
@pytest.mark.timeout(2)
def test_oom(self, test_file):
def test_oom(self, test_file) -> None:
with pytest.raises(UnidentifiedImageError):
with pytest.warns(UserWarning):
with Image.open(test_file):
@ -868,7 +869,7 @@ class TestFileTiff:
@pytest.mark.skipif(not is_win32(), reason="Windows only")
class TestFileTiffW32:
def test_fd_leak(self, tmp_path):
def test_fd_leak(self, tmp_path: Path) -> None:
tmpfile = str(tmp_path / "temp.tif")
# this is an mmaped file.

View File

@ -2,6 +2,7 @@ from __future__ import annotations
import io
import struct
from pathlib import Path
import pytest
@ -13,7 +14,7 @@ from .helper import assert_deep_equal, hopper
TAG_IDS = {info.name: info.value for info in TiffTags.TAGS_V2.values()}
def test_rt_metadata(tmp_path):
def test_rt_metadata(tmp_path: Path) -> None:
"""Test writing arbitrary metadata into the tiff image directory
Use case is ImageJ private tags, one numeric, one arbitrary
data. https://github.com/python-pillow/Pillow/issues/291
@ -79,7 +80,7 @@ def test_rt_metadata(tmp_path):
assert loaded.tag_v2[ImageJMetaDataByteCounts] == (8, len(bin_data) - 8)
def test_read_metadata():
def test_read_metadata() -> None:
with Image.open("Tests/images/hopper_g4.tif") as img:
assert {
"YResolution": IFDRational(4294967295, 113653537),
@ -120,7 +121,7 @@ def test_read_metadata():
} == img.tag.named()
def test_write_metadata(tmp_path):
def test_write_metadata(tmp_path: Path) -> None:
"""Test metadata writing through the python code"""
with Image.open("Tests/images/hopper.tif") as img:
f = str(tmp_path / "temp.tiff")
@ -157,7 +158,7 @@ def test_write_metadata(tmp_path):
assert value == reloaded[tag], f"{tag} didn't roundtrip"
def test_change_stripbytecounts_tag_type(tmp_path):
def test_change_stripbytecounts_tag_type(tmp_path: Path) -> None:
out = str(tmp_path / "temp.tiff")
with Image.open("Tests/images/hopper.tif") as im:
info = im.tag_v2
@ -176,19 +177,19 @@ def test_change_stripbytecounts_tag_type(tmp_path):
assert reloaded.tag_v2.tagtype[TiffImagePlugin.STRIPBYTECOUNTS] == TiffTags.LONG
def test_no_duplicate_50741_tag():
def test_no_duplicate_50741_tag() -> None:
assert TAG_IDS["MakerNoteSafety"] == 50741
assert TAG_IDS["BestQualityScale"] == 50780
def test_iptc(tmp_path):
def test_iptc(tmp_path: Path) -> None:
out = str(tmp_path / "temp.tiff")
with Image.open("Tests/images/hopper.Lab.tif") as im:
im.save(out)
@pytest.mark.parametrize("value, expected", ((b"test", "test"), (1, "1")))
def test_writing_other_types_to_ascii(value, expected, tmp_path):
def test_writing_other_types_to_ascii(value, expected, tmp_path: Path) -> None:
info = TiffImagePlugin.ImageFileDirectory_v2()
tag = TiffTags.TAGS_V2[271]
@ -205,7 +206,7 @@ def test_writing_other_types_to_ascii(value, expected, tmp_path):
@pytest.mark.parametrize("value", (1, IFDRational(1)))
def test_writing_other_types_to_bytes(value, tmp_path):
def test_writing_other_types_to_bytes(value, tmp_path: Path) -> None:
im = hopper()
info = TiffImagePlugin.ImageFileDirectory_v2()
@ -221,7 +222,7 @@ def test_writing_other_types_to_bytes(value, tmp_path):
assert reloaded.tag_v2[700] == b"\x01"
def test_writing_other_types_to_undefined(tmp_path):
def test_writing_other_types_to_undefined(tmp_path: Path) -> None:
im = hopper()
info = TiffImagePlugin.ImageFileDirectory_v2()
@ -237,7 +238,7 @@ def test_writing_other_types_to_undefined(tmp_path):
assert reloaded.tag_v2[33723] == b"1"
def test_undefined_zero(tmp_path):
def test_undefined_zero(tmp_path: Path) -> None:
# Check that the tag has not been changed since this test was created
tag = TiffTags.TAGS_V2[45059]
assert tag.type == TiffTags.UNDEFINED
@ -252,7 +253,7 @@ def test_undefined_zero(tmp_path):
assert info[45059] == original
def test_empty_metadata():
def test_empty_metadata() -> None:
f = io.BytesIO(b"II*\x00\x08\x00\x00\x00")
head = f.read(8)
info = TiffImagePlugin.ImageFileDirectory(head)
@ -261,7 +262,7 @@ def test_empty_metadata():
info.load(f)
def test_iccprofile(tmp_path):
def test_iccprofile(tmp_path: Path) -> None:
# https://github.com/python-pillow/Pillow/issues/1462
out = str(tmp_path / "temp.tiff")
with Image.open("Tests/images/hopper.iccprofile.tif") as im:
@ -272,7 +273,7 @@ def test_iccprofile(tmp_path):
assert im.info["icc_profile"] == reloaded.info["icc_profile"]
def test_iccprofile_binary():
def test_iccprofile_binary() -> None:
# https://github.com/python-pillow/Pillow/issues/1526
# We should be able to load this,
# but probably won't be able to save it.
@ -282,19 +283,19 @@ def test_iccprofile_binary():
assert im.info["icc_profile"]
def test_iccprofile_save_png(tmp_path):
def test_iccprofile_save_png(tmp_path: Path) -> None:
with Image.open("Tests/images/hopper.iccprofile.tif") as im:
outfile = str(tmp_path / "temp.png")
im.save(outfile)
def test_iccprofile_binary_save_png(tmp_path):
def test_iccprofile_binary_save_png(tmp_path: Path) -> None:
with Image.open("Tests/images/hopper.iccprofile_binary.tif") as im:
outfile = str(tmp_path / "temp.png")
im.save(outfile)
def test_exif_div_zero(tmp_path):
def test_exif_div_zero(tmp_path: Path) -> None:
im = hopper()
info = TiffImagePlugin.ImageFileDirectory_v2()
info[41988] = TiffImagePlugin.IFDRational(0, 0)
@ -307,7 +308,7 @@ def test_exif_div_zero(tmp_path):
assert 0 == reloaded.tag_v2[41988].denominator
def test_ifd_unsigned_rational(tmp_path):
def test_ifd_unsigned_rational(tmp_path: Path) -> None:
im = hopper()
info = TiffImagePlugin.ImageFileDirectory_v2()
@ -338,7 +339,7 @@ def test_ifd_unsigned_rational(tmp_path):
assert 1 == reloaded.tag_v2[41493].denominator
def test_ifd_signed_rational(tmp_path):
def test_ifd_signed_rational(tmp_path: Path) -> None:
im = hopper()
info = TiffImagePlugin.ImageFileDirectory_v2()
@ -381,7 +382,7 @@ def test_ifd_signed_rational(tmp_path):
assert -1 == reloaded.tag_v2[37380].denominator
def test_ifd_signed_long(tmp_path):
def test_ifd_signed_long(tmp_path: Path) -> None:
im = hopper()
info = TiffImagePlugin.ImageFileDirectory_v2()
@ -394,7 +395,7 @@ def test_ifd_signed_long(tmp_path):
assert reloaded.tag_v2[37000] == -60000
def test_empty_values():
def test_empty_values() -> None:
data = io.BytesIO(
b"II*\x00\x08\x00\x00\x00\x03\x00\x1a\x01\x05\x00\x00\x00\x00\x00"
b"\x00\x00\x00\x00\x1b\x01\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00"
@ -409,7 +410,7 @@ def test_empty_values():
assert 33432 in info
def test_photoshop_info(tmp_path):
def test_photoshop_info(tmp_path: Path) -> None:
with Image.open("Tests/images/issue_2278.tif") as im:
assert len(im.tag_v2[34377]) == 70
assert isinstance(im.tag_v2[34377], bytes)
@ -420,7 +421,7 @@ def test_photoshop_info(tmp_path):
assert isinstance(reloaded.tag_v2[34377], bytes)
def test_too_many_entries():
def test_too_many_entries() -> None:
ifd = TiffImagePlugin.ImageFileDirectory_v2()
# 277: ("SamplesPerPixel", SHORT, 1),
@ -432,7 +433,7 @@ def test_too_many_entries():
assert ifd[277] == 4
def test_tag_group_data():
def test_tag_group_data() -> None:
base_ifd = TiffImagePlugin.ImageFileDirectory_v2()
interop_ifd = TiffImagePlugin.ImageFileDirectory_v2(group=40965)
for ifd in (base_ifd, interop_ifd):
@ -446,7 +447,7 @@ def test_tag_group_data():
assert base_ifd.tagtype[2] != interop_ifd.tagtype[256]
def test_empty_subifd(tmp_path):
def test_empty_subifd(tmp_path: Path) -> None:
out = str(tmp_path / "temp.jpg")
im = hopper()

View File

@ -4,6 +4,7 @@ import io
import re
import sys
import warnings
from pathlib import Path
import pytest
@ -26,7 +27,7 @@ except ImportError:
class TestUnsupportedWebp:
def test_unsupported(self):
def test_unsupported(self) -> None:
if HAVE_WEBP:
WebPImagePlugin.SUPPORTED = False
@ -42,15 +43,15 @@ class TestUnsupportedWebp:
@skip_unless_feature("webp")
class TestFileWebp:
def setup_method(self):
def setup_method(self) -> None:
self.rgb_mode = "RGB"
def test_version(self):
def test_version(self) -> None:
_webp.WebPDecoderVersion()
_webp.WebPDecoderBuggyAlpha()
assert re.search(r"\d+\.\d+\.\d+$", features.version_module("webp"))
def test_read_rgb(self):
def test_read_rgb(self) -> None:
"""
Can we read a RGB mode WebP file without error?
Does it have the bits we expect?
@ -67,7 +68,7 @@ class TestFileWebp:
# dwebp -ppm ../../Tests/images/hopper.webp -o hopper_webp_bits.ppm
assert_image_similar_tofile(image, "Tests/images/hopper_webp_bits.ppm", 1.0)
def _roundtrip(self, tmp_path, mode, epsilon, args={}):
def _roundtrip(self, tmp_path: Path, mode, epsilon, args={}) -> None:
temp_file = str(tmp_path / "temp.webp")
hopper(mode).save(temp_file, **args)
@ -93,7 +94,7 @@ class TestFileWebp:
target = target.convert(self.rgb_mode)
assert_image_similar(image, target, epsilon)
def test_write_rgb(self, tmp_path):
def test_write_rgb(self, tmp_path: Path) -> None:
"""
Can we write a RGB mode file to webp without error?
Does it have the bits we expect?
@ -101,7 +102,7 @@ class TestFileWebp:
self._roundtrip(tmp_path, self.rgb_mode, 12.5)
def test_write_method(self, tmp_path):
def test_write_method(self, tmp_path: Path) -> None:
self._roundtrip(tmp_path, self.rgb_mode, 12.0, {"method": 6})
buffer_no_args = io.BytesIO()
@ -112,7 +113,7 @@ class TestFileWebp:
assert buffer_no_args.getbuffer() != buffer_method.getbuffer()
@skip_unless_feature("webp_anim")
def test_save_all(self, tmp_path):
def test_save_all(self, tmp_path: Path) -> None:
temp_file = str(tmp_path / "temp.webp")
im = Image.new("RGB", (1, 1))
im2 = Image.new("RGB", (1, 1), "#f00")
@ -124,14 +125,14 @@ class TestFileWebp:
reloaded.seek(1)
assert_image_similar(im2, reloaded, 1)
def test_icc_profile(self, tmp_path):
def test_icc_profile(self, tmp_path: Path) -> None:
self._roundtrip(tmp_path, self.rgb_mode, 12.5, {"icc_profile": None})
if _webp.HAVE_WEBPANIM:
self._roundtrip(
tmp_path, self.rgb_mode, 12.5, {"icc_profile": None, "save_all": True}
)
def test_write_unsupported_mode_L(self, tmp_path):
def test_write_unsupported_mode_L(self, tmp_path: Path) -> None:
"""
Saving a black-and-white file to WebP format should work, and be
similar to the original file.
@ -139,7 +140,7 @@ class TestFileWebp:
self._roundtrip(tmp_path, "L", 10.0)
def test_write_unsupported_mode_P(self, tmp_path):
def test_write_unsupported_mode_P(self, tmp_path: Path) -> None:
"""
Saving a palette-based file to WebP format should work, and be
similar to the original file.
@ -148,14 +149,14 @@ class TestFileWebp:
self._roundtrip(tmp_path, "P", 50.0)
@pytest.mark.skipif(sys.maxsize <= 2**32, reason="Requires 64-bit system")
def test_write_encoding_error_message(self, tmp_path):
def test_write_encoding_error_message(self, tmp_path: Path) -> None:
temp_file = str(tmp_path / "temp.webp")
im = Image.new("RGB", (15000, 15000))
with pytest.raises(ValueError) as e:
im.save(temp_file, method=0)
assert str(e.value) == "encoding error 6"
def test_WebPEncode_with_invalid_args(self):
def test_WebPEncode_with_invalid_args(self) -> None:
"""
Calling encoder functions with no arguments should result in an error.
"""
@ -166,7 +167,7 @@ class TestFileWebp:
with pytest.raises(TypeError):
_webp.WebPEncode()
def test_WebPDecode_with_invalid_args(self):
def test_WebPDecode_with_invalid_args(self) -> None:
"""
Calling decoder functions with no arguments should result in an error.
"""
@ -177,14 +178,14 @@ class TestFileWebp:
with pytest.raises(TypeError):
_webp.WebPDecode()
def test_no_resource_warning(self, tmp_path):
def test_no_resource_warning(self, tmp_path: Path) -> None:
file_path = "Tests/images/hopper.webp"
with Image.open(file_path) as image:
temp_file = str(tmp_path / "temp.webp")
with warnings.catch_warnings():
image.save(temp_file)
def test_file_pointer_could_be_reused(self):
def test_file_pointer_could_be_reused(self) -> None:
file_path = "Tests/images/hopper.webp"
with open(file_path, "rb") as blob:
Image.open(blob).load()
@ -195,14 +196,14 @@ class TestFileWebp:
(0, (0,), (-1, 0, 1, 2), (253, 254, 255, 256)),
)
@skip_unless_feature("webp_anim")
def test_invalid_background(self, background, tmp_path):
def test_invalid_background(self, background, tmp_path: Path) -> None:
temp_file = str(tmp_path / "temp.webp")
im = hopper()
with pytest.raises(OSError):
im.save(temp_file, save_all=True, append_images=[im], background=background)
@skip_unless_feature("webp_anim")
def test_background_from_gif(self, tmp_path):
def test_background_from_gif(self, tmp_path: Path) -> None:
# Save L mode GIF with background
with Image.open("Tests/images/no_palette_with_background.gif") as im:
out_webp = str(tmp_path / "temp.webp")
@ -227,7 +228,7 @@ class TestFileWebp:
assert difference < 5
@skip_unless_feature("webp_anim")
def test_duration(self, tmp_path):
def test_duration(self, tmp_path: Path) -> None:
with Image.open("Tests/images/dispose_bgnd.gif") as im:
assert im.info["duration"] == 1000
@ -238,7 +239,7 @@ class TestFileWebp:
reloaded.load()
assert reloaded.info["duration"] == 1000
def test_roundtrip_rgba_palette(self, tmp_path):
def test_roundtrip_rgba_palette(self, tmp_path: Path) -> None:
temp_file = str(tmp_path / "temp.webp")
im = Image.new("RGBA", (1, 1)).convert("P")
assert im.mode == "P"

View File

@ -1,5 +1,7 @@
from __future__ import annotations
from pathlib import Path
import pytest
from PIL import Image
@ -14,12 +16,12 @@ from .helper import (
_webp = pytest.importorskip("PIL._webp", reason="WebP support not installed")
def setup_module():
def setup_module() -> None:
if _webp.WebPDecoderBuggyAlpha():
pytest.skip("Buggy early version of WebP installed, not testing transparency")
def test_read_rgba():
def test_read_rgba() -> None:
"""
Can we read an RGBA mode file without error?
Does it have the bits we expect?
@ -39,7 +41,7 @@ def test_read_rgba():
assert_image_similar_tofile(image, "Tests/images/transparent.png", 20.0)
def test_write_lossless_rgb(tmp_path):
def test_write_lossless_rgb(tmp_path: Path) -> None:
"""
Can we write an RGBA mode file with lossless compression without error?
Does it have the bits we expect?
@ -68,7 +70,7 @@ def test_write_lossless_rgb(tmp_path):
assert_image_equal(image, pil_image)
def test_write_rgba(tmp_path):
def test_write_rgba(tmp_path: Path) -> None:
"""
Can we write a RGBA mode file to WebP without error.
Does it have the bits we expect?
@ -99,7 +101,7 @@ def test_write_rgba(tmp_path):
assert_image_similar(image, pil_image, 1.0)
def test_keep_rgb_values_when_transparent(tmp_path):
def test_keep_rgb_values_when_transparent(tmp_path: Path) -> None:
"""
Saving transparent pixels should retain their original RGB values
when using the "exact" parameter.
@ -128,7 +130,7 @@ def test_keep_rgb_values_when_transparent(tmp_path):
assert_image_equal(reloaded.convert("RGB"), image)
def test_write_unsupported_mode_PA(tmp_path):
def test_write_unsupported_mode_PA(tmp_path: Path) -> None:
"""
Saving a palette-based file with transparency to WebP format
should work, and be similar to the original file.

View File

@ -1,5 +1,7 @@
from __future__ import annotations
from pathlib import Path
import pytest
from packaging.version import parse as parse_version
@ -18,7 +20,7 @@ pytestmark = [
]
def test_n_frames():
def test_n_frames() -> None:
"""Ensure that WebP format sets n_frames and is_animated attributes correctly."""
with Image.open("Tests/images/hopper.webp") as im:
@ -30,7 +32,7 @@ def test_n_frames():
assert im.is_animated
def test_write_animation_L(tmp_path):
def test_write_animation_L(tmp_path: Path) -> None:
"""
Convert an animated GIF to animated WebP, then compare the frame count, and first
and last frames to ensure they're visually similar.
@ -60,13 +62,13 @@ def test_write_animation_L(tmp_path):
assert_image_similar(im, orig.convert("RGBA"), 32.9)
def test_write_animation_RGB(tmp_path):
def test_write_animation_RGB(tmp_path: Path) -> None:
"""
Write an animated WebP from RGB frames, and ensure the frames
are visually similar to the originals.
"""
def check(temp_file):
def check(temp_file) -> None:
with Image.open(temp_file) as im:
assert im.n_frames == 2
@ -105,7 +107,7 @@ def test_write_animation_RGB(tmp_path):
check(temp_file2)
def test_timestamp_and_duration(tmp_path):
def test_timestamp_and_duration(tmp_path: Path) -> None:
"""
Try passing a list of durations, and make sure the encoded
timestamps and durations are correct.
@ -136,7 +138,7 @@ def test_timestamp_and_duration(tmp_path):
ts += durations[frame]
def test_float_duration(tmp_path):
def test_float_duration(tmp_path: Path) -> None:
temp_file = str(tmp_path / "temp.webp")
with Image.open("Tests/images/iss634.apng") as im:
assert im.info["duration"] == 70.0
@ -148,7 +150,7 @@ def test_float_duration(tmp_path):
assert reloaded.info["duration"] == 70
def test_seeking(tmp_path):
def test_seeking(tmp_path: Path) -> None:
"""
Create an animated WebP file, and then try seeking through frames in reverse-order,
verifying the timestamps and durations are correct.
@ -179,7 +181,7 @@ def test_seeking(tmp_path):
ts -= dur
def test_seek_errors():
def test_seek_errors() -> None:
with Image.open("Tests/images/iss634.webp") as im:
with pytest.raises(EOFError):
im.seek(-1)

View File

@ -1,6 +1,7 @@
from __future__ import annotations
from io import BytesIO
from pathlib import Path
import pytest
@ -19,7 +20,7 @@ except ImportError:
ElementTree = None
def test_read_exif_metadata():
def test_read_exif_metadata() -> None:
file_path = "Tests/images/flower.webp"
with Image.open(file_path) as image:
assert image.format == "WEBP"
@ -37,7 +38,7 @@ def test_read_exif_metadata():
assert exif_data == expected_exif
def test_read_exif_metadata_without_prefix():
def test_read_exif_metadata_without_prefix() -> None:
with Image.open("Tests/images/flower2.webp") as im:
# Assert prefix is not present
assert im.info["exif"][:6] != b"Exif\x00\x00"
@ -49,7 +50,7 @@ def test_read_exif_metadata_without_prefix():
@mark_if_feature_version(
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
)
def test_write_exif_metadata():
def test_write_exif_metadata() -> None:
file_path = "Tests/images/flower.jpg"
test_buffer = BytesIO()
with Image.open(file_path) as image:
@ -63,7 +64,7 @@ def test_write_exif_metadata():
assert webp_exif == expected_exif[6:], "WebP EXIF didn't match"
def test_read_icc_profile():
def test_read_icc_profile() -> None:
file_path = "Tests/images/flower2.webp"
with Image.open(file_path) as image:
assert image.format == "WEBP"
@ -80,7 +81,7 @@ def test_read_icc_profile():
@mark_if_feature_version(
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
)
def test_write_icc_metadata():
def test_write_icc_metadata() -> None:
file_path = "Tests/images/flower2.jpg"
test_buffer = BytesIO()
with Image.open(file_path) as image:
@ -100,7 +101,7 @@ def test_write_icc_metadata():
@mark_if_feature_version(
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
)
def test_read_no_exif():
def test_read_no_exif() -> None:
file_path = "Tests/images/flower.jpg"
test_buffer = BytesIO()
with Image.open(file_path) as image:
@ -113,7 +114,7 @@ def test_read_no_exif():
assert not webp_image._getexif()
def test_getxmp():
def test_getxmp() -> None:
with Image.open("Tests/images/flower.webp") as im:
assert "xmp" not in im.info
assert im.getxmp() == {}
@ -133,7 +134,7 @@ def test_getxmp():
@skip_unless_feature("webp_anim")
def test_write_animated_metadata(tmp_path):
def test_write_animated_metadata(tmp_path: Path) -> None:
iccp_data = b"<iccp_data>"
exif_data = b"<exif_data>"
xmp_data = b"<xmp_data>"

View File

@ -1,5 +1,7 @@
from __future__ import annotations
from pathlib import Path
import pytest
from PIL import Image, WmfImagePlugin
@ -7,7 +9,7 @@ from PIL import Image, WmfImagePlugin
from .helper import assert_image_similar_tofile, hopper
def test_load_raw():
def test_load_raw() -> None:
# Test basic EMF open and rendering
with Image.open("Tests/images/drawing.emf") as im:
if hasattr(Image.core, "drawwmf"):
@ -25,17 +27,17 @@ def test_load_raw():
assert_image_similar_tofile(im, "Tests/images/drawing_wmf_ref.png", 2.0)
def test_load():
def test_load() -> None:
with Image.open("Tests/images/drawing.emf") as im:
if hasattr(Image.core, "drawwmf"):
assert im.load()[0, 0] == (255, 255, 255)
def test_register_handler(tmp_path):
def test_register_handler(tmp_path: Path) -> None:
class TestHandler:
methodCalled = False
def save(self, im, fp, filename):
def save(self, im, fp, filename) -> None:
self.methodCalled = True
handler = TestHandler()
@ -51,12 +53,12 @@ def test_register_handler(tmp_path):
WmfImagePlugin.register_handler(original_handler)
def test_load_float_dpi():
def test_load_float_dpi() -> None:
with Image.open("Tests/images/drawing.emf") as im:
assert im.info["dpi"] == 1423.7668161434979
def test_load_set_dpi():
def test_load_set_dpi() -> None:
with Image.open("Tests/images/drawing.wmf") as im:
assert im.size == (82, 82)
@ -68,7 +70,7 @@ def test_load_set_dpi():
@pytest.mark.parametrize("ext", (".wmf", ".emf"))
def test_save(ext, tmp_path):
def test_save(ext, tmp_path: Path) -> None:
im = hopper()
tmpfile = str(tmp_path / ("temp" + ext))

View File

@ -1,6 +1,7 @@
from __future__ import annotations
from io import BytesIO
from pathlib import Path
import pytest
@ -32,14 +33,14 @@ static char basic_bits[] = {
"""
def test_pil151():
def test_pil151() -> None:
with Image.open(BytesIO(PIL151)) as im:
im.load()
assert im.mode == "1"
assert im.size == (32, 32)
def test_open():
def test_open() -> None:
# Arrange
# Created with `convert hopper.png hopper.xbm`
filename = "Tests/images/hopper.xbm"
@ -51,7 +52,7 @@ def test_open():
assert im.size == (128, 128)
def test_open_filename_with_underscore():
def test_open_filename_with_underscore() -> None:
# Arrange
# Created with `convert hopper.png hopper_underscore.xbm`
filename = "Tests/images/hopper_underscore.xbm"
@ -63,14 +64,14 @@ def test_open_filename_with_underscore():
assert im.size == (128, 128)
def test_invalid_file():
def test_invalid_file() -> None:
invalid_file = "Tests/images/flower.jpg"
with pytest.raises(SyntaxError):
XbmImagePlugin.XbmImageFile(invalid_file)
def test_save_wrong_mode(tmp_path):
def test_save_wrong_mode(tmp_path: Path) -> None:
im = hopper()
out = str(tmp_path / "temp.xbm")
@ -78,7 +79,7 @@ def test_save_wrong_mode(tmp_path):
im.save(out)
def test_hotspot(tmp_path):
def test_hotspot(tmp_path: Path) -> None:
im = hopper("1")
out = str(tmp_path / "temp.xbm")

View File

@ -21,7 +21,7 @@ def tuple_to_ints(tp):
return int(x * 255.0), int(y * 255.0), int(z * 255.0)
def test_sanity():
def test_sanity() -> None:
Image.new("HSV", (100, 100))
@ -78,7 +78,7 @@ def to_rgb_colorsys(im):
return to_xxx_colorsys(im, colorsys.hsv_to_rgb, "RGB")
def test_wedge():
def test_wedge() -> None:
src = wedge().resize((3 * 32, 32), Image.Resampling.BILINEAR)
im = src.convert("HSV")
comparable = to_hsv_colorsys(src)
@ -110,7 +110,7 @@ def test_wedge():
)
def test_convert():
def test_convert() -> None:
im = hopper("RGB").convert("HSV")
comparable = to_hsv_colorsys(hopper("RGB"))
@ -128,7 +128,7 @@ def test_convert():
)
def test_hsv_to_rgb():
def test_hsv_to_rgb() -> None:
comparable = to_hsv_colorsys(hopper("RGB"))
converted = comparable.convert("RGB")
comparable = to_rgb_colorsys(comparable)

View File

@ -7,6 +7,7 @@ import shutil
import sys
import tempfile
import warnings
from pathlib import Path
import pytest
@ -60,19 +61,19 @@ class TestImage:
"HSV",
),
)
def test_image_modes_success(self, mode):
def test_image_modes_success(self, mode) -> None:
Image.new(mode, (1, 1))
@pytest.mark.parametrize("mode", ("", "bad", "very very long"))
def test_image_modes_fail(self, mode):
def test_image_modes_fail(self, mode) -> None:
with pytest.raises(ValueError) as e:
Image.new(mode, (1, 1))
assert str(e.value) == "unrecognized image mode"
def test_exception_inheritance(self):
def test_exception_inheritance(self) -> None:
assert issubclass(UnidentifiedImageError, OSError)
def test_sanity(self):
def test_sanity(self) -> None:
im = Image.new("L", (100, 100))
assert repr(im)[:45] == "<PIL.Image.Image image mode=L size=100x100 at"
assert im.mode == "L"
@ -97,9 +98,9 @@ class TestImage:
# with pytest.raises(MemoryError):
# Image.new("L", (1000000, 1000000))
def test_repr_pretty(self):
def test_repr_pretty(self) -> None:
class Pretty:
def text(self, text):
def text(self, text) -> None:
self.pretty_output = text
im = Image.new("L", (100, 100))
@ -108,7 +109,7 @@ class TestImage:
im._repr_pretty_(p, None)
assert p.pretty_output == "<PIL.Image.Image image mode=L size=100x100>"
def test_open_formats(self):
def test_open_formats(self) -> None:
PNGFILE = "Tests/images/hopper.png"
JPGFILE = "Tests/images/hopper.jpg"
@ -130,7 +131,7 @@ class TestImage:
assert im.mode == "RGB"
assert im.size == (128, 128)
def test_width_height(self):
def test_width_height(self) -> None:
im = Image.new("RGB", (1, 2))
assert im.width == 1
assert im.height == 2
@ -138,29 +139,29 @@ class TestImage:
with pytest.raises(AttributeError):
im.size = (3, 4)
def test_set_mode(self):
def test_set_mode(self) -> None:
im = Image.new("RGB", (1, 1))
with pytest.raises(AttributeError):
im.mode = "P"
def test_invalid_image(self):
def test_invalid_image(self) -> None:
im = io.BytesIO(b"")
with pytest.raises(UnidentifiedImageError):
with Image.open(im):
pass
def test_bad_mode(self):
def test_bad_mode(self) -> None:
with pytest.raises(ValueError):
with Image.open("filename", "bad mode"):
pass
def test_stringio(self):
def test_stringio(self) -> None:
with pytest.raises(ValueError):
with Image.open(io.StringIO()):
pass
def test_pathlib(self, tmp_path):
def test_pathlib(self, tmp_path: Path) -> None:
from PIL.Image import Path
with Image.open(Path("Tests/images/multipage-mmap.tiff")) as im:
@ -179,11 +180,11 @@ class TestImage:
os.remove(temp_file)
im.save(Path(temp_file))
def test_fp_name(self, tmp_path):
def test_fp_name(self, tmp_path: Path) -> None:
temp_file = str(tmp_path / "temp.jpg")
class FP:
def write(self, b):
def write(self, b) -> None:
pass
fp = FP()
@ -192,7 +193,7 @@ class TestImage:
im = hopper()
im.save(fp)
def test_tempfile(self):
def test_tempfile(self) -> None:
# see #1460, pathlib support breaks tempfile.TemporaryFile on py27
# Will error out on save on 3.0.0
im = hopper()
@ -201,13 +202,13 @@ class TestImage:
fp.seek(0)
assert_image_similar_tofile(im, fp, 20)
def test_unknown_extension(self, tmp_path):
def test_unknown_extension(self, tmp_path: Path) -> None:
im = hopper()
temp_file = str(tmp_path / "temp.unknown")
with pytest.raises(ValueError):
im.save(temp_file)
def test_internals(self):
def test_internals(self) -> None:
im = Image.new("L", (100, 100))
im.readonly = 1
im._copy()
@ -222,7 +223,7 @@ class TestImage:
sys.platform == "cygwin",
reason="Test requires opening an mmaped file for writing",
)
def test_readonly_save(self, tmp_path):
def test_readonly_save(self, tmp_path: Path) -> None:
temp_file = str(tmp_path / "temp.bmp")
shutil.copy("Tests/images/rgb32bf-rgba.bmp", temp_file)
@ -230,7 +231,7 @@ class TestImage:
assert im.readonly
im.save(temp_file)
def test_dump(self, tmp_path):
def test_dump(self, tmp_path: Path) -> None:
im = Image.new("L", (10, 10))
im._dump(str(tmp_path / "temp_L.ppm"))
@ -241,7 +242,7 @@ class TestImage:
with pytest.raises(ValueError):
im._dump(str(tmp_path / "temp_HSV.ppm"))
def test_comparison_with_other_type(self):
def test_comparison_with_other_type(self) -> None:
# Arrange
item = Image.new("RGB", (25, 25), "#000")
num = 12
@ -251,7 +252,7 @@ class TestImage:
assert item is not None
assert item != num
def test_expand_x(self):
def test_expand_x(self) -> None:
# Arrange
im = hopper()
orig_size = im.size
@ -264,7 +265,7 @@ class TestImage:
assert im.size[0] == orig_size[0] + 2 * xmargin
assert im.size[1] == orig_size[1] + 2 * xmargin
def test_expand_xy(self):
def test_expand_xy(self) -> None:
# Arrange
im = hopper()
orig_size = im.size
@ -278,12 +279,12 @@ class TestImage:
assert im.size[0] == orig_size[0] + 2 * xmargin
assert im.size[1] == orig_size[1] + 2 * ymargin
def test_getbands(self):
def test_getbands(self) -> None:
# Assert
assert hopper("RGB").getbands() == ("R", "G", "B")
assert hopper("YCbCr").getbands() == ("Y", "Cb", "Cr")
def test_getchannel_wrong_params(self):
def test_getchannel_wrong_params(self) -> None:
im = hopper()
with pytest.raises(ValueError):
@ -295,7 +296,7 @@ class TestImage:
with pytest.raises(ValueError):
im.getchannel("1")
def test_getchannel(self):
def test_getchannel(self) -> None:
im = hopper("YCbCr")
Y, Cb, Cr = im.split()
@ -306,7 +307,7 @@ class TestImage:
assert_image_equal(Cr, im.getchannel(2))
assert_image_equal(Cr, im.getchannel("Cr"))
def test_getbbox(self):
def test_getbbox(self) -> None:
# Arrange
im = hopper()
@ -316,7 +317,7 @@ class TestImage:
# Assert
assert bbox == (0, 0, 128, 128)
def test_ne(self):
def test_ne(self) -> None:
# Arrange
im1 = Image.new("RGB", (25, 25), "black")
im2 = Image.new("RGB", (25, 25), "white")
@ -324,7 +325,7 @@ class TestImage:
# Act / Assert
assert im1 != im2
def test_alpha_composite(self):
def test_alpha_composite(self) -> None:
# https://stackoverflow.com/questions/3374878
# Arrange
expected_colors = sorted(
@ -355,7 +356,7 @@ class TestImage:
img_colors = sorted(img.getcolors())
assert img_colors == expected_colors
def test_alpha_inplace(self):
def test_alpha_inplace(self) -> None:
src = Image.new("RGBA", (128, 128), "blue")
over = Image.new("RGBA", (128, 128), "red")
@ -407,7 +408,7 @@ class TestImage:
with pytest.raises(ValueError):
source.alpha_composite(over, (0, 0), (0, -1))
def test_register_open_duplicates(self):
def test_register_open_duplicates(self) -> None:
# Arrange
factory, accept = Image.OPEN["JPEG"]
id_length = len(Image.ID)
@ -418,7 +419,7 @@ class TestImage:
# Assert
assert len(Image.ID) == id_length
def test_registered_extensions_uninitialized(self):
def test_registered_extensions_uninitialized(self) -> None:
# Arrange
Image._initialized = 0
@ -428,7 +429,7 @@ class TestImage:
# Assert
assert Image._initialized == 2
def test_registered_extensions(self):
def test_registered_extensions(self) -> None:
# Arrange
# Open an image to trigger plugin registration
with Image.open("Tests/images/rgb.jpg"):
@ -442,7 +443,7 @@ class TestImage:
for ext in [".cur", ".icns", ".tif", ".tiff"]:
assert ext in extensions
def test_effect_mandelbrot(self):
def test_effect_mandelbrot(self) -> None:
# Arrange
size = (512, 512)
extent = (-3, -2.5, 2, 2.5)
@ -455,7 +456,7 @@ class TestImage:
assert im.size == (512, 512)
assert_image_equal_tofile(im, "Tests/images/effect_mandelbrot.png")
def test_effect_mandelbrot_bad_arguments(self):
def test_effect_mandelbrot_bad_arguments(self) -> None:
# Arrange
size = (512, 512)
# Get coordinates the wrong way round:
@ -467,7 +468,7 @@ class TestImage:
with pytest.raises(ValueError):
Image.effect_mandelbrot(size, extent, quality)
def test_effect_noise(self):
def test_effect_noise(self) -> None:
# Arrange
size = (100, 100)
sigma = 128
@ -485,7 +486,7 @@ class TestImage:
p4 = im.getpixel((0, 4))
assert_not_all_same([p0, p1, p2, p3, p4])
def test_effect_spread(self):
def test_effect_spread(self) -> None:
# Arrange
im = hopper()
distance = 10
@ -497,7 +498,7 @@ class TestImage:
assert im.size == (128, 128)
assert_image_similar_tofile(im2, "Tests/images/effect_spread.png", 110)
def test_effect_spread_zero(self):
def test_effect_spread_zero(self) -> None:
# Arrange
im = hopper()
distance = 0
@ -508,7 +509,7 @@ class TestImage:
# Assert
assert_image_equal(im, im2)
def test_check_size(self):
def test_check_size(self) -> None:
# 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
@ -537,10 +538,10 @@ class TestImage:
"PILLOW_VALGRIND_TEST" in os.environ, reason="Valgrind is slower"
)
@pytest.mark.parametrize("size", ((0, 100000000), (100000000, 0)))
def test_empty_image(self, size):
def test_empty_image(self, size) -> None:
Image.new("RGB", size)
def test_storage_neg(self):
def test_storage_neg(self) -> None:
# Storage.c accepted negative values for xsize, ysize. Was
# test_neg_ppm, but the core function for that has been
# removed Calling directly into core to test the error in
@ -549,13 +550,13 @@ class TestImage:
with pytest.raises(ValueError):
Image.core.fill("RGB", (2, -2), (0, 0, 0))
def test_one_item_tuple(self):
def test_one_item_tuple(self) -> None:
for mode in ("I", "F", "L"):
im = Image.new(mode, (100, 100), (5,))
px = im.load()
assert px[0, 0] == 5
def test_linear_gradient_wrong_mode(self):
def test_linear_gradient_wrong_mode(self) -> None:
# Arrange
wrong_mode = "RGB"
@ -564,7 +565,7 @@ class TestImage:
Image.linear_gradient(wrong_mode)
@pytest.mark.parametrize("mode", ("L", "P", "I", "F"))
def test_linear_gradient(self, mode):
def test_linear_gradient(self, mode) -> None:
# Arrange
target_file = "Tests/images/linear_gradient.png"
@ -580,7 +581,7 @@ class TestImage:
target = target.convert(mode)
assert_image_equal(im, target)
def test_radial_gradient_wrong_mode(self):
def test_radial_gradient_wrong_mode(self) -> None:
# Arrange
wrong_mode = "RGB"
@ -589,7 +590,7 @@ class TestImage:
Image.radial_gradient(wrong_mode)
@pytest.mark.parametrize("mode", ("L", "P", "I", "F"))
def test_radial_gradient(self, mode):
def test_radial_gradient(self, mode) -> None:
# Arrange
target_file = "Tests/images/radial_gradient.png"
@ -605,7 +606,7 @@ class TestImage:
target = target.convert(mode)
assert_image_equal(im, target)
def test_register_extensions(self):
def test_register_extensions(self) -> None:
test_format = "a"
exts = ["b", "c"]
for ext in exts:
@ -621,7 +622,7 @@ class TestImage:
assert ext_individual == ext_multiple
def test_remap_palette(self):
def test_remap_palette(self) -> None:
# Test identity transform
with Image.open("Tests/images/hopper.gif") as im:
assert_image_equal(im, im.remap_palette(list(range(256))))
@ -640,7 +641,7 @@ class TestImage:
with pytest.raises(ValueError):
im.remap_palette(None)
def test_remap_palette_transparency(self):
def test_remap_palette_transparency(self) -> None:
im = Image.new("P", (1, 2), (0, 0, 0))
im.putpixel((0, 1), (255, 0, 0))
im.info["transparency"] = 0
@ -655,7 +656,7 @@ class TestImage:
im_remapped = im.remap_palette([1, 0])
assert "transparency" not in im_remapped.info
def test__new(self):
def test__new(self) -> None:
im = hopper("RGB")
im_p = hopper("P")
@ -664,7 +665,7 @@ class TestImage:
blank_p.palette = None
blank_pa.palette = None
def _make_new(base_image, image, palette_result=None):
def _make_new(base_image, image, palette_result=None) -> None:
new_image = base_image._new(image.im)
assert new_image.mode == image.mode
assert new_image.size == image.size
@ -679,7 +680,7 @@ class TestImage:
_make_new(im, blank_p, ImagePalette.ImagePalette())
_make_new(im, blank_pa, ImagePalette.ImagePalette())
def test_p_from_rgb_rgba(self):
def test_p_from_rgb_rgba(self) -> None:
for mode, color in [
("RGB", "#DDEEFF"),
("RGB", (221, 238, 255)),
@ -689,7 +690,7 @@ class TestImage:
expected = Image.new(mode, (100, 100), color)
assert_image_equal(im.convert(mode), expected)
def test_no_resource_warning_on_save(self, tmp_path):
def test_no_resource_warning_on_save(self, tmp_path: Path) -> None:
# https://github.com/python-pillow/Pillow/issues/835
# Arrange
test_file = "Tests/images/hopper.png"
@ -700,7 +701,7 @@ class TestImage:
with warnings.catch_warnings():
im.save(temp_file)
def test_no_new_file_on_error(self, tmp_path):
def test_no_new_file_on_error(self, tmp_path: Path) -> None:
temp_file = str(tmp_path / "temp.jpg")
im = Image.new("RGB", (0, 0))
@ -709,10 +710,10 @@ class TestImage:
assert not os.path.exists(temp_file)
def test_load_on_nonexclusive_multiframe(self):
def test_load_on_nonexclusive_multiframe(self) -> None:
with open("Tests/images/frozenpond.mpo", "rb") as fp:
def act(fp):
def act(fp) -> None:
im = Image.open(fp)
im.load()
@ -723,7 +724,7 @@ class TestImage:
assert not fp.closed
def test_empty_exif(self):
def test_empty_exif(self) -> None:
with Image.open("Tests/images/exif.png") as im:
exif = im.getexif()
assert dict(exif)
@ -739,7 +740,7 @@ class TestImage:
@mark_if_feature_version(
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
)
def test_exif_jpeg(self, tmp_path):
def test_exif_jpeg(self, tmp_path: Path) -> None:
with Image.open("Tests/images/exif-72dpi-int.jpg") as im: # Little endian
exif = im.getexif()
assert 258 not in exif
@ -785,7 +786,7 @@ class TestImage:
@skip_unless_feature("webp")
@skip_unless_feature("webp_anim")
def test_exif_webp(self, tmp_path):
def test_exif_webp(self, tmp_path: Path) -> None:
with Image.open("Tests/images/hopper.webp") as im:
exif = im.getexif()
assert exif == {}
@ -795,7 +796,7 @@ class TestImage:
exif[40963] = 455
exif[305] = "Pillow test"
def check_exif():
def check_exif() -> None:
with Image.open(out) as reloaded:
reloaded_exif = reloaded.getexif()
assert reloaded_exif[258] == 8
@ -807,7 +808,7 @@ class TestImage:
im.save(out, exif=exif, save_all=True)
check_exif()
def test_exif_png(self, tmp_path):
def test_exif_png(self, tmp_path: Path) -> None:
with Image.open("Tests/images/exif.png") as im:
exif = im.getexif()
assert exif == {274: 1}
@ -823,7 +824,7 @@ class TestImage:
reloaded_exif = reloaded.getexif()
assert reloaded_exif == {258: 8, 40963: 455, 305: "Pillow test"}
def test_exif_interop(self):
def test_exif_interop(self) -> None:
with Image.open("Tests/images/flower.jpg") as im:
exif = im.getexif()
assert exif.get_ifd(0xA005) == {
@ -837,7 +838,7 @@ class TestImage:
reloaded_exif.load(exif.tobytes())
assert reloaded_exif.get_ifd(0xA005) == exif.get_ifd(0xA005)
def test_exif_ifd1(self):
def test_exif_ifd1(self) -> None:
with Image.open("Tests/images/flower.jpg") as im:
exif = im.getexif()
assert exif.get_ifd(ExifTags.IFD.IFD1) == {
@ -849,7 +850,7 @@ class TestImage:
283: 180.0,
}
def test_exif_ifd(self):
def test_exif_ifd(self) -> None:
with Image.open("Tests/images/flower.jpg") as im:
exif = im.getexif()
del exif.get_ifd(0x8769)[0xA005]
@ -858,7 +859,7 @@ class TestImage:
reloaded_exif.load(exif.tobytes())
assert reloaded_exif.get_ifd(0x8769) == exif.get_ifd(0x8769)
def test_exif_load_from_fp(self):
def test_exif_load_from_fp(self) -> None:
with Image.open("Tests/images/flower.jpg") as im:
data = im.info["exif"]
if data.startswith(b"Exif\x00\x00"):
@ -879,7 +880,7 @@ class TestImage:
34665: 196,
}
def test_exif_hide_offsets(self):
def test_exif_hide_offsets(self) -> None:
with Image.open("Tests/images/flower.jpg") as im:
exif = im.getexif()
@ -905,18 +906,18 @@ class TestImage:
assert exif.get_ifd(0xA005)
@pytest.mark.parametrize("size", ((1, 0), (0, 1), (0, 0)))
def test_zero_tobytes(self, size):
def test_zero_tobytes(self, size) -> None:
im = Image.new("RGB", size)
assert im.tobytes() == b""
@pytest.mark.parametrize("size", ((1, 0), (0, 1), (0, 0)))
def test_zero_frombytes(self, size):
def test_zero_frombytes(self, size) -> None:
Image.frombytes("RGB", size, b"")
im = Image.new("RGB", size)
im.frombytes(b"")
def test_has_transparency_data(self):
def test_has_transparency_data(self) -> None:
for mode in ("1", "L", "P", "RGB"):
im = Image.new(mode, (1, 1))
assert not im.has_transparency_data
@ -941,7 +942,7 @@ class TestImage:
assert im.palette.mode == "RGBA"
assert im.has_transparency_data
def test_apply_transparency(self):
def test_apply_transparency(self) -> None:
im = Image.new("P", (1, 1))
im.putpalette((0, 0, 0, 1, 1, 1))
assert im.palette.colors == {(0, 0, 0): 0, (1, 1, 1): 1}
@ -970,7 +971,7 @@ class TestImage:
im.apply_transparency()
assert im.palette.colors[(27, 35, 6, 214)] == 24
def test_constants(self):
def test_constants(self) -> None:
for enum in (
Image.Transpose,
Image.Transform,
@ -995,7 +996,7 @@ class TestImage:
"01r_00.pcx",
],
)
def test_overrun(self, path):
def test_overrun(self, path) -> None:
"""For overrun completeness, test as:
valgrind pytest -qq Tests/test_image.py::TestImage::test_overrun | grep decode.c
"""
@ -1009,7 +1010,7 @@ class TestImage:
assert buffer_overrun or truncated
def test_fli_overrun2(self):
def test_fli_overrun2(self) -> None:
with Image.open("Tests/images/fli_overrun2.bin") as im:
try:
im.seek(1)
@ -1017,12 +1018,12 @@ class TestImage:
except OSError as e:
assert str(e) == "buffer overrun when reading image file"
def test_exit_fp(self):
def test_exit_fp(self) -> None:
with Image.new("L", (1, 1)) as im:
pass
assert not hasattr(im, "fp")
def test_close_graceful(self, caplog):
def test_close_graceful(self, caplog) -> None:
with Image.open("Tests/images/hopper.jpg") as im:
copy = im.copy()
with caplog.at_level(logging.DEBUG):
@ -1043,7 +1044,7 @@ def mock_encode(*args):
class TestRegistry:
def test_encode_registry(self):
def test_encode_registry(self) -> None:
Image.register_encoder("MOCK", mock_encode)
assert "MOCK" in Image.ENCODERS
@ -1052,6 +1053,6 @@ class TestRegistry:
assert isinstance(enc, MockEncoder)
assert enc.args == ("RGB", "args", "extra")
def test_encode_registry_fail(self):
def test_encode_registry_fail(self) -> None:
with pytest.raises(OSError):
Image._getencoder("RGB", "DoesNotExist", ("args",), extra=("extra",))

View File

@ -35,16 +35,16 @@ class AccessTest:
_need_cffi_access = False
@classmethod
def setup_class(cls):
def setup_class(cls) -> None:
Image.USE_CFFI_ACCESS = cls._need_cffi_access
@classmethod
def teardown_class(cls):
def teardown_class(cls) -> None:
Image.USE_CFFI_ACCESS = cls._init_cffi_access
class TestImagePutPixel(AccessTest):
def test_sanity(self):
def test_sanity(self) -> None:
im1 = hopper()
im2 = Image.new(im1.mode, im1.size, 0)
@ -81,7 +81,7 @@ class TestImagePutPixel(AccessTest):
assert_image_equal(im1, im2)
def test_sanity_negative_index(self):
def test_sanity_negative_index(self) -> None:
im1 = hopper()
im2 = Image.new(im1.mode, im1.size, 0)
@ -119,7 +119,7 @@ class TestImagePutPixel(AccessTest):
assert_image_equal(im1, im2)
@pytest.mark.skipif(numpy is None, reason="NumPy not installed")
def test_numpy(self):
def test_numpy(self) -> None:
im = hopper()
pix = im.load()
@ -138,7 +138,7 @@ class TestImageGetPixel(AccessTest):
return (16, 32, 49)
return tuple(range(1, bands + 1))
def check(self, mode, expected_color=None):
def check(self, mode, expected_color=None) -> None:
if self._need_cffi_access and mode.startswith("BGR;"):
pytest.skip("Support not added to deprecated module for BGR;* modes")
@ -222,10 +222,10 @@ class TestImageGetPixel(AccessTest):
"YCbCr",
),
)
def test_basic(self, mode):
def test_basic(self, mode) -> None:
self.check(mode)
def test_list(self):
def test_list(self) -> None:
im = hopper()
assert im.getpixel([0, 0]) == (20, 20, 70)
@ -233,14 +233,14 @@ class TestImageGetPixel(AccessTest):
@pytest.mark.parametrize(
"expected_color", (2**15 - 1, 2**15, 2**15 + 1, 2**16 - 1)
)
def test_signedness(self, mode, expected_color):
def test_signedness(self, mode, expected_color) -> None:
# see https://github.com/python-pillow/Pillow/issues/452
# pixelaccess is using signed int* instead of uint*
self.check(mode, expected_color)
@pytest.mark.parametrize("mode", ("P", "PA"))
@pytest.mark.parametrize("color", ((255, 0, 0), (255, 0, 0, 255)))
def test_p_putpixel_rgb_rgba(self, mode, color):
def test_p_putpixel_rgb_rgba(self, mode, color) -> None:
im = Image.new(mode, (1, 1))
im.putpixel((0, 0), color)
@ -264,7 +264,7 @@ class TestCffiGetPixel(TestImageGetPixel):
class TestCffi(AccessTest):
_need_cffi_access = True
def _test_get_access(self, im):
def _test_get_access(self, im) -> None:
"""Do we get the same thing as the old pixel access
Using private interfaces, forcing a capi access and
@ -282,7 +282,7 @@ class TestCffi(AccessTest):
with pytest.raises(ValueError):
access[(access.xsize + 1, access.ysize + 1)]
def test_get_vs_c(self):
def test_get_vs_c(self) -> None:
with pytest.warns(DeprecationWarning):
rgb = hopper("RGB")
rgb.load()
@ -301,7 +301,7 @@ class TestCffi(AccessTest):
# im = Image.new('I;32B', (10, 10), 2**10)
# self._test_get_access(im)
def _test_set_access(self, im, color):
def _test_set_access(self, im, color) -> None:
"""Are we writing the correct bits into the image?
Using private interfaces, forcing a capi access and
@ -322,7 +322,7 @@ class TestCffi(AccessTest):
with pytest.raises(ValueError):
access[(0, 0)] = color
def test_set_vs_c(self):
def test_set_vs_c(self) -> None:
rgb = hopper("RGB")
with pytest.warns(DeprecationWarning):
rgb.load()
@ -345,11 +345,11 @@ class TestCffi(AccessTest):
# self._test_set_access(im, 2**13-1)
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_not_implemented(self):
def test_not_implemented(self) -> None:
assert PyAccess.new(hopper("BGR;15")) is None
# ref https://github.com/python-pillow/Pillow/pull/2009
def test_reference_counting(self):
def test_reference_counting(self) -> None:
size = 10
for _ in range(10):
@ -361,7 +361,7 @@ class TestCffi(AccessTest):
assert px[i, 0] == 0
@pytest.mark.parametrize("mode", ("P", "PA"))
def test_p_putpixel_rgb_rgba(self, mode):
def test_p_putpixel_rgb_rgba(self, mode) -> None:
for color in ((255, 0, 0), (255, 0, 0, 127 if mode == "PA" else 255)):
im = Image.new(mode, (1, 1))
with pytest.warns(DeprecationWarning):
@ -379,7 +379,7 @@ class TestImagePutPixelError(AccessTest):
INVALID_TYPES = ["foo", 1.0, None]
@pytest.mark.parametrize("mode", IMAGE_MODES1)
def test_putpixel_type_error1(self, mode):
def test_putpixel_type_error1(self, mode) -> None:
im = hopper(mode)
for v in self.INVALID_TYPES:
with pytest.raises(TypeError, match="color must be int or tuple"):
@ -402,14 +402,14 @@ class TestImagePutPixelError(AccessTest):
),
),
)
def test_putpixel_invalid_number_of_bands(self, mode, band_numbers, match):
def test_putpixel_invalid_number_of_bands(self, mode, band_numbers, match) -> None:
im = hopper(mode)
for band_number in band_numbers:
with pytest.raises(TypeError, match=match):
im.putpixel((0, 0), (0,) * band_number)
@pytest.mark.parametrize("mode", IMAGE_MODES2)
def test_putpixel_type_error2(self, mode):
def test_putpixel_type_error2(self, mode) -> None:
im = hopper(mode)
for v in self.INVALID_TYPES:
with pytest.raises(
@ -418,7 +418,7 @@ class TestImagePutPixelError(AccessTest):
im.putpixel((0, 0), v)
@pytest.mark.parametrize("mode", IMAGE_MODES1 + IMAGE_MODES2)
def test_putpixel_overflow_error(self, mode):
def test_putpixel_overflow_error(self, mode) -> None:
im = hopper(mode)
with pytest.raises(OverflowError):
im.putpixel((0, 0), 2**80)
@ -427,7 +427,7 @@ class TestImagePutPixelError(AccessTest):
class TestEmbeddable:
@pytest.mark.xfail(reason="failing test")
@pytest.mark.skipif(not is_win32(), reason="requires Windows")
def test_embeddable(self):
def test_embeddable(self) -> None:
import ctypes
from setuptools.command.build_ext import new_compiler

View File

@ -12,12 +12,12 @@ numpy = pytest.importorskip("numpy", reason="NumPy not installed")
im = hopper().resize((128, 100))
def test_toarray():
def test_toarray() -> None:
def test(mode):
ai = numpy.array(im.convert(mode))
return ai.shape, ai.dtype.str, ai.nbytes
def test_with_dtype(dtype):
def test_with_dtype(dtype) -> None:
ai = numpy.array(im, dtype=dtype)
assert ai.dtype == dtype
@ -46,11 +46,11 @@ def test_toarray():
numpy.array(im_truncated)
def test_fromarray():
def test_fromarray() -> None:
class Wrapper:
"""Class with API matching Image.fromarray"""
def __init__(self, img, arr_params):
def __init__(self, img, arr_params) -> None:
self.img = img
self.__array_interface__ = arr_params
@ -89,7 +89,7 @@ def test_fromarray():
Image.fromarray(wrapped)
def test_fromarray_palette():
def test_fromarray_palette() -> None:
# Arrange
i = im.convert("L")
a = numpy.array(i)

View File

@ -19,7 +19,7 @@ def draft_roundtrip(in_mode, in_size, req_mode, req_size):
return im
def test_size():
def test_size() -> None:
for in_size, req_size, out_size in [
((435, 361), (2048, 2048), (435, 361)), # bigger
((435, 361), (435, 361), (435, 361)), # same
@ -48,7 +48,7 @@ def test_size():
assert im.size == out_size
def test_mode():
def test_mode() -> None:
for in_mode, req_mode, out_mode in [
("RGB", "1", "RGB"),
("RGB", "L", "L"),
@ -68,7 +68,7 @@ def test_mode():
assert im.mode == out_mode
def test_several_drafts():
def test_several_drafts() -> None:
im = draft_roundtrip("L", (128, 128), None, (64, 64))
im.draft(None, (64, 64))
im.load()

View File

@ -3,7 +3,7 @@ from __future__ import annotations
from .helper import hopper
def test_entropy():
def test_entropy() -> None:
def entropy(mode):
return hopper(mode).entropy()

View File

@ -36,7 +36,7 @@ from .helper import assert_image_equal, hopper
),
)
@pytest.mark.parametrize("mode", ("L", "I", "RGB", "CMYK"))
def test_sanity(filter_to_apply, mode):
def test_sanity(filter_to_apply, mode) -> None:
im = hopper(mode)
if mode != "I" or isinstance(filter_to_apply, ImageFilter.BuiltinFilter):
out = im.filter(filter_to_apply)
@ -45,7 +45,7 @@ def test_sanity(filter_to_apply, mode):
@pytest.mark.parametrize("mode", ("L", "I", "RGB", "CMYK"))
def test_sanity_error(mode):
def test_sanity_error(mode) -> None:
with pytest.raises(TypeError):
im = hopper(mode)
im.filter("hello")
@ -53,7 +53,7 @@ def test_sanity_error(mode):
# crashes on small images
@pytest.mark.parametrize("size", ((1, 1), (2, 2), (3, 3)))
def test_crash(size):
def test_crash(size) -> None:
im = Image.new("RGB", size)
im.filter(ImageFilter.SMOOTH)
@ -67,7 +67,7 @@ def test_crash(size):
("RGB", ((4, 0, 0), (0, 0, 0))),
),
)
def test_modefilter(mode, expected):
def test_modefilter(mode, expected) -> None:
im = Image.new(mode, (3, 3), None)
im.putdata(list(range(9)))
# image is:
@ -90,7 +90,7 @@ def test_modefilter(mode, expected):
("F", (0.0, 4.0, 8.0)),
),
)
def test_rankfilter(mode, expected):
def test_rankfilter(mode, expected) -> None:
im = Image.new(mode, (3, 3), None)
im.putdata(list(range(9)))
# image is:
@ -106,7 +106,7 @@ def test_rankfilter(mode, expected):
@pytest.mark.parametrize(
"filter", (ImageFilter.MinFilter, ImageFilter.MedianFilter, ImageFilter.MaxFilter)
)
def test_rankfilter_error(filter):
def test_rankfilter_error(filter) -> None:
with pytest.raises(ValueError):
im = Image.new("P", (3, 3), None)
im.putdata(list(range(9)))
@ -117,27 +117,27 @@ def test_rankfilter_error(filter):
im.filter(filter).getpixel((1, 1))
def test_rankfilter_properties():
def test_rankfilter_properties() -> None:
rankfilter = ImageFilter.RankFilter(1, 2)
assert rankfilter.size == 1
assert rankfilter.rank == 2
def test_builtinfilter_p():
def test_builtinfilter_p() -> None:
builtin_filter = ImageFilter.BuiltinFilter()
with pytest.raises(ValueError):
builtin_filter.filter(hopper("P"))
def test_kernel_not_enough_coefficients():
def test_kernel_not_enough_coefficients() -> None:
with pytest.raises(ValueError):
ImageFilter.Kernel((3, 3), (0, 0))
@pytest.mark.parametrize("mode", ("L", "LA", "I", "RGB", "CMYK"))
def test_consistency_3x3(mode):
def test_consistency_3x3(mode) -> None:
with Image.open("Tests/images/hopper.bmp") as source:
reference_name = "hopper_emboss"
reference_name += "_I.png" if mode == "I" else ".bmp"
@ -163,7 +163,7 @@ def test_consistency_3x3(mode):
@pytest.mark.parametrize("mode", ("L", "LA", "I", "RGB", "CMYK"))
def test_consistency_5x5(mode):
def test_consistency_5x5(mode) -> None:
with Image.open("Tests/images/hopper.bmp") as source:
reference_name = "hopper_emboss_more"
reference_name += "_I.png" if mode == "I" else ".bmp"
@ -199,7 +199,7 @@ def test_consistency_5x5(mode):
(2, -2),
),
)
def test_invalid_box_blur_filter(radius):
def test_invalid_box_blur_filter(radius) -> None:
with pytest.raises(ValueError):
ImageFilter.BoxBlur(radius)

View File

@ -5,7 +5,7 @@ from PIL import Image
from .helper import hopper
def test_extrema():
def test_extrema() -> None:
def extrema(mode):
return hopper(mode).getextrema()
@ -20,7 +20,7 @@ def test_extrema():
assert extrema("I;16") == (1, 255)
def test_true_16():
def test_true_16() -> None:
with Image.open("Tests/images/16_bit_noise.tif") as im:
assert im.mode == "I;16"
extrema = im.getextrema()

View File

@ -5,7 +5,7 @@ from PIL import Image
from .helper import hopper
def test_palette():
def test_palette() -> None:
def palette(mode):
p = hopper(mode).getpalette()
if p:
@ -23,7 +23,7 @@ def test_palette():
assert palette("YCbCr") is None
def test_palette_rawmode():
def test_palette_rawmode() -> None:
im = Image.new("P", (1, 1))
im.putpalette((1, 2, 3))

View File

@ -10,14 +10,14 @@ from PIL import Image
from .helper import hopper
def test_sanity():
def test_sanity() -> None:
im = hopper()
pix = im.load()
assert pix[0, 0] == (20, 20, 70)
def test_close():
def test_close() -> None:
im = Image.open("Tests/images/hopper.gif")
im.close()
with pytest.raises(ValueError):
@ -26,7 +26,7 @@ def test_close():
im.getpixel((0, 0))
def test_close_after_load(caplog):
def test_close_after_load(caplog) -> None:
im = Image.open("Tests/images/hopper.gif")
im.load()
with caplog.at_level(logging.DEBUG):
@ -34,7 +34,7 @@ def test_close_after_load(caplog):
assert len(caplog.records) == 0
def test_contextmanager():
def test_contextmanager() -> None:
fn = None
with Image.open("Tests/images/hopper.gif") as im:
fn = im.fp.fileno()
@ -44,7 +44,7 @@ def test_contextmanager():
os.fstat(fn)
def test_contextmanager_non_exclusive_fp():
def test_contextmanager_non_exclusive_fp() -> None:
with open("Tests/images/hopper.gif", "rb") as fp:
with Image.open(fp):
pass

View File

@ -7,7 +7,7 @@ from PIL import Image, ImageMode
from .helper import hopper
def test_sanity():
def test_sanity() -> None:
with hopper() as im:
im.mode
@ -69,7 +69,7 @@ def test_sanity():
)
def test_properties(
mode, expected_base, expected_type, expected_bands, expected_band_names
):
) -> None:
assert Image.getmodebase(mode) == expected_base
assert Image.getmodetype(mode) == expected_type
assert Image.getmodebands(mode) == expected_bands

View File

@ -11,7 +11,7 @@ class TestImagingPaste:
masks = {}
size = 128
def assert_9points_image(self, im, expected):
def assert_9points_image(self, im, expected) -> None:
expected = [
point[0] if im.mode == "L" else point[: len(im.mode)] for point in expected
]
@ -29,7 +29,7 @@ class TestImagingPaste:
]
assert actual == expected
def assert_9points_paste(self, im, im2, mask, expected):
def assert_9points_paste(self, im, im2, mask, expected) -> None:
im3 = im.copy()
im3.paste(im2, (0, 0), mask)
self.assert_9points_image(im3, expected)
@ -106,7 +106,7 @@ class TestImagingPaste:
)
@pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
def test_image_solid(self, mode):
def test_image_solid(self, mode) -> None:
im = Image.new(mode, (200, 200), "red")
im2 = getattr(self, "gradient_" + mode)
@ -116,7 +116,7 @@ class TestImagingPaste:
assert_image_equal(im, im2)
@pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
def test_image_mask_1(self, mode):
def test_image_mask_1(self, mode) -> None:
im = Image.new(mode, (200, 200), "white")
im2 = getattr(self, "gradient_" + mode)
@ -138,7 +138,7 @@ class TestImagingPaste:
)
@pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
def test_image_mask_L(self, mode):
def test_image_mask_L(self, mode) -> None:
im = Image.new(mode, (200, 200), "white")
im2 = getattr(self, "gradient_" + mode)
@ -160,7 +160,7 @@ class TestImagingPaste:
)
@pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
def test_image_mask_LA(self, mode):
def test_image_mask_LA(self, mode) -> None:
im = Image.new(mode, (200, 200), "white")
im2 = getattr(self, "gradient_" + mode)
@ -182,7 +182,7 @@ class TestImagingPaste:
)
@pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
def test_image_mask_RGBA(self, mode):
def test_image_mask_RGBA(self, mode) -> None:
im = Image.new(mode, (200, 200), "white")
im2 = getattr(self, "gradient_" + mode)
@ -204,7 +204,7 @@ class TestImagingPaste:
)
@pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
def test_image_mask_RGBa(self, mode):
def test_image_mask_RGBa(self, mode) -> None:
im = Image.new(mode, (200, 200), "white")
im2 = getattr(self, "gradient_" + mode)
@ -226,7 +226,7 @@ class TestImagingPaste:
)
@pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
def test_color_solid(self, mode):
def test_color_solid(self, mode) -> None:
im = Image.new(mode, (200, 200), "black")
rect = (12, 23, 128 + 12, 128 + 23)
@ -239,7 +239,7 @@ class TestImagingPaste:
assert sum(head[:255]) == 0
@pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
def test_color_mask_1(self, mode):
def test_color_mask_1(self, mode) -> None:
im = Image.new(mode, (200, 200), (50, 60, 70, 80)[: len(mode)])
color = (10, 20, 30, 40)[: len(mode)]
@ -261,7 +261,7 @@ class TestImagingPaste:
)
@pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
def test_color_mask_L(self, mode):
def test_color_mask_L(self, mode) -> None:
im = getattr(self, "gradient_" + mode).copy()
color = "white"
@ -283,7 +283,7 @@ class TestImagingPaste:
)
@pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
def test_color_mask_RGBA(self, mode):
def test_color_mask_RGBA(self, mode) -> None:
im = getattr(self, "gradient_" + mode).copy()
color = "white"
@ -305,7 +305,7 @@ class TestImagingPaste:
)
@pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
def test_color_mask_RGBa(self, mode):
def test_color_mask_RGBa(self, mode) -> None:
im = getattr(self, "gradient_" + mode).copy()
color = "white"
@ -326,7 +326,7 @@ class TestImagingPaste:
],
)
def test_different_sizes(self):
def test_different_sizes(self) -> None:
im = Image.new("RGB", (100, 100))
im2 = Image.new("RGB", (50, 50))

View File

@ -10,7 +10,7 @@ from PIL import Image
from .helper import assert_image_equal, hopper
def test_sanity():
def test_sanity() -> None:
im1 = hopper()
data = list(im1.getdata())
@ -29,7 +29,7 @@ def test_sanity():
assert_image_equal(im1, im2)
def test_long_integers():
def test_long_integers() -> None:
# see bug-200802-systemerror
def put(value):
im = Image.new("RGBA", (1, 1))
@ -46,19 +46,19 @@ def test_long_integers():
assert put(sys.maxsize) == (255, 255, 255, 127)
def test_pypy_performance():
def test_pypy_performance() -> None:
im = Image.new("L", (256, 256))
im.putdata(list(range(256)) * 256)
def test_mode_with_L_with_float():
def test_mode_with_L_with_float() -> None:
im = Image.new("L", (1, 1), 0)
im.putdata([2.0])
assert im.getpixel((0, 0)) == 2
@pytest.mark.parametrize("mode", ("I", "I;16", "I;16L", "I;16B"))
def test_mode_i(mode):
def test_mode_i(mode) -> None:
src = hopper("L")
data = list(src.getdata())
im = Image.new(mode, src.size, 0)
@ -68,7 +68,7 @@ def test_mode_i(mode):
assert list(im.getdata()) == target
def test_mode_F():
def test_mode_F() -> None:
src = hopper("L")
data = list(src.getdata())
im = Image.new("F", src.size, 0)
@ -79,7 +79,7 @@ def test_mode_F():
@pytest.mark.parametrize("mode", ("BGR;15", "BGR;16", "BGR;24"))
def test_mode_BGR(mode):
def test_mode_BGR(mode) -> None:
data = [(16, 32, 49), (32, 32, 98)]
im = Image.new(mode, (1, 2))
im.putdata(data)
@ -87,7 +87,7 @@ def test_mode_BGR(mode):
assert list(im.getdata()) == data
def test_array_B():
def test_array_B() -> None:
# shouldn't segfault
# see https://github.com/python-pillow/Pillow/issues/1008
@ -98,7 +98,7 @@ def test_array_B():
assert len(im.getdata()) == len(arr)
def test_array_F():
def test_array_F() -> None:
# shouldn't segfault
# see https://github.com/python-pillow/Pillow/issues/1008
@ -109,7 +109,7 @@ def test_array_F():
assert len(im.getdata()) == len(arr)
def test_not_flattened():
def test_not_flattened() -> None:
im = Image.new("L", (1, 1))
with pytest.raises(TypeError):
im.putdata([[0]])

View File

@ -7,7 +7,7 @@ from PIL import Image, ImagePalette
from .helper import assert_image_equal, assert_image_equal_tofile, hopper
def test_putpalette():
def test_putpalette() -> None:
def palette(mode):
im = hopper(mode).copy()
im.putpalette(list(range(256)) * 3)
@ -43,7 +43,7 @@ def test_putpalette():
im.putpalette(list(range(256)) * 3)
def test_imagepalette():
def test_imagepalette() -> None:
im = hopper("P")
im.putpalette(ImagePalette.negative())
assert_image_equal_tofile(im.convert("RGB"), "Tests/images/palette_negative.png")
@ -57,7 +57,7 @@ def test_imagepalette():
assert_image_equal_tofile(im.convert("RGB"), "Tests/images/palette_wedge.png")
def test_putpalette_with_alpha_values():
def test_putpalette_with_alpha_values() -> None:
with Image.open("Tests/images/transparent.gif") as im:
expected = im.convert("RGBA")
@ -81,19 +81,19 @@ def test_putpalette_with_alpha_values():
("RGBAX", (1, 2, 3, 4, 0)),
),
)
def test_rgba_palette(mode, palette):
def test_rgba_palette(mode, palette) -> None:
im = Image.new("P", (1, 1))
im.putpalette(palette, mode)
assert im.getpalette() == [1, 2, 3]
assert im.palette.colors == {(1, 2, 3, 4): 0}
def test_empty_palette():
def test_empty_palette() -> None:
im = Image.new("P", (1, 1))
assert im.getpalette() == []
def test_undefined_palette_index():
def test_undefined_palette_index() -> None:
im = Image.new("P", (1, 1), 3)
im.putpalette((1, 2, 3))
assert im.convert("RGB").getpixel((0, 0)) == (0, 0, 0)

View File

@ -48,7 +48,7 @@ gradients_image.load()
((1, 3), (10, 4)),
),
)
def test_args_factor(size, expected):
def test_args_factor(size, expected) -> None:
im = Image.new("L", (10, 10))
assert expected == im.reduce(size).size
@ -56,7 +56,7 @@ def test_args_factor(size, expected):
@pytest.mark.parametrize(
"size, expected_error", ((0, ValueError), (2.0, TypeError), ((0, 10), ValueError))
)
def test_args_factor_error(size, expected_error):
def test_args_factor_error(size, expected_error) -> None:
im = Image.new("L", (10, 10))
with pytest.raises(expected_error):
im.reduce(size)
@ -69,7 +69,7 @@ def test_args_factor_error(size, expected_error):
((5, 5, 6, 6), (1, 1)),
),
)
def test_args_box(size, expected):
def test_args_box(size, expected) -> None:
im = Image.new("L", (10, 10))
assert expected == im.reduce(2, size).size
@ -86,14 +86,14 @@ def test_args_box(size, expected):
((5, 0, 5, 10), ValueError),
),
)
def test_args_box_error(size, expected_error):
def test_args_box_error(size, expected_error) -> None:
im = Image.new("L", (10, 10))
with pytest.raises(expected_error):
im.reduce(2, size).size
@pytest.mark.parametrize("mode", ("P", "1", "I;16"))
def test_unsupported_modes(mode):
def test_unsupported_modes(mode) -> None:
im = Image.new("P", (10, 10))
with pytest.raises(ValueError):
im.reduce(3)
@ -119,14 +119,16 @@ def get_image(mode):
return im.crop((0, 0, im.width, im.height - 5))
def compare_reduce_with_box(im, factor):
def compare_reduce_with_box(im, factor) -> None:
box = (11, 13, 146, 164)
reduced = im.reduce(factor, box=box)
reference = im.crop(box).reduce(factor)
assert reduced == reference
def compare_reduce_with_reference(im, factor, average_diff=0.4, max_diff=1):
def compare_reduce_with_reference(
im, factor, average_diff: float = 0.4, max_diff: int = 1
) -> None:
"""Image.reduce() should look very similar to Image.resize(BOX).
A reference image is compiled from a large source area
@ -171,7 +173,7 @@ def compare_reduce_with_reference(im, factor, average_diff=0.4, max_diff=1):
assert_compare_images(reduced, reference, average_diff, max_diff)
def assert_compare_images(a, b, max_average_diff, max_diff=255):
def assert_compare_images(a, b, max_average_diff, max_diff: int = 255) -> None:
assert a.mode == b.mode, f"got mode {repr(a.mode)}, expected {repr(b.mode)}"
assert a.size == b.size, f"got size {repr(a.size)}, expected {repr(b.size)}"
@ -199,20 +201,20 @@ def assert_compare_images(a, b, max_average_diff, max_diff=255):
@pytest.mark.parametrize("factor", remarkable_factors)
def test_mode_L(factor):
def test_mode_L(factor) -> None:
im = get_image("L")
compare_reduce_with_reference(im, factor)
compare_reduce_with_box(im, factor)
@pytest.mark.parametrize("factor", remarkable_factors)
def test_mode_LA(factor):
def test_mode_LA(factor) -> None:
im = get_image("LA")
compare_reduce_with_reference(im, factor, 0.8, 5)
@pytest.mark.parametrize("factor", remarkable_factors)
def test_mode_LA_opaque(factor):
def test_mode_LA_opaque(factor) -> None:
im = get_image("LA")
# With opaque alpha, an error should be way smaller.
im.putalpha(Image.new("L", im.size, 255))
@ -221,27 +223,27 @@ def test_mode_LA_opaque(factor):
@pytest.mark.parametrize("factor", remarkable_factors)
def test_mode_La(factor):
def test_mode_La(factor) -> None:
im = get_image("La")
compare_reduce_with_reference(im, factor)
compare_reduce_with_box(im, factor)
@pytest.mark.parametrize("factor", remarkable_factors)
def test_mode_RGB(factor):
def test_mode_RGB(factor) -> None:
im = get_image("RGB")
compare_reduce_with_reference(im, factor)
compare_reduce_with_box(im, factor)
@pytest.mark.parametrize("factor", remarkable_factors)
def test_mode_RGBA(factor):
def test_mode_RGBA(factor) -> None:
im = get_image("RGBA")
compare_reduce_with_reference(im, factor, 0.8, 5)
@pytest.mark.parametrize("factor", remarkable_factors)
def test_mode_RGBA_opaque(factor):
def test_mode_RGBA_opaque(factor) -> None:
im = get_image("RGBA")
# With opaque alpha, an error should be way smaller.
im.putalpha(Image.new("L", im.size, 255))
@ -250,27 +252,27 @@ def test_mode_RGBA_opaque(factor):
@pytest.mark.parametrize("factor", remarkable_factors)
def test_mode_RGBa(factor):
def test_mode_RGBa(factor) -> None:
im = get_image("RGBa")
compare_reduce_with_reference(im, factor)
compare_reduce_with_box(im, factor)
@pytest.mark.parametrize("factor", remarkable_factors)
def test_mode_I(factor):
def test_mode_I(factor) -> None:
im = get_image("I")
compare_reduce_with_reference(im, factor)
compare_reduce_with_box(im, factor)
@pytest.mark.parametrize("factor", remarkable_factors)
def test_mode_F(factor):
def test_mode_F(factor) -> None:
im = get_image("F")
compare_reduce_with_reference(im, factor, 0, 0)
compare_reduce_with_box(im, factor)
@skip_unless_feature("jpg_2000")
def test_jpeg2k():
def test_jpeg2k() -> None:
with Image.open("Tests/images/test-card-lossless.jp2") as im:
assert im.reduce(2).size == (320, 240)

View File

@ -16,7 +16,7 @@ from .helper import (
class TestImagingResampleVulnerability:
# see https://github.com/python-pillow/Pillow/issues/1710
def test_overflow(self):
def test_overflow(self) -> None:
im = hopper("L")
size_too_large = 0x100000008 // 4
size_normal = 1000 # unimportant
@ -28,7 +28,7 @@ class TestImagingResampleVulnerability:
# any resampling filter will do here
im.im.resize((xsize, ysize), Image.Resampling.BILINEAR)
def test_invalid_size(self):
def test_invalid_size(self) -> None:
im = hopper()
# Should not crash
@ -40,7 +40,7 @@ class TestImagingResampleVulnerability:
with pytest.raises(ValueError):
im.resize((100, -100))
def test_modify_after_resizing(self):
def test_modify_after_resizing(self) -> None:
im = hopper("RGB")
# get copy with same size
copy = im.resize(im.size)
@ -83,7 +83,7 @@ class TestImagingCoreResampleAccuracy:
s_px[size[0] - x - 1, y] = 255 - val
return sample
def check_case(self, case, sample):
def check_case(self, case, sample) -> None:
s_px = sample.load()
c_px = case.load()
for y in range(case.size[1]):
@ -103,7 +103,7 @@ class TestImagingCoreResampleAccuracy:
)
@pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
def test_reduce_box(self, mode):
def test_reduce_box(self, mode) -> None:
case = self.make_case(mode, (8, 8), 0xE1)
case = case.resize((4, 4), Image.Resampling.BOX)
# fmt: off
@ -114,7 +114,7 @@ class TestImagingCoreResampleAccuracy:
self.check_case(channel, self.make_sample(data, (4, 4)))
@pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
def test_reduce_bilinear(self, mode):
def test_reduce_bilinear(self, mode) -> None:
case = self.make_case(mode, (8, 8), 0xE1)
case = case.resize((4, 4), Image.Resampling.BILINEAR)
# fmt: off
@ -125,7 +125,7 @@ class TestImagingCoreResampleAccuracy:
self.check_case(channel, self.make_sample(data, (4, 4)))
@pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
def test_reduce_hamming(self, mode):
def test_reduce_hamming(self, mode) -> None:
case = self.make_case(mode, (8, 8), 0xE1)
case = case.resize((4, 4), Image.Resampling.HAMMING)
# fmt: off
@ -136,7 +136,7 @@ class TestImagingCoreResampleAccuracy:
self.check_case(channel, self.make_sample(data, (4, 4)))
@pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
def test_reduce_bicubic(self, mode):
def test_reduce_bicubic(self, mode) -> None:
case = self.make_case(mode, (12, 12), 0xE1)
case = case.resize((6, 6), Image.Resampling.BICUBIC)
# fmt: off
@ -148,7 +148,7 @@ class TestImagingCoreResampleAccuracy:
self.check_case(channel, self.make_sample(data, (6, 6)))
@pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
def test_reduce_lanczos(self, mode):
def test_reduce_lanczos(self, mode) -> None:
case = self.make_case(mode, (16, 16), 0xE1)
case = case.resize((8, 8), Image.Resampling.LANCZOS)
# fmt: off
@ -161,7 +161,7 @@ class TestImagingCoreResampleAccuracy:
self.check_case(channel, self.make_sample(data, (8, 8)))
@pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
def test_enlarge_box(self, mode):
def test_enlarge_box(self, mode) -> None:
case = self.make_case(mode, (2, 2), 0xE1)
case = case.resize((4, 4), Image.Resampling.BOX)
# fmt: off
@ -172,7 +172,7 @@ class TestImagingCoreResampleAccuracy:
self.check_case(channel, self.make_sample(data, (4, 4)))
@pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
def test_enlarge_bilinear(self, mode):
def test_enlarge_bilinear(self, mode) -> None:
case = self.make_case(mode, (2, 2), 0xE1)
case = case.resize((4, 4), Image.Resampling.BILINEAR)
# fmt: off
@ -183,7 +183,7 @@ class TestImagingCoreResampleAccuracy:
self.check_case(channel, self.make_sample(data, (4, 4)))
@pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
def test_enlarge_hamming(self, mode):
def test_enlarge_hamming(self, mode) -> None:
case = self.make_case(mode, (2, 2), 0xE1)
case = case.resize((4, 4), Image.Resampling.HAMMING)
# fmt: off
@ -194,7 +194,7 @@ class TestImagingCoreResampleAccuracy:
self.check_case(channel, self.make_sample(data, (4, 4)))
@pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
def test_enlarge_bicubic(self, mode):
def test_enlarge_bicubic(self, mode) -> None:
case = self.make_case(mode, (4, 4), 0xE1)
case = case.resize((8, 8), Image.Resampling.BICUBIC)
# fmt: off
@ -207,7 +207,7 @@ class TestImagingCoreResampleAccuracy:
self.check_case(channel, self.make_sample(data, (8, 8)))
@pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
def test_enlarge_lanczos(self, mode):
def test_enlarge_lanczos(self, mode) -> None:
case = self.make_case(mode, (6, 6), 0xE1)
case = case.resize((12, 12), Image.Resampling.LANCZOS)
data = (
@ -221,7 +221,7 @@ class TestImagingCoreResampleAccuracy:
for channel in case.split():
self.check_case(channel, self.make_sample(data, (12, 12)))
def test_box_filter_correct_range(self):
def test_box_filter_correct_range(self) -> None:
im = Image.new("RGB", (8, 8), "#1688ff").resize(
(100, 100), Image.Resampling.BOX
)
@ -234,7 +234,7 @@ class TestCoreResampleConsistency:
im = Image.new(mode, (512, 9), fill)
return im.resize((9, 512), Image.Resampling.LANCZOS), im.load()[0, 0]
def run_case(self, case):
def run_case(self, case) -> None:
channel, color = case
px = channel.load()
for x in range(channel.size[0]):
@ -243,7 +243,7 @@ class TestCoreResampleConsistency:
message = f"{px[x, y]} != {color} for pixel {(x, y)}"
assert px[x, y] == color, message
def test_8u(self):
def test_8u(self) -> None:
im, color = self.make_case("RGB", (0, 64, 255))
r, g, b = im.split()
self.run_case((r, color[0]))
@ -251,13 +251,13 @@ class TestCoreResampleConsistency:
self.run_case((b, color[2]))
self.run_case(self.make_case("L", 12))
def test_32i(self):
def test_32i(self) -> None:
self.run_case(self.make_case("I", 12))
self.run_case(self.make_case("I", 0x7FFFFFFF))
self.run_case(self.make_case("I", -12))
self.run_case(self.make_case("I", -1 << 31))
def test_32f(self):
def test_32f(self) -> None:
self.run_case(self.make_case("F", 1))
self.run_case(self.make_case("F", 3.40282306074e38))
self.run_case(self.make_case("F", 1.175494e-38))
@ -275,7 +275,7 @@ class TestCoreResampleAlphaCorrect:
px[x, y] = tuple(pix)
return i
def run_levels_case(self, i):
def run_levels_case(self, i) -> None:
px = i.load()
for y in range(i.size[1]):
used_colors = {px[x, y][0] for x in range(i.size[0])}
@ -285,7 +285,7 @@ class TestCoreResampleAlphaCorrect:
)
@pytest.mark.xfail(reason="Current implementation isn't precise enough")
def test_levels_rgba(self):
def test_levels_rgba(self) -> None:
case = self.make_levels_case("RGBA")
self.run_levels_case(case.resize((512, 32), Image.Resampling.BOX))
self.run_levels_case(case.resize((512, 32), Image.Resampling.BILINEAR))
@ -294,7 +294,7 @@ class TestCoreResampleAlphaCorrect:
self.run_levels_case(case.resize((512, 32), Image.Resampling.LANCZOS))
@pytest.mark.xfail(reason="Current implementation isn't precise enough")
def test_levels_la(self):
def test_levels_la(self) -> None:
case = self.make_levels_case("LA")
self.run_levels_case(case.resize((512, 32), Image.Resampling.BOX))
self.run_levels_case(case.resize((512, 32), Image.Resampling.BILINEAR))
@ -312,7 +312,7 @@ class TestCoreResampleAlphaCorrect:
px[x + xdiv4, y + ydiv4] = clean_pixel
return i
def run_dirty_case(self, i, clean_pixel):
def run_dirty_case(self, i, clean_pixel) -> None:
px = i.load()
for y in range(i.size[1]):
for x in range(i.size[0]):
@ -323,7 +323,7 @@ class TestCoreResampleAlphaCorrect:
)
assert px[x, y][:3] == clean_pixel, message
def test_dirty_pixels_rgba(self):
def test_dirty_pixels_rgba(self) -> None:
case = self.make_dirty_case("RGBA", (255, 255, 0, 128), (0, 0, 255, 0))
self.run_dirty_case(case.resize((20, 20), Image.Resampling.BOX), (255, 255, 0))
self.run_dirty_case(
@ -339,7 +339,7 @@ class TestCoreResampleAlphaCorrect:
case.resize((20, 20), Image.Resampling.LANCZOS), (255, 255, 0)
)
def test_dirty_pixels_la(self):
def test_dirty_pixels_la(self) -> None:
case = self.make_dirty_case("LA", (255, 128), (0, 0))
self.run_dirty_case(case.resize((20, 20), Image.Resampling.BOX), (255,))
self.run_dirty_case(case.resize((20, 20), Image.Resampling.BILINEAR), (255,))
@ -355,22 +355,22 @@ class TestCoreResamplePasses:
yield
assert Image.core.get_stats()["new_count"] - count == diff
def test_horizontal(self):
def test_horizontal(self) -> None:
im = hopper("L")
with self.count(1):
im.resize((im.size[0] - 10, im.size[1]), Image.Resampling.BILINEAR)
def test_vertical(self):
def test_vertical(self) -> None:
im = hopper("L")
with self.count(1):
im.resize((im.size[0], im.size[1] - 10), Image.Resampling.BILINEAR)
def test_both(self):
def test_both(self) -> None:
im = hopper("L")
with self.count(2):
im.resize((im.size[0] - 10, im.size[1] - 10), Image.Resampling.BILINEAR)
def test_box_horizontal(self):
def test_box_horizontal(self) -> None:
im = hopper("L")
box = (20, 0, im.size[0] - 20, im.size[1])
with self.count(1):
@ -380,7 +380,7 @@ class TestCoreResamplePasses:
cropped = im.crop(box).resize(im.size, Image.Resampling.BILINEAR)
assert_image_similar(with_box, cropped, 0.1)
def test_box_vertical(self):
def test_box_vertical(self) -> None:
im = hopper("L")
box = (0, 20, im.size[0], im.size[1] - 20)
with self.count(1):
@ -392,7 +392,7 @@ class TestCoreResamplePasses:
class TestCoreResampleCoefficients:
def test_reduce(self):
def test_reduce(self) -> None:
test_color = 254
for size in range(400000, 400010, 2):
@ -404,7 +404,7 @@ class TestCoreResampleCoefficients:
if px[2, 0] != test_color // 2:
assert test_color // 2 == px[2, 0]
def test_non_zero_coefficients(self):
def test_non_zero_coefficients(self) -> None:
# regression test for the wrong coefficients calculation
# due to bug https://github.com/python-pillow/Pillow/issues/2161
im = Image.new("RGBA", (1280, 1280), (0x20, 0x40, 0x60, 0xFF))
@ -432,7 +432,7 @@ class TestCoreResampleBox:
Image.Resampling.LANCZOS,
),
)
def test_wrong_arguments(self, resample):
def test_wrong_arguments(self, resample) -> None:
im = hopper()
im.resize((32, 32), resample, (0, 0, im.width, im.height))
im.resize((32, 32), resample, (20, 20, im.width, im.height))
@ -478,7 +478,7 @@ class TestCoreResampleBox:
@mark_if_feature_version(
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
)
def test_tiles(self):
def test_tiles(self) -> None:
with Image.open("Tests/images/flower.jpg") as im:
assert im.size == (480, 360)
dst_size = (251, 188)
@ -491,7 +491,7 @@ class TestCoreResampleBox:
@mark_if_feature_version(
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
)
def test_subsample(self):
def test_subsample(self) -> None:
# This test shows advantages of the subpixel resizing
# after supersampling (e.g. during JPEG decoding).
with Image.open("Tests/images/flower.jpg") as im:
@ -518,14 +518,14 @@ class TestCoreResampleBox:
@pytest.mark.parametrize(
"resample", (Image.Resampling.NEAREST, Image.Resampling.BILINEAR)
)
def test_formats(self, mode, resample):
def test_formats(self, mode, resample) -> None:
im = hopper(mode)
box = (20, 20, im.size[0] - 20, im.size[1] - 20)
with_box = im.resize((32, 32), resample, box)
cropped = im.crop(box).resize((32, 32), resample)
assert_image_similar(cropped, with_box, 0.4)
def test_passthrough(self):
def test_passthrough(self) -> None:
# When no resize is required
im = hopper()
@ -539,7 +539,7 @@ class TestCoreResampleBox:
assert res.size == size
assert_image_equal(res, im.crop(box), f">>> {size} {box}")
def test_no_passthrough(self):
def test_no_passthrough(self) -> None:
# When resize is required
im = hopper()
@ -558,7 +558,7 @@ class TestCoreResampleBox:
@pytest.mark.parametrize(
"flt", (Image.Resampling.NEAREST, Image.Resampling.BICUBIC)
)
def test_skip_horizontal(self, flt):
def test_skip_horizontal(self, flt) -> None:
# Can skip resize for one dimension
im = hopper()
@ -581,7 +581,7 @@ class TestCoreResampleBox:
@pytest.mark.parametrize(
"flt", (Image.Resampling.NEAREST, Image.Resampling.BICUBIC)
)
def test_skip_vertical(self, flt):
def test_skip_vertical(self, flt) -> None:
# Can skip resize for one dimension
im = hopper()

View File

@ -12,7 +12,7 @@ from .helper import (
)
def rotate(im, mode, angle, center=None, translate=None):
def rotate(im, mode, angle, center=None, translate=None) -> None:
out = im.rotate(angle, center=center, translate=translate)
assert out.mode == mode
assert out.size == im.size # default rotate clips output
@ -27,13 +27,13 @@ def rotate(im, mode, angle, center=None, translate=None):
@pytest.mark.parametrize("mode", ("1", "P", "L", "RGB", "I", "F"))
def test_mode(mode):
def test_mode(mode) -> None:
im = hopper(mode)
rotate(im, mode, 45)
@pytest.mark.parametrize("angle", (0, 90, 180, 270))
def test_angle(angle):
def test_angle(angle) -> None:
with Image.open("Tests/images/test-card.png") as im:
rotate(im, im.mode, angle)
@ -42,12 +42,12 @@ def test_angle(angle):
@pytest.mark.parametrize("angle", (0, 45, 90, 180, 270))
def test_zero(angle):
def test_zero(angle) -> None:
im = Image.new("RGB", (0, 0))
rotate(im, im.mode, angle)
def test_resample():
def test_resample() -> None:
# Target image creation, inspected by eye.
# >>> im = Image.open('Tests/images/hopper.ppm')
# >>> im = im.rotate(45, resample=Image.Resampling.BICUBIC, expand=True)
@ -64,7 +64,7 @@ def test_resample():
assert_image_similar(im, target, epsilon)
def test_center_0():
def test_center_0() -> None:
im = hopper()
im = im.rotate(45, center=(0, 0), resample=Image.Resampling.BICUBIC)
@ -75,7 +75,7 @@ def test_center_0():
assert_image_similar(im, target, 15)
def test_center_14():
def test_center_14() -> None:
im = hopper()
im = im.rotate(45, center=(14, 14), resample=Image.Resampling.BICUBIC)
@ -86,7 +86,7 @@ def test_center_14():
assert_image_similar(im, target, 10)
def test_translate():
def test_translate() -> None:
im = hopper()
with Image.open("Tests/images/hopper_45.png") as target:
target_origin = (target.size[1] / 2 - 64) - 5
@ -99,7 +99,7 @@ def test_translate():
assert_image_similar(im, target, 1)
def test_fastpath_center():
def test_fastpath_center() -> None:
# if the center is -1,-1 and we rotate by 90<=x<=270 the
# resulting image should be black
for angle in (90, 180, 270):
@ -107,7 +107,7 @@ def test_fastpath_center():
assert_image_equal(im, Image.new("RGB", im.size, "black"))
def test_fastpath_translate():
def test_fastpath_translate() -> None:
# if we post-translate by -128
# resulting image should be black
for angle in (0, 90, 180, 270):
@ -115,26 +115,26 @@ def test_fastpath_translate():
assert_image_equal(im, Image.new("RGB", im.size, "black"))
def test_center():
def test_center() -> None:
im = hopper()
rotate(im, im.mode, 45, center=(0, 0))
rotate(im, im.mode, 45, translate=(im.size[0] / 2, 0))
rotate(im, im.mode, 45, center=(0, 0), translate=(im.size[0] / 2, 0))
def test_rotate_no_fill():
def test_rotate_no_fill() -> None:
im = Image.new("RGB", (100, 100), "green")
im = im.rotate(45)
assert_image_equal_tofile(im, "Tests/images/rotate_45_no_fill.png")
def test_rotate_with_fill():
def test_rotate_with_fill() -> None:
im = Image.new("RGB", (100, 100), "green")
im = im.rotate(45, fillcolor="white")
assert_image_equal_tofile(im, "Tests/images/rotate_45_with_fill.png")
def test_alpha_rotate_no_fill():
def test_alpha_rotate_no_fill() -> None:
# Alpha images are handled differently internally
im = Image.new("RGBA", (10, 10), "green")
im = im.rotate(45, expand=1)
@ -142,7 +142,7 @@ def test_alpha_rotate_no_fill():
assert corner == (0, 0, 0, 0)
def test_alpha_rotate_with_fill():
def test_alpha_rotate_with_fill() -> None:
# Alpha images are handled differently internally
im = Image.new("RGBA", (10, 10), "green")
im = im.rotate(45, expand=1, fillcolor=(255, 0, 0, 255))

View File

@ -14,14 +14,14 @@ from .helper import (
)
def test_sanity():
def test_sanity() -> None:
im = hopper()
assert im.thumbnail((100, 100)) is None
assert im.size == (100, 100)
def test_aspect():
def test_aspect() -> None:
im = Image.new("L", (128, 128))
im.thumbnail((100, 100))
assert im.size == (100, 100)
@ -67,19 +67,19 @@ def test_aspect():
assert im.size == (75, 23) # ratio is 3.260869565217
def test_division_by_zero():
def test_division_by_zero() -> None:
im = Image.new("L", (200, 2))
im.thumbnail((75, 75))
assert im.size == (75, 1)
def test_float():
def test_float() -> None:
im = Image.new("L", (128, 128))
im.thumbnail((99.9, 99.9))
assert im.size == (99, 99)
def test_no_resize():
def test_no_resize() -> None:
# Check that draft() can resize the image to the destination size
with Image.open("Tests/images/hopper.jpg") as im:
im.draft(None, (64, 64))
@ -92,7 +92,7 @@ def test_no_resize():
@skip_unless_feature("libtiff")
def test_load_first():
def test_load_first() -> None:
# load() may change the size of the image
# Test that thumbnail() is calling it before performing size calculations
with Image.open("Tests/images/g4_orientation_5.tif") as im:
@ -106,7 +106,7 @@ def test_load_first():
assert im.size == (590, 88)
def test_load_first_unless_jpeg():
def test_load_first_unless_jpeg() -> None:
# Test that thumbnail() still uses draft() for JPEG
with Image.open("Tests/images/hopper.jpg") as im:
draft = im.draft
@ -124,7 +124,7 @@ def test_load_first_unless_jpeg():
# valgrind test is failing with memory allocated in libjpeg
@pytest.mark.valgrind_known_error(reason="Known Failing")
def test_DCT_scaling_edges():
def test_DCT_scaling_edges() -> None:
# Make an image with red borders and size (N * 8) + 1 to cross DCT grid
im = Image.new("RGB", (257, 257), "red")
im.paste(Image.new("RGB", (235, 235)), (11, 11))
@ -138,7 +138,7 @@ def test_DCT_scaling_edges():
assert_image_similar(thumb, ref, 1.5)
def test_reducing_gap_values():
def test_reducing_gap_values() -> None:
im = hopper()
im.thumbnail((18, 18), Image.Resampling.BICUBIC)
@ -155,7 +155,7 @@ def test_reducing_gap_values():
assert_image_similar(ref, im, 3.5)
def test_reducing_gap_for_DCT_scaling():
def test_reducing_gap_for_DCT_scaling() -> None:
with Image.open("Tests/images/hopper.jpg") as ref:
# thumbnail should call draft with reducing_gap scale
ref.draft(None, (18 * 3, 18 * 3))

View File

@ -10,7 +10,7 @@ from .helper import assert_image_equal, assert_image_similar, hopper
class TestImageTransform:
def test_sanity(self):
def test_sanity(self) -> None:
im = hopper()
for transform in (
@ -31,7 +31,7 @@ class TestImageTransform:
):
assert_image_equal(im, im.transform(im.size, transform))
def test_info(self):
def test_info(self) -> None:
comment = b"File written by Adobe Photoshop\xa8 4.0"
with Image.open("Tests/images/hopper.gif") as im:
@ -41,14 +41,14 @@ class TestImageTransform:
new_im = im.transform((100, 100), transform)
assert new_im.info["comment"] == comment
def test_palette(self):
def test_palette(self) -> None:
with Image.open("Tests/images/hopper.gif") as im:
transformed = im.transform(
im.size, Image.Transform.AFFINE, [1, 0, 0, 0, 1, 0]
)
assert im.palette.palette == transformed.palette.palette
def test_extent(self):
def test_extent(self) -> None:
im = hopper("RGB")
(w, h) = im.size
transformed = im.transform(
@ -63,7 +63,7 @@ class TestImageTransform:
# undone -- precision?
assert_image_similar(transformed, scaled, 23)
def test_quad(self):
def test_quad(self) -> None:
# one simple quad transform, equivalent to scale & crop upper left quad
im = hopper("RGB")
(w, h) = im.size
@ -91,7 +91,7 @@ class TestImageTransform:
("LA", (76, 0)),
),
)
def test_fill(self, mode, expected_pixel):
def test_fill(self, mode, expected_pixel) -> None:
im = hopper(mode)
(w, h) = im.size
transformed = im.transform(
@ -103,7 +103,7 @@ class TestImageTransform:
)
assert transformed.getpixel((w - 1, h - 1)) == expected_pixel
def test_mesh(self):
def test_mesh(self) -> None:
# this should be a checkerboard of halfsized hoppers in ul, lr
im = hopper("RGBA")
(w, h) = im.size
@ -142,7 +142,7 @@ class TestImageTransform:
assert_image_equal(blank, transformed.crop((w // 2, 0, w, h // 2)))
assert_image_equal(blank, transformed.crop((0, h // 2, w // 2, h)))
def _test_alpha_premult(self, op):
def _test_alpha_premult(self, op) -> None:
# create image with half white, half black,
# with the black half transparent.
# do op,
@ -158,13 +158,13 @@ class TestImageTransform:
hist = im_background.histogram()
assert 40 * 10 == hist[-1]
def test_alpha_premult_resize(self):
def test_alpha_premult_resize(self) -> None:
def op(im, sz):
return im.resize(sz, Image.Resampling.BILINEAR)
self._test_alpha_premult(op)
def test_alpha_premult_transform(self):
def test_alpha_premult_transform(self) -> None:
def op(im, sz):
(w, h) = im.size
return im.transform(
@ -173,7 +173,7 @@ class TestImageTransform:
self._test_alpha_premult(op)
def _test_nearest(self, op, mode):
def _test_nearest(self, op, mode) -> None:
# create white image with half transparent,
# do op,
# the image should remain white with half transparent
@ -196,14 +196,14 @@ class TestImageTransform:
)
@pytest.mark.parametrize("mode", ("RGBA", "LA"))
def test_nearest_resize(self, mode):
def test_nearest_resize(self, mode) -> None:
def op(im, sz):
return im.resize(sz, Image.Resampling.NEAREST)
self._test_nearest(op, mode)
@pytest.mark.parametrize("mode", ("RGBA", "LA"))
def test_nearest_transform(self, mode):
def test_nearest_transform(self, mode) -> None:
def op(im, sz):
(w, h) = im.size
return im.transform(
@ -212,7 +212,7 @@ class TestImageTransform:
self._test_nearest(op, mode)
def test_blank_fill(self):
def test_blank_fill(self) -> None:
# attempting to hit
# https://github.com/python-pillow/Pillow/issues/254 reported
#
@ -234,13 +234,13 @@ class TestImageTransform:
self.test_mesh()
def test_missing_method_data(self):
def test_missing_method_data(self) -> None:
with hopper() as im:
with pytest.raises(ValueError):
im.transform((100, 100), None)
@pytest.mark.parametrize("resample", (Image.Resampling.BOX, "unknown"))
def test_unknown_resampling_filter(self, resample):
def test_unknown_resampling_filter(self, resample) -> None:
with hopper() as im:
(w, h) = im.size
with pytest.raises(ValueError):
@ -263,7 +263,7 @@ class TestImageTransformAffine:
(270, Image.Transpose.ROTATE_270),
),
)
def test_rotate(self, deg, transpose):
def test_rotate(self, deg, transpose) -> None:
im = self._test_image()
angle = -math.radians(deg)
@ -313,7 +313,7 @@ class TestImageTransformAffine:
(Image.Resampling.BICUBIC, 1),
),
)
def test_resize(self, scale, epsilon_scale, resample, epsilon):
def test_resize(self, scale, epsilon_scale, resample, epsilon) -> None:
im = self._test_image()
size_up = int(round(im.width * scale)), int(round(im.height * scale))
@ -342,7 +342,7 @@ class TestImageTransformAffine:
(Image.Resampling.BICUBIC, 1),
),
)
def test_translate(self, x, y, epsilon_scale, resample, epsilon):
def test_translate(self, x, y, epsilon_scale, resample, epsilon) -> None:
im = self._test_image()
size_up = int(round(im.width + x)), int(round(im.height + y))

View File

@ -15,7 +15,7 @@ WHITE = (255, 255, 255)
GRAY = 128
def test_sanity():
def test_sanity() -> None:
im = hopper("L")
ImageChops.constant(im, 128)
@ -48,7 +48,7 @@ def test_sanity():
ImageChops.offset(im, 10, 20)
def test_add():
def test_add() -> None:
# Arrange
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
@ -60,7 +60,7 @@ def test_add():
assert new.getpixel((50, 50)) == ORANGE
def test_add_scale_offset():
def test_add_scale_offset() -> None:
# Arrange
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
@ -72,7 +72,7 @@ def test_add_scale_offset():
assert new.getpixel((50, 50)) == (202, 151, 100)
def test_add_clip():
def test_add_clip() -> None:
# Arrange
im = hopper()
@ -83,7 +83,7 @@ def test_add_clip():
assert new.getpixel((50, 50)) == (255, 255, 254)
def test_add_modulo():
def test_add_modulo() -> None:
# Arrange
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
@ -95,7 +95,7 @@ def test_add_modulo():
assert new.getpixel((50, 50)) == ORANGE
def test_add_modulo_no_clip():
def test_add_modulo_no_clip() -> None:
# Arrange
im = hopper()
@ -106,7 +106,7 @@ def test_add_modulo_no_clip():
assert new.getpixel((50, 50)) == (224, 76, 254)
def test_blend():
def test_blend() -> None:
# Arrange
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
@ -118,7 +118,7 @@ def test_blend():
assert new.getpixel((50, 50)) == BROWN
def test_constant():
def test_constant() -> None:
# Arrange
im = Image.new("RGB", (20, 10))
@ -131,7 +131,7 @@ def test_constant():
assert new.getpixel((19, 9)) == GRAY
def test_darker_image():
def test_darker_image() -> None:
# Arrange
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
@ -142,7 +142,7 @@ def test_darker_image():
assert_image_equal(new, im2)
def test_darker_pixel():
def test_darker_pixel() -> None:
# Arrange
im1 = hopper()
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
@ -153,7 +153,7 @@ def test_darker_pixel():
assert new.getpixel((50, 50)) == (240, 166, 0)
def test_difference():
def test_difference() -> None:
# Arrange
with Image.open("Tests/images/imagedraw_arc_end_le_start.png") as im1:
with Image.open("Tests/images/imagedraw_arc_no_loops.png") as im2:
@ -164,7 +164,7 @@ def test_difference():
assert new.getbbox() == (25, 25, 76, 76)
def test_difference_pixel():
def test_difference_pixel() -> None:
# Arrange
im1 = hopper()
with Image.open("Tests/images/imagedraw_polygon_kite_RGB.png") as im2:
@ -175,7 +175,7 @@ def test_difference_pixel():
assert new.getpixel((50, 50)) == (240, 166, 128)
def test_duplicate():
def test_duplicate() -> None:
# Arrange
im = hopper()
@ -186,7 +186,7 @@ def test_duplicate():
assert_image_equal(new, im)
def test_invert():
def test_invert() -> None:
# Arrange
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im:
# Act
@ -198,7 +198,7 @@ def test_invert():
assert new.getpixel((50, 50)) == CYAN
def test_lighter_image():
def test_lighter_image() -> None:
# Arrange
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
@ -209,7 +209,7 @@ def test_lighter_image():
assert_image_equal(new, im1)
def test_lighter_pixel():
def test_lighter_pixel() -> None:
# Arrange
im1 = hopper()
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
@ -220,7 +220,7 @@ def test_lighter_pixel():
assert new.getpixel((50, 50)) == (255, 255, 127)
def test_multiply_black():
def test_multiply_black() -> None:
"""If you multiply an image with a solid black image,
the result is black."""
# Arrange
@ -234,7 +234,7 @@ def test_multiply_black():
assert_image_equal(new, black)
def test_multiply_green():
def test_multiply_green() -> None:
# Arrange
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im:
green = Image.new("RGB", im.size, "green")
@ -248,7 +248,7 @@ def test_multiply_green():
assert new.getpixel((50, 50)) == BLACK
def test_multiply_white():
def test_multiply_white() -> None:
"""If you multiply with a solid white image, the image is unaffected."""
# Arrange
im1 = hopper()
@ -261,7 +261,7 @@ def test_multiply_white():
assert_image_equal(new, im1)
def test_offset():
def test_offset() -> None:
# Arrange
xoffset = 45
yoffset = 20
@ -278,7 +278,7 @@ def test_offset():
assert ImageChops.offset(im, xoffset) == ImageChops.offset(im, xoffset, xoffset)
def test_screen():
def test_screen() -> None:
# Arrange
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
@ -290,7 +290,7 @@ def test_screen():
assert new.getpixel((50, 50)) == ORANGE
def test_subtract():
def test_subtract() -> None:
# Arrange
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
@ -303,7 +303,7 @@ def test_subtract():
assert new.getpixel((50, 52)) == BLACK
def test_subtract_scale_offset():
def test_subtract_scale_offset() -> None:
# Arrange
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
@ -315,7 +315,7 @@ def test_subtract_scale_offset():
assert new.getpixel((50, 50)) == (100, 202, 100)
def test_subtract_clip():
def test_subtract_clip() -> None:
# Arrange
im1 = hopper()
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
@ -326,7 +326,7 @@ def test_subtract_clip():
assert new.getpixel((50, 50)) == (0, 0, 127)
def test_subtract_modulo():
def test_subtract_modulo() -> None:
# Arrange
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
@ -339,7 +339,7 @@ def test_subtract_modulo():
assert new.getpixel((50, 52)) == BLACK
def test_subtract_modulo_no_clip():
def test_subtract_modulo_no_clip() -> None:
# Arrange
im1 = hopper()
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
@ -350,7 +350,7 @@ def test_subtract_modulo_no_clip():
assert new.getpixel((50, 50)) == (241, 167, 127)
def test_soft_light():
def test_soft_light() -> None:
# Arrange
with Image.open("Tests/images/hopper.png") as im1:
with Image.open("Tests/images/hopper-XYZ.png") as im2:
@ -362,7 +362,7 @@ def test_soft_light():
assert new.getpixel((15, 100)) == (1, 1, 3)
def test_hard_light():
def test_hard_light() -> None:
# Arrange
with Image.open("Tests/images/hopper.png") as im1:
with Image.open("Tests/images/hopper-XYZ.png") as im2:
@ -374,7 +374,7 @@ def test_hard_light():
assert new.getpixel((15, 100)) == (1, 1, 2)
def test_overlay():
def test_overlay() -> None:
# Arrange
with Image.open("Tests/images/hopper.png") as im1:
with Image.open("Tests/images/hopper-XYZ.png") as im2:
@ -386,7 +386,7 @@ def test_overlay():
assert new.getpixel((15, 100)) == (1, 1, 2)
def test_logical():
def test_logical() -> None:
def table(op, a, b):
out = []
for x in (a, b):

View File

@ -5,6 +5,7 @@ import os
import re
import shutil
from io import BytesIO
from pathlib import Path
import pytest
@ -32,7 +33,7 @@ SRGB = "Tests/icc/sRGB_IEC61966-2-1_black_scaled.icc"
HAVE_PROFILE = os.path.exists(SRGB)
def setup_module():
def setup_module() -> None:
try:
from PIL import ImageCms
@ -42,12 +43,12 @@ def setup_module():
pytest.skip(str(v))
def skip_missing():
def skip_missing() -> None:
if not HAVE_PROFILE:
pytest.skip("SRGB profile not available")
def test_sanity():
def test_sanity() -> None:
# basic smoke test.
# this mostly follows the cms_test outline.
with pytest.warns(DeprecationWarning):
@ -91,7 +92,7 @@ def test_sanity():
hopper().point(t)
def test_flags():
def test_flags() -> None:
assert ImageCms.Flags.NONE == 0
assert ImageCms.Flags.GRIDPOINTS(0) == ImageCms.Flags.NONE
assert ImageCms.Flags.GRIDPOINTS(256) == ImageCms.Flags.NONE
@ -101,7 +102,7 @@ def test_flags():
assert ImageCms.Flags.GRIDPOINTS(511) == ImageCms.Flags.GRIDPOINTS(255)
def test_name():
def test_name() -> None:
skip_missing()
# get profile information for file
assert (
@ -110,7 +111,7 @@ def test_name():
)
def test_info():
def test_info() -> None:
skip_missing()
assert ImageCms.getProfileInfo(SRGB).splitlines() == [
"sRGB IEC61966-2-1 black scaled",
@ -120,7 +121,7 @@ def test_info():
]
def test_copyright():
def test_copyright() -> None:
skip_missing()
assert (
ImageCms.getProfileCopyright(SRGB).strip()
@ -128,12 +129,12 @@ def test_copyright():
)
def test_manufacturer():
def test_manufacturer() -> None:
skip_missing()
assert ImageCms.getProfileManufacturer(SRGB).strip() == ""
def test_model():
def test_model() -> None:
skip_missing()
assert (
ImageCms.getProfileModel(SRGB).strip()
@ -141,14 +142,14 @@ def test_model():
)
def test_description():
def test_description() -> None:
skip_missing()
assert (
ImageCms.getProfileDescription(SRGB).strip() == "sRGB IEC61966-2-1 black scaled"
)
def test_intent():
def test_intent() -> None:
skip_missing()
assert ImageCms.getDefaultIntent(SRGB) == 0
support = ImageCms.isIntentSupported(
@ -157,7 +158,7 @@ def test_intent():
assert support == 1
def test_profile_object():
def test_profile_object() -> None:
# same, using profile object
p = ImageCms.createProfile("sRGB")
# assert ImageCms.getProfileName(p).strip() == "sRGB built-in - (lcms internal)"
@ -170,7 +171,7 @@ def test_profile_object():
assert support == 1
def test_extensions():
def test_extensions() -> None:
# extensions
with Image.open("Tests/images/rgb.jpg") as i:
@ -181,7 +182,7 @@ def test_extensions():
)
def test_exceptions():
def test_exceptions() -> None:
# Test mode mismatch
psRGB = ImageCms.createProfile("sRGB")
pLab = ImageCms.createProfile("LAB")
@ -207,17 +208,17 @@ def test_exceptions():
ImageCms.isIntentSupported(SRGB, None, None)
def test_display_profile():
def test_display_profile() -> None:
# try fetching the profile for the current display device
ImageCms.get_display_profile()
def test_lab_color_profile():
def test_lab_color_profile() -> None:
ImageCms.createProfile("LAB", 5000)
ImageCms.createProfile("LAB", 6500)
def test_unsupported_color_space():
def test_unsupported_color_space() -> None:
with pytest.raises(
ImageCms.PyCMSError,
match=re.escape(
@ -227,7 +228,7 @@ def test_unsupported_color_space():
ImageCms.createProfile("unsupported")
def test_invalid_color_temperature():
def test_invalid_color_temperature() -> None:
with pytest.raises(
ImageCms.PyCMSError,
match='Color temperature must be numeric, "invalid" not valid',
@ -236,7 +237,7 @@ def test_invalid_color_temperature():
@pytest.mark.parametrize("flag", ("my string", -1))
def test_invalid_flag(flag):
def test_invalid_flag(flag) -> None:
with hopper() as im:
with pytest.raises(
ImageCms.PyCMSError, match="flags must be an integer between 0 and "
@ -244,7 +245,7 @@ def test_invalid_flag(flag):
ImageCms.profileToProfile(im, "foo", "bar", flags=flag)
def test_simple_lab():
def test_simple_lab() -> None:
i = Image.new("RGB", (10, 10), (128, 128, 128))
psRGB = ImageCms.createProfile("sRGB")
@ -268,7 +269,7 @@ def test_simple_lab():
assert list(b_data) == [128] * 100
def test_lab_color():
def test_lab_color() -> None:
psRGB = ImageCms.createProfile("sRGB")
pLab = ImageCms.createProfile("LAB")
t = ImageCms.buildTransform(psRGB, pLab, "RGB", "LAB")
@ -283,7 +284,7 @@ def test_lab_color():
assert_image_similar_tofile(i, "Tests/images/hopper.Lab.tif", 3.5)
def test_lab_srgb():
def test_lab_srgb() -> None:
psRGB = ImageCms.createProfile("sRGB")
pLab = ImageCms.createProfile("LAB")
t = ImageCms.buildTransform(pLab, psRGB, "LAB", "RGB")
@ -300,7 +301,7 @@ def test_lab_srgb():
assert "sRGB" in ImageCms.getProfileDescription(profile)
def test_lab_roundtrip():
def test_lab_roundtrip() -> None:
# check to see if we're at least internally consistent.
psRGB = ImageCms.createProfile("sRGB")
pLab = ImageCms.createProfile("LAB")
@ -317,7 +318,7 @@ def test_lab_roundtrip():
assert_image_similar(hopper(), out, 2)
def test_profile_tobytes():
def test_profile_tobytes() -> None:
with Image.open("Tests/images/rgb.jpg") as i:
p = ImageCms.getOpenProfile(BytesIO(i.info["icc_profile"]))
@ -329,12 +330,12 @@ def test_profile_tobytes():
assert ImageCms.getProfileDescription(p) == ImageCms.getProfileDescription(p2)
def test_extended_information():
def test_extended_information() -> None:
skip_missing()
o = ImageCms.getOpenProfile(SRGB)
p = o.profile
def assert_truncated_tuple_equal(tup1, tup2, digits=10):
def assert_truncated_tuple_equal(tup1, tup2, digits: int = 10) -> None:
# Helper function to reduce precision of tuples of floats
# recursively and then check equality.
power = 10**digits
@ -476,7 +477,7 @@ def test_extended_information():
assert p.xcolor_space == "RGB "
def test_non_ascii_path(tmp_path):
def test_non_ascii_path(tmp_path: Path) -> None:
skip_missing()
tempfile = str(tmp_path / ("temp_" + chr(128) + ".icc"))
try:
@ -489,7 +490,7 @@ def test_non_ascii_path(tmp_path):
assert p.model == "IEC 61966-2-1 Default RGB Colour Space - sRGB"
def test_profile_typesafety():
def test_profile_typesafety() -> None:
"""Profile init type safety
prepatch, these would segfault, postpatch they should emit a typeerror
@ -501,7 +502,7 @@ def test_profile_typesafety():
ImageCms.ImageCmsProfile(1).tobytes()
def assert_aux_channel_preserved(mode, transform_in_place, preserved_channel):
def assert_aux_channel_preserved(mode, transform_in_place, preserved_channel) -> None:
def create_test_image():
# set up test image with something interesting in the tested aux channel.
# fmt: off
@ -556,31 +557,31 @@ def assert_aux_channel_preserved(mode, transform_in_place, preserved_channel):
assert_image_equal(source_image_aux, result_image_aux)
def test_preserve_auxiliary_channels_rgba():
def test_preserve_auxiliary_channels_rgba() -> None:
assert_aux_channel_preserved(
mode="RGBA", transform_in_place=False, preserved_channel="A"
)
def test_preserve_auxiliary_channels_rgba_in_place():
def test_preserve_auxiliary_channels_rgba_in_place() -> None:
assert_aux_channel_preserved(
mode="RGBA", transform_in_place=True, preserved_channel="A"
)
def test_preserve_auxiliary_channels_rgbx():
def test_preserve_auxiliary_channels_rgbx() -> None:
assert_aux_channel_preserved(
mode="RGBX", transform_in_place=False, preserved_channel="X"
)
def test_preserve_auxiliary_channels_rgbx_in_place():
def test_preserve_auxiliary_channels_rgbx_in_place() -> None:
assert_aux_channel_preserved(
mode="RGBX", transform_in_place=True, preserved_channel="X"
)
def test_auxiliary_channels_isolated():
def test_auxiliary_channels_isolated() -> None:
# test data in aux channels does not affect non-aux channels
aux_channel_formats = [
# format, profile, color-only format, source test image
@ -630,7 +631,7 @@ def test_auxiliary_channels_isolated():
@pytest.mark.parametrize("mode", ("RGB", "RGBA", "RGBX"))
def test_rgb_lab(mode):
def test_rgb_lab(mode) -> None:
im = Image.new(mode, (1, 1))
converted_im = im.convert("LAB")
assert converted_im.getpixel((0, 0)) == (0, 128, 128)

View File

@ -5,7 +5,7 @@ import pytest
from PIL import Image, ImageColor
def test_hash():
def test_hash() -> None:
# short 3 components
assert (255, 0, 0) == ImageColor.getrgb("#f00")
assert (0, 255, 0) == ImageColor.getrgb("#0f0")
@ -57,7 +57,7 @@ def test_hash():
ImageColor.getrgb("#f00000 ")
def test_colormap():
def test_colormap() -> None:
assert (0, 0, 0) == ImageColor.getrgb("black")
assert (255, 255, 255) == ImageColor.getrgb("white")
assert (255, 255, 255) == ImageColor.getrgb("WHITE")
@ -66,7 +66,7 @@ def test_colormap():
ImageColor.getrgb("black ")
def test_functions():
def test_functions() -> None:
# rgb numbers
assert (255, 0, 0) == ImageColor.getrgb("rgb(255,0,0)")
assert (0, 255, 0) == ImageColor.getrgb("rgb(0,255,0)")
@ -160,7 +160,7 @@ def test_functions():
# look for rounding errors (based on code by Tim Hatch)
def test_rounding_errors():
def test_rounding_errors() -> None:
for color in ImageColor.colormap:
expected = Image.new("RGB", (1, 1), color).convert("L").getpixel((0, 0))
actual = ImageColor.getcolor(color, "L")
@ -195,11 +195,11 @@ def test_rounding_errors():
Image.new("LA", (1, 1), "white")
def test_color_hsv():
def test_color_hsv() -> None:
assert (170, 255, 255) == ImageColor.getcolor("hsv(240, 100%, 100%)", "HSV")
def test_color_too_long():
def test_color_too_long() -> None:
# Arrange
color_too_long = "hsl(" + "1" * 40 + "," + "1" * 40 + "%," + "1" * 40 + "%)"

View File

@ -47,7 +47,7 @@ KITE_POINTS = (
)
def test_sanity():
def test_sanity() -> None:
im = hopper("RGB").copy()
draw = ImageDraw.ImageDraw(im)
@ -59,13 +59,13 @@ def test_sanity():
draw.rectangle(list(range(4)))
def test_valueerror():
def test_valueerror() -> None:
with Image.open("Tests/images/chi.gif") as im:
draw = ImageDraw.Draw(im)
draw.line((0, 0), fill=(0, 0, 0))
def test_mode_mismatch():
def test_mode_mismatch() -> None:
im = hopper("RGB").copy()
with pytest.raises(ValueError):
@ -74,7 +74,7 @@ def test_mode_mismatch():
@pytest.mark.parametrize("bbox", BBOX)
@pytest.mark.parametrize("start, end", ((0, 180), (0.5, 180.4)))
def test_arc(bbox, start, end):
def test_arc(bbox, start, end) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -87,7 +87,7 @@ def test_arc(bbox, start, end):
@pytest.mark.parametrize("bbox", BBOX)
def test_arc_end_le_start(bbox):
def test_arc_end_le_start(bbox) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -102,7 +102,7 @@ def test_arc_end_le_start(bbox):
@pytest.mark.parametrize("bbox", BBOX)
def test_arc_no_loops(bbox):
def test_arc_no_loops(bbox) -> None:
# No need to go in loops
# Arrange
im = Image.new("RGB", (W, H))
@ -118,7 +118,7 @@ def test_arc_no_loops(bbox):
@pytest.mark.parametrize("bbox", BBOX)
def test_arc_width(bbox):
def test_arc_width(bbox) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -131,7 +131,7 @@ def test_arc_width(bbox):
@pytest.mark.parametrize("bbox", BBOX)
def test_arc_width_pieslice_large(bbox):
def test_arc_width_pieslice_large(bbox) -> None:
# Tests an arc with a large enough width that it is a pieslice
# Arrange
im = Image.new("RGB", (W, H))
@ -145,7 +145,7 @@ def test_arc_width_pieslice_large(bbox):
@pytest.mark.parametrize("bbox", BBOX)
def test_arc_width_fill(bbox):
def test_arc_width_fill(bbox) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -158,7 +158,7 @@ def test_arc_width_fill(bbox):
@pytest.mark.parametrize("bbox", BBOX)
def test_arc_width_non_whole_angle(bbox):
def test_arc_width_non_whole_angle(bbox) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -171,7 +171,7 @@ def test_arc_width_non_whole_angle(bbox):
assert_image_similar_tofile(im, expected, 1)
def test_arc_high():
def test_arc_high() -> None:
# Arrange
im = Image.new("RGB", (200, 200))
draw = ImageDraw.Draw(im)
@ -184,7 +184,7 @@ def test_arc_high():
assert_image_equal_tofile(im, "Tests/images/imagedraw_arc_high.png")
def test_bitmap():
def test_bitmap() -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -200,7 +200,7 @@ def test_bitmap():
@pytest.mark.parametrize("mode", ("RGB", "L"))
@pytest.mark.parametrize("bbox", BBOX)
def test_chord(mode, bbox):
def test_chord(mode, bbox) -> None:
# Arrange
im = Image.new(mode, (W, H))
draw = ImageDraw.Draw(im)
@ -214,7 +214,7 @@ def test_chord(mode, bbox):
@pytest.mark.parametrize("bbox", BBOX)
def test_chord_width(bbox):
def test_chord_width(bbox) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -227,7 +227,7 @@ def test_chord_width(bbox):
@pytest.mark.parametrize("bbox", BBOX)
def test_chord_width_fill(bbox):
def test_chord_width_fill(bbox) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -240,7 +240,7 @@ def test_chord_width_fill(bbox):
@pytest.mark.parametrize("bbox", BBOX)
def test_chord_zero_width(bbox):
def test_chord_zero_width(bbox) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -252,7 +252,7 @@ def test_chord_zero_width(bbox):
assert_image_equal_tofile(im, "Tests/images/imagedraw_chord_zero_width.png")
def test_chord_too_fat():
def test_chord_too_fat() -> None:
# Arrange
im = Image.new("RGB", (100, 100))
draw = ImageDraw.Draw(im)
@ -266,7 +266,7 @@ def test_chord_too_fat():
@pytest.mark.parametrize("mode", ("RGB", "L"))
@pytest.mark.parametrize("bbox", BBOX)
def test_ellipse(mode, bbox):
def test_ellipse(mode, bbox) -> None:
# Arrange
im = Image.new(mode, (W, H))
draw = ImageDraw.Draw(im)
@ -280,7 +280,7 @@ def test_ellipse(mode, bbox):
@pytest.mark.parametrize("bbox", BBOX)
def test_ellipse_translucent(bbox):
def test_ellipse_translucent(bbox) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im, "RGBA")
@ -293,7 +293,7 @@ def test_ellipse_translucent(bbox):
assert_image_similar_tofile(im, expected, 1)
def test_ellipse_edge():
def test_ellipse_edge() -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -305,7 +305,7 @@ def test_ellipse_edge():
assert_image_similar_tofile(im, "Tests/images/imagedraw_ellipse_edge.png", 1)
def test_ellipse_symmetric():
def test_ellipse_symmetric() -> None:
for width, bbox in (
(100, (24, 24, 75, 75)),
(101, (25, 25, 75, 75)),
@ -317,7 +317,7 @@ def test_ellipse_symmetric():
@pytest.mark.parametrize("bbox", BBOX)
def test_ellipse_width(bbox):
def test_ellipse_width(bbox) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -329,7 +329,7 @@ def test_ellipse_width(bbox):
assert_image_similar_tofile(im, "Tests/images/imagedraw_ellipse_width.png", 1)
def test_ellipse_width_large():
def test_ellipse_width_large() -> None:
# Arrange
im = Image.new("RGB", (500, 500))
draw = ImageDraw.Draw(im)
@ -342,7 +342,7 @@ def test_ellipse_width_large():
@pytest.mark.parametrize("bbox", BBOX)
def test_ellipse_width_fill(bbox):
def test_ellipse_width_fill(bbox) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -355,7 +355,7 @@ def test_ellipse_width_fill(bbox):
@pytest.mark.parametrize("bbox", BBOX)
def test_ellipse_zero_width(bbox):
def test_ellipse_zero_width(bbox) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -394,13 +394,13 @@ def ellipse_various_sizes_helper(filled):
return im
def test_ellipse_various_sizes():
def test_ellipse_various_sizes() -> None:
im = ellipse_various_sizes_helper(False)
assert_image_equal_tofile(im, "Tests/images/imagedraw_ellipse_various_sizes.png")
def test_ellipse_various_sizes_filled():
def test_ellipse_various_sizes_filled() -> None:
im = ellipse_various_sizes_helper(True)
assert_image_equal_tofile(
@ -409,7 +409,7 @@ def test_ellipse_various_sizes_filled():
@pytest.mark.parametrize("points", POINTS)
def test_line(points):
def test_line(points) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -421,7 +421,7 @@ def test_line(points):
assert_image_equal_tofile(im, "Tests/images/imagedraw_line.png")
def test_shape1():
def test_shape1() -> None:
# Arrange
im = Image.new("RGB", (100, 100), "white")
draw = ImageDraw.Draw(im)
@ -442,7 +442,7 @@ def test_shape1():
assert_image_equal_tofile(im, "Tests/images/imagedraw_shape1.png")
def test_shape2():
def test_shape2() -> None:
# Arrange
im = Image.new("RGB", (100, 100), "white")
draw = ImageDraw.Draw(im)
@ -463,7 +463,7 @@ def test_shape2():
assert_image_equal_tofile(im, "Tests/images/imagedraw_shape2.png")
def test_transform():
def test_transform() -> None:
# Arrange
im = Image.new("RGB", (100, 100), "white")
expected = im.copy()
@ -482,7 +482,7 @@ def test_transform():
@pytest.mark.parametrize("bbox", BBOX)
@pytest.mark.parametrize("start, end", ((-92, 46), (-92.2, 46.2)))
def test_pieslice(bbox, start, end):
def test_pieslice(bbox, start, end) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -495,7 +495,7 @@ def test_pieslice(bbox, start, end):
@pytest.mark.parametrize("bbox", BBOX)
def test_pieslice_width(bbox):
def test_pieslice_width(bbox) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -508,7 +508,7 @@ def test_pieslice_width(bbox):
@pytest.mark.parametrize("bbox", BBOX)
def test_pieslice_width_fill(bbox):
def test_pieslice_width_fill(bbox) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -522,7 +522,7 @@ def test_pieslice_width_fill(bbox):
@pytest.mark.parametrize("bbox", BBOX)
def test_pieslice_zero_width(bbox):
def test_pieslice_zero_width(bbox) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -534,7 +534,7 @@ def test_pieslice_zero_width(bbox):
assert_image_equal_tofile(im, "Tests/images/imagedraw_pieslice_zero_width.png")
def test_pieslice_wide():
def test_pieslice_wide() -> None:
# Arrange
im = Image.new("RGB", (200, 100))
draw = ImageDraw.Draw(im)
@ -546,7 +546,7 @@ def test_pieslice_wide():
assert_image_equal_tofile(im, "Tests/images/imagedraw_pieslice_wide.png")
def test_pieslice_no_spikes():
def test_pieslice_no_spikes() -> None:
im = Image.new("RGB", (161, 161), "white")
draw = ImageDraw.Draw(im)
cxs = (
@ -577,7 +577,7 @@ def test_pieslice_no_spikes():
@pytest.mark.parametrize("points", POINTS)
def test_point(points):
def test_point(points) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -589,7 +589,7 @@ def test_point(points):
assert_image_equal_tofile(im, "Tests/images/imagedraw_point.png")
def test_point_I16():
def test_point_I16() -> None:
# Arrange
im = Image.new("I;16", (1, 1))
draw = ImageDraw.Draw(im)
@ -602,7 +602,7 @@ def test_point_I16():
@pytest.mark.parametrize("points", POINTS)
def test_polygon(points):
def test_polygon(points) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -616,7 +616,7 @@ def test_polygon(points):
@pytest.mark.parametrize("mode", ("RGB", "L"))
@pytest.mark.parametrize("kite_points", KITE_POINTS)
def test_polygon_kite(mode, kite_points):
def test_polygon_kite(mode, kite_points) -> None:
# Test drawing lines of different gradients (dx>dy, dy>dx) and
# vertical (dx==0) and horizontal (dy==0) lines
# Arrange
@ -631,7 +631,7 @@ def test_polygon_kite(mode, kite_points):
assert_image_equal_tofile(im, expected)
def test_polygon_1px_high():
def test_polygon_1px_high() -> None:
# Test drawing a 1px high polygon
# Arrange
im = Image.new("RGB", (3, 3))
@ -645,7 +645,7 @@ def test_polygon_1px_high():
assert_image_equal_tofile(im, expected)
def test_polygon_1px_high_translucent():
def test_polygon_1px_high_translucent() -> None:
# Test drawing a translucent 1px high polygon
# Arrange
im = Image.new("RGB", (4, 3))
@ -659,7 +659,7 @@ def test_polygon_1px_high_translucent():
assert_image_equal_tofile(im, expected)
def test_polygon_translucent():
def test_polygon_translucent() -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im, "RGBA")
@ -673,7 +673,7 @@ def test_polygon_translucent():
@pytest.mark.parametrize("bbox", BBOX)
def test_rectangle(bbox):
def test_rectangle(bbox) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -685,7 +685,7 @@ def test_rectangle(bbox):
assert_image_equal_tofile(im, "Tests/images/imagedraw_rectangle.png")
def test_big_rectangle():
def test_big_rectangle() -> None:
# Test drawing a rectangle bigger than the image
# Arrange
im = Image.new("RGB", (W, H))
@ -700,7 +700,7 @@ def test_big_rectangle():
@pytest.mark.parametrize("bbox", BBOX)
def test_rectangle_width(bbox):
def test_rectangle_width(bbox) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -714,7 +714,7 @@ def test_rectangle_width(bbox):
@pytest.mark.parametrize("bbox", BBOX)
def test_rectangle_width_fill(bbox):
def test_rectangle_width_fill(bbox) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -728,7 +728,7 @@ def test_rectangle_width_fill(bbox):
@pytest.mark.parametrize("bbox", BBOX)
def test_rectangle_zero_width(bbox):
def test_rectangle_zero_width(bbox) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -741,7 +741,7 @@ def test_rectangle_zero_width(bbox):
@pytest.mark.parametrize("bbox", BBOX)
def test_rectangle_I16(bbox):
def test_rectangle_I16(bbox) -> None:
# Arrange
im = Image.new("I;16", (W, H))
draw = ImageDraw.Draw(im)
@ -754,7 +754,7 @@ def test_rectangle_I16(bbox):
@pytest.mark.parametrize("bbox", BBOX)
def test_rectangle_translucent_outline(bbox):
def test_rectangle_translucent_outline(bbox) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im, "RGBA")
@ -772,7 +772,7 @@ def test_rectangle_translucent_outline(bbox):
"xy",
[(10, 20, 190, 180), ([10, 20], [190, 180]), ((10, 20), (190, 180))],
)
def test_rounded_rectangle(xy):
def test_rounded_rectangle(xy) -> None:
# Arrange
im = Image.new("RGB", (200, 200))
draw = ImageDraw.Draw(im)
@ -788,7 +788,9 @@ def test_rounded_rectangle(xy):
@pytest.mark.parametrize("top_right", (True, False))
@pytest.mark.parametrize("bottom_right", (True, False))
@pytest.mark.parametrize("bottom_left", (True, False))
def test_rounded_rectangle_corners(top_left, top_right, bottom_right, bottom_left):
def test_rounded_rectangle_corners(
top_left, top_right, bottom_right, bottom_left
) -> None:
corners = (top_left, top_right, bottom_right, bottom_left)
# Arrange
@ -822,7 +824,7 @@ def test_rounded_rectangle_corners(top_left, top_right, bottom_right, bottom_lef
((10, 20, 190, 181), 85, "height"),
],
)
def test_rounded_rectangle_non_integer_radius(xy, radius, type):
def test_rounded_rectangle_non_integer_radius(xy, radius, type) -> None:
# Arrange
im = Image.new("RGB", (200, 200))
draw = ImageDraw.Draw(im)
@ -838,7 +840,7 @@ def test_rounded_rectangle_non_integer_radius(xy, radius, type):
@pytest.mark.parametrize("bbox", BBOX)
def test_rounded_rectangle_zero_radius(bbox):
def test_rounded_rectangle_zero_radius(bbox) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -860,7 +862,7 @@ def test_rounded_rectangle_zero_radius(bbox):
((20, 20, 80, 80), "both"),
],
)
def test_rounded_rectangle_translucent(xy, suffix):
def test_rounded_rectangle_translucent(xy, suffix) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im, "RGBA")
@ -877,7 +879,7 @@ def test_rounded_rectangle_translucent(xy, suffix):
@pytest.mark.parametrize("bbox", BBOX)
def test_floodfill(bbox):
def test_floodfill(bbox) -> None:
red = ImageColor.getrgb("red")
for mode, value in [("L", 1), ("RGBA", (255, 0, 0, 0)), ("RGB", red)]:
@ -910,7 +912,7 @@ def test_floodfill(bbox):
@pytest.mark.parametrize("bbox", BBOX)
def test_floodfill_border(bbox):
def test_floodfill_border(bbox) -> None:
# floodfill() is experimental
# Arrange
@ -932,7 +934,7 @@ def test_floodfill_border(bbox):
@pytest.mark.parametrize("bbox", BBOX)
def test_floodfill_thresh(bbox):
def test_floodfill_thresh(bbox) -> None:
# floodfill() is experimental
# Arrange
@ -948,7 +950,7 @@ def test_floodfill_thresh(bbox):
assert_image_equal_tofile(im, "Tests/images/imagedraw_floodfill2.png")
def test_floodfill_not_negative():
def test_floodfill_not_negative() -> None:
# floodfill() is experimental
# Test that floodfill does not extend into negative coordinates
@ -976,7 +978,7 @@ def create_base_image_draw(
return img, ImageDraw.Draw(img)
def test_square():
def test_square() -> None:
expected = os.path.join(IMAGES_PATH, "square.png")
img, draw = create_base_image_draw((10, 10))
draw.polygon([(2, 2), (2, 7), (7, 7), (7, 2)], BLACK)
@ -989,7 +991,7 @@ def test_square():
assert_image_equal_tofile(img, expected, "square as normal rectangle failed")
def test_triangle_right():
def test_triangle_right() -> None:
img, draw = create_base_image_draw((20, 20))
draw.polygon([(3, 5), (17, 5), (10, 12)], BLACK)
assert_image_equal_tofile(
@ -1001,7 +1003,7 @@ def test_triangle_right():
"fill, suffix",
((BLACK, "width"), (None, "width_no_fill")),
)
def test_triangle_right_width(fill, suffix):
def test_triangle_right_width(fill, suffix) -> None:
img, draw = create_base_image_draw((100, 100))
draw.polygon([(15, 25), (85, 25), (50, 60)], fill, WHITE, width=5)
assert_image_equal_tofile(
@ -1009,7 +1011,7 @@ def test_triangle_right_width(fill, suffix):
)
def test_line_horizontal():
def test_line_horizontal() -> None:
img, draw = create_base_image_draw((20, 20))
draw.line((5, 5, 14, 5), BLACK, 2)
assert_image_equal_tofile(
@ -1047,7 +1049,7 @@ def test_line_horizontal():
)
def test_line_h_s1_w2():
def test_line_h_s1_w2() -> None:
pytest.skip("failing")
img, draw = create_base_image_draw((20, 20))
draw.line((5, 5, 14, 6), BLACK, 2)
@ -1058,7 +1060,7 @@ def test_line_h_s1_w2():
)
def test_line_vertical():
def test_line_vertical() -> None:
img, draw = create_base_image_draw((20, 20))
draw.line((5, 5, 5, 14), BLACK, 2)
assert_image_equal_tofile(
@ -1104,7 +1106,7 @@ def test_line_vertical():
)
def test_line_oblique_45():
def test_line_oblique_45() -> None:
expected = os.path.join(IMAGES_PATH, "line_oblique_45_w3px_a.png")
img, draw = create_base_image_draw((20, 20))
draw.line((5, 5, 14, 14), BLACK, 3)
@ -1126,7 +1128,7 @@ def test_line_oblique_45():
)
def test_wide_line_dot():
def test_wide_line_dot() -> None:
# Test drawing a wide "line" from one point to another just draws a single point
# Arrange
im = Image.new("RGB", (W, H))
@ -1139,7 +1141,7 @@ def test_wide_line_dot():
assert_image_similar_tofile(im, "Tests/images/imagedraw_wide_line_dot.png", 1)
def test_wide_line_larger_than_int():
def test_wide_line_larger_than_int() -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -1233,7 +1235,7 @@ def test_wide_line_larger_than_int():
],
],
)
def test_line_joint(xy):
def test_line_joint(xy) -> None:
im = Image.new("RGB", (500, 325))
draw = ImageDraw.Draw(im)
@ -1244,7 +1246,7 @@ def test_line_joint(xy):
assert_image_similar_tofile(im, "Tests/images/imagedraw_line_joint_curve.png", 3)
def test_textsize_empty_string():
def test_textsize_empty_string() -> None:
# https://github.com/python-pillow/Pillow/issues/2783
# Arrange
im = Image.new("RGB", (W, H))
@ -1260,7 +1262,7 @@ def test_textsize_empty_string():
@skip_unless_feature("freetype2")
def test_textbbox_stroke():
def test_textbbox_stroke() -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
@ -1274,7 +1276,7 @@ def test_textbbox_stroke():
@skip_unless_feature("freetype2")
def test_stroke():
def test_stroke() -> None:
for suffix, stroke_fill in {"same": None, "different": "#0f0"}.items():
# Arrange
im = Image.new("RGB", (120, 130))
@ -1291,7 +1293,7 @@ def test_stroke():
@skip_unless_feature("freetype2")
def test_stroke_descender():
def test_stroke_descender() -> None:
# Arrange
im = Image.new("RGB", (120, 130))
draw = ImageDraw.Draw(im)
@ -1305,7 +1307,7 @@ def test_stroke_descender():
@skip_unless_feature("freetype2")
def test_split_word():
def test_split_word() -> None:
# Arrange
im = Image.new("RGB", (230, 55))
expected = im.copy()
@ -1326,7 +1328,7 @@ def test_split_word():
@skip_unless_feature("freetype2")
def test_stroke_multiline():
def test_stroke_multiline() -> None:
# Arrange
im = Image.new("RGB", (100, 250))
draw = ImageDraw.Draw(im)
@ -1342,7 +1344,7 @@ def test_stroke_multiline():
@skip_unless_feature("freetype2")
def test_setting_default_font():
def test_setting_default_font() -> None:
# Arrange
im = Image.new("RGB", (100, 250))
draw = ImageDraw.Draw(im)
@ -1359,7 +1361,7 @@ def test_setting_default_font():
assert isinstance(draw.getfont(), ImageFont.load_default().__class__)
def test_default_font_size():
def test_default_font_size() -> None:
freetype_support = features.check_module("freetype2")
text = "Default font at a specific size."
@ -1386,7 +1388,7 @@ def test_default_font_size():
@pytest.mark.parametrize("bbox", BBOX)
def test_same_color_outline(bbox):
def test_same_color_outline(bbox) -> None:
# Prepare shape
x0, y0 = 5, 5
x1, y1 = 5, 50
@ -1432,7 +1434,7 @@ def test_same_color_outline(bbox):
(3, "triangle_width", {"width": 5, "outline": "yellow"}),
],
)
def test_draw_regular_polygon(n_sides, polygon_name, args):
def test_draw_regular_polygon(n_sides, polygon_name, args) -> None:
im = Image.new("RGBA", size=(W, H), color=(255, 0, 0, 0))
filename = f"Tests/images/imagedraw_{polygon_name}.png"
draw = ImageDraw.Draw(im)
@ -1469,7 +1471,7 @@ def test_draw_regular_polygon(n_sides, polygon_name, args):
),
],
)
def test_compute_regular_polygon_vertices(n_sides, expected_vertices):
def test_compute_regular_polygon_vertices(n_sides, expected_vertices) -> None:
bounding_circle = (W // 2, H // 2, 25)
vertices = ImageDraw._compute_regular_polygon_vertices(bounding_circle, n_sides, 0)
assert vertices == expected_vertices
@ -1521,13 +1523,13 @@ def test_compute_regular_polygon_vertices(n_sides, expected_vertices):
)
def test_compute_regular_polygon_vertices_input_error_handling(
n_sides, bounding_circle, rotation, expected_error, error_message
):
) -> None:
with pytest.raises(expected_error) as e:
ImageDraw._compute_regular_polygon_vertices(bounding_circle, n_sides, rotation)
assert str(e.value) == error_message
def test_continuous_horizontal_edges_polygon():
def test_continuous_horizontal_edges_polygon() -> None:
xy = [
(2, 6),
(6, 6),
@ -1546,7 +1548,7 @@ def test_continuous_horizontal_edges_polygon():
)
def test_discontiguous_corners_polygon():
def test_discontiguous_corners_polygon() -> None:
img, draw = create_base_image_draw((84, 68))
draw.polygon(((1, 21), (34, 4), (71, 1), (38, 18)), BLACK)
draw.polygon(((71, 44), (38, 27), (1, 24)), BLACK)
@ -1558,7 +1560,7 @@ def test_discontiguous_corners_polygon():
assert_image_similar_tofile(img, expected, 1)
def test_polygon2():
def test_polygon2() -> None:
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
draw.polygon([(18, 30), (19, 31), (18, 30), (85, 30), (60, 72)], "red")
@ -1567,7 +1569,7 @@ def test_polygon2():
@pytest.mark.parametrize("xy", ((1, 1, 0, 1), (1, 1, 1, 0)))
def test_incorrectly_ordered_coordinates(xy):
def test_incorrectly_ordered_coordinates(xy) -> None:
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
with pytest.raises(ValueError):

View File

@ -43,7 +43,7 @@ POINTS = (
FONT_PATH = "Tests/fonts/FreeMono.ttf"
def test_sanity():
def test_sanity() -> None:
im = hopper("RGB").copy()
draw = ImageDraw2.Draw(im)
@ -56,7 +56,7 @@ def test_sanity():
@pytest.mark.parametrize("bbox", BBOX)
def test_ellipse(bbox):
def test_ellipse(bbox) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
@ -70,7 +70,7 @@ def test_ellipse(bbox):
assert_image_similar_tofile(im, "Tests/images/imagedraw_ellipse_RGB.png", 1)
def test_ellipse_edge():
def test_ellipse_edge() -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
@ -84,7 +84,7 @@ def test_ellipse_edge():
@pytest.mark.parametrize("points", POINTS)
def test_line(points):
def test_line(points) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
@ -98,7 +98,7 @@ def test_line(points):
@pytest.mark.parametrize("points", POINTS)
def test_line_pen_as_brush(points):
def test_line_pen_as_brush(points) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
@ -114,7 +114,7 @@ def test_line_pen_as_brush(points):
@pytest.mark.parametrize("points", POINTS)
def test_polygon(points):
def test_polygon(points) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
@ -129,7 +129,7 @@ def test_polygon(points):
@pytest.mark.parametrize("bbox", BBOX)
def test_rectangle(bbox):
def test_rectangle(bbox) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
@ -143,7 +143,7 @@ def test_rectangle(bbox):
assert_image_equal_tofile(im, "Tests/images/imagedraw_rectangle.png")
def test_big_rectangle():
def test_big_rectangle() -> None:
# Test drawing a rectangle bigger than the image
# Arrange
im = Image.new("RGB", (W, H))
@ -160,7 +160,7 @@ def test_big_rectangle():
@skip_unless_feature("freetype2")
def test_text():
def test_text() -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
@ -175,7 +175,7 @@ def test_text():
@skip_unless_feature("freetype2")
def test_textbbox():
def test_textbbox() -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
@ -190,7 +190,7 @@ def test_textbbox():
@skip_unless_feature("freetype2")
def test_textsize_empty_string():
def test_textsize_empty_string() -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
@ -206,7 +206,7 @@ def test_textsize_empty_string():
@skip_unless_feature("freetype2")
def test_flush():
def test_flush() -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)

View File

@ -7,7 +7,7 @@ from PIL import Image, ImageEnhance
from .helper import assert_image_equal, hopper
def test_sanity():
def test_sanity() -> None:
# FIXME: assert_image
# Implicit asserts no exception:
ImageEnhance.Color(hopper()).enhance(0.5)
@ -16,7 +16,7 @@ def test_sanity():
ImageEnhance.Sharpness(hopper()).enhance(0.5)
def test_crash():
def test_crash() -> None:
# crashes on small images
im = Image.new("RGB", (1, 1))
ImageEnhance.Sharpness(im).enhance(0.5)
@ -34,7 +34,7 @@ def _half_transparent_image():
return im
def _check_alpha(im, original, op, amount):
def _check_alpha(im, original, op, amount) -> None:
assert im.getbands() == original.getbands()
assert_image_equal(
im.getchannel("A"),
@ -44,7 +44,7 @@ def _check_alpha(im, original, op, amount):
@pytest.mark.parametrize("op", ("Color", "Brightness", "Contrast", "Sharpness"))
def test_alpha(op):
def test_alpha(op) -> None:
# Issue https://github.com/python-pillow/Pillow/issues/899
# Is alpha preserved through image enhancement?

View File

@ -30,7 +30,7 @@ SAFEBLOCK = ImageFile.SAFEBLOCK
class TestImageFile:
def test_parser(self):
def test_parser(self) -> None:
def roundtrip(format):
im = hopper("L").resize((1000, 1000), Image.Resampling.NEAREST)
if format in ("MSP", "XBM"):
@ -84,7 +84,7 @@ class TestImageFile:
with pytest.raises(OSError):
roundtrip("PDF")
def test_ico(self):
def test_ico(self) -> None:
with open("Tests/images/python.ico", "rb") as f:
data = f.read()
with ImageFile.Parser() as p:
@ -93,7 +93,7 @@ class TestImageFile:
@skip_unless_feature("webp")
@skip_unless_feature("webp_anim")
def test_incremental_webp(self):
def test_incremental_webp(self) -> None:
with ImageFile.Parser() as p:
with open("Tests/images/hopper.webp", "rb") as f:
p.feed(f.read(1024))
@ -105,7 +105,7 @@ class TestImageFile:
assert (128, 128) == p.image.size
@skip_unless_feature("zlib")
def test_safeblock(self):
def test_safeblock(self) -> None:
im1 = hopper()
try:
@ -116,17 +116,17 @@ class TestImageFile:
assert_image_equal(im1, im2)
def test_raise_oserror(self):
def test_raise_oserror(self) -> None:
with pytest.warns(DeprecationWarning):
with pytest.raises(OSError):
ImageFile.raise_oserror(1)
def test_raise_typeerror(self):
def test_raise_typeerror(self) -> None:
with pytest.raises(TypeError):
parser = ImageFile.Parser()
parser.feed(1)
def test_negative_stride(self):
def test_negative_stride(self) -> None:
with open("Tests/images/raw_negative_stride.bin", "rb") as f:
input = f.read()
p = ImageFile.Parser()
@ -134,11 +134,11 @@ class TestImageFile:
with pytest.raises(OSError):
p.close()
def test_no_format(self):
def test_no_format(self) -> None:
buf = BytesIO(b"\x00" * 255)
class DummyImageFile(ImageFile.ImageFile):
def _open(self):
def _open(self) -> None:
self._mode = "RGB"
self._size = (1, 1)
@ -146,12 +146,12 @@ class TestImageFile:
assert im.format is None
assert im.get_format_mimetype() is None
def test_oserror(self):
def test_oserror(self) -> None:
im = Image.new("RGB", (1, 1))
with pytest.raises(OSError):
im.save(BytesIO(), "JPEG2000", num_resolutions=2)
def test_truncated(self):
def test_truncated(self) -> None:
b = BytesIO(
b"BM000000000000" # head_data
+ _binary.o32le(
@ -166,7 +166,7 @@ class TestImageFile:
assert str(e.value) == "Truncated File Read"
@skip_unless_feature("zlib")
def test_truncated_with_errors(self):
def test_truncated_with_errors(self) -> None:
with Image.open("Tests/images/truncated_image.png") as im:
with pytest.raises(OSError):
im.load()
@ -176,7 +176,7 @@ class TestImageFile:
im.load()
@skip_unless_feature("zlib")
def test_truncated_without_errors(self):
def test_truncated_without_errors(self) -> None:
with Image.open("Tests/images/truncated_image.png") as im:
ImageFile.LOAD_TRUNCATED_IMAGES = True
try:
@ -185,13 +185,13 @@ class TestImageFile:
ImageFile.LOAD_TRUNCATED_IMAGES = False
@skip_unless_feature("zlib")
def test_broken_datastream_with_errors(self):
def test_broken_datastream_with_errors(self) -> None:
with Image.open("Tests/images/broken_data_stream.png") as im:
with pytest.raises(OSError):
im.load()
@skip_unless_feature("zlib")
def test_broken_datastream_without_errors(self):
def test_broken_datastream_without_errors(self) -> None:
with Image.open("Tests/images/broken_data_stream.png") as im:
ImageFile.LOAD_TRUNCATED_IMAGES = True
try:
@ -210,7 +210,7 @@ class MockPyEncoder(ImageFile.PyEncoder):
def encode(self, buffer):
return 1, 1, b""
def cleanup(self):
def cleanup(self) -> None:
self.cleanup_called = True
@ -218,7 +218,7 @@ xoff, yoff, xsize, ysize = 10, 20, 100, 100
class MockImageFile(ImageFile.ImageFile):
def _open(self):
def _open(self) -> None:
self.rawmode = "RGBA"
self._mode = "RGBA"
self._size = (200, 200)
@ -227,7 +227,7 @@ class MockImageFile(ImageFile.ImageFile):
class CodecsTest:
@classmethod
def setup_class(cls):
def setup_class(cls) -> None:
cls.decoder = MockPyDecoder(None)
cls.encoder = MockPyEncoder(None)
@ -244,7 +244,7 @@ class CodecsTest:
class TestPyDecoder(CodecsTest):
def test_setimage(self):
def test_setimage(self) -> None:
buf = BytesIO(b"\x00" * 255)
im = MockImageFile(buf)
@ -259,7 +259,7 @@ class TestPyDecoder(CodecsTest):
with pytest.raises(ValueError):
self.decoder.set_as_raw(b"\x00")
def test_extents_none(self):
def test_extents_none(self) -> None:
buf = BytesIO(b"\x00" * 255)
im = MockImageFile(buf)
@ -272,7 +272,7 @@ class TestPyDecoder(CodecsTest):
assert self.decoder.state.xsize == 200
assert self.decoder.state.ysize == 200
def test_negsize(self):
def test_negsize(self) -> None:
buf = BytesIO(b"\x00" * 255)
im = MockImageFile(buf)
@ -285,7 +285,7 @@ class TestPyDecoder(CodecsTest):
with pytest.raises(ValueError):
im.load()
def test_oversize(self):
def test_oversize(self) -> None:
buf = BytesIO(b"\x00" * 255)
im = MockImageFile(buf)
@ -298,14 +298,14 @@ class TestPyDecoder(CodecsTest):
with pytest.raises(ValueError):
im.load()
def test_decode(self):
def test_decode(self) -> None:
decoder = ImageFile.PyDecoder(None)
with pytest.raises(NotImplementedError):
decoder.decode(None)
class TestPyEncoder(CodecsTest):
def test_setimage(self):
def test_setimage(self) -> None:
buf = BytesIO(b"\x00" * 255)
im = MockImageFile(buf)
@ -320,7 +320,7 @@ class TestPyEncoder(CodecsTest):
assert self.encoder.state.xsize == xsize
assert self.encoder.state.ysize == ysize
def test_extents_none(self):
def test_extents_none(self) -> None:
buf = BytesIO(b"\x00" * 255)
im = MockImageFile(buf)
@ -334,7 +334,7 @@ class TestPyEncoder(CodecsTest):
assert self.encoder.state.xsize == 200
assert self.encoder.state.ysize == 200
def test_negsize(self):
def test_negsize(self) -> None:
buf = BytesIO(b"\x00" * 255)
im = MockImageFile(buf)
@ -352,7 +352,7 @@ class TestPyEncoder(CodecsTest):
im, fp, [("MOCK", (xoff, yoff, xoff + xsize, -10), 0, "RGB")]
)
def test_oversize(self):
def test_oversize(self) -> None:
buf = BytesIO(b"\x00" * 255)
im = MockImageFile(buf)
@ -372,7 +372,7 @@ class TestPyEncoder(CodecsTest):
[("MOCK", (xoff, yoff, xoff + xsize, yoff + ysize + 100), 0, "RGB")],
)
def test_encode(self):
def test_encode(self) -> None:
encoder = ImageFile.PyEncoder(None)
with pytest.raises(NotImplementedError):
encoder.encode(None)
@ -388,6 +388,6 @@ class TestPyEncoder(CodecsTest):
with pytest.raises(NotImplementedError):
encoder.encode_to_file(None, None)
def test_zero_height(self):
def test_zero_height(self) -> None:
with pytest.raises(UnidentifiedImageError):
Image.open("Tests/images/zero_height.j2k")

View File

@ -31,7 +31,7 @@ TEST_TEXT = "hey you\nyou are awesome\nthis looks awkward"
pytestmark = skip_unless_feature("freetype2")
def test_sanity():
def test_sanity() -> None:
assert re.search(r"\d+\.\d+\.\d+$", features.version_module("freetype2"))
@ -51,7 +51,7 @@ def font(layout_engine):
return ImageFont.truetype(FONT_PATH, FONT_SIZE, layout_engine=layout_engine)
def test_font_properties(font):
def test_font_properties(font) -> None:
assert font.path == FONT_PATH
assert font.size == FONT_SIZE
@ -80,11 +80,11 @@ def _render(font, layout_engine):
@pytest.mark.parametrize("font", (FONT_PATH, Path(FONT_PATH)))
def test_font_with_name(layout_engine, font):
def test_font_with_name(layout_engine, font) -> None:
_render(font, layout_engine)
def test_font_with_filelike(layout_engine):
def test_font_with_filelike(layout_engine) -> None:
def _font_as_bytes():
with open(FONT_PATH, "rb") as f:
font_bytes = BytesIO(f.read())
@ -102,12 +102,12 @@ def test_font_with_filelike(layout_engine):
# _render(shared_bytes)
def test_font_with_open_file(layout_engine):
def test_font_with_open_file(layout_engine) -> None:
with open(FONT_PATH, "rb") as f:
_render(f, layout_engine)
def test_render_equal(layout_engine):
def test_render_equal(layout_engine) -> None:
img_path = _render(FONT_PATH, layout_engine)
with open(FONT_PATH, "rb") as f:
font_filelike = BytesIO(f.read())
@ -116,7 +116,7 @@ def test_render_equal(layout_engine):
assert_image_equal(img_path, img_filelike)
def test_non_ascii_path(tmp_path, layout_engine):
def test_non_ascii_path(tmp_path: Path, layout_engine) -> None:
tempfile = str(tmp_path / ("temp_" + chr(128) + ".ttf"))
try:
shutil.copy(FONT_PATH, tempfile)
@ -126,7 +126,7 @@ def test_non_ascii_path(tmp_path, layout_engine):
ImageFont.truetype(tempfile, FONT_SIZE, layout_engine=layout_engine)
def test_transparent_background(font):
def test_transparent_background(font) -> None:
im = Image.new(mode="RGBA", size=(300, 100))
draw = ImageDraw.Draw(im)
@ -140,7 +140,7 @@ def test_transparent_background(font):
assert_image_similar_tofile(im.convert("L"), target, 0.01)
def test_I16(font):
def test_I16(font) -> None:
im = Image.new(mode="I;16", size=(300, 100))
draw = ImageDraw.Draw(im)
@ -153,7 +153,7 @@ def test_I16(font):
assert_image_similar_tofile(im.convert("L"), target, 0.01)
def test_textbbox_equal(font):
def test_textbbox_equal(font) -> None:
im = Image.new(mode="RGB", size=(300, 100))
draw = ImageDraw.Draw(im)
@ -182,7 +182,7 @@ def test_textbbox_equal(font):
)
def test_getlength(
text, mode, fontname, size, layout_engine, length_basic, length_raqm
):
) -> None:
f = ImageFont.truetype("Tests/fonts/" + fontname, size, layout_engine=layout_engine)
im = Image.new(mode, (1, 1), 0)
@ -197,7 +197,7 @@ def test_getlength(
assert length == length_raqm
def test_float_size():
def test_float_size() -> None:
lengths = []
for size in (48, 48.5, 49):
f = ImageFont.truetype(
@ -207,7 +207,7 @@ def test_float_size():
assert lengths[0] != lengths[1] != lengths[2]
def test_render_multiline(font):
def test_render_multiline(font) -> None:
im = Image.new(mode="RGB", size=(300, 100))
draw = ImageDraw.Draw(im)
line_spacing = font.getbbox("A")[3] + 4
@ -223,7 +223,7 @@ def test_render_multiline(font):
assert_image_similar_tofile(im, "Tests/images/multiline_text.png", 6.2)
def test_render_multiline_text(font):
def test_render_multiline_text(font) -> None:
# Test that text() correctly connects to multiline_text()
# and that align defaults to left
im = Image.new(mode="RGB", size=(300, 100))
@ -243,7 +243,7 @@ def test_render_multiline_text(font):
@pytest.mark.parametrize(
"align, ext", (("left", ""), ("center", "_center"), ("right", "_right"))
)
def test_render_multiline_text_align(font, align, ext):
def test_render_multiline_text_align(font, align, ext) -> None:
im = Image.new(mode="RGB", size=(300, 100))
draw = ImageDraw.Draw(im)
draw.multiline_text((0, 0), TEST_TEXT, font=font, align=align)
@ -251,7 +251,7 @@ def test_render_multiline_text_align(font, align, ext):
assert_image_similar_tofile(im, f"Tests/images/multiline_text{ext}.png", 0.01)
def test_unknown_align(font):
def test_unknown_align(font) -> None:
im = Image.new(mode="RGB", size=(300, 100))
draw = ImageDraw.Draw(im)
@ -260,14 +260,14 @@ def test_unknown_align(font):
draw.multiline_text((0, 0), TEST_TEXT, font=font, align="unknown")
def test_draw_align(font):
def test_draw_align(font) -> None:
im = Image.new("RGB", (300, 100), "white")
draw = ImageDraw.Draw(im)
line = "some text"
draw.text((100, 40), line, (0, 0, 0), font=font, align="left")
def test_multiline_bbox(font):
def test_multiline_bbox(font) -> None:
im = Image.new(mode="RGB", size=(300, 100))
draw = ImageDraw.Draw(im)
@ -285,7 +285,7 @@ def test_multiline_bbox(font):
draw.textbbox((0, 0), TEST_TEXT, font=font, spacing=4)
def test_multiline_width(font):
def test_multiline_width(font) -> None:
im = Image.new(mode="RGB", size=(300, 100))
draw = ImageDraw.Draw(im)
@ -295,7 +295,7 @@ def test_multiline_width(font):
)
def test_multiline_spacing(font):
def test_multiline_spacing(font) -> None:
im = Image.new(mode="RGB", size=(300, 100))
draw = ImageDraw.Draw(im)
draw.multiline_text((0, 0), TEST_TEXT, font=font, spacing=10)
@ -306,7 +306,7 @@ def test_multiline_spacing(font):
@pytest.mark.parametrize(
"orientation", (Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_270)
)
def test_rotated_transposed_font(font, orientation):
def test_rotated_transposed_font(font, orientation) -> None:
img_gray = Image.new("L", (100, 100))
draw = ImageDraw.Draw(img_gray)
word = "testing"
@ -347,7 +347,7 @@ def test_rotated_transposed_font(font, orientation):
Image.Transpose.FLIP_TOP_BOTTOM,
),
)
def test_unrotated_transposed_font(font, orientation):
def test_unrotated_transposed_font(font, orientation) -> None:
img_gray = Image.new("L", (100, 100))
draw = ImageDraw.Draw(img_gray)
word = "testing"
@ -382,7 +382,7 @@ def test_unrotated_transposed_font(font, orientation):
@pytest.mark.parametrize(
"orientation", (Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_270)
)
def test_rotated_transposed_font_get_mask(font, orientation):
def test_rotated_transposed_font_get_mask(font, orientation) -> None:
# Arrange
text = "mask this"
transposed_font = ImageFont.TransposedFont(font, orientation=orientation)
@ -403,7 +403,7 @@ def test_rotated_transposed_font_get_mask(font, orientation):
Image.Transpose.FLIP_TOP_BOTTOM,
),
)
def test_unrotated_transposed_font_get_mask(font, orientation):
def test_unrotated_transposed_font_get_mask(font, orientation) -> None:
# Arrange
text = "mask this"
transposed_font = ImageFont.TransposedFont(font, orientation=orientation)
@ -415,11 +415,11 @@ def test_unrotated_transposed_font_get_mask(font, orientation):
assert mask.size == (108, 13)
def test_free_type_font_get_name(font):
def test_free_type_font_get_name(font) -> None:
assert ("FreeMono", "Regular") == font.getname()
def test_free_type_font_get_metrics(font):
def test_free_type_font_get_metrics(font) -> None:
ascent, descent = font.getmetrics()
assert isinstance(ascent, int)
@ -427,7 +427,7 @@ def test_free_type_font_get_metrics(font):
assert (ascent, descent) == (16, 4)
def test_free_type_font_get_mask(font):
def test_free_type_font_get_mask(font) -> None:
# Arrange
text = "mask this"
@ -438,7 +438,7 @@ def test_free_type_font_get_mask(font):
assert mask.size == (108, 13)
def test_load_path_not_found():
def test_load_path_not_found() -> None:
# Arrange
filename = "somefilenamethatdoesntexist.ttf"
@ -449,13 +449,13 @@ def test_load_path_not_found():
ImageFont.truetype(filename)
def test_load_non_font_bytes():
def test_load_non_font_bytes() -> None:
with open("Tests/images/hopper.jpg", "rb") as f:
with pytest.raises(OSError):
ImageFont.truetype(f)
def test_default_font():
def test_default_font() -> None:
# Arrange
txt = "This is a default font using FreeType support."
im = Image.new(mode="RGB", size=(300, 100))
@ -473,16 +473,16 @@ def test_default_font():
@pytest.mark.parametrize("mode", (None, "1", "RGBA"))
def test_getbbox(font, mode):
def test_getbbox(font, mode) -> None:
assert (0, 4, 12, 16) == font.getbbox("A", mode)
def test_getbbox_empty(font):
def test_getbbox_empty(font) -> None:
# issue #2614, should not crash.
assert (0, 0, 0, 0) == font.getbbox("")
def test_render_empty(font):
def test_render_empty(font) -> None:
# issue 2666
im = Image.new(mode="RGB", size=(300, 100))
target = im.copy()
@ -492,7 +492,7 @@ def test_render_empty(font):
assert_image_equal(im, target)
def test_unicode_extended(layout_engine):
def test_unicode_extended(layout_engine) -> None:
# issue #3777
text = "A\u278A\U0001F12B"
target = "Tests/images/unicode_extended.png"
@ -515,8 +515,8 @@ def test_unicode_extended(layout_engine):
(("linux", "/usr/local/share/fonts"), ("darwin", "/System/Library/Fonts")),
)
@pytest.mark.skipif(is_win32(), reason="requires Unix or macOS")
def test_find_font(monkeypatch, platform, font_directory):
def _test_fake_loading_font(path_to_fake, fontname):
def test_find_font(monkeypatch, platform, font_directory) -> None:
def _test_fake_loading_font(path_to_fake, fontname) -> None:
# Make a copy of FreeTypeFont so we can patch the original
free_type_font = copy.deepcopy(ImageFont.FreeTypeFont)
with monkeypatch.context() as m:
@ -567,7 +567,7 @@ def test_find_font(monkeypatch, platform, font_directory):
_test_fake_loading_font(font_directory + "/Duplicate.ttf", "Duplicate")
def test_imagefont_getters(font):
def test_imagefont_getters(font) -> None:
assert font.getmetrics() == (16, 4)
assert font.font.ascent == 16
assert font.font.descent == 4
@ -588,7 +588,7 @@ def test_imagefont_getters(font):
@pytest.mark.parametrize("stroke_width", (0, 2))
def test_getsize_stroke(font, stroke_width):
def test_getsize_stroke(font, stroke_width) -> None:
assert font.getbbox("A", stroke_width=stroke_width) == (
0 - stroke_width,
4 - stroke_width,
@ -597,7 +597,7 @@ def test_getsize_stroke(font, stroke_width):
)
def test_complex_font_settings():
def test_complex_font_settings() -> None:
t = ImageFont.truetype(FONT_PATH, FONT_SIZE, layout_engine=ImageFont.Layout.BASIC)
with pytest.raises(KeyError):
t.getmask("абвг", direction="rtl")
@ -607,7 +607,7 @@ def test_complex_font_settings():
t.getmask("абвг", language="sr")
def test_variation_get(font):
def test_variation_get(font) -> None:
freetype = parse_version(features.version_module("freetype2"))
if freetype < parse_version("2.9.1"):
with pytest.raises(NotImplementedError):
@ -677,7 +677,7 @@ def _check_text(font, path, epsilon):
raise
def test_variation_set_by_name(font):
def test_variation_set_by_name(font) -> None:
freetype = parse_version(features.version_module("freetype2"))
if freetype < parse_version("2.9.1"):
with pytest.raises(NotImplementedError):
@ -702,7 +702,7 @@ def test_variation_set_by_name(font):
_check_text(font, "Tests/images/variation_tiny_name.png", 40)
def test_variation_set_by_axes(font):
def test_variation_set_by_axes(font) -> None:
freetype = parse_version(features.version_module("freetype2"))
if freetype < parse_version("2.9.1"):
with pytest.raises(NotImplementedError):
@ -737,7 +737,7 @@ def test_variation_set_by_axes(font):
),
ids=("ls", "ms", "rs", "ma", "mt", "mm", "mb", "md"),
)
def test_anchor(layout_engine, anchor, left, top):
def test_anchor(layout_engine, anchor, left, top) -> None:
name, text = "quick", "Quick"
path = f"Tests/images/test_anchor_{name}_{anchor}.png"
@ -782,7 +782,7 @@ def test_anchor(layout_engine, anchor, left, top):
("md", "center"),
),
)
def test_anchor_multiline(layout_engine, anchor, align):
def test_anchor_multiline(layout_engine, anchor, align) -> None:
target = f"Tests/images/test_anchor_multiline_{anchor}_{align}.png"
text = "a\nlong\ntext sample"
@ -800,7 +800,7 @@ def test_anchor_multiline(layout_engine, anchor, align):
assert_image_similar_tofile(im, target, 4)
def test_anchor_invalid(font):
def test_anchor_invalid(font) -> None:
im = Image.new("RGB", (100, 100), "white")
d = ImageDraw.Draw(im)
d.font = font
@ -826,7 +826,7 @@ def test_anchor_invalid(font):
@pytest.mark.parametrize("bpp", (1, 2, 4, 8))
def test_bitmap_font(layout_engine, bpp):
def test_bitmap_font(layout_engine, bpp) -> None:
text = "Bitmap Font"
layout_name = ["basic", "raqm"][layout_engine]
target = f"Tests/images/bitmap_font_{bpp}_{layout_name}.png"
@ -843,7 +843,7 @@ def test_bitmap_font(layout_engine, bpp):
assert_image_equal_tofile(im, target)
def test_bitmap_font_stroke(layout_engine):
def test_bitmap_font_stroke(layout_engine) -> None:
text = "Bitmap Font"
layout_name = ["basic", "raqm"][layout_engine]
target = f"Tests/images/bitmap_font_stroke_{layout_name}.png"
@ -861,7 +861,7 @@ def test_bitmap_font_stroke(layout_engine):
@pytest.mark.parametrize("embedded_color", (False, True))
def test_bitmap_blend(layout_engine, embedded_color):
def test_bitmap_blend(layout_engine, embedded_color) -> None:
font = ImageFont.truetype(
"Tests/fonts/EBDTTestFont.ttf", size=64, layout_engine=layout_engine
)
@ -873,7 +873,7 @@ def test_bitmap_blend(layout_engine, embedded_color):
assert_image_equal_tofile(im, "Tests/images/bitmap_font_blend.png")
def test_standard_embedded_color(layout_engine):
def test_standard_embedded_color(layout_engine) -> None:
txt = "Hello World!"
ttf = ImageFont.truetype(FONT_PATH, 40, layout_engine=layout_engine)
ttf.getbbox(txt)
@ -908,7 +908,7 @@ def test_float_coord(layout_engine, fontmode):
raise
def test_cbdt(layout_engine):
def test_cbdt(layout_engine) -> None:
try:
font = ImageFont.truetype(
"Tests/fonts/CBDTTestFont.ttf", size=64, layout_engine=layout_engine
@ -925,7 +925,7 @@ def test_cbdt(layout_engine):
pytest.skip("freetype compiled without libpng or CBDT support")
def test_cbdt_mask(layout_engine):
def test_cbdt_mask(layout_engine) -> None:
try:
font = ImageFont.truetype(
"Tests/fonts/CBDTTestFont.ttf", size=64, layout_engine=layout_engine
@ -942,7 +942,7 @@ def test_cbdt_mask(layout_engine):
pytest.skip("freetype compiled without libpng or CBDT support")
def test_sbix(layout_engine):
def test_sbix(layout_engine) -> None:
try:
font = ImageFont.truetype(
"Tests/fonts/chromacheck-sbix.woff", size=300, layout_engine=layout_engine
@ -959,7 +959,7 @@ def test_sbix(layout_engine):
pytest.skip("freetype compiled without libpng or SBIX support")
def test_sbix_mask(layout_engine):
def test_sbix_mask(layout_engine) -> None:
try:
font = ImageFont.truetype(
"Tests/fonts/chromacheck-sbix.woff", size=300, layout_engine=layout_engine
@ -977,7 +977,7 @@ def test_sbix_mask(layout_engine):
@skip_unless_feature_version("freetype2", "2.10.0")
def test_colr(layout_engine):
def test_colr(layout_engine) -> None:
font = ImageFont.truetype(
"Tests/fonts/BungeeColor-Regular_colr_Windows.ttf",
size=64,
@ -993,7 +993,7 @@ def test_colr(layout_engine):
@skip_unless_feature_version("freetype2", "2.10.0")
def test_colr_mask(layout_engine):
def test_colr_mask(layout_engine) -> None:
font = ImageFont.truetype(
"Tests/fonts/BungeeColor-Regular_colr_Windows.ttf",
size=64,
@ -1008,7 +1008,7 @@ def test_colr_mask(layout_engine):
assert_image_similar_tofile(im, "Tests/images/colr_bungee_mask.png", 22)
def test_woff2(layout_engine):
def test_woff2(layout_engine) -> None:
try:
font = ImageFont.truetype(
"Tests/fonts/OpenSans.woff2",
@ -1027,7 +1027,7 @@ def test_woff2(layout_engine):
assert_image_similar_tofile(im, "Tests/images/test_woff2.png", 5)
def test_render_mono_size():
def test_render_mono_size() -> None:
# issue 4177
im = Image.new("P", (100, 30), "white")
@ -1042,7 +1042,7 @@ def test_render_mono_size():
assert_image_equal_tofile(im, "Tests/images/text_mono.gif")
def test_too_many_characters(font):
def test_too_many_characters(font) -> None:
with pytest.raises(ValueError):
font.getlength("A" * 1_000_001)
with pytest.raises(ValueError):
@ -1070,14 +1070,14 @@ def test_too_many_characters(font):
"Tests/fonts/oom-4da0210eb7081b0bf15bf16cc4c52ce02c1e1bbc.ttf",
],
)
def test_oom(test_file):
def test_oom(test_file) -> None:
with open(test_file, "rb") as f:
font = ImageFont.truetype(BytesIO(f.read()))
with pytest.raises(Image.DecompressionBombError):
font.getmask("Test Text")
def test_raqm_missing_warning(monkeypatch):
def test_raqm_missing_warning(monkeypatch) -> None:
monkeypatch.setattr(ImageFont.core, "HAVE_RAQM", False)
with pytest.warns(UserWarning) as record:
font = ImageFont.truetype(
@ -1091,6 +1091,6 @@ def test_raqm_missing_warning(monkeypatch):
@pytest.mark.parametrize("size", [-1, 0])
def test_invalid_truetype_sizes_raise_valueerror(layout_engine, size):
def test_invalid_truetype_sizes_raise_valueerror(layout_engine, size) -> None:
with pytest.raises(ValueError):
ImageFont.truetype(FONT_PATH, size, layout_engine=layout_engine)

View File

@ -12,7 +12,7 @@ FONT_PATH = "Tests/fonts/DejaVuSans/DejaVuSans.ttf"
pytestmark = skip_unless_feature("raqm")
def test_english():
def test_english() -> None:
# smoke test, this should not fail
ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
im = Image.new(mode="RGB", size=(300, 100))
@ -20,7 +20,7 @@ def test_english():
draw.text((0, 0), "TEST", font=ttf, fill=500, direction="ltr")
def test_complex_text():
def test_complex_text() -> None:
ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
im = Image.new(mode="RGB", size=(300, 100))
@ -31,7 +31,7 @@ def test_complex_text():
assert_image_similar_tofile(im, target, 0.5)
def test_y_offset():
def test_y_offset() -> None:
ttf = ImageFont.truetype("Tests/fonts/NotoNastaliqUrdu-Regular.ttf", FONT_SIZE)
im = Image.new(mode="RGB", size=(300, 100))
@ -42,7 +42,7 @@ def test_y_offset():
assert_image_similar_tofile(im, target, 1.7)
def test_complex_unicode_text():
def test_complex_unicode_text() -> None:
ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
im = Image.new(mode="RGB", size=(300, 100))
@ -62,7 +62,7 @@ def test_complex_unicode_text():
assert_image_similar_tofile(im, target, 2.33)
def test_text_direction_rtl():
def test_text_direction_rtl() -> None:
ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
im = Image.new(mode="RGB", size=(300, 100))
@ -73,7 +73,7 @@ def test_text_direction_rtl():
assert_image_similar_tofile(im, target, 0.5)
def test_text_direction_ltr():
def test_text_direction_ltr() -> None:
ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
im = Image.new(mode="RGB", size=(300, 100))
@ -84,7 +84,7 @@ def test_text_direction_ltr():
assert_image_similar_tofile(im, target, 0.5)
def test_text_direction_rtl2():
def test_text_direction_rtl2() -> None:
ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
im = Image.new(mode="RGB", size=(300, 100))
@ -95,7 +95,7 @@ def test_text_direction_rtl2():
assert_image_similar_tofile(im, target, 0.5)
def test_text_direction_ttb():
def test_text_direction_ttb() -> None:
ttf = ImageFont.truetype("Tests/fonts/NotoSansJP-Regular.otf", FONT_SIZE)
im = Image.new(mode="RGB", size=(100, 300))
@ -110,7 +110,7 @@ def test_text_direction_ttb():
assert_image_similar_tofile(im, target, 2.8)
def test_text_direction_ttb_stroke():
def test_text_direction_ttb_stroke() -> None:
ttf = ImageFont.truetype("Tests/fonts/NotoSansJP-Regular.otf", 50)
im = Image.new(mode="RGB", size=(100, 300))
@ -133,7 +133,7 @@ def test_text_direction_ttb_stroke():
assert_image_similar_tofile(im, target, 19.4)
def test_ligature_features():
def test_ligature_features() -> None:
ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
im = Image.new(mode="RGB", size=(300, 100))
@ -146,7 +146,7 @@ def test_ligature_features():
assert liga_bbox == (0, 4, 13, 19)
def test_kerning_features():
def test_kerning_features() -> None:
ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
im = Image.new(mode="RGB", size=(300, 100))
@ -157,7 +157,7 @@ def test_kerning_features():
assert_image_similar_tofile(im, target, 0.5)
def test_arabictext_features():
def test_arabictext_features() -> None:
ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
im = Image.new(mode="RGB", size=(300, 100))
@ -174,7 +174,7 @@ def test_arabictext_features():
assert_image_similar_tofile(im, target, 0.5)
def test_x_max_and_y_offset():
def test_x_max_and_y_offset() -> None:
ttf = ImageFont.truetype("Tests/fonts/ArefRuqaa-Regular.ttf", 40)
im = Image.new(mode="RGB", size=(50, 100))
@ -185,7 +185,7 @@ def test_x_max_and_y_offset():
assert_image_similar_tofile(im, target, 0.5)
def test_language():
def test_language() -> None:
ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
im = Image.new(mode="RGB", size=(300, 100))
@ -208,7 +208,7 @@ def test_language():
),
ids=("None", "ltr", "rtl2", "rtl", "ttb"),
)
def test_getlength(mode, text, direction, expected):
def test_getlength(mode, text, direction, expected) -> None:
ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
im = Image.new(mode, (1, 1), 0)
d = ImageDraw.Draw(im)
@ -230,7 +230,7 @@ def test_getlength(mode, text, direction, expected):
("i" + ("\u030C" * 15) + "i", "i" + "\u032C" * 15 + "i", "\u035Cii", "i\u0305i"),
ids=("caron-above", "caron-below", "double-breve", "overline"),
)
def test_getlength_combine(mode, direction, text):
def test_getlength_combine(mode, direction, text) -> None:
if text == "i\u0305i" and direction == "ttb":
pytest.skip("fails with this font")
@ -250,7 +250,7 @@ def test_getlength_combine(mode, direction, text):
@pytest.mark.parametrize("anchor", ("lt", "mm", "rb", "sm"))
def test_anchor_ttb(anchor):
def test_anchor_ttb(anchor) -> None:
text = "f"
path = f"Tests/images/test_anchor_ttb_{text}_{anchor}.png"
f = ImageFont.truetype("Tests/fonts/NotoSans-Regular.ttf", 120)
@ -306,7 +306,7 @@ combine_tests = (
@pytest.mark.parametrize(
"name, text, anchor, dir, epsilon", combine_tests, ids=[r[0] for r in combine_tests]
)
def test_combine(name, text, dir, anchor, epsilon):
def test_combine(name, text, dir, anchor, epsilon) -> None:
path = f"Tests/images/test_combine_{name}.png"
f = ImageFont.truetype("Tests/fonts/NotoSans-Regular.ttf", 48)
@ -337,7 +337,7 @@ def test_combine(name, text, dir, anchor, epsilon):
("rm", "right"), # pass with getsize
),
)
def test_combine_multiline(anchor, align):
def test_combine_multiline(anchor, align) -> None:
# test that multiline text uses getlength, not getsize or getbbox
path = f"Tests/images/test_combine_multiline_{anchor}_{align}.png"
@ -355,7 +355,7 @@ def test_combine_multiline(anchor, align):
assert_image_similar_tofile(im, path, 0.015)
def test_anchor_invalid_ttb():
def test_anchor_invalid_ttb() -> None:
font = ImageFont.truetype(FONT_PATH, FONT_SIZE)
im = Image.new("RGB", (100, 100), "white")
d = ImageDraw.Draw(im)

View File

@ -12,16 +12,16 @@ from .helper import assert_image_equal_tofile
original_core = ImageFont.core
def setup_module():
def setup_module() -> None:
if features.check_module("freetype2"):
ImageFont.core = _util.DeferredError(ImportError)
def teardown_module():
def teardown_module() -> None:
ImageFont.core = original_core
def test_default_font():
def test_default_font() -> None:
# Arrange
txt = 'This is a "better than nothing" default font.'
im = Image.new(mode="RGB", size=(300, 100))
@ -35,12 +35,12 @@ def test_default_font():
assert_image_equal_tofile(im, "Tests/images/default_font.png")
def test_size_without_freetype():
def test_size_without_freetype() -> None:
with pytest.raises(ImportError):
ImageFont.load_default(size=14)
def test_unicode():
def test_unicode() -> None:
# should not segfault, should return UnicodeDecodeError
# issue #2826
font = ImageFont.load_default()
@ -48,7 +48,7 @@ def test_unicode():
font.getbbox("")
def test_textbbox():
def test_textbbox() -> None:
im = Image.new("RGB", (200, 200))
d = ImageDraw.Draw(im)
default_font = ImageFont.load_default()
@ -56,7 +56,7 @@ def test_textbbox():
assert d.textbbox((0, 0), "test", font=default_font) == (0, 0, 24, 11)
def test_decompression_bomb():
def test_decompression_bomb() -> None:
glyph = struct.pack(">hhhhhhhhhh", 1, 0, 0, 0, 256, 256, 0, 0, 256, 256)
fp = BytesIO(b"PILfont\n\nDATA\n" + glyph * 256)
@ -67,7 +67,7 @@ def test_decompression_bomb():
@pytest.mark.timeout(4)
def test_oom():
def test_oom() -> None:
glyph = struct.pack(
">hhhhhhhhhh", 1, 0, -32767, -32767, 32767, 32767, -32767, -32767, 32767, 32767
)

View File

@ -20,7 +20,7 @@ class TestImageGrab:
@pytest.mark.skipif(
sys.platform not in ("win32", "darwin"), reason="requires Windows or macOS"
)
def test_grab(self):
def test_grab(self) -> None:
ImageGrab.grab()
ImageGrab.grab(include_layered_windows=True)
ImageGrab.grab(all_screens=True)
@ -29,7 +29,7 @@ class TestImageGrab:
assert im.size == (40, 60)
@skip_unless_feature("xcb")
def test_grab_x11(self):
def test_grab_x11(self) -> None:
try:
if sys.platform not in ("win32", "darwin"):
ImageGrab.grab()
@ -39,7 +39,7 @@ class TestImageGrab:
pytest.skip(str(e))
@pytest.mark.skipif(Image.core.HAVE_XCB, reason="tests missing XCB")
def test_grab_no_xcb(self):
def test_grab_no_xcb(self) -> None:
if sys.platform not in ("win32", "darwin") and not shutil.which(
"gnome-screenshot"
):
@ -52,12 +52,12 @@ class TestImageGrab:
assert str(e.value).startswith("Pillow was built without XCB support")
@skip_unless_feature("xcb")
def test_grab_invalid_xdisplay(self):
def test_grab_invalid_xdisplay(self) -> None:
with pytest.raises(OSError) as e:
ImageGrab.grab(xdisplay="error.test:0.0")
assert str(e.value).startswith("X connection failed")
def test_grabclipboard(self):
def test_grabclipboard(self) -> None:
if sys.platform == "darwin":
subprocess.call(["screencapture", "-cx"])
elif sys.platform == "win32":
@ -82,7 +82,7 @@ $bmp = New-Object Drawing.Bitmap 200, 200
ImageGrab.grabclipboard()
@pytest.mark.skipif(sys.platform != "win32", reason="Windows only")
def test_grabclipboard_file(self):
def test_grabclipboard_file(self) -> None:
p = subprocess.Popen(["powershell", "-command", "-"], stdin=subprocess.PIPE)
p.stdin.write(rb'Set-Clipboard -Path "Tests\images\hopper.gif"')
p.communicate()
@ -92,7 +92,7 @@ $bmp = New-Object Drawing.Bitmap 200, 200
assert os.path.samefile(im[0], "Tests/images/hopper.gif")
@pytest.mark.skipif(sys.platform != "win32", reason="Windows only")
def test_grabclipboard_png(self):
def test_grabclipboard_png(self) -> None:
p = subprocess.Popen(["powershell", "-command", "-"], stdin=subprocess.PIPE)
p.stdin.write(
rb"""$bytes = [System.IO.File]::ReadAllBytes("Tests\images\hopper.png")
@ -113,7 +113,7 @@ $ms = new-object System.IO.MemoryStream(, $bytes)
reason="Linux with wl-clipboard only",
)
@pytest.mark.parametrize("ext", ("gif", "png", "ico"))
def test_grabclipboard_wl_clipboard(self, ext):
def test_grabclipboard_wl_clipboard(self, ext) -> None:
image_path = "Tests/images/hopper." + ext
with open(image_path, "rb") as fp:
subprocess.call(["wl-copy"], stdin=fp)

View File

@ -24,7 +24,7 @@ B2 = B.resize((2, 2))
images = {"A": A, "B": B, "F": F, "I": I}
def test_sanity():
def test_sanity() -> None:
assert ImageMath.eval("1") == 1
assert ImageMath.eval("1+A", A=2) == 3
assert pixel(ImageMath.eval("A+B", A=A, B=B)) == "I 3"
@ -33,7 +33,7 @@ def test_sanity():
assert pixel(ImageMath.eval("int(float(A)+B)", images)) == "I 3"
def test_ops():
def test_ops() -> None:
assert pixel(ImageMath.eval("-A", images)) == "I -1"
assert pixel(ImageMath.eval("+B", images)) == "L 2"
@ -60,51 +60,51 @@ def test_ops():
"(lambda: (lambda: exec('pass'))())()",
),
)
def test_prevent_exec(expression):
def test_prevent_exec(expression) -> None:
with pytest.raises(ValueError):
ImageMath.eval(expression)
def test_prevent_double_underscores():
def test_prevent_double_underscores() -> None:
with pytest.raises(ValueError):
ImageMath.eval("1", {"__": None})
def test_prevent_builtins():
def test_prevent_builtins() -> None:
with pytest.raises(ValueError):
ImageMath.eval("(lambda: exec('exit()'))()", {"exec": None})
def test_logical():
def test_logical() -> None:
assert pixel(ImageMath.eval("not A", images)) == 0
assert pixel(ImageMath.eval("A and B", images)) == "L 2"
assert pixel(ImageMath.eval("A or B", images)) == "L 1"
def test_convert():
def test_convert() -> None:
assert pixel(ImageMath.eval("convert(A+B, 'L')", images)) == "L 3"
assert pixel(ImageMath.eval("convert(A+B, '1')", images)) == "1 0"
assert pixel(ImageMath.eval("convert(A+B, 'RGB')", images)) == "RGB (3, 3, 3)"
def test_compare():
def test_compare() -> None:
assert pixel(ImageMath.eval("min(A, B)", images)) == "I 1"
assert pixel(ImageMath.eval("max(A, B)", images)) == "I 2"
assert pixel(ImageMath.eval("A == 1", images)) == "I 1"
assert pixel(ImageMath.eval("A == 2", images)) == "I 0"
def test_one_image_larger():
def test_one_image_larger() -> None:
assert pixel(ImageMath.eval("A+B", A=A2, B=B)) == "I 3"
assert pixel(ImageMath.eval("A+B", A=A, B=B2)) == "I 3"
def test_abs():
def test_abs() -> None:
assert pixel(ImageMath.eval("abs(A)", A=A)) == "I 1"
assert pixel(ImageMath.eval("abs(B)", B=B)) == "I 2"
def test_binary_mod():
def test_binary_mod() -> None:
assert pixel(ImageMath.eval("A%A", A=A)) == "I 0"
assert pixel(ImageMath.eval("B%B", B=B)) == "I 0"
assert pixel(ImageMath.eval("A%B", A=A, B=B)) == "I 1"
@ -113,90 +113,90 @@ def test_binary_mod():
assert pixel(ImageMath.eval("Z%B", B=B, Z=Z)) == "I 0"
def test_bitwise_invert():
def test_bitwise_invert() -> None:
assert pixel(ImageMath.eval("~Z", Z=Z)) == "I -1"
assert pixel(ImageMath.eval("~A", A=A)) == "I -2"
assert pixel(ImageMath.eval("~B", B=B)) == "I -3"
def test_bitwise_and():
def test_bitwise_and() -> None:
assert pixel(ImageMath.eval("Z&Z", A=A, Z=Z)) == "I 0"
assert pixel(ImageMath.eval("Z&A", A=A, Z=Z)) == "I 0"
assert pixel(ImageMath.eval("A&Z", A=A, Z=Z)) == "I 0"
assert pixel(ImageMath.eval("A&A", A=A, Z=Z)) == "I 1"
def test_bitwise_or():
def test_bitwise_or() -> None:
assert pixel(ImageMath.eval("Z|Z", A=A, Z=Z)) == "I 0"
assert pixel(ImageMath.eval("Z|A", A=A, Z=Z)) == "I 1"
assert pixel(ImageMath.eval("A|Z", A=A, Z=Z)) == "I 1"
assert pixel(ImageMath.eval("A|A", A=A, Z=Z)) == "I 1"
def test_bitwise_xor():
def test_bitwise_xor() -> None:
assert pixel(ImageMath.eval("Z^Z", A=A, Z=Z)) == "I 0"
assert pixel(ImageMath.eval("Z^A", A=A, Z=Z)) == "I 1"
assert pixel(ImageMath.eval("A^Z", A=A, Z=Z)) == "I 1"
assert pixel(ImageMath.eval("A^A", A=A, Z=Z)) == "I 0"
def test_bitwise_leftshift():
def test_bitwise_leftshift() -> None:
assert pixel(ImageMath.eval("Z<<0", Z=Z)) == "I 0"
assert pixel(ImageMath.eval("Z<<1", Z=Z)) == "I 0"
assert pixel(ImageMath.eval("A<<0", A=A)) == "I 1"
assert pixel(ImageMath.eval("A<<1", A=A)) == "I 2"
def test_bitwise_rightshift():
def test_bitwise_rightshift() -> None:
assert pixel(ImageMath.eval("Z>>0", Z=Z)) == "I 0"
assert pixel(ImageMath.eval("Z>>1", Z=Z)) == "I 0"
assert pixel(ImageMath.eval("A>>0", A=A)) == "I 1"
assert pixel(ImageMath.eval("A>>1", A=A)) == "I 0"
def test_logical_eq():
def test_logical_eq() -> None:
assert pixel(ImageMath.eval("A==A", A=A)) == "I 1"
assert pixel(ImageMath.eval("B==B", B=B)) == "I 1"
assert pixel(ImageMath.eval("A==B", A=A, B=B)) == "I 0"
assert pixel(ImageMath.eval("B==A", A=A, B=B)) == "I 0"
def test_logical_ne():
def test_logical_ne() -> None:
assert pixel(ImageMath.eval("A!=A", A=A)) == "I 0"
assert pixel(ImageMath.eval("B!=B", B=B)) == "I 0"
assert pixel(ImageMath.eval("A!=B", A=A, B=B)) == "I 1"
assert pixel(ImageMath.eval("B!=A", A=A, B=B)) == "I 1"
def test_logical_lt():
def test_logical_lt() -> None:
assert pixel(ImageMath.eval("A<A", A=A)) == "I 0"
assert pixel(ImageMath.eval("B<B", B=B)) == "I 0"
assert pixel(ImageMath.eval("A<B", A=A, B=B)) == "I 1"
assert pixel(ImageMath.eval("B<A", A=A, B=B)) == "I 0"
def test_logical_le():
def test_logical_le() -> None:
assert pixel(ImageMath.eval("A<=A", A=A)) == "I 1"
assert pixel(ImageMath.eval("B<=B", B=B)) == "I 1"
assert pixel(ImageMath.eval("A<=B", A=A, B=B)) == "I 1"
assert pixel(ImageMath.eval("B<=A", A=A, B=B)) == "I 0"
def test_logical_gt():
def test_logical_gt() -> None:
assert pixel(ImageMath.eval("A>A", A=A)) == "I 0"
assert pixel(ImageMath.eval("B>B", B=B)) == "I 0"
assert pixel(ImageMath.eval("A>B", A=A, B=B)) == "I 0"
assert pixel(ImageMath.eval("B>A", A=A, B=B)) == "I 1"
def test_logical_ge():
def test_logical_ge() -> None:
assert pixel(ImageMath.eval("A>=A", A=A)) == "I 1"
assert pixel(ImageMath.eval("B>=B", B=B)) == "I 1"
assert pixel(ImageMath.eval("A>=B", A=A, B=B)) == "I 0"
assert pixel(ImageMath.eval("B>=A", A=A, B=B)) == "I 1"
def test_logical_equal():
def test_logical_equal() -> None:
assert pixel(ImageMath.eval("equal(A, A)", A=A)) == "I 1"
assert pixel(ImageMath.eval("equal(B, B)", B=B)) == "I 1"
assert pixel(ImageMath.eval("equal(Z, Z)", Z=Z)) == "I 1"
@ -205,7 +205,7 @@ def test_logical_equal():
assert pixel(ImageMath.eval("equal(A, Z)", A=A, Z=Z)) == "I 0"
def test_logical_not_equal():
def test_logical_not_equal() -> None:
assert pixel(ImageMath.eval("notequal(A, A)", A=A)) == "I 0"
assert pixel(ImageMath.eval("notequal(B, B)", B=B)) == "I 0"
assert pixel(ImageMath.eval("notequal(Z, Z)", Z=Z)) == "I 0"

View File

@ -1,6 +1,8 @@
# Test the ImageMorphology functionality
from __future__ import annotations
from pathlib import Path
import pytest
from PIL import Image, ImageMorph, _imagingmorph
@ -50,18 +52,18 @@ def img_string_normalize(im):
return img_to_string(string_to_img(im))
def assert_img_equal_img_string(a, b_string):
def assert_img_equal_img_string(a, b_string) -> None:
assert img_to_string(a) == img_string_normalize(b_string)
def test_str_to_img():
def test_str_to_img() -> None:
assert_image_equal_tofile(A, "Tests/images/morph_a.png")
@pytest.mark.parametrize(
"op", ("corner", "dilation4", "dilation8", "erosion4", "erosion8", "edge")
)
def test_lut(op):
def test_lut(op) -> None:
lb = ImageMorph.LutBuilder(op_name=op)
assert lb.get_lut() is None
@ -70,7 +72,7 @@ def test_lut(op):
assert lut == bytearray(f.read())
def test_no_operator_loaded():
def test_no_operator_loaded() -> None:
mop = ImageMorph.MorphOp()
with pytest.raises(Exception) as e:
mop.apply(None)
@ -84,7 +86,7 @@ def test_no_operator_loaded():
# Test the named patterns
def test_erosion8():
def test_erosion8() -> None:
# erosion8
mop = ImageMorph.MorphOp(op_name="erosion8")
count, Aout = mop.apply(A)
@ -103,7 +105,7 @@ def test_erosion8():
)
def test_dialation8():
def test_dialation8() -> None:
# dialation8
mop = ImageMorph.MorphOp(op_name="dilation8")
count, Aout = mop.apply(A)
@ -122,7 +124,7 @@ def test_dialation8():
)
def test_erosion4():
def test_erosion4() -> None:
# erosion4
mop = ImageMorph.MorphOp(op_name="dilation4")
count, Aout = mop.apply(A)
@ -141,7 +143,7 @@ def test_erosion4():
)
def test_edge():
def test_edge() -> None:
# edge
mop = ImageMorph.MorphOp(op_name="edge")
count, Aout = mop.apply(A)
@ -160,7 +162,7 @@ def test_edge():
)
def test_corner():
def test_corner() -> None:
# Create a corner detector pattern
mop = ImageMorph.MorphOp(patterns=["1:(... ... ...)->0", "4:(00. 01. ...)->1"])
count, Aout = mop.apply(A)
@ -188,7 +190,7 @@ def test_corner():
assert tuple(coords) == ((2, 2), (4, 2), (2, 4), (4, 4))
def test_mirroring():
def test_mirroring() -> None:
# Test 'M' for mirroring
mop = ImageMorph.MorphOp(patterns=["1:(... ... ...)->0", "M:(00. 01. ...)->1"])
count, Aout = mop.apply(A)
@ -207,7 +209,7 @@ def test_mirroring():
)
def test_negate():
def test_negate() -> None:
# Test 'N' for negate
mop = ImageMorph.MorphOp(patterns=["1:(... ... ...)->0", "N:(00. 01. ...)->1"])
count, Aout = mop.apply(A)
@ -226,7 +228,7 @@ def test_negate():
)
def test_incorrect_mode():
def test_incorrect_mode() -> None:
im = hopper("RGB")
mop = ImageMorph.MorphOp(op_name="erosion8")
@ -241,7 +243,7 @@ def test_incorrect_mode():
assert str(e.value) == "Image mode must be L"
def test_add_patterns():
def test_add_patterns() -> None:
# Arrange
lb = ImageMorph.LutBuilder(op_name="corner")
assert lb.patterns == ["1:(... ... ...)->0", "4:(00. 01. ...)->1"]
@ -259,12 +261,12 @@ def test_add_patterns():
]
def test_unknown_pattern():
def test_unknown_pattern() -> None:
with pytest.raises(Exception):
ImageMorph.LutBuilder(op_name="unknown")
def test_pattern_syntax_error():
def test_pattern_syntax_error() -> None:
# Arrange
lb = ImageMorph.LutBuilder(op_name="corner")
new_patterns = ["a pattern with a syntax error"]
@ -276,7 +278,7 @@ def test_pattern_syntax_error():
assert str(e.value) == 'Syntax error in pattern "a pattern with a syntax error"'
def test_load_invalid_mrl():
def test_load_invalid_mrl() -> None:
# Arrange
invalid_mrl = "Tests/images/hopper.png"
mop = ImageMorph.MorphOp()
@ -287,7 +289,7 @@ def test_load_invalid_mrl():
assert str(e.value) == "Wrong size operator file!"
def test_roundtrip_mrl(tmp_path):
def test_roundtrip_mrl(tmp_path: Path) -> None:
# Arrange
tempfile = str(tmp_path / "temp.mrl")
mop = ImageMorph.MorphOp(op_name="corner")
@ -301,7 +303,7 @@ def test_roundtrip_mrl(tmp_path):
assert mop.lut == initial_lut
def test_set_lut():
def test_set_lut() -> None:
# Arrange
lb = ImageMorph.LutBuilder(op_name="corner")
lut = lb.build_lut()
@ -314,7 +316,7 @@ def test_set_lut():
assert mop.lut == lut
def test_wrong_mode():
def test_wrong_mode() -> None:
lut = ImageMorph.LutBuilder(op_name="corner").build_lut()
imrgb = Image.new("RGB", (10, 10))
iml = Image.new("L", (10, 10))

View File

@ -22,7 +22,7 @@ class Deformer:
deformer = Deformer()
def test_sanity():
def test_sanity() -> None:
ImageOps.autocontrast(hopper("L"))
ImageOps.autocontrast(hopper("RGB"))
@ -84,7 +84,7 @@ def test_sanity():
ImageOps.exif_transpose(hopper("RGB"))
def test_1pxfit():
def test_1pxfit() -> None:
# Division by zero in equalize if image is 1 pixel high
newimg = ImageOps.fit(hopper("RGB").resize((1, 1)), (35, 35))
assert newimg.size == (35, 35)
@ -96,7 +96,7 @@ def test_1pxfit():
assert newimg.size == (35, 35)
def test_fit_same_ratio():
def test_fit_same_ratio() -> None:
# The ratio for this image is 1000.0 / 755 = 1.3245033112582782
# If the ratios are not acknowledged to be the same,
# and Pillow attempts to adjust the width to
@ -108,13 +108,13 @@ def test_fit_same_ratio():
@pytest.mark.parametrize("new_size", ((256, 256), (512, 256), (256, 512)))
def test_contain(new_size):
def test_contain(new_size) -> None:
im = hopper()
new_im = ImageOps.contain(im, new_size)
assert new_im.size == (256, 256)
def test_contain_round():
def test_contain_round() -> None:
im = Image.new("1", (43, 63), 1)
new_im = ImageOps.contain(im, (5, 7))
assert new_im.width == 5
@ -132,13 +132,13 @@ def test_contain_round():
("hopper.png", (256, 256)), # square
),
)
def test_cover(image_name, expected_size):
def test_cover(image_name, expected_size) -> None:
with Image.open("Tests/images/" + image_name) as im:
new_im = ImageOps.cover(im, (256, 256))
assert new_im.size == expected_size
def test_pad():
def test_pad() -> None:
# Same ratio
im = hopper()
new_size = (im.width * 2, im.height * 2)
@ -158,7 +158,7 @@ def test_pad():
)
def test_pad_round():
def test_pad_round() -> None:
im = Image.new("1", (1, 1), 1)
new_im = ImageOps.pad(im, (4, 1))
assert new_im.load()[2, 0] == 1
@ -168,7 +168,7 @@ def test_pad_round():
@pytest.mark.parametrize("mode", ("P", "PA"))
def test_palette(mode):
def test_palette(mode) -> None:
im = hopper(mode)
# Expand
@ -182,7 +182,7 @@ def test_palette(mode):
)
def test_pil163():
def test_pil163() -> None:
# Division by zero in equalize if < 255 pixels in image (@PIL163)
i = hopper("RGB").resize((15, 16))
@ -192,7 +192,7 @@ def test_pil163():
ImageOps.equalize(i.convert("RGB"))
def test_scale():
def test_scale() -> None:
# Test the scaling function
i = hopper("L").resize((50, 50))
@ -210,7 +210,7 @@ def test_scale():
@pytest.mark.parametrize("border", (10, (1, 2, 3, 4)))
def test_expand_palette(border):
def test_expand_palette(border) -> None:
with Image.open("Tests/images/p_16.tga") as im:
im_expanded = ImageOps.expand(im, border, (255, 0, 0))
@ -236,7 +236,7 @@ def test_expand_palette(border):
assert_image_equal(im_cropped, im)
def test_colorize_2color():
def test_colorize_2color() -> None:
# Test the colorizing function with 2-color functionality
# Open test image (256px by 10px, black to white)
@ -270,7 +270,7 @@ def test_colorize_2color():
)
def test_colorize_2color_offset():
def test_colorize_2color_offset() -> None:
# Test the colorizing function with 2-color functionality and offset
# Open test image (256px by 10px, black to white)
@ -306,7 +306,7 @@ def test_colorize_2color_offset():
)
def test_colorize_3color_offset():
def test_colorize_3color_offset() -> None:
# Test the colorizing function with 3-color functionality and offset
# Open test image (256px by 10px, black to white)
@ -359,14 +359,14 @@ def test_colorize_3color_offset():
)
def test_exif_transpose():
def test_exif_transpose() -> None:
exts = [".jpg"]
if features.check("webp") and features.check("webp_anim"):
exts.append(".webp")
for ext in exts:
with Image.open("Tests/images/hopper" + ext) as base_im:
def check(orientation_im):
def check(orientation_im) -> None:
for im in [
orientation_im,
orientation_im.copy(),
@ -423,7 +423,7 @@ def test_exif_transpose():
assert 0x0112 not in transposed_im.getexif()
def test_exif_transpose_in_place():
def test_exif_transpose_in_place() -> None:
with Image.open("Tests/images/orientation_rectangle.jpg") as im:
assert im.size == (2, 1)
assert im.getexif()[0x0112] == 8
@ -435,13 +435,13 @@ def test_exif_transpose_in_place():
assert_image_equal(im, expected)
def test_autocontrast_unsupported_mode():
def test_autocontrast_unsupported_mode() -> None:
im = Image.new("RGBA", (1, 1))
with pytest.raises(OSError):
ImageOps.autocontrast(im)
def test_autocontrast_cutoff():
def test_autocontrast_cutoff() -> None:
# Test the cutoff argument of autocontrast
with Image.open("Tests/images/bw_gradient.png") as img:
@ -452,7 +452,7 @@ def test_autocontrast_cutoff():
assert autocontrast(10) != autocontrast((1, 10))
def test_autocontrast_mask_toy_input():
def test_autocontrast_mask_toy_input() -> None:
# Test the mask argument of autocontrast
with Image.open("Tests/images/bw_gradient.png") as img:
rect_mask = Image.new("L", img.size, 0)
@ -471,7 +471,7 @@ def test_autocontrast_mask_toy_input():
assert ImageStat.Stat(result_nomask).median == [128]
def test_autocontrast_mask_real_input():
def test_autocontrast_mask_real_input() -> None:
# Test the autocontrast with a rectangular mask
with Image.open("Tests/images/iptc.jpg") as img:
rect_mask = Image.new("L", img.size, 0)
@ -498,7 +498,7 @@ def test_autocontrast_mask_real_input():
)
def test_autocontrast_preserve_tone():
def test_autocontrast_preserve_tone() -> None:
def autocontrast(mode, preserve_tone):
im = hopper(mode)
return ImageOps.autocontrast(im, preserve_tone=preserve_tone).histogram()
@ -507,7 +507,7 @@ def test_autocontrast_preserve_tone():
assert autocontrast("L", True) == autocontrast("L", False)
def test_autocontrast_preserve_gradient():
def test_autocontrast_preserve_gradient() -> None:
gradient = Image.linear_gradient("L")
# test with a grayscale gradient that extends to 0,255.
@ -533,7 +533,7 @@ def test_autocontrast_preserve_gradient():
@pytest.mark.parametrize(
"color", ((255, 255, 255), (127, 255, 0), (127, 127, 127), (0, 0, 0))
)
def test_autocontrast_preserve_one_color(color):
def test_autocontrast_preserve_one_color(color) -> None:
img = Image.new("RGB", (10, 10), color)
# single color images shouldn't change

View File

@ -18,7 +18,7 @@ def test_images():
im.close()
def test_filter_api(test_images):
def test_filter_api(test_images) -> None:
im = test_images["im"]
test_filter = ImageFilter.GaussianBlur(2.0)
@ -32,7 +32,7 @@ def test_filter_api(test_images):
assert i.size == (128, 128)
def test_usm_formats(test_images):
def test_usm_formats(test_images) -> None:
im = test_images["im"]
usm = ImageFilter.UnsharpMask
@ -50,7 +50,7 @@ def test_usm_formats(test_images):
im.convert("YCbCr").filter(usm)
def test_blur_formats(test_images):
def test_blur_formats(test_images) -> None:
im = test_images["im"]
blur = ImageFilter.GaussianBlur
@ -68,7 +68,7 @@ def test_blur_formats(test_images):
im.convert("YCbCr").filter(blur)
def test_usm_accuracy(test_images):
def test_usm_accuracy(test_images) -> None:
snakes = test_images["snakes"]
src = snakes.convert("RGB")
@ -77,7 +77,7 @@ def test_usm_accuracy(test_images):
assert i.tobytes() == src.tobytes()
def test_blur_accuracy(test_images):
def test_blur_accuracy(test_images) -> None:
snakes = test_images["snakes"]
i = snakes.filter(ImageFilter.GaussianBlur(0.4))

View File

@ -1,5 +1,7 @@
from __future__ import annotations
from pathlib import Path
import pytest
from PIL import Image, ImagePalette
@ -7,19 +9,19 @@ from PIL import Image, ImagePalette
from .helper import assert_image_equal, assert_image_equal_tofile
def test_sanity():
def test_sanity() -> None:
palette = ImagePalette.ImagePalette("RGB", list(range(256)) * 3)
assert len(palette.colors) == 256
def test_reload():
def test_reload() -> None:
with Image.open("Tests/images/hopper.gif") as im:
original = im.copy()
im.palette.dirty = 1
assert_image_equal(im.convert("RGB"), original.convert("RGB"))
def test_getcolor():
def test_getcolor() -> None:
palette = ImagePalette.ImagePalette()
assert len(palette.palette) == 0
assert len(palette.colors) == 0
@ -46,7 +48,7 @@ def test_getcolor():
palette.getcolor("unknown")
def test_getcolor_rgba_color_rgb_palette():
def test_getcolor_rgba_color_rgb_palette() -> None:
palette = ImagePalette.ImagePalette("RGB")
# Opaque RGBA colors are converted
@ -65,7 +67,7 @@ def test_getcolor_rgba_color_rgb_palette():
(255, ImagePalette.ImagePalette("RGB", list(range(256)) * 3)),
],
)
def test_getcolor_not_special(index, palette):
def test_getcolor_not_special(index, palette) -> None:
im = Image.new("P", (1, 1))
# Do not use transparency index as a new color
@ -79,7 +81,7 @@ def test_getcolor_not_special(index, palette):
assert index2 not in (index, index1)
def test_file(tmp_path):
def test_file(tmp_path: Path) -> None:
palette = ImagePalette.ImagePalette("RGB", list(range(256)) * 3)
f = str(tmp_path / "temp.lut")
@ -97,7 +99,7 @@ def test_file(tmp_path):
assert p.palette == palette.tobytes()
def test_make_linear_lut():
def test_make_linear_lut() -> None:
# Arrange
black = 0
white = 255
@ -113,7 +115,7 @@ def test_make_linear_lut():
assert lut[i] == i
def test_make_linear_lut_not_yet_implemented():
def test_make_linear_lut_not_yet_implemented() -> None:
# Update after FIXME
# Arrange
black = 1
@ -124,7 +126,7 @@ def test_make_linear_lut_not_yet_implemented():
ImagePalette.make_linear_lut(black, white)
def test_make_gamma_lut():
def test_make_gamma_lut() -> None:
# Arrange
exp = 5
@ -142,7 +144,7 @@ def test_make_gamma_lut():
assert lut[255] == 255
def test_rawmode_valueerrors(tmp_path):
def test_rawmode_valueerrors(tmp_path: Path) -> None:
# Arrange
palette = ImagePalette.raw("RGB", list(range(256)) * 3)
@ -156,7 +158,7 @@ def test_rawmode_valueerrors(tmp_path):
palette.save(f)
def test_getdata():
def test_getdata() -> None:
# Arrange
data_in = list(range(256)) * 3
palette = ImagePalette.ImagePalette("RGB", data_in)
@ -168,7 +170,7 @@ def test_getdata():
assert mode == "RGB"
def test_rawmode_getdata():
def test_rawmode_getdata() -> None:
# Arrange
data_in = list(range(256)) * 3
palette = ImagePalette.raw("RGB", data_in)
@ -181,7 +183,7 @@ def test_rawmode_getdata():
assert data_in == data_out
def test_2bit_palette(tmp_path):
def test_2bit_palette(tmp_path: Path) -> None:
# issue #2258, 2 bit palettes are corrupted.
outfile = str(tmp_path / "temp.png")
@ -193,6 +195,6 @@ def test_2bit_palette(tmp_path):
assert_image_equal_tofile(img, outfile)
def test_invalid_palette():
def test_invalid_palette() -> None:
with pytest.raises(OSError):
ImagePalette.load("Tests/images/hopper.jpg")

View File

@ -9,7 +9,7 @@ import pytest
from PIL import Image, ImagePath
def test_path():
def test_path() -> None:
p = ImagePath.Path(list(range(10)))
# sequence interface
@ -57,7 +57,7 @@ def test_path():
ImagePath.Path((0, 1)),
),
)
def test_path_constructors(coords):
def test_path_constructors(coords) -> None:
# Arrange / Act
p = ImagePath.Path(coords)
@ -75,7 +75,7 @@ def test_path_constructors(coords):
[[0.0, 1.0]],
),
)
def test_invalid_path_constructors(coords):
def test_invalid_path_constructors(coords) -> None:
# Act
with pytest.raises(ValueError) as e:
ImagePath.Path(coords)
@ -93,7 +93,7 @@ def test_invalid_path_constructors(coords):
[0, 1, 2],
),
)
def test_path_odd_number_of_coordinates(coords):
def test_path_odd_number_of_coordinates(coords) -> None:
# Act
with pytest.raises(ValueError) as e:
ImagePath.Path(coords)
@ -111,7 +111,7 @@ def test_path_odd_number_of_coordinates(coords):
(1, (0.0, 0.0, 0.0, 0.0)),
],
)
def test_getbbox(coords, expected):
def test_getbbox(coords, expected) -> None:
# Arrange
p = ImagePath.Path(coords)
@ -119,7 +119,7 @@ def test_getbbox(coords, expected):
assert p.getbbox() == expected
def test_getbbox_no_args():
def test_getbbox_no_args() -> None:
# Arrange
p = ImagePath.Path([0, 1, 2, 3])
@ -135,7 +135,7 @@ def test_getbbox_no_args():
(list(range(6)), [(0.0, 3.0), (4.0, 9.0), (8.0, 15.0)]),
],
)
def test_map(coords, expected):
def test_map(coords, expected) -> None:
# Arrange
p = ImagePath.Path(coords)
@ -147,7 +147,7 @@ def test_map(coords, expected):
assert list(p) == expected
def test_transform():
def test_transform() -> None:
# Arrange
p = ImagePath.Path([0, 1, 2, 3])
theta = math.pi / 15
@ -165,7 +165,7 @@ def test_transform():
]
def test_transform_with_wrap():
def test_transform_with_wrap() -> None:
# Arrange
p = ImagePath.Path([0, 1, 2, 3])
theta = math.pi / 15
@ -184,7 +184,7 @@ def test_transform_with_wrap():
]
def test_overflow_segfault():
def test_overflow_segfault() -> None:
# Some Pythons fail getting the argument as an integer, and it falls
# through to the sequence. Seeing this on 32-bit Windows.
with pytest.raises((TypeError, MemoryError)):
@ -198,12 +198,12 @@ def test_overflow_segfault():
class Evil:
def __init__(self):
def __init__(self) -> None:
self.corrupt = Image.core.path(0x4000000000000000)
def __getitem__(self, i):
x = self.corrupt[i]
return struct.pack("dd", x[0], x[1])
def __setitem__(self, i, x):
def __setitem__(self, i, x) -> None:
self.corrupt[i] = struct.unpack("dd", x)

View File

@ -16,7 +16,7 @@ if ImageQt.qt_is_installed:
from PIL.ImageQt import qRgba
def test_rgb():
def test_rgb() -> None:
# from https://doc.qt.io/archives/qt-4.8/qcolor.html
# typedef QRgb
# An ARGB quadruplet on the format #AARRGGBB,
@ -28,7 +28,7 @@ def test_rgb():
assert qRgb(0, 0, 0) == qRgba(0, 0, 0, 255)
def checkrgb(r, g, b):
def checkrgb(r, g, b) -> None:
val = ImageQt.rgb(r, g, b)
val = val % 2**24 # drop the alpha
assert val >> 16 == r
@ -41,7 +41,7 @@ def test_rgb():
checkrgb(0, 0, 255)
def test_image():
def test_image() -> None:
modes = ["1", "RGB", "RGBA", "L", "P"]
qt_format = ImageQt.QImage.Format if ImageQt.qt_version == "6" else ImageQt.QImage
if hasattr(qt_format, "Format_Grayscale16"): # Qt 5.13+
@ -55,6 +55,6 @@ def test_image():
assert_image_similar(roundtripped_im, im, 1)
def test_closed_file():
def test_closed_file() -> None:
with warnings.catch_warnings():
ImageQt.ImageQt("Tests/images/hopper.gif")

View File

@ -1,5 +1,7 @@
from __future__ import annotations
from pathlib import Path
import pytest
from PIL import Image, ImageSequence, TiffImagePlugin
@ -7,7 +9,7 @@ from PIL import Image, ImageSequence, TiffImagePlugin
from .helper import assert_image_equal, hopper, skip_unless_feature
def test_sanity(tmp_path):
def test_sanity(tmp_path: Path) -> None:
test_file = str(tmp_path / "temp.im")
im = hopper("RGB")
@ -27,7 +29,7 @@ def test_sanity(tmp_path):
ImageSequence.Iterator(0)
def test_iterator():
def test_iterator() -> None:
with Image.open("Tests/images/multipage.tiff") as im:
i = ImageSequence.Iterator(im)
for index in range(0, im.n_frames):
@ -38,14 +40,14 @@ def test_iterator():
next(i)
def test_iterator_min_frame():
def test_iterator_min_frame() -> None:
with Image.open("Tests/images/hopper.psd") as im:
i = ImageSequence.Iterator(im)
for index in range(1, im.n_frames):
assert i[index] == next(i)
def _test_multipage_tiff():
def _test_multipage_tiff() -> None:
with Image.open("Tests/images/multipage.tiff") as im:
for index, frame in enumerate(ImageSequence.Iterator(im)):
frame.load()
@ -53,18 +55,18 @@ def _test_multipage_tiff():
frame.convert("RGB")
def test_tiff():
def test_tiff() -> None:
_test_multipage_tiff()
@skip_unless_feature("libtiff")
def test_libtiff():
def test_libtiff() -> None:
TiffImagePlugin.READ_LIBTIFF = True
_test_multipage_tiff()
TiffImagePlugin.READ_LIBTIFF = False
def test_consecutive():
def test_consecutive() -> None:
with Image.open("Tests/images/multipage.tiff") as im:
first_frame = None
for frame in ImageSequence.Iterator(im):
@ -75,7 +77,7 @@ def test_consecutive():
break
def test_palette_mmap():
def test_palette_mmap() -> None:
# Using mmap in ImageFile can require to reload the palette.
with Image.open("Tests/images/multipage-mmap.tiff") as im:
color1 = im.getpalette()[:3]
@ -84,7 +86,7 @@ def test_palette_mmap():
assert color1 == color2
def test_all_frames():
def test_all_frames() -> None:
# Test a single image
with Image.open("Tests/images/iss634.gif") as im:
ims = ImageSequence.all_frames(im)

View File

@ -7,12 +7,12 @@ from PIL import Image, ImageShow
from .helper import hopper, is_win32, on_ci
def test_sanity():
def test_sanity() -> None:
dir(Image)
dir(ImageShow)
def test_register():
def test_register() -> None:
# Test registering a viewer that is not a class
ImageShow.register("not a class")
@ -24,9 +24,9 @@ def test_register():
"order",
[-1, 0],
)
def test_viewer_show(order):
def test_viewer_show(order) -> None:
class TestViewer(ImageShow.Viewer):
def show_image(self, image, **options):
def show_image(self, image, **options) -> bool:
self.methodCalled = True
return True
@ -48,12 +48,12 @@ def test_viewer_show(order):
reason="Only run on CIs; hangs on Windows CIs",
)
@pytest.mark.parametrize("mode", ("1", "I;16", "LA", "RGB", "RGBA"))
def test_show(mode):
def test_show(mode) -> None:
im = hopper(mode)
assert ImageShow.show(im)
def test_show_without_viewers():
def test_show_without_viewers() -> None:
viewers = ImageShow._viewers
ImageShow._viewers = []
@ -63,7 +63,7 @@ def test_show_without_viewers():
ImageShow._viewers = viewers
def test_viewer():
def test_viewer() -> None:
viewer = ImageShow.Viewer()
assert viewer.get_format(None) is None
@ -73,14 +73,14 @@ def test_viewer():
@pytest.mark.parametrize("viewer", ImageShow._viewers)
def test_viewers(viewer):
def test_viewers(viewer) -> None:
try:
viewer.get_command("test.jpg")
except NotImplementedError:
pass
def test_ipythonviewer():
def test_ipythonviewer() -> None:
pytest.importorskip("IPython", reason="IPython not installed")
for viewer in ImageShow._viewers:
if isinstance(viewer, ImageShow.IPythonViewer):

View File

@ -7,7 +7,7 @@ from PIL import Image, ImageStat
from .helper import hopper
def test_sanity():
def test_sanity() -> None:
im = hopper()
st = ImageStat.Stat(im)
@ -31,7 +31,7 @@ def test_sanity():
ImageStat.Stat(1)
def test_hopper():
def test_hopper() -> None:
im = hopper()
st = ImageStat.Stat(im)
@ -44,7 +44,7 @@ def test_hopper():
assert st.sum[2] == 1563008
def test_constant():
def test_constant() -> None:
im = Image.new("L", (128, 128), 128)
st = ImageStat.Stat(im)

View File

@ -23,7 +23,7 @@ TK_MODES = ("1", "L", "P", "RGB", "RGBA")
pytestmark = pytest.mark.skipif(not HAS_TK, reason="Tk not installed")
def setup_module():
def setup_module() -> None:
try:
# setup tk
tk.Frame()
@ -34,7 +34,7 @@ def setup_module():
pytest.skip(f"TCL Error: {v}")
def test_kw():
def test_kw() -> None:
TEST_JPG = "Tests/images/hopper.jpg"
TEST_PNG = "Tests/images/hopper.png"
with Image.open(TEST_JPG) as im1:
@ -57,7 +57,7 @@ def test_kw():
@pytest.mark.parametrize("mode", TK_MODES)
def test_photoimage(mode):
def test_photoimage(mode) -> None:
# test as image:
im = hopper(mode)
@ -71,7 +71,7 @@ def test_photoimage(mode):
assert_image_equal(reloaded, im.convert("RGBA"))
def test_photoimage_apply_transparency():
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)
@ -79,7 +79,7 @@ def test_photoimage_apply_transparency():
@pytest.mark.parametrize("mode", TK_MODES)
def test_photoimage_blank(mode):
def test_photoimage_blank(mode) -> None:
# test a image using mode/size:
im_tk = ImageTk.PhotoImage(mode, (100, 100))
@ -91,7 +91,7 @@ def test_photoimage_blank(mode):
assert_image_equal(reloaded.convert(mode), im)
def test_bitmapimage():
def test_bitmapimage() -> None:
im = hopper("1")
# this should not crash

View File

@ -8,10 +8,10 @@ from .helper import hopper, is_win32
class TestImageWin:
def test_sanity(self):
def test_sanity(self) -> None:
dir(ImageWin)
def test_hdc(self):
def test_hdc(self) -> None:
# Arrange
dc = 50
@ -22,7 +22,7 @@ class TestImageWin:
# Assert
assert dc2 == 50
def test_hwnd(self):
def test_hwnd(self) -> None:
# Arrange
wnd = 50
@ -36,7 +36,7 @@ class TestImageWin:
@pytest.mark.skipif(not is_win32(), reason="Windows only")
class TestImageWinDib:
def test_dib_image(self):
def test_dib_image(self) -> None:
# Arrange
im = hopper()
@ -46,7 +46,7 @@ class TestImageWinDib:
# Assert
assert dib.size == im.size
def test_dib_mode_string(self):
def test_dib_mode_string(self) -> None:
# Arrange
mode = "RGBA"
size = (128, 128)
@ -57,7 +57,7 @@ class TestImageWinDib:
# Assert
assert dib.size == (128, 128)
def test_dib_paste(self):
def test_dib_paste(self) -> None:
# Arrange
im = hopper()
@ -71,7 +71,7 @@ class TestImageWinDib:
# Assert
assert dib.size == (128, 128)
def test_dib_paste_bbox(self):
def test_dib_paste_bbox(self) -> None:
# Arrange
im = hopper()
bbox = (0, 0, 10, 10)
@ -86,7 +86,7 @@ class TestImageWinDib:
# Assert
assert dib.size == (128, 128)
def test_dib_frombytes_tobytes_roundtrip(self):
def test_dib_frombytes_tobytes_roundtrip(self) -> None:
# Arrange
# Make two different DIB images
im = hopper()

View File

@ -1,6 +1,7 @@
from __future__ import annotations
from io import BytesIO
from pathlib import Path
from PIL import Image, ImageWin
@ -83,7 +84,7 @@ if is_win32():
memcpy(bp + bf.bfOffBits, pixels, bi.biSizeImage)
return bytearray(buf)
def test_pointer(tmp_path):
def test_pointer(tmp_path: Path) -> None:
im = hopper()
(width, height) = im.size
opath = str(tmp_path / "temp.png")

View File

@ -10,7 +10,7 @@ X = 255
class TestLibPack:
def assert_pack(self, mode, rawmode, data, *pixels):
def assert_pack(self, mode, rawmode, data, *pixels) -> None:
"""
data - either raw bytes with data or just number of bytes in rawmode.
"""
@ -24,7 +24,7 @@ class TestLibPack:
assert data == im.tobytes("raw", rawmode)
def test_1(self):
def test_1(self) -> None:
self.assert_pack("1", "1", b"\x01", 0, 0, 0, 0, 0, 0, 0, X)
self.assert_pack("1", "1;I", b"\x01", X, X, X, X, X, X, X, 0)
self.assert_pack("1", "1;R", b"\x01", X, 0, 0, 0, 0, 0, 0, 0)
@ -37,29 +37,29 @@ class TestLibPack:
self.assert_pack("1", "L", b"\xff\x00\x00\xff\x00\x00", X, 0, 0, X, 0, 0)
def test_L(self):
def test_L(self) -> None:
self.assert_pack("L", "L", 1, 1, 2, 3, 4)
self.assert_pack("L", "L;16", b"\x00\xc6\x00\xaf", 198, 175)
self.assert_pack("L", "L;16B", b"\xc6\x00\xaf\x00", 198, 175)
def test_LA(self):
def test_LA(self) -> None:
self.assert_pack("LA", "LA", 2, (1, 2), (3, 4), (5, 6))
self.assert_pack("LA", "LA;L", 2, (1, 4), (2, 5), (3, 6))
def test_La(self):
def test_La(self) -> None:
self.assert_pack("La", "La", 2, (1, 2), (3, 4), (5, 6))
def test_P(self):
def test_P(self) -> None:
self.assert_pack("P", "P;1", b"\xe4", 1, 1, 1, 0, 0, 255, 0, 0)
self.assert_pack("P", "P;2", b"\xe4", 3, 2, 1, 0)
self.assert_pack("P", "P;4", b"\x02\xef", 0, 2, 14, 15)
self.assert_pack("P", "P", 1, 1, 2, 3, 4)
def test_PA(self):
def test_PA(self) -> None:
self.assert_pack("PA", "PA", 2, (1, 2), (3, 4), (5, 6))
self.assert_pack("PA", "PA;L", 2, (1, 4), (2, 5), (3, 6))
def test_RGB(self):
def test_RGB(self) -> None:
self.assert_pack("RGB", "RGB", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9))
self.assert_pack(
"RGB", "RGBX", b"\x01\x02\x03\xff\x05\x06\x07\xff", (1, 2, 3), (5, 6, 7)
@ -79,7 +79,7 @@ class TestLibPack:
self.assert_pack("RGB", "G", 1, (9, 1, 9), (9, 2, 9), (9, 3, 9))
self.assert_pack("RGB", "B", 1, (9, 9, 1), (9, 9, 2), (9, 9, 3))
def test_RGBA(self):
def test_RGBA(self) -> None:
self.assert_pack("RGBA", "RGBA", 4, (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12))
self.assert_pack(
"RGBA", "RGBA;L", 4, (1, 4, 7, 10), (2, 5, 8, 11), (3, 6, 9, 12)
@ -101,12 +101,12 @@ class TestLibPack:
self.assert_pack("RGBA", "B", 1, (6, 7, 1, 9), (6, 7, 2, 0), (6, 7, 3, 9))
self.assert_pack("RGBA", "A", 1, (6, 7, 0, 1), (6, 7, 0, 2), (0, 7, 0, 3))
def test_RGBa(self):
def test_RGBa(self) -> None:
self.assert_pack("RGBa", "RGBa", 4, (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12))
self.assert_pack("RGBa", "BGRa", 4, (3, 2, 1, 4), (7, 6, 5, 8), (11, 10, 9, 12))
self.assert_pack("RGBa", "aBGR", 4, (4, 3, 2, 1), (8, 7, 6, 5), (12, 11, 10, 9))
def test_RGBX(self):
def test_RGBX(self) -> None:
self.assert_pack("RGBX", "RGBX", 4, (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12))
self.assert_pack(
"RGBX", "RGBX;L", 4, (1, 4, 7, 10), (2, 5, 8, 11), (3, 6, 9, 12)
@ -134,7 +134,7 @@ class TestLibPack:
self.assert_pack("RGBX", "B", 1, (6, 7, 1, 9), (6, 7, 2, 0), (6, 7, 3, 9))
self.assert_pack("RGBX", "X", 1, (6, 7, 0, 1), (6, 7, 0, 2), (0, 7, 0, 3))
def test_CMYK(self):
def test_CMYK(self) -> None:
self.assert_pack("CMYK", "CMYK", 4, (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12))
self.assert_pack(
"CMYK",
@ -149,7 +149,7 @@ class TestLibPack:
)
self.assert_pack("CMYK", "K", 1, (6, 7, 0, 1), (6, 7, 0, 2), (0, 7, 0, 3))
def test_YCbCr(self):
def test_YCbCr(self) -> None:
self.assert_pack("YCbCr", "YCbCr", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9))
self.assert_pack("YCbCr", "YCbCr;L", 3, (1, 4, 7), (2, 5, 8), (3, 6, 9))
self.assert_pack(
@ -172,19 +172,19 @@ class TestLibPack:
self.assert_pack("YCbCr", "Cb", 1, (6, 1, 8, 9), (6, 2, 8, 9), (6, 3, 8, 9))
self.assert_pack("YCbCr", "Cr", 1, (6, 7, 1, 9), (6, 7, 2, 0), (6, 7, 3, 9))
def test_LAB(self):
def test_LAB(self) -> None:
self.assert_pack("LAB", "LAB", 3, (1, 130, 131), (4, 133, 134), (7, 136, 137))
self.assert_pack("LAB", "L", 1, (1, 9, 9), (2, 9, 9), (3, 9, 9))
self.assert_pack("LAB", "A", 1, (9, 1, 9), (9, 2, 9), (9, 3, 9))
self.assert_pack("LAB", "B", 1, (9, 9, 1), (9, 9, 2), (9, 9, 3))
def test_HSV(self):
def test_HSV(self) -> None:
self.assert_pack("HSV", "HSV", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9))
self.assert_pack("HSV", "H", 1, (1, 9, 9), (2, 9, 9), (3, 9, 9))
self.assert_pack("HSV", "S", 1, (9, 1, 9), (9, 2, 9), (9, 3, 9))
self.assert_pack("HSV", "V", 1, (9, 9, 1), (9, 9, 2), (9, 9, 3))
def test_I(self):
def test_I(self) -> None:
self.assert_pack("I", "I;16B", 2, 0x0102, 0x0304)
self.assert_pack(
"I", "I;32S", b"\x83\x00\x00\x01\x01\x00\x00\x83", 0x01000083, -2097151999
@ -209,10 +209,10 @@ class TestLibPack:
0x01000083,
)
def test_I16(self):
def test_I16(self) -> None:
self.assert_pack("I;16N", "I;16N", 2, 0x0201, 0x0403, 0x0605)
def test_F_float(self):
def test_F_float(self) -> None:
self.assert_pack("F", "F;32F", 4, 1.539989614439558e-36, 4.063216068939723e-34)
if sys.byteorder == "little":
@ -228,7 +228,7 @@ class TestLibPack:
class TestLibUnpack:
def assert_unpack(self, mode, rawmode, data, *pixels):
def assert_unpack(self, mode, rawmode, data, *pixels) -> None:
"""
data - either raw bytes with data or just number of bytes in rawmode.
"""
@ -241,7 +241,7 @@ class TestLibUnpack:
for x, pixel in enumerate(pixels):
assert pixel == im.getpixel((x, 0))
def test_1(self):
def test_1(self) -> None:
self.assert_unpack("1", "1", b"\x01", 0, 0, 0, 0, 0, 0, 0, X)
self.assert_unpack("1", "1;I", b"\x01", X, X, X, X, X, X, X, 0)
self.assert_unpack("1", "1;R", b"\x01", X, 0, 0, 0, 0, 0, 0, 0)
@ -254,7 +254,7 @@ class TestLibUnpack:
self.assert_unpack("1", "1;8", b"\x00\x01\x02\xff", 0, X, X, X)
def test_L(self):
def test_L(self) -> None:
self.assert_unpack("L", "L;2", b"\xe4", 255, 170, 85, 0)
self.assert_unpack("L", "L;2I", b"\xe4", 0, 85, 170, 255)
self.assert_unpack("L", "L;2R", b"\xe4", 0, 170, 85, 255)
@ -273,14 +273,14 @@ class TestLibUnpack:
self.assert_unpack("L", "L;16", b"\x00\xc6\x00\xaf", 198, 175)
self.assert_unpack("L", "L;16B", b"\xc6\x00\xaf\x00", 198, 175)
def test_LA(self):
def test_LA(self) -> None:
self.assert_unpack("LA", "LA", 2, (1, 2), (3, 4), (5, 6))
self.assert_unpack("LA", "LA;L", 2, (1, 4), (2, 5), (3, 6))
def test_La(self):
def test_La(self) -> None:
self.assert_unpack("La", "La", 2, (1, 2), (3, 4), (5, 6))
def test_P(self):
def test_P(self) -> None:
self.assert_unpack("P", "P;1", b"\xe4", 1, 1, 1, 0, 0, 1, 0, 0)
self.assert_unpack("P", "P;2", b"\xe4", 3, 2, 1, 0)
# erroneous?
@ -291,11 +291,11 @@ class TestLibUnpack:
self.assert_unpack("P", "P", 1, 1, 2, 3, 4)
self.assert_unpack("P", "P;R", 1, 128, 64, 192, 32)
def test_PA(self):
def test_PA(self) -> None:
self.assert_unpack("PA", "PA", 2, (1, 2), (3, 4), (5, 6))
self.assert_unpack("PA", "PA;L", 2, (1, 4), (2, 5), (3, 6))
def test_RGB(self):
def test_RGB(self) -> None:
self.assert_unpack("RGB", "RGB", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9))
self.assert_unpack("RGB", "RGB;L", 3, (1, 4, 7), (2, 5, 8), (3, 6, 9))
self.assert_unpack("RGB", "RGB;R", 3, (128, 64, 192), (32, 160, 96))
@ -346,14 +346,14 @@ class TestLibUnpack:
"RGB", "CMYK", 4, (250, 249, 248), (242, 241, 240), (234, 233, 233)
)
def test_BGR(self):
def test_BGR(self) -> None:
self.assert_unpack("BGR;15", "BGR;15", 3, (8, 131, 0), (24, 0, 8), (41, 131, 8))
self.assert_unpack(
"BGR;16", "BGR;16", 3, (8, 64, 0), (24, 129, 0), (41, 194, 0)
)
self.assert_unpack("BGR;24", "BGR;24", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9))
def test_RGBA(self):
def test_RGBA(self) -> None:
self.assert_unpack("RGBA", "LA", 2, (1, 1, 1, 2), (3, 3, 3, 4), (5, 5, 5, 6))
self.assert_unpack(
"RGBA", "LA;16B", 4, (1, 1, 1, 3), (5, 5, 5, 7), (9, 9, 9, 11)
@ -522,7 +522,7 @@ class TestLibUnpack:
"RGBA", "A;16N", 2, (0, 0, 0, 1), (0, 0, 0, 3), (0, 0, 0, 5)
)
def test_RGBa(self):
def test_RGBa(self) -> None:
self.assert_unpack(
"RGBa", "RGBa", 4, (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)
)
@ -536,7 +536,7 @@ class TestLibUnpack:
"RGBa", "aBGR", 4, (4, 3, 2, 1), (8, 7, 6, 5), (12, 11, 10, 9)
)
def test_RGBX(self):
def test_RGBX(self) -> None:
self.assert_unpack("RGBX", "RGB", 3, (1, 2, 3, X), (4, 5, 6, X), (7, 8, 9, X))
self.assert_unpack("RGBX", "RGB;L", 3, (1, 4, 7, X), (2, 5, 8, X), (3, 6, 9, X))
self.assert_unpack("RGBX", "RGB;16B", 6, (1, 3, 5, X), (7, 9, 11, X))
@ -581,7 +581,7 @@ class TestLibUnpack:
self.assert_unpack("RGBX", "B", 1, (0, 0, 1, 0), (0, 0, 2, 0), (0, 0, 3, 0))
self.assert_unpack("RGBX", "X", 1, (0, 0, 0, 1), (0, 0, 0, 2), (0, 0, 0, 3))
def test_CMYK(self):
def test_CMYK(self) -> None:
self.assert_unpack(
"CMYK", "CMYK", 4, (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)
)
@ -619,25 +619,25 @@ class TestLibUnpack:
"CMYK", "K;I", 1, (0, 0, 0, 254), (0, 0, 0, 253), (0, 0, 0, 252)
)
def test_YCbCr(self):
def test_YCbCr(self) -> None:
self.assert_unpack("YCbCr", "YCbCr", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9))
self.assert_unpack("YCbCr", "YCbCr;L", 3, (1, 4, 7), (2, 5, 8), (3, 6, 9))
self.assert_unpack("YCbCr", "YCbCrK", 4, (1, 2, 3), (5, 6, 7), (9, 10, 11))
self.assert_unpack("YCbCr", "YCbCrX", 4, (1, 2, 3), (5, 6, 7), (9, 10, 11))
def test_LAB(self):
def test_LAB(self) -> None:
self.assert_unpack("LAB", "LAB", 3, (1, 130, 131), (4, 133, 134), (7, 136, 137))
self.assert_unpack("LAB", "L", 1, (1, 0, 0), (2, 0, 0), (3, 0, 0))
self.assert_unpack("LAB", "A", 1, (0, 1, 0), (0, 2, 0), (0, 3, 0))
self.assert_unpack("LAB", "B", 1, (0, 0, 1), (0, 0, 2), (0, 0, 3))
def test_HSV(self):
def test_HSV(self) -> None:
self.assert_unpack("HSV", "HSV", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9))
self.assert_unpack("HSV", "H", 1, (1, 0, 0), (2, 0, 0), (3, 0, 0))
self.assert_unpack("HSV", "S", 1, (0, 1, 0), (0, 2, 0), (0, 3, 0))
self.assert_unpack("HSV", "V", 1, (0, 0, 1), (0, 0, 2), (0, 0, 3))
def test_I(self):
def test_I(self) -> None:
self.assert_unpack("I", "I;8", 1, 0x01, 0x02, 0x03, 0x04)
self.assert_unpack("I", "I;8S", b"\x01\x83", 1, -125)
self.assert_unpack("I", "I;16", 2, 0x0201, 0x0403)
@ -678,7 +678,7 @@ class TestLibUnpack:
0x01000083,
)
def test_F_int(self):
def test_F_int(self) -> None:
self.assert_unpack("F", "F;8", 1, 0x01, 0x02, 0x03, 0x04)
self.assert_unpack("F", "F;8S", b"\x01\x83", 1, -125)
self.assert_unpack("F", "F;16", 2, 0x0201, 0x0403)
@ -717,7 +717,7 @@ class TestLibUnpack:
16777348,
)
def test_F_float(self):
def test_F_float(self) -> None:
self.assert_unpack(
"F", "F;32F", 4, 1.539989614439558e-36, 4.063216068939723e-34
)
@ -768,7 +768,7 @@ class TestLibUnpack:
-1234.5,
)
def test_I16(self):
def test_I16(self) -> None:
self.assert_unpack("I;16", "I;16", 2, 0x0201, 0x0403, 0x0605)
self.assert_unpack("I;16", "I;16B", 2, 0x0102, 0x0304, 0x0506)
self.assert_unpack("I;16B", "I;16B", 2, 0x0102, 0x0304, 0x0506)
@ -785,7 +785,7 @@ class TestLibUnpack:
self.assert_unpack("I;16L", "I;16N", 2, 0x0102, 0x0304, 0x0506)
self.assert_unpack("I;16N", "I;16N", 2, 0x0102, 0x0304, 0x0506)
def test_CMYK16(self):
def test_CMYK16(self) -> None:
self.assert_unpack("CMYK", "CMYK;16L", 8, (2, 4, 6, 8), (10, 12, 14, 16))
self.assert_unpack("CMYK", "CMYK;16B", 8, (1, 3, 5, 7), (9, 11, 13, 15))
if sys.byteorder == "little":
@ -793,7 +793,7 @@ class TestLibUnpack:
else:
self.assert_unpack("CMYK", "CMYK;16N", 8, (1, 3, 5, 7), (9, 11, 13, 15))
def test_value_error(self):
def test_value_error(self) -> None:
with pytest.raises(ValueError):
self.assert_unpack("L", "L", 0, 0)
with pytest.raises(ValueError):

View File

@ -7,7 +7,7 @@ import pytest
from PIL import Image
def test_overflow():
def test_overflow() -> None:
# There is the potential to overflow comparisons in map.c
# if there are > SIZE_MAX bytes in the image or if
# the file encodes an offset that makes
@ -25,7 +25,7 @@ def test_overflow():
Image.MAX_IMAGE_PIXELS = max_pixels
def test_tobytes():
def test_tobytes() -> None:
# Note that this image triggers the decompression bomb warning:
max_pixels = Image.MAX_IMAGE_PIXELS
Image.MAX_IMAGE_PIXELS = None
@ -39,7 +39,7 @@ def test_tobytes():
@pytest.mark.skipif(sys.maxsize <= 2**32, reason="Requires 64-bit system")
def test_ysize():
def test_ysize() -> None:
numpy = pytest.importorskip("numpy", reason="NumPy not installed")
# Should not raise 'Integer overflow in ysize'

View File

@ -1,5 +1,7 @@
from __future__ import annotations
from pathlib import Path
import pytest
from PIL import Image
@ -9,7 +11,7 @@ from .helper import hopper
original = hopper().resize((32, 32)).convert("I")
def verify(im1):
def verify(im1) -> None:
im2 = original.copy()
assert im1.size == im2.size
pix1 = im1.load()
@ -25,7 +27,7 @@ def verify(im1):
@pytest.mark.parametrize("mode", ("L", "I;16", "I;16B", "I;16L", "I"))
def test_basic(tmp_path, mode):
def test_basic(tmp_path: Path, mode) -> None:
# PIL 1.1 has limited support for 16-bit image data. Check that
# create/copy/transform and save works as expected.
@ -75,7 +77,7 @@ def test_basic(tmp_path, mode):
assert im_in.getpixel((0, 0)) == min(512, maximum)
def test_tobytes():
def test_tobytes() -> None:
def tobytes(mode):
return Image.new(mode, (1, 1), 1).tobytes()
@ -87,7 +89,7 @@ def test_tobytes():
assert tobytes("I") == b"\x01\x00\x00\x00"[::order]
def test_convert():
def test_convert() -> None:
im = original.copy()
for mode in ("I;16", "I;16B", "I;16N"):

View File

@ -13,8 +13,8 @@ numpy = pytest.importorskip("numpy", reason="NumPy not installed")
TEST_IMAGE_SIZE = (10, 10)
def test_numpy_to_image():
def to_image(dtype, bands=1, boolean=0):
def test_numpy_to_image() -> None:
def to_image(dtype, bands: int = 1, boolean: int = 0):
if bands == 1:
if boolean:
data = [0, 255] * 50
@ -82,7 +82,7 @@ def test_numpy_to_image():
# Based on an erring example at
# https://stackoverflow.com/questions/10854903/what-is-causing-dimension-dependent-attributeerror-in-pil-fromarray-function
def test_3d_array():
def test_3d_array() -> None:
size = (5, TEST_IMAGE_SIZE[0], TEST_IMAGE_SIZE[1])
a = numpy.ones(size, dtype=numpy.uint8)
assert_image(Image.fromarray(a[1, :, :]), "L", TEST_IMAGE_SIZE)
@ -94,12 +94,12 @@ def test_3d_array():
assert_image(Image.fromarray(a[:, :, 1]), "L", TEST_IMAGE_SIZE)
def test_1d_array():
def test_1d_array() -> None:
a = numpy.ones(5, dtype=numpy.uint8)
assert_image(Image.fromarray(a), "L", (1, 5))
def _test_img_equals_nparray(img, np):
def _test_img_equals_nparray(img, np) -> None:
assert len(np.shape) >= 2
np_size = np.shape[1], np.shape[0]
assert img.size == np_size
@ -109,14 +109,14 @@ def _test_img_equals_nparray(img, np):
assert_deep_equal(px[x, y], np[y, x])
def test_16bit():
def test_16bit() -> None:
with Image.open("Tests/images/16bit.cropped.tif") as img:
np_img = numpy.array(img)
_test_img_equals_nparray(img, np_img)
assert np_img.dtype == numpy.dtype("<u2")
def test_1bit():
def test_1bit() -> None:
# Test that 1-bit arrays convert to numpy and back
# See: https://github.com/python-pillow/Pillow/issues/350
arr = numpy.array([[1, 0, 0, 1, 0], [0, 1, 0, 0, 0]], "u1")
@ -126,7 +126,7 @@ def test_1bit():
numpy.testing.assert_array_equal(arr, arr_back)
def test_save_tiff_uint16():
def test_save_tiff_uint16() -> None:
# Tests that we're getting the pixel value in the right byte order.
pixel_value = 0x1234
a = numpy.array(
@ -157,7 +157,7 @@ def test_save_tiff_uint16():
("HSV", numpy.uint8),
),
)
def test_to_array(mode, dtype):
def test_to_array(mode, dtype) -> None:
img = hopper(mode)
# Resize to non-square
@ -169,7 +169,7 @@ def test_to_array(mode, dtype):
assert np_img.dtype == dtype
def test_point_lut():
def test_point_lut() -> None:
# See https://github.com/python-pillow/Pillow/issues/439
data = list(range(256)) * 3
@ -180,7 +180,7 @@ def test_point_lut():
im.point(lut)
def test_putdata():
def test_putdata() -> None:
# Shouldn't segfault
# See https://github.com/python-pillow/Pillow/issues/1008
@ -207,12 +207,12 @@ def test_putdata():
numpy.float64,
),
)
def test_roundtrip_eye(dtype):
def test_roundtrip_eye(dtype) -> None:
arr = numpy.eye(10, dtype=dtype)
numpy.testing.assert_array_equal(arr, numpy.array(Image.fromarray(arr)))
def test_zero_size():
def test_zero_size() -> None:
# Shouldn't cause floating point exception
# See https://github.com/python-pillow/Pillow/issues/2259
@ -222,13 +222,13 @@ def test_zero_size():
@skip_unless_feature("libtiff")
def test_load_first():
def test_load_first() -> None:
with Image.open("Tests/images/g4_orientation_5.tif") as im:
a = numpy.array(im)
assert a.shape == (88, 590)
def test_bool():
def test_bool() -> None:
# https://github.com/python-pillow/Pillow/issues/2044
a = numpy.zeros((10, 2), dtype=bool)
a[0][0] = True
@ -237,7 +237,7 @@ def test_bool():
assert im2.getdata()[0] == 255
def test_no_resource_warning_for_numpy_array():
def test_no_resource_warning_for_numpy_array() -> None:
# https://github.com/python-pillow/Pillow/issues/835
# Arrange
from numpy import array

Some files were not shown because too many files have changed in this diff Show More