Skip to content

Commit 2de1bf2

Browse files
authored
Merge pull request #7236 from radarhere/pyaccess
2 parents b2387f9 + b5ce319 commit 2de1bf2

File tree

5 files changed

+57
-25
lines changed

5 files changed

+57
-25
lines changed

Tests/test_image_access.py

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -232,11 +232,13 @@ def test_p_putpixel_rgb_rgba(self, mode, color):
232232
assert im.convert("RGBA").getpixel((0, 0)) == (255, 0, 0, alpha)
233233

234234

235+
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
235236
@pytest.mark.skipif(cffi is None, reason="No CFFI")
236237
class TestCffiPutPixel(TestImagePutPixel):
237238
_need_cffi_access = True
238239

239240

241+
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
240242
@pytest.mark.skipif(cffi is None, reason="No CFFI")
241243
class TestCffiGetPixel(TestImageGetPixel):
242244
_need_cffi_access = True
@@ -252,7 +254,8 @@ def _test_get_access(self, im):
252254
Using private interfaces, forcing a capi access and
253255
a pyaccess for the same image"""
254256
caccess = im.im.pixel_access(False)
255-
access = PyAccess.new(im, False)
257+
with pytest.warns(DeprecationWarning):
258+
access = PyAccess.new(im, False)
256259

257260
w, h = im.size
258261
for x in range(0, w, 10):
@@ -264,20 +267,16 @@ def _test_get_access(self, im):
264267
access[(access.xsize + 1, access.ysize + 1)]
265268

266269
def test_get_vs_c(self):
267-
rgb = hopper("RGB")
268-
rgb.load()
269-
self._test_get_access(rgb)
270-
self._test_get_access(hopper("RGBA"))
271-
self._test_get_access(hopper("L"))
272-
self._test_get_access(hopper("LA"))
273-
self._test_get_access(hopper("1"))
274-
self._test_get_access(hopper("P"))
275-
# self._test_get_access(hopper('PA')) # PA -- how do I make a PA image?
276-
self._test_get_access(hopper("F"))
270+
with pytest.warns(DeprecationWarning):
271+
rgb = hopper("RGB")
272+
rgb.load()
273+
self._test_get_access(rgb)
274+
for mode in ("RGBA", "L", "LA", "1", "P", "F"):
275+
self._test_get_access(hopper(mode))
277276

278-
for mode in ("I;16", "I;16L", "I;16B", "I;16N", "I"):
279-
im = Image.new(mode, (10, 10), 40000)
280-
self._test_get_access(im)
277+
for mode in ("I;16", "I;16L", "I;16B", "I;16N", "I"):
278+
im = Image.new(mode, (10, 10), 40000)
279+
self._test_get_access(im)
281280

282281
# These don't actually appear to be modes that I can actually make,
283282
# as unpack sets them directly into the I mode.
@@ -292,7 +291,8 @@ def _test_set_access(self, im, color):
292291
Using private interfaces, forcing a capi access and
293292
a pyaccess for the same image"""
294293
caccess = im.im.pixel_access(False)
295-
access = PyAccess.new(im, False)
294+
with pytest.warns(DeprecationWarning):
295+
access = PyAccess.new(im, False)
296296

297297
w, h = im.size
298298
for x in range(0, w, 10):
@@ -301,13 +301,15 @@ def _test_set_access(self, im, color):
301301
assert color == caccess[(x, y)]
302302

303303
# Attempt to set the value on a read-only image
304-
access = PyAccess.new(im, True)
304+
with pytest.warns(DeprecationWarning):
305+
access = PyAccess.new(im, True)
305306
with pytest.raises(ValueError):
306307
access[(0, 0)] = color
307308

308309
def test_set_vs_c(self):
309310
rgb = hopper("RGB")
310-
rgb.load()
311+
with pytest.warns(DeprecationWarning):
312+
rgb.load()
311313
self._test_set_access(rgb, (255, 128, 0))
312314
self._test_set_access(hopper("RGBA"), (255, 192, 128, 0))
313315
self._test_set_access(hopper("L"), 128)
@@ -326,6 +328,7 @@ def test_set_vs_c(self):
326328
# im = Image.new('I;32B', (10, 10), 2**10)
327329
# self._test_set_access(im, 2**13-1)
328330

