|
1 | 1 | #!/usr/bin/env python3 |
2 | 2 | from __future__ import annotations |
3 | 3 |
|
| 4 | +from typing import Any, Callable |
| 5 | + |
4 | 6 | import pytest |
5 | 7 |
|
6 | 8 | from PIL import Image |
|
13 | 15 | pytestmark = pytest.mark.skipif(is_win32(), reason="requires Unix or macOS") |
14 | 16 |
|
15 | 17 |
|
16 | | -def _get_mem_usage(): |
| 18 | +def _get_mem_usage() -> float: |
17 | 19 | from resource import RUSAGE_SELF, getpagesize, getrusage |
18 | 20 |
|
19 | 21 | mem = getrusage(RUSAGE_SELF).ru_maxrss |
20 | 22 | return mem * getpagesize() / 1024 / 1024 |
21 | 23 |
|
22 | 24 |
|
23 | | -def _test_leak(min_iterations, max_iterations, fn, *args, **kwargs): |
| 25 | +def _test_leak( |
| 26 | + min_iterations: int, max_iterations: int, fn: Callable[..., None], *args: Any |
| 27 | +) -> None: |
24 | 28 | mem_limit = None |
25 | 29 | for i in range(max_iterations): |
26 | | - fn(*args, **kwargs) |
| 30 | + fn(*args) |
27 | 31 | mem = _get_mem_usage() |
28 | 32 | if i < min_iterations: |
29 | 33 | mem_limit = mem + 1 |
30 | 34 | continue |
31 | 35 | msg = f"memory usage limit exceeded after {i + 1} iterations" |
| 36 | + assert mem_limit is not None |
32 | 37 | assert mem <= mem_limit, msg |
33 | 38 |
|
34 | 39 |
|
35 | | -def test_leak_putdata(): |
| 40 | +def test_leak_putdata() -> None: |
36 | 41 | im = Image.new("RGB", (25, 25)) |
37 | 42 | _test_leak(min_iterations, max_iterations, im.putdata, im.getdata()) |
38 | 43 |
|
39 | 44 |
|
40 | | -def test_leak_getlist(): |
| 45 | +def test_leak_getlist() -> None: |
41 | 46 | im = Image.new("P", (25, 25)) |
42 | 47 | _test_leak( |
43 | 48 | min_iterations, |
|
0 commit comments