Skip to content

Commit

Permalink
Merge pull request #7732 from radarhere/type_hints_check
Browse files Browse the repository at this point in the history
Added type hints to Tests/check_*.py
  • Loading branch information
radarhere committed Jan 21, 2024
2 parents 1891b61 + 3453a99 commit 9c98162
Show file tree
Hide file tree
Showing 10 changed files with 39 additions and 27 deletions.
2 changes: 1 addition & 1 deletion Tests/check_fli_overflow.py
Expand Up @@ -5,7 +5,7 @@
TEST_FILE = "Tests/images/fli_overflow.fli"


def test_fli_overflow():
def test_fli_overflow() -> None:
# this should not crash with a malloc error or access violation
with Image.open(TEST_FILE) as im:
im.load()
15 changes: 10 additions & 5 deletions Tests/check_imaging_leaks.py
@@ -1,6 +1,8 @@
#!/usr/bin/env python3
from __future__ import annotations

from typing import Any, Callable

import pytest

from PIL import Image
Expand All @@ -13,31 +15,34 @@
pytestmark = pytest.mark.skipif(is_win32(), reason="requires Unix or macOS")


def _get_mem_usage():
def _get_mem_usage() -> float:
from resource import RUSAGE_SELF, getpagesize, getrusage

mem = getrusage(RUSAGE_SELF).ru_maxrss
return mem * getpagesize() / 1024 / 1024


def _test_leak(min_iterations, max_iterations, fn, *args, **kwargs):
def _test_leak(
min_iterations: int, max_iterations: int, fn: Callable[..., None], *args: Any
) -> None:
mem_limit = None
for i in range(max_iterations):
fn(*args, **kwargs)
fn(*args)
mem = _get_mem_usage()
if i < min_iterations:
mem_limit = mem + 1
continue
msg = f"memory usage limit exceeded after {i + 1} iterations"
assert mem_limit is not None
assert mem <= mem_limit, msg


def test_leak_putdata():
def test_leak_putdata() -> None:
im = Image.new("RGB", (25, 25))
_test_leak(min_iterations, max_iterations, im.putdata, im.getdata())


def test_leak_getlist():
def test_leak_getlist() -> None:
im = Image.new("P", (25, 25))
_test_leak(
min_iterations,
Expand Down
4 changes: 2 additions & 2 deletions Tests/check_j2k_leaks.py
Expand Up @@ -20,7 +20,7 @@
]


def test_leak_load():
def test_leak_load() -> None:
from resource import RLIMIT_AS, RLIMIT_STACK, setrlimit

setrlimit(RLIMIT_STACK, (stack_size, stack_size))
Expand All @@ -30,7 +30,7 @@ def test_leak_load():
im.load()


def test_leak_save():
def test_leak_save() -> None:
from resource import RLIMIT_AS, RLIMIT_STACK, setrlimit

setrlimit(RLIMIT_STACK, (stack_size, stack_size))
Expand Down
4 changes: 3 additions & 1 deletion Tests/check_j2k_overflow.py
@@ -1,11 +1,13 @@
from __future__ import annotations

from pathlib import PosixPath

import pytest

from PIL import Image


def test_j2k_overflow(tmp_path):
def test_j2k_overflow(tmp_path: PosixPath) -> None:
im = Image.new("RGBA", (1024, 131584))
target = str(tmp_path / "temp.jpc")
with pytest.raises(OSError):
Expand Down
6 changes: 3 additions & 3 deletions Tests/check_jpeg_leaks.py
Expand Up @@ -111,14 +111,14 @@
[standard_l_qtable, standard_chrominance_qtable],
),
)
def test_qtables_leak(qtables):
def test_qtables_leak(qtables: tuple[tuple[int, ...]] | list[tuple[int, ...]]) -> None:
im = hopper("RGB")
for _ in range(iterations):
test_output = BytesIO()
im.save(test_output, "JPEG", qtables=qtables)


def test_exif_leak():
def test_exif_leak() -> None:
"""
pre patch:
Expand Down Expand Up @@ -181,7 +181,7 @@ def test_exif_leak():
im.save(test_output, "JPEG", exif=exif)


def test_base_save():
def test_base_save() -> None:
"""
base case:
MB
Expand Down
12 changes: 8 additions & 4 deletions Tests/check_large_memory.py
@@ -1,6 +1,8 @@
from __future__ import annotations

import sys
from pathlib import PosixPath
from types import ModuleType

import pytest

Expand All @@ -16,6 +18,7 @@
# 2.7 and 3.2.


