Skip to content

Commit

Permalink
[pre-commit.ci] auto fixes from pre-commit.com hooks
Browse files Browse the repository at this point in the history
for more information, see https://pre-commit.ci
  • Loading branch information
pre-commit-ci[bot] committed Jan 21, 2025
1 parent 97eb7c0 commit 34a8c56
Show file tree
Hide file tree
Showing 8 changed files with 433 additions and 434 deletions.
53 changes: 26 additions & 27 deletions Tests/test_arrow.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
from __future__ import annotations

import warnings
from typing import Any # undone

import pytest

from PIL import Image

from .helper import assert_deep_equal, assert_image, hopper, skip_unless_feature, assert_image_equal

from typing import Any # undone
from .helper import (
assert_deep_equal,
assert_image_equal,
hopper,
)

pyarrow = pytest.importorskip("pyarrow", reason="PyArrow not installed")

TEST_IMAGE_SIZE = (10, 10)

Check warning on line 17 in Tests/test_arrow.py

View check run for this annotation

Codecov / codecov/patch

Tests/test_arrow.py#L17

Added line #L17 was not covered by tests
from numbers import Number


def _test_img_equals_pyarray(img: Image.Image, arr: Any, mask) -> None:
Expand All @@ -24,36 +25,33 @@ def _test_img_equals_pyarray(img: Image.Image, arr: Any, mask) -> None:
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]
assert px[x, y][ix] == arr[y * img.width + x].as_py()[elt]

Check warning on line 28 in Tests/test_arrow.py

View check run for this annotation

Codecov / codecov/patch

Tests/test_arrow.py#L20-L28

Added lines #L20 - L28 were not covered by tests
else:
assert_deep_equal(px[x, y], arr[y * img.width + x].as_py())

Check warning on line 30 in Tests/test_arrow.py

View check run for this annotation

Codecov / codecov/patch

Tests/test_arrow.py#L30

Added line #L30 was not covered by tests


# 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
fl_uint8_4_type = pyarrow.field(

Check warning on line 34 in Tests/test_arrow.py

View check run for this annotation

Codecov / codecov/patch

Tests/test_arrow.py#L34

Added line #L34 was not covered by tests
"_", pyarrow.list_(pyarrow.field("_", pyarrow.uint8()).with_nullable(False), 4)
).type