331+
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
329332
def test_not_implemented(self):
330333
assert PyAccess.new(hopper("BGR;15")) is None
331334

@@ -335,7 +338,8 @@ def test_reference_counting(self):
335338

336339
for _ in range(10):
337340
# Do not save references to the image, only to the access object
338-
px = Image.new("L", (size, 1), 0).load()
341+
with pytest.warns(DeprecationWarning):
342+
px = Image.new("L", (size, 1), 0).load()
339343
for i in range(size):
340344
# pixels can contain garbage if image is released
341345
assert px[i, 0] == 0
@@ -344,12 +348,13 @@ def test_reference_counting(self):
344348
def test_p_putpixel_rgb_rgba(self, mode):
345349
for color in ((255, 0, 0), (255, 0, 0, 127 if mode == "PA" else 255)):
346350
im = Image.new(mode, (1, 1))
347-
access = PyAccess.new(im, False)
348-
access.putpixel((0, 0), color)
351+
with pytest.warns(DeprecationWarning):
352+
access = PyAccess.new(im, False)
353+
access.putpixel((0, 0), color)
349354

350-
if len(color) == 3:
351-
color += (255,)
352-
assert im.convert("RGBA").getpixel((0, 0)) == color
355+
if len(color) == 3:
356+
color += (255,)
357+
assert im.convert("RGBA").getpixel((0, 0)) == color
353358

354359

355360
class TestImagePutPixelError(AccessTest):

docs/deprecations.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,18 @@ be removed in Pillow 11 (2024-10-15). This class was only made as a helper to
2222
be used internally, so there is no replacement. If you need this functionality
2323
though, it is a very short class that can easily be recreated in your own code.
2424

25+
PyAccess and Image.USE_CFFI_ACCESS
26+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27+
28+
.. deprecated:: 10.0.0
29+
30+
Since Pillow's C API is now faster than PyAccess on PyPy,
31+
:py:mod:`~PIL.PyAccess` has been deprecated and will be removed in Pillow
32+
11.0.0 (2024-10-15). Pillow's C API will now be used by default on PyPy instead.
33+
34+
``Image.USE_CFFI_ACCESS``, for switching from the C API to PyAccess, is
35+
similarly deprecated.
36+
2537
Removed features
2638
----------------
2739

docs/releasenotes/10.0.0.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,19 @@ Image.coerce_e
124124

125125
This undocumented method has been removed.
126126

127+
Deprecations
128+
============
129+
130+
PyAccess and Image.USE_CFFI_ACCESS
131+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
132+
133+
Since Pillow's C API is now faster than PyAccess on PyPy,
134+
:py:mod:`~PIL.PyAccess` has been deprecated and will be removed in Pillow
135+
11.0.0 (2024-10-15). Pillow's C API will now be used by default on PyPy instead.
136+
137+
``Image.USE_CFFI_ACCESS``, for switching from the C API to PyAccess, is
138+
similarly deprecated.
139+
127140
API Changes
128141
===========
129142

src/PIL/Image.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,7 @@ class DecompressionBombError(Exception):
107107
raise
108108

109109

110-
# works everywhere, win for pypy, not cpython
111-
USE_CFFI_ACCESS = hasattr(sys, "pypy_version_info")
110+
USE_CFFI_ACCESS = False
112111
try:
113112
import cffi
114113
except ImportError:

src/PIL/PyAccess.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import logging
2323
import sys
2424

25+
from ._deprecate import deprecate
26+
2527
try:
2628
from cffi import FFI
2729

@@ -47,6 +49,7 @@
4749

4850
class PyAccess:
4951
def __init__(self, img, readonly=False):
52+
deprecate("PyAccess", 11)
5053
vals = dict(img.im.unsafe_ptrs)
5154
self.readonly = readonly
5255
self.image8 = ffi.cast("unsigned char **", vals["image8"])

0 commit comments

Comments
 (0)