Deprecate PyAccess

This commit is contained in:
Andrew Murray 2023-06-28 20:10:10 +10:00
parent 811bfe3658
commit 8a36b0fc2d
4 changed files with 50 additions and 23 deletions

View File

@ -232,11 +232,13 @@ class TestImageGetPixel(AccessTest):
assert im.convert("RGBA").getpixel((0, 0)) == (255, 0, 0, alpha) assert im.convert("RGBA").getpixel((0, 0)) == (255, 0, 0, alpha)
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
@pytest.mark.skipif(cffi is None, reason="No CFFI") @pytest.mark.skipif(cffi is None, reason="No CFFI")
class TestCffiPutPixel(TestImagePutPixel): class TestCffiPutPixel(TestImagePutPixel):
_need_cffi_access = True _need_cffi_access = True
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
@pytest.mark.skipif(cffi is None, reason="No CFFI") @pytest.mark.skipif(cffi is None, reason="No CFFI")
class TestCffiGetPixel(TestImageGetPixel): class TestCffiGetPixel(TestImageGetPixel):
_need_cffi_access = True _need_cffi_access = True
@ -252,7 +254,8 @@ class TestCffi(AccessTest):
Using private interfaces, forcing a capi access and Using private interfaces, forcing a capi access and
a pyaccess for the same image""" a pyaccess for the same image"""
caccess = im.im.pixel_access(False) caccess = im.im.pixel_access(False)
access = PyAccess.new(im, False) with pytest.warns(DeprecationWarning):
access = PyAccess.new(im, False)
w, h = im.size w, h = im.size
for x in range(0, w, 10): for x in range(0, w, 10):
@ -264,20 +267,16 @@ class TestCffi(AccessTest):
access[(access.xsize + 1, access.ysize + 1)] access[(access.xsize + 1, access.ysize + 1)]
def test_get_vs_c(self): def test_get_vs_c(self):
rgb = hopper("RGB") with pytest.warns(DeprecationWarning):
rgb.load() rgb = hopper("RGB")
self._test_get_access(rgb) rgb.load()
self._test_get_access(hopper("RGBA")) self._test_get_access(rgb)
self._test_get_access(hopper("L")) for mode in ("RGBA", "L", "LA", "1", "P", "F"):
self._test_get_access(hopper("LA")) self._test_get_access(hopper(mode))
self._test_get_access(hopper("1"))
self._test_get_access(hopper("P"))
# self._test_get_access(hopper('PA')) # PA -- how do I make a PA image?
self._test_get_access(hopper("F"))
for mode in ("I;16", "I;16L", "I;16B", "I;16N", "I"): for mode in ("I;16", "I;16L", "I;16B", "I;16N", "I"):
im = Image.new(mode, (10, 10), 40000) im = Image.new(mode, (10, 10), 40000)
self._test_get_access(im) self._test_get_access(im)
# These don't actually appear to be modes that I can actually make, # These don't actually appear to be modes that I can actually make,
# as unpack sets them directly into the I mode. # as unpack sets them directly into the I mode.
@ -292,7 +291,8 @@ class TestCffi(AccessTest):
Using private interfaces, forcing a capi access and Using private interfaces, forcing a capi access and
a pyaccess for the same image""" a pyaccess for the same image"""
caccess = im.im.pixel_access(False) caccess = im.im.pixel_access(False)
access = PyAccess.new(im, False) with pytest.warns(DeprecationWarning):
access = PyAccess.new(im, False)
w, h = im.size w, h = im.size
for x in range(0, w, 10): for x in range(0, w, 10):
@ -301,13 +301,15 @@ class TestCffi(AccessTest):
assert color == caccess[(x, y)] assert color == caccess[(x, y)]
# Attempt to set the value on a read-only image # Attempt to set the value on a read-only image
access = PyAccess.new(im, True) with pytest.warns(DeprecationWarning):
access = PyAccess.new(im, True)
with pytest.raises(ValueError): with pytest.raises(ValueError):
access[(0, 0)] = color access[(0, 0)] = color
def test_set_vs_c(self): def test_set_vs_c(self):
rgb = hopper("RGB") rgb = hopper("RGB")
rgb.load() with pytest.warns(DeprecationWarning):
rgb.load()
self._test_set_access(rgb, (255, 128, 0)) self._test_set_access(rgb, (255, 128, 0))
self._test_set_access(hopper("RGBA"), (255, 192, 128, 0)) self._test_set_access(hopper("RGBA"), (255, 192, 128, 0))
self._test_set_access(hopper("L"), 128) self._test_set_access(hopper("L"), 128)
@ -326,6 +328,7 @@ class TestCffi(AccessTest):
# im = Image.new('I;32B', (10, 10), 2**10) # im = Image.new('I;32B', (10, 10), 2**10)
# self._test_set_access(im, 2**13-1) # self._test_set_access(im, 2**13-1)
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_not_implemented(self): def test_not_implemented(self):
assert PyAccess.new(hopper("BGR;15")) is None assert PyAccess.new(hopper("BGR;15")) is None
@ -335,7 +338,8 @@ class TestCffi(AccessTest):
for _ in range(10): for _ in range(10):
# Do not save references to the image, only to the access object # Do not save references to the image, only to the access object
px = Image.new("L", (size, 1), 0).load() with pytest.warns(DeprecationWarning):
px = Image.new("L", (size, 1), 0).load()
for i in range(size): for i in range(size):
# pixels can contain garbage if image is released # pixels can contain garbage if image is released
assert px[i, 0] == 0 assert px[i, 0] == 0
@ -344,12 +348,13 @@ class TestCffi(AccessTest):
def test_p_putpixel_rgb_rgba(self, mode): def test_p_putpixel_rgb_rgba(self, mode):
for color in ((255, 0, 0), (255, 0, 0, 127 if mode == "PA" else 255)): for color in ((255, 0, 0), (255, 0, 0, 127 if mode == "PA" else 255)):
im = Image.new(mode, (1, 1)) im = Image.new(mode, (1, 1))
access = PyAccess.new(im, False) with pytest.warns(DeprecationWarning):
access.putpixel((0, 0), color) access = PyAccess.new(im, False)
access.putpixel((0, 0), color)
if len(color) == 3: if len(color) == 3:
color += (255,) color += (255,)
assert im.convert("RGBA").getpixel((0, 0)) == color assert im.convert("RGBA").getpixel((0, 0)) == color
class TestImagePutPixelError(AccessTest): class TestImagePutPixelError(AccessTest):