numpy: ModuleType | None
try:
import numpy
except ImportError:
Expand All @@ -28,23 +31,24 @@
pytestmark = pytest.mark.skipif(sys.maxsize <= 2**32, reason="requires 64-bit system")


def _write_png(tmp_path, xdim, ydim):
def _write_png(tmp_path: PosixPath, xdim: int, ydim: int) -> None:
f = str(tmp_path / "temp.png")
im = Image.new("L", (xdim, ydim), 0)
im.save(f)


def test_large(tmp_path):
def test_large(tmp_path: PosixPath) -> None:
"""succeeded prepatch"""
_write_png(tmp_path, XDIM, YDIM)


def test_2gpx(tmp_path):
def test_2gpx(tmp_path: PosixPath) -> None:
"""failed prepatch"""
_write_png(tmp_path, XDIM, XDIM)


@pytest.mark.skipif(numpy is None, reason="Numpy is not installed")
def test_size_greater_than_int():
def test_size_greater_than_int() -> None:
assert numpy is not None
arr = numpy.ndarray(shape=(16394, 16394))
Image.fromarray(arr)
7 changes: 4 additions & 3 deletions Tests/check_large_memory_numpy.py
@@ -1,6 +1,7 @@
from __future__ import annotations

import sys
from pathlib import PosixPath

import pytest

Expand All @@ -24,19 +25,19 @@
pytestmark = pytest.mark.skipif(sys.maxsize <= 2**32, reason="requires 64-bit system")


def _write_png(tmp_path, xdim, ydim):
def _write_png(tmp_path: PosixPath, xdim: int, ydim: int) -> None:
dtype = np.uint8
a = np.zeros((xdim, ydim), dtype=dtype)
f = str(tmp_path / "temp.png")
im = Image.fromarray(a, "L")
im.save(f)


def test_large(tmp_path):
def test_large(tmp_path: PosixPath) -> None:
"""succeeded prepatch"""
_write_png(tmp_path, XDIM, YDIM)


def test_2gpx(tmp_path):
def test_2gpx(tmp_path: PosixPath) -> None:
"""failed prepatch"""
_write_png(tmp_path, XDIM, XDIM)
2 changes: 1 addition & 1 deletion Tests/check_libtiff_segfault.py
Expand Up @@ -7,7 +7,7 @@
TEST_FILE = "Tests/images/libtiff_segfault.tif"


def test_libtiff_segfault():
def test_libtiff_segfault() -> None:
"""This test should not segfault. It will on Pillow <= 3.1.0 and
libtiff >= 4.0.0
"""
Expand Down
8 changes: 4 additions & 4 deletions Tests/check_png_dos.py
Expand Up @@ -8,7 +8,7 @@
TEST_FILE = "Tests/images/png_decompression_dos.png"


def test_ignore_dos_text():
def test_ignore_dos_text() -> None:
ImageFile.LOAD_TRUNCATED_IMAGES = True

try:
Expand All @@ -24,7 +24,7 @@ def test_ignore_dos_text():
assert len(s) < 1024 * 1024, "Text chunk larger than 1M"


def test_dos_text():
def test_dos_text() -> None:
try:
im = Image.open(TEST_FILE)
im.load()
Expand All @@ -36,7 +36,7 @@ def test_dos_text():
assert len(s) < 1024 * 1024, "Text chunk larger than 1M"


def test_dos_total_memory():
def test_dos_total_memory() -> None:
im = Image.new("L", (1, 1))
compressed_data = zlib.compress(b"a" * 1024 * 1023)

Expand All @@ -53,7 +53,7 @@ def test_dos_total_memory():
try:
im2 = Image.open(b)
except ValueError as msg:
assert "Too much memory" in msg
assert "Too much memory" in str(msg)
return

total_len = 0
Expand Down
6 changes: 3 additions & 3 deletions Tests/check_wheel.py
Expand Up @@ -5,7 +5,7 @@
from PIL import features


def test_wheel_modules():
def test_wheel_modules() -> None:
expected_modules = {"pil", "tkinter", "freetype2", "littlecms2", "webp"}

# tkinter is not available in cibuildwheel installed CPython on Windows
Expand All @@ -19,13 +19,13 @@ def test_wheel_modules():
assert set(features.get_supported_modules()) == expected_modules


def test_wheel_codecs():
def test_wheel_codecs() -> None:
expected_codecs = {"jpg", "jpg_2000", "zlib", "libtiff"}

assert set(features.get_supported_codecs()) == expected_codecs


def test_wheel_features():
def test_wheel_features() -> None:
expected_features = {
"webp_anim",
"webp_mux",
Expand Down

0 comments on commit 9c98162

Please sign in to comment.