@pytest.mark.parametrize(

Check warning on line 39 in Tests/test_arrow.py

View check run for this annotation

Codecov / codecov/patch

Tests/test_arrow.py#L39

Added line #L39 was not covered by tests
"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]),
("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]),
("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:
def test_to_array(mode: str, dtype: Any, mask: Any) -> None:
img = hopper(mode)

Check warning on line 55 in Tests/test_arrow.py

View check run for this annotation

Codecov / codecov/patch

Tests/test_arrow.py#L54-L55

Added lines #L54 - L55 were not covered by tests

# Resize to non-square
Expand All @@ -70,39 +68,40 @@ def test_to_array(mode: str, dtype: Any, mask: Any ) -> None:

assert_image_equal(img, reloaded)

Check warning on line 69 in Tests/test_arrow.py

View check run for this annotation

Codecov / codecov/patch

Tests/test_arrow.py#L69

Added line #L69 was not covered by tests


def test_lifetime():

Check warning on line 72 in Tests/test_arrow.py

View check run for this annotation

Codecov / codecov/patch

Tests/test_arrow.py#L72

Added line #L72 was not covered by tests
# valgrind shouldn't error out here.
# arrays should be accessible after the image is deleted.

img = hopper('L')
img = hopper("L")

Check warning on line 76 in Tests/test_arrow.py

View check run for this annotation

Codecov / codecov/patch

Tests/test_arrow.py#L76

Added line #L76 was not covered by tests

arr_1 = pyarrow.array(img)
arr_2 = pyarrow.array(img)

Check warning on line 79 in Tests/test_arrow.py

View check run for this annotation

Codecov / codecov/patch

Tests/test_arrow.py#L78-L79

Added lines #L78 - L79 were not covered by tests

del(img)
del img

Check warning on line 81 in Tests/test_arrow.py

View check run for this annotation

Codecov / codecov/patch

Tests/test_arrow.py#L81

Added line #L81 was not covered by tests

assert arr_1.sum().as_py() > 0
del(arr_1)
del arr_1

Check warning on line 84 in Tests/test_arrow.py

View check run for this annotation

Codecov / codecov/patch

Tests/test_arrow.py#L83-L84

Added lines #L83 - L84 were not covered by tests

assert arr_2.sum().as_py() > 0
del(arr_2)
del arr_2

Check warning on line 87 in Tests/test_arrow.py

View check run for this annotation

Codecov / codecov/patch

Tests/test_arrow.py#L86-L87

Added lines #L86 - L87 were not covered by tests


def test_lifetime2():

Check warning on line 90 in Tests/test_arrow.py

View check run for this annotation

Codecov / codecov/patch

Tests/test_arrow.py#L90

Added line #L90 was not covered by tests
# valgrind shouldn't error out here.
# img should remain after the arrays are collected.

img = hopper('L')
img = hopper("L")

Check warning on line 94 in Tests/test_arrow.py

View check run for this annotation

Codecov / codecov/patch

Tests/test_arrow.py#L94

Added line #L94 was not covered by tests

arr_1 = pyarrow.array(img)
arr_2 = pyarrow.array(img)

Check warning on line 97 in Tests/test_arrow.py

View check run for this annotation

Codecov / codecov/patch

Tests/test_arrow.py#L96-L97

Added lines #L96 - L97 were not covered by tests


assert arr_1.sum().as_py() > 0
del(arr_1)
del arr_1

Check warning on line 100 in Tests/test_arrow.py

View check run for this annotation

Codecov / codecov/patch

Tests/test_arrow.py#L99-L100

Added lines #L99 - L100 were not covered by tests

assert arr_2.sum().as_py() > 0
del(arr_2)
del arr_2

Check warning on line 103 in Tests/test_arrow.py

View check run for this annotation

Codecov / codecov/patch

Tests/test_arrow.py#L102-L103

Added lines #L102 - L103 were not covered by tests

img2 = img.copy()
px = img2.load()
assert isinstance(px[0,0], int)
assert isinstance(px[0, 0], int)

Check warning on line 107 in Tests/test_arrow.py

View check run for this annotation

Codecov / codecov/patch

Tests/test_arrow.py#L105-L107

Added lines #L105 - L107 were not covered by tests
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@ optional-dependencies.tests = [
"markdown2",
"olefile",
"packaging",
"pyarrow",
"pyroma",
"pytest",
"pytest-cov",
"pytest-timeout",
"trove-classifiers>=2024.10.12",
"pyarrow",
]
optional-dependencies.typing = [
"typing-extensions; python_version<'3.10'",
Expand Down
14 changes: 9 additions & 5 deletions src/PIL/Image.py
Original file line number Diff line number Diff line change
Expand Up @@ -748,12 +748,13 @@ def __array_interface__(self) -> dict[str, str | bytes | int | tuple[int, ...]]:
new["shape"], new["typestr"] = _conv_type_shape(self)
return new


def __arrow_c_schema__(self) -> object:
self.load()
return self.im.__arrow_c_schema__()

def __arrow_c_array__(self, requested_schema: object | None = None) -> Tuple[object, object]:
def __arrow_c_array__(
self, requested_schema: object | None = None
) -> Tuple[object, object]:
self.load()
return (self.im.__arrow_c_schema__(), self.im.__arrow_c_array__())

Expand Down Expand Up @@ -3258,12 +3259,15 @@ class SupportsArrayInterface(Protocol):
def __array_interface__(self) -> dict[str, Any]:
raise NotImplementedError()


class SupportsArrowArrayInterface(Protocol):
"""
An object that has an ``__arrow_c_array__`` method corresponding to the arrow c data interface.
"""

def __arrow_c_array__(self, requested_schema:"PyCapsule"=None) -> tuple["PyCapsule", "PyCapsule"]:
def __arrow_c_array__(
self, requested_schema: PyCapsule = None
) -> tuple[PyCapsule, PyCapsule]:
raise NotImplementedError()


Expand Down Expand Up @@ -3356,12 +3360,12 @@ def fromarray(obj: SupportsArrayInterface, mode: str | None = None) -> Image:


def fromarrow(obj: SupportsArrowArrayIngerface, mode, size) -> ImageFile.ImageFile:
if not hasattr(obj, '__arrow_c_array__'):
if not hasattr(obj, "__arrow_c_array__"):
raise ValueError("arrow_c_array interface not found")

(schema_capsule, array_capsule) = obj.__arrow_c_array__()
_im = core.new_arrow(mode, size, schema_capsule, array_capsule)
if (_im):
if _im:
return Image()._new(_im)

return None
Expand Down
54 changes: 28 additions & 26 deletions src/_imaging.c
Original file line number Diff line number Diff line change
Expand Up @@ -227,71 +227,73 @@ PyImaging_GetBuffer(PyObject *buffer, Py_buffer *view) {
/* Arrow HANDLING */
/* -------------------------------------------------------------------- */

Check warning on line 228 in src/_imaging.c

View check run for this annotation

Codecov / codecov/patch

src/_imaging.c#L228

Added line #L228 was not covered by tests

void ReleaseArrowSchemaPyCapsule(PyObject* capsule) {
struct ArrowSchema* schema =
(struct ArrowSchema*)PyCapsule_GetPointer(capsule, "arrow_schema");
void

Check warning on line 230 in src/_imaging.c

View check run for this annotation

Codecov / codecov/patch

src/_imaging.c#L230

Added line #L230 was not covered by tests
ReleaseArrowSchemaPyCapsule(PyObject *capsule) {
struct ArrowSchema *schema =
(struct ArrowSchema *)PyCapsule_GetPointer(capsule, "arrow_schema");
if (schema->release != NULL) {
schema->release(schema);
}
free(schema);
}

Check warning on line 238 in src/_imaging.c

View check run for this annotation

Codecov / codecov/patch

src/_imaging.c#L238

Added line #L238 was not covered by tests

PyObject* ExportArrowSchemaPyCapsule(ImagingObject *self) {
struct ArrowSchema* schema =
(struct ArrowSchema*)calloc(1, sizeof(struct ArrowSchema));
PyObject *

Check warning on line 240 in src/_imaging.c

View check run for this annotation

Codecov / codecov/patch

src/_imaging.c#L240

Added line #L240 was not covered by tests
ExportArrowSchemaPyCapsule(ImagingObject *self) {
struct ArrowSchema *schema =

Check warning on line 242 in src/_imaging.c

View check run for this annotation

Codecov / codecov/patch

src/_imaging.c#L242

Added line #L242 was not covered by tests
(struct ArrowSchema *)calloc(1, sizeof(struct ArrowSchema));
export_imaging_schema(self->image, schema);

Check warning on line 244 in src/_imaging.c

View check run for this annotation

Codecov / codecov/patch

src/_imaging.c#L244

Added line #L244 was not covered by tests
return PyCapsule_New(schema, "arrow_schema", ReleaseArrowSchemaPyCapsule);
}

void ReleaseArrowArrayPyCapsule(PyObject* capsule) {
struct ArrowArray* array =
(struct ArrowArray*)PyCapsule_GetPointer(capsule, "arrow_array");
void

Check warning on line 248 in src/_imaging.c

View check run for this annotation

Codecov / codecov/patch

src/_imaging.c#L248

Added line #L248 was not covered by tests
ReleaseArrowArrayPyCapsule(PyObject *capsule) {
struct ArrowArray *array =
(struct ArrowArray *)PyCapsule_GetPointer(capsule, "arrow_array");
if (array->release != NULL) {

Check warning on line 252 in src/_imaging.c

View check run for this annotation

Codecov / codecov/patch

src/_imaging.c#L250-L252

Added lines #L250 - L252 were not covered by tests
array->release(array);
}
free(array);
}

Check warning on line 256 in src/_imaging.c

View check run for this annotation

Codecov / codecov/patch

src/_imaging.c#L256

Added line #L256 was not covered by tests

PyObject* ExportArrowArrayPyCapsule(ImagingObject *self) {
struct ArrowArray* array =
(struct ArrowArray*)calloc(1, sizeof(struct ArrowArray));
PyObject *

Check warning on line 258 in src/_imaging.c

View check run for this annotation

Codecov / codecov/patch

src/_imaging.c#L258

Added line #L258 was not covered by tests
ExportArrowArrayPyCapsule(ImagingObject *self) {
struct ArrowArray *array =

Check warning on line 260 in src/_imaging.c

View check run for this annotation

Codecov / codecov/patch

src/_imaging.c#L260

Added line #L260 was not covered by tests
(struct ArrowArray *)calloc(1, sizeof(struct ArrowArray));
export_imaging_array(self->image, array);

Check warning on line 262 in src/_imaging.c

View check run for this annotation

Codecov / codecov/patch

src/_imaging.c#L262

Added line #L262 was not covered by tests
return PyCapsule_New(array, "arrow_array", ReleaseArrowArrayPyCapsule);
}


static PyObject *

Check warning on line 266 in src/_imaging.c

View check run for this annotation

Codecov / codecov/patch

src/_imaging.c#L266

Added line #L266 was not covered by tests
_new_arrow(PyObject *self, PyObject *args) {
char *mode;
int xsize, ysize;
PyObject *schema_capsule, *array_capsule;

Check warning on line 270 in src/_imaging.c

View check run for this annotation

Codecov / codecov/patch

src/_imaging.c#L268-L270

Added lines #L268 - L270 were not covered by tests
PyObject *ret;

if (!PyArg_ParseTuple(args, "s(ii)OO", &mode, &xsize, &ysize,
&schema_capsule, &array_capsule)) {
if (!PyArg_ParseTuple(
args, "s(ii)OO", &mode, &xsize, &ysize, &schema_capsule, &array_capsule

Check warning on line 274 in src/_imaging.c

View check run for this annotation

Codecov / codecov/patch

src/_imaging.c#L274

Added line #L274 was not covered by tests
)) {
return NULL;
}

struct ArrowSchema* schema =
(struct ArrowSchema*)PyCapsule_GetPointer(schema_capsule, "arrow_schema");
struct ArrowSchema *schema =
(struct ArrowSchema *)PyCapsule_GetPointer(schema_capsule, "arrow_schema");

struct ArrowArray* array =
(struct ArrowArray*)PyCapsule_GetPointer(array_capsule, "arrow_array");
struct ArrowArray *array =
(struct ArrowArray *)PyCapsule_GetPointer(array_capsule, "arrow_array");

Check warning on line 283 in src/_imaging.c

View check run for this annotation

Codecov / codecov/patch

src/_imaging.c#L283

Added line #L283 was not covered by tests

ret = PyImagingNew(ImagingNewArrow(mode, xsize, ysize, schema, array));
if (schema->release){
schema->release(schema);
schema->release = NULL;
if (schema->release) {
schema->release(schema);

Check warning on line 287 in src/_imaging.c

View check run for this annotation

Codecov / codecov/patch

src/_imaging.c#L287

Added line #L287 was not covered by tests
schema->release = NULL;
}
if (!ret && array->release) {

Check warning on line 290 in src/_imaging.c

View check run for this annotation

Codecov / codecov/patch

src/_imaging.c#L290

Added line #L290 was not covered by tests
array->release(array);
array->release = NULL;
array->release(array);
array->release = NULL;

Check warning on line 292 in src/_imaging.c

View check run for this annotation

Codecov / codecov/patch

src/_imaging.c#L292

Added line #L292 was not covered by tests
}
return ret;
}

Check warning on line 295 in src/_imaging.c

View check run for this annotation

Codecov / codecov/patch

src/_imaging.c#L294-L295

Added lines #L294 - L295 were not covered by tests



/* -------------------------------------------------------------------- */
/* EXCEPTION REROUTING */
/* -------------------------------------------------------------------- */
Expand Down
Loading

0 comments on commit 34a8c56

Please sign in to comment.