View File

@ -22,6 +22,15 @@ be removed in Pillow 11 (2024-10-15). This class was only made as a helper to
be used internally, so there is no replacement. If you need this functionality be used internally, so there is no replacement. If you need this functionality
though, it is a very short class that can easily be recreated in your own code. though, it is a very short class that can easily be recreated in your own code.
PyAccess
~~~~~~~~
.. deprecated:: 10.0.0
Since Pillow's C API is now faster than PyAccess on PyPy,
:py:mod:`~PIL.PyAccess` has been deprecated and will be removed in Pillow
11.0.0 (2024-10-15).
Removed features Removed features
---------------- ----------------

View File

@ -124,6 +124,16 @@ Image.coerce_e
This undocumented method has been removed. This undocumented method has been removed.
Deprecations
============
PyAccess
^^^^^^^^
Since Pillow's C API is now faster than PyAccess on PyPy,
:py:mod:`~PIL.PyAccess` has been deprecated and will be removed in Pillow
11.0.0 (2024-10-15).
API Changes API Changes
=========== ===========

View File

@ -22,6 +22,8 @@
import logging import logging
import sys import sys
from ._deprecate import deprecate
try: try:
from cffi import FFI from cffi import FFI
@ -47,6 +49,7 @@ logger = logging.getLogger(__name__)
class PyAccess: class PyAccess:
def __init__(self, img, readonly=False): def __init__(self, img, readonly=False):
deprecate("PyAccess", 11)
vals = dict(img.im.unsafe_ptrs) vals = dict(img.im.unsafe_ptrs)
self.readonly = readonly self.readonly = readonly
self.image8 = ffi.cast("unsigned char **", vals["image8"]) self.image8 = ffi.cast("unsigned char **", vals["image8"])