Merge pull request #7236 from radarhere/pyaccess

This commit is contained in:
Hugo van Kemenade 2023-06-29 13:58:50 +03:00 committed by GitHub
commit 2de1bf221a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 57 additions and 25 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,6 +254,7 @@ 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)
with pytest.warns(DeprecationWarning):
access = PyAccess.new(im, False) access = PyAccess.new(im, False)
w, h = im.size w, h = im.size
@ -264,16 +267,12 @@ 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):
with pytest.warns(DeprecationWarning):
rgb = hopper("RGB") rgb = hopper("RGB")
rgb.load() rgb.load()
self._test_get_access(rgb) self._test_get_access(rgb)
self._test_get_access(hopper("RGBA")) for mode in ("RGBA", "L", "LA", "1", "P", "F"):
self._test_get_access(hopper("L")) self._test_get_access(hopper(mode))
self._test_get_access(hopper("LA"))
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)
@ -292,6 +291,7 @@ 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)
with pytest.warns(DeprecationWarning):
access = PyAccess.new(im, False) access = PyAccess.new(im, False)
w, h = im.size w, h = im.size
@ -301,12 +301,14 @@ 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
with pytest.warns(DeprecationWarning):
access = PyAccess.new(im, True) 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")
with pytest.warns(DeprecationWarning):
rgb.load() 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))
@ -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,6 +338,7 @@ 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
with pytest.warns(DeprecationWarning):
px = Image.new("L", (size, 1), 0).load() 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
@ -344,6 +348,7 @@ 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))
with pytest.warns(DeprecationWarning):
access = PyAccess.new(im, False) access = PyAccess.new(im, False)
access.putpixel((0, 0), color) access.putpixel((0, 0), color)

View File

@ -22,6 +22,18 @@ 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 and Image.USE_CFFI_ACCESS
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. 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). Pillow's C API will now be used by default on PyPy instead.
``Image.USE_CFFI_ACCESS``, for switching from the C API to PyAccess, is
similarly deprecated.
Removed features Removed features
---------------- ----------------

View File

@ -124,6 +124,19 @@ Image.coerce_e
This undocumented method has been removed. This undocumented method has been removed.
Deprecations
============
PyAccess and Image.USE_CFFI_ACCESS
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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). Pillow's C API will now be used by default on PyPy instead.
``Image.USE_CFFI_ACCESS``, for switching from the C API to PyAccess, is
similarly deprecated.
API Changes API Changes
=========== ===========

View File

@ -107,8 +107,7 @@ except ImportError as v:
raise raise
# works everywhere, win for pypy, not cpython USE_CFFI_ACCESS = False
USE_CFFI_ACCESS = hasattr(sys, "pypy_version_info")
try: try:
import cffi import cffi
except ImportError: except ImportError:

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"])