12
12
13
13
from .helper import assert_image_equal , hopper , is_win32
14
14
15
- # CFFI imports pycparser which doesn't support PYTHONOPTIMIZE=2
16
- # https://github.com/eliben/pycparser/pull/198#issuecomment-317001670
17
- cffi : ModuleType | None
18
- if os .environ .get ("PYTHONOPTIMIZE" ) == "2" :
19
- cffi = None
20
- else :
21
- try :
22
- import cffi
23
-
24
- from PIL import PyAccess
25
- except ImportError :
26
- cffi = None
27
-
28
15
numpy : ModuleType | None
29
16
try :
30
17
import numpy
31
18
except ImportError :
32
19
numpy = None
33
20
34
21
35
- class AccessTest :
36
- # Initial value
37
- _init_cffi_access = Image .USE_CFFI_ACCESS
38
- _need_cffi_access = False
39
-
40
- @classmethod
41
- def setup_class (cls ) -> None :
42
- Image .USE_CFFI_ACCESS = cls ._need_cffi_access
43
-
44
- @classmethod
45
- def teardown_class (cls ) -> None :
46
- Image .USE_CFFI_ACCESS = cls ._init_cffi_access
47
-
48
-
49
- class TestImagePutPixel (AccessTest ):
22
+ class TestImagePutPixel :
50
23
def test_sanity (self ) -> None :
51
24
im1 = hopper ()
52
25
im2 = Image .new (im1 .mode , im1 .size , 0 )
@@ -131,7 +104,7 @@ def test_numpy(self) -> None:
131
104
assert pix [numpy .int32 (1 ), numpy .int32 (2 )] == (18 , 20 , 59 )
132
105
133
106
134
- class TestImageGetPixel ( AccessTest ) :
107
+ class TestImageGetPixel :
135
108
@staticmethod
136
109
def color (mode : str ) -> int | tuple [int , ...]:
137
110
bands = Image .getmodebands (mode )
@@ -144,9 +117,6 @@ def color(mode: str) -> int | tuple[int, ...]:
144
117
return tuple (range (1 , bands + 1 ))
145
118
146
119
def check (self , mode : str , expected_color_int : int | None = None ) -> None :
147
- if self ._need_cffi_access and mode .startswith ("BGR;" ):
148
- pytest .skip ("Support not added to deprecated module for BGR;* modes" )
149
-
150
120
expected_color = (
151
121
self .color (mode ) if expected_color_int is None else expected_color_int
152
122
)
@@ -171,15 +141,14 @@ def check(self, mode: str, expected_color_int: int | None = None) -> None:
171
141
# Check 0x0 image with None initial color
172
142
im = Image .new (mode , (0 , 0 ), None )
173
143
assert im .load () is not None
174
- error = ValueError if self ._need_cffi_access else IndexError
175
- with pytest .raises (error ):
144
+ with pytest .raises (IndexError ):
176
145
im .putpixel ((0 , 0 ), expected_color )
177
- with pytest .raises (error ):
146
+ with pytest .raises (IndexError ):
178
147
im .getpixel ((0 , 0 ))
179
148
# Check negative index
180
- with pytest .raises (error ):
149
+ with pytest .raises (IndexError ):
181
150
im .putpixel ((- 1 , - 1 ), expected_color )
182
- with pytest .raises (error ):
151
+ with pytest .raises (IndexError ):
183
152
im .getpixel ((- 1 , - 1 ))
184
153
185
154
# Check initial color
@@ -199,10 +168,10 @@ def check(self, mode: str, expected_color_int: int | None = None) -> None:
199
168
200
169
# Check 0x0 image with initial color
201
170
im = Image .new (mode , (0 , 0 ), expected_color )
202
- with pytest .raises (error ):
171
+ with pytest .raises (IndexError ):
203
172
im .getpixel ((0 , 0 ))
204
173
# Check negative index
205
- with pytest .raises (error ):
174
+ with pytest .raises (IndexError ):
206
175
im .getpixel ((- 1 , - 1 ))
207
176
208
177
@pytest .mark .parametrize ("mode" , Image .MODES )
@@ -235,126 +204,7 @@ def test_p_putpixel_rgb_rgba(self, mode: str, color: tuple[int, ...]) -> None:
235
204
assert im .convert ("RGBA" ).getpixel ((0 , 0 )) == (255 , 0 , 0 , alpha )
236
205
237
206
238
- @pytest .mark .filterwarnings ("ignore::DeprecationWarning" )
239
- @pytest .mark .skipif (cffi is None , reason = "No CFFI" )
240
- class TestCffiPutPixel (TestImagePutPixel ):
241
- _need_cffi_access = True
242
-
243
-
244
- @pytest .mark .filterwarnings ("ignore::DeprecationWarning" )
245
- @pytest .mark .skipif (cffi is None , reason = "No CFFI" )
246
- class TestCffiGetPixel (TestImageGetPixel ):
247
- _need_cffi_access = True
248
-
249
-
250
- @pytest .mark .skipif (cffi is None , reason = "No CFFI" )
251
- class TestCffi (AccessTest ):
252
- _need_cffi_access = True
253
-
254
- def _test_get_access (self , im : Image .Image ) -> None :
255
- """Do we get the same thing as the old pixel access
256
-
257
- Using private interfaces, forcing a capi access and
258
- a pyaccess for the same image"""
259
- caccess = im .im .pixel_access (False )
260
- with pytest .warns (DeprecationWarning ):
261
- access = PyAccess .new (im , False )
262
- assert access is not None
263
-
264
- w , h = im .size
265
- for x in range (0 , w , 10 ):
266
- for y in range (0 , h , 10 ):
267
- assert access [(x , y )] == caccess [(x , y )]
268
-
269
- # Access an out-of-range pixel
270
- with pytest .raises (ValueError ):
271
- access [(access .xsize + 1 , access .ysize + 1 )]
272
-
273
- def test_get_vs_c (self ) -> None :
274
- with pytest .warns (DeprecationWarning ):
275
- rgb = hopper ("RGB" )
276
- rgb .load ()
277
- self ._test_get_access (rgb )
278
- for mode in ("RGBA" , "L" , "LA" , "1" , "P" , "F" ):
279
- self ._test_get_access (hopper (mode ))
280
-
281
- for mode in ("I;16" , "I;16L" , "I;16B" , "I;16N" , "I" ):
282
- im = Image .new (mode , (10 , 10 ), 40000 )
283
- self ._test_get_access (im )
284
-
285
- def _test_set_access (self , im : Image .Image , color : tuple [int , ...] | float ) -> None :
286
- """Are we writing the correct bits into the image?
287
-
288
- Using private interfaces, forcing a capi access and
289
- a pyaccess for the same image"""
290
- caccess = im .im .pixel_access (False )
291
- with pytest .warns (DeprecationWarning ):
292
- access = PyAccess .new (im , False )
293
- assert access is not None
294
-
295
- w , h = im .size
296
- for x in range (0 , w , 10 ):
297
- for y in range (0 , h , 10 ):
298
- access [(x , y )] = color
299
- assert color == caccess [(x , y )]
300
-
301
- # Attempt to set the value on a read-only image
302
- with pytest .warns (DeprecationWarning ):
303
- access = PyAccess .new (im , True )
304
- assert access is not None
305
-
306
- with pytest .raises (ValueError ):
307
- access [(0 , 0 )] = color
308
-
309
- def test_set_vs_c (self ) -> None :
310
- rgb = hopper ("RGB" )
311
- with pytest .warns (DeprecationWarning ):
312
- rgb .load ()
313
- self ._test_set_access (rgb , (255 , 128 , 0 ))
314
- self ._test_set_access (hopper ("RGBA" ), (255 , 192 , 128 , 0 ))
315
- self ._test_set_access (hopper ("L" ), 128 )
316
- self ._test_set_access (hopper ("LA" ), (128 , 128 ))
317
- self ._test_set_access (hopper ("1" ), 255 )
318
- self ._test_set_access (hopper ("P" ), 128 )
319
- self ._test_set_access (hopper ("PA" ), (128 , 128 ))
320
- self ._test_set_access (hopper ("F" ), 1024.0 )
321
-
322
- for mode in ("I;16" , "I;16L" , "I;16B" , "I;16N" , "I" ):
323
- im = Image .new (mode , (10 , 10 ), 40000 )
324
- self ._test_set_access (im , 45000 )
325
-
326
- @pytest .mark .filterwarnings ("ignore::DeprecationWarning" )
327
- def test_not_implemented (self ) -> None :
328
- assert PyAccess .new (hopper ("BGR;15" )) is None
329
-
330
- # Ref https://github.com/python-pillow/Pillow/pull/2009
331
- def test_reference_counting (self ) -> None :
332
- size = 10
333
-
334
- for _ in range (10 ):
335
- # Do not save references to the image, only to the access object
336
- with pytest .warns (DeprecationWarning ):
337
- px = Image .new ("L" , (size , 1 ), 0 ).load ()
338
- for i in range (size ):
339
- # Pixels can contain garbage if image is released
340
- assert px [i , 0 ] == 0
341
-
342
- @pytest .mark .parametrize ("mode" , ("P" , "PA" ))
343
- def test_p_putpixel_rgb_rgba (self , mode : str ) -> None :
344
- for color in ((255 , 0 , 0 ), (255 , 0 , 0 , 127 if mode == "PA" else 255 )):
345
- im = Image .new (mode , (1 , 1 ))
346
- with pytest .warns (DeprecationWarning ):
347
- access = PyAccess .new (im , False )
348
- assert access is not None
349
-
350
- access .putpixel ((0 , 0 ), color )
351
-
352
- if len (color ) == 3 :
353
- color += (255 ,)
354
- assert im .convert ("RGBA" ).getpixel ((0 , 0 )) == color
355
-
356
-
357
- class TestImagePutPixelError (AccessTest ):
207
+ class TestImagePutPixelError :
358
208
IMAGE_MODES1 = ["LA" , "RGB" , "RGBA" , "BGR;15" ]
359
209
IMAGE_MODES2 = ["L" , "I" , "I;16" ]
360
210
INVALID_TYPES = ["foo" , 1.0 , None ]
0 commit comments