mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-06-30 18:03:07 +03:00
split pyarrow tests out from plain loopback arrow tests
This commit is contained in:
parent
159ffe3bc3
commit
91e275965f
|
@ -12,62 +12,6 @@ from .helper import (
|
||||||
hopper,
|
hopper,
|
||||||
)
|
)
|
||||||
|
|
||||||
pyarrow = pytest.importorskip("pyarrow", reason="PyArrow not installed")
|
|
||||||
|
|
||||||
TEST_IMAGE_SIZE = (10, 10)
|
|
||||||
|
|
||||||
|
|
||||||
def _test_img_equals_pyarray(img: Image.Image, arr: Any, mask) -> None:
|
|
||||||
assert img.height * img.width == len(arr)
|
|
||||||
px = img.load()
|
|
||||||
assert px is not None
|
|
||||||
for x in range(0, img.size[0], int(img.size[0] / 10)):
|
|
||||||
for y in range(0, img.size[1], int(img.size[1] / 10)):
|
|
||||||
if mask:
|
|
||||||
for ix, elt in enumerate(mask):
|
|
||||||
assert px[x, y][ix] == arr[y * img.width + x].as_py()[elt]
|
|
||||||
else:
|
|
||||||
assert_deep_equal(px[x, y], arr[y * img.width + x].as_py())
|
|
||||||
|
|
||||||
|
|
||||||
# really hard to get a non-nullable list type
|
|
||||||
fl_uint8_4_type = pyarrow.field(
|
|
||||||
"_", pyarrow.list_(pyarrow.field("_", pyarrow.uint8()).with_nullable(False), 4)
|
|
||||||
).type
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
"mode, dtype, mask",
|
|
||||||
(
|
|
||||||
("L", pyarrow.uint8(), None),
|
|
||||||
("I", pyarrow.int32(), None),
|
|
||||||
("F", pyarrow.float32(), None),
|
|
||||||
("LA", fl_uint8_4_type, [0, 3]),
|
|
||||||
("RGB", fl_uint8_4_type, [0, 1, 2]),
|
|
||||||
("RGBA", fl_uint8_4_type, None),
|
|
||||||
("RGBX", fl_uint8_4_type, None),
|
|
||||||
("CMYK", fl_uint8_4_type, None),
|
|
||||||
("YCbCr", fl_uint8_4_type, [0, 1, 2]),
|
|
||||||
("HSV", fl_uint8_4_type, [0, 1, 2]),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
def test_to_array(mode: str, dtype: Any, mask: Any) -> None:
|
|
||||||
img = hopper(mode)
|
|
||||||
|
|
||||||
# Resize to non-square
|
|
||||||
img = img.crop((3, 0, 124, 127))
|
|
||||||
assert img.size == (121, 127)
|
|
||||||
|
|
||||||
arr = pyarrow.array(img)
|
|
||||||
_test_img_equals_pyarray(img, arr, mask)
|
|
||||||
assert arr.type == dtype
|
|
||||||
|
|
||||||
reloaded = Image.fromarrow(arr, mode, img.size)
|
|
||||||
|
|
||||||
assert reloaded
|
|
||||||
|
|
||||||
assert_image_equal(img, reloaded)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"mode, dest_modes",
|
"mode, dest_modes",
|
||||||
|
@ -99,43 +43,6 @@ def test_invalid_array_size():
|
||||||
Image.fromarrow(img, "RGB", (10, 10))
|
Image.fromarrow(img, "RGB", (10, 10))
|
||||||
|
|
||||||
|
|
||||||
def test_lifetime():
|
|
||||||
# valgrind shouldn't error out here.
|
|
||||||
# arrays should be accessible after the image is deleted.
|
|
||||||
|
|
||||||
img = hopper("L")
|
|
||||||
|
|
||||||
arr_1 = pyarrow.array(img)
|
|
||||||
arr_2 = pyarrow.array(img)
|
|
||||||
|
|
||||||
del img
|
|
||||||
|
|
||||||
assert arr_1.sum().as_py() > 0
|
|
||||||
del arr_1
|
|
||||||
|
|
||||||
assert arr_2.sum().as_py() > 0
|
|
||||||
del arr_2
|
|
||||||
|
|
||||||
|
|
||||||
def test_lifetime2():
|
|
||||||
# valgrind shouldn't error out here.
|
|
||||||
# img should remain after the arrays are collected.
|
|
||||||
|
|
||||||
img = hopper("L")
|
|
||||||
|
|
||||||
arr_1 = pyarrow.array(img)
|
|
||||||
arr_2 = pyarrow.array(img)
|
|
||||||
|
|
||||||
assert arr_1.sum().as_py() > 0
|
|
||||||
del arr_1
|
|
||||||
|
|
||||||
assert arr_2.sum().as_py() > 0
|
|
||||||
del arr_2
|
|
||||||
|
|
||||||
img2 = img.copy()
|
|
||||||
px = img2.load()
|
|
||||||
assert isinstance(px[0, 0], int)
|
|
||||||
|
|
||||||
|
|
||||||
def test_release_schema():
|
def test_release_schema():
|
||||||
# these should not error out, valgrind should be clean
|
# these should not error out, valgrind should be clean
|
||||||
|
|
108
Tests/test_pyarrow.py
Normal file
108
Tests/test_pyarrow.py
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any # undone
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
from .helper import (
|
||||||
|
assert_deep_equal,
|
||||||
|
assert_image_equal,
|
||||||
|
hopper,
|
||||||
|
)
|
||||||
|
|
||||||
|
pyarrow = pytest.importorskip("pyarrow", reason="PyArrow not installed")
|
||||||
|
|
||||||
|
TEST_IMAGE_SIZE = (10, 10)
|
||||||
|
|
||||||
|
|
||||||
|
def _test_img_equals_pyarray(img: Image.Image, arr: Any, mask) -> None:
|
||||||
|
assert img.height * img.width == len(arr)
|
||||||
|
px = img.load()
|
||||||
|
assert px is not None
|
||||||
|
for x in range(0, img.size[0], int(img.size[0] / 10)):
|
||||||
|
for y in range(0, img.size[1], int(img.size[1] / 10)):
|
||||||
|
if mask:
|
||||||
|
for ix, elt in enumerate(mask):
|
||||||
|
assert px[x, y][ix] == arr[y * img.width + x].as_py()[elt]
|
||||||
|
else:
|
||||||
|
assert_deep_equal(px[x, y], arr[y * img.width + x].as_py())
|
||||||
|
|
||||||
|
|
||||||
|
# really hard to get a non-nullable list type
|
||||||
|
fl_uint8_4_type = pyarrow.field(
|
||||||
|
"_", pyarrow.list_(pyarrow.field("_", pyarrow.uint8()).with_nullable(False), 4)
|
||||||
|
).type
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"mode, dtype, mask",
|
||||||
|
(
|
||||||
|
("L", pyarrow.uint8(), None),
|
||||||
|
("I", pyarrow.int32(), None),
|
||||||
|
("F", pyarrow.float32(), None),
|
||||||
|
("LA", fl_uint8_4_type, [0, 3]),
|
||||||
|
("RGB", fl_uint8_4_type, [0, 1, 2]),
|
||||||
|
("RGBA", fl_uint8_4_type, None),
|
||||||
|
("RGBX", fl_uint8_4_type, None),
|
||||||
|
("CMYK", fl_uint8_4_type, None),
|
||||||
|
("YCbCr", fl_uint8_4_type, [0, 1, 2]),
|
||||||
|
("HSV", fl_uint8_4_type, [0, 1, 2]),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def test_to_array(mode: str, dtype: Any, mask: Any) -> None:
|
||||||
|
img = hopper(mode)
|
||||||
|
|
||||||
|
# Resize to non-square
|
||||||
|
img = img.crop((3, 0, 124, 127))
|
||||||
|
assert img.size == (121, 127)
|
||||||
|
|
||||||
|
arr = pyarrow.array(img)
|
||||||
|
_test_img_equals_pyarray(img, arr, mask)
|
||||||
|
assert arr.type == dtype
|
||||||
|
|
||||||
|
reloaded = Image.fromarrow(arr, mode, img.size)
|
||||||
|
|
||||||
|
assert reloaded
|
||||||
|
|
||||||
|
assert_image_equal(img, reloaded)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_lifetime():
|
||||||
|
# valgrind shouldn't error out here.
|
||||||
|
# arrays should be accessible after the image is deleted.
|
||||||
|
|
||||||
|
img = hopper("L")
|
||||||
|
|
||||||
|
arr_1 = pyarrow.array(img)
|
||||||
|
arr_2 = pyarrow.array(img)
|
||||||
|
|
||||||
|
del img
|
||||||
|
|
||||||
|
assert arr_1.sum().as_py() > 0
|
||||||
|
del arr_1
|
||||||
|
|
||||||
|
assert arr_2.sum().as_py() > 0
|
||||||
|
del arr_2
|
||||||
|
|
||||||
|
|
||||||
|
def test_lifetime2():
|
||||||
|
# valgrind shouldn't error out here.
|
||||||
|
# img should remain after the arrays are collected.
|
||||||
|
|
||||||
|
img = hopper("L")
|
||||||
|
|
||||||
|
arr_1 = pyarrow.array(img)
|
||||||
|
arr_2 = pyarrow.array(img)
|
||||||
|
|
||||||
|
assert arr_1.sum().as_py() > 0
|
||||||
|
del arr_1
|
||||||
|
|
||||||
|
assert arr_2.sum().as_py() > 0
|
||||||
|
del arr_2
|
||||||
|
|
||||||
|
img2 = img.copy()
|
||||||
|
px = img2.load()
|
||||||
|
assert isinstance(px[0, 0], int)
|
|
@ -61,13 +61,17 @@ optional-dependencies.tests = [
|
||||||
"markdown2",
|
"markdown2",
|
||||||
"olefile",
|
"olefile",
|
||||||
"packaging",
|
"packaging",
|
||||||
"pyarrow",
|
|
||||||
"pyroma",
|
"pyroma",
|
||||||
"pytest",
|
"pytest",
|
||||||
"pytest-cov",
|
"pytest-cov",
|
||||||
"pytest-timeout",
|
"pytest-timeout",
|
||||||
"trove-classifiers>=2024.10.12",
|
"trove-classifiers>=2024.10.12",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
optional-dependencies.test-arrow = [
|
||||||
|
"pyarrow",
|
||||||
|
]
|
||||||
|
|
||||||
optional-dependencies.typing = [
|
optional-dependencies.typing = [
|
||||||
"typing-extensions; python_version<'3.10'",
|
"typing-extensions; python_version<'3.10'",
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user