55import warnings
66from io import BytesIO
77from pathlib import Path
8+ from typing import Any
89
910import pytest
1011
4243
4344@skip_unless_feature ("jpg" )
4445class TestFileJpeg :
45- def roundtrip (self , im , ** options ) :
46+ def roundtrip (self , im : Image . Image , ** options : Any ) -> Image . Image :
4647 out = BytesIO ()
4748 im .save (out , "JPEG" , ** options )
4849 test_bytes = out .tell ()
@@ -51,7 +52,7 @@ def roundtrip(self, im, **options):
5152 im .bytes = test_bytes # for testing only
5253 return im
5354
54- def gen_random_image (self , size , mode : str = "RGB" ):
55+ def gen_random_image (self , size : tuple [ int , int ], mode : str = "RGB" ) -> Image . Image :
5556 """Generates a very hard to compress file
5657 :param size: tuple
5758 :param mode: optional image mode
@@ -71,7 +72,7 @@ def test_sanity(self) -> None:
7172 assert im .get_format_mimetype () == "image/jpeg"
7273
7374 @pytest .mark .parametrize ("size" , ((1 , 0 ), (0 , 1 ), (0 , 0 )))
74- def test_zero (self , size , tmp_path : Path ) -> None :
75+ def test_zero (self , size : tuple [ int , int ] , tmp_path : Path ) -> None :
7576 f = str (tmp_path / "temp.jpg" )
7677 im = Image .new ("RGB" , size )
7778 with pytest .raises (ValueError ):
@@ -108,13 +109,11 @@ def test_comment_write(self) -> None:
108109 assert "comment" not in reloaded .info
109110
110111 # Test that a comment argument overrides the default comment
111- for comment in ("Test comment text" , b"Text comment text" ):
112+ for comment in ("Test comment text" , b"Test comment text" ):
112113 out = BytesIO ()
113114 im .save (out , format = "JPEG" , comment = comment )
114115 with Image .open (out ) as reloaded :
115- if not isinstance (comment , bytes ):
116- comment = comment .encode ()
117- assert reloaded .info ["comment" ] == comment
116+ assert reloaded .info ["comment" ] == b"Test comment text"
118117
119118 def test_cmyk (self ) -> None :
120119 # Test CMYK handling. Thanks to Tim and Charlie for test data,
@@ -145,7 +144,7 @@ def test_cmyk(self) -> None:
145144 assert k > 0.9
146145
147146 def test_rgb (self ) -> None :
148- def getchannels (im ) :
147+ def getchannels (im : Image . Image ) -> tuple [ int , int , int ] :
149148 return tuple (v [0 ] for v in im .layer )
150149
151150 im = hopper ()
@@ -161,8 +160,8 @@ def getchannels(im):
161160 "test_image_path" ,
162161 [TEST_FILE , "Tests/images/pil_sample_cmyk.jpg" ],
163162 )
164- def test_dpi (self , test_image_path ) -> None :
165- def test (xdpi , ydpi = None ):
163+ def test_dpi (self , test_image_path : str ) -> None :
164+ def test (xdpi : int , ydpi : int | None = None ):
166165 with Image .open (test_image_path ) as im :
167166 im = self .roundtrip (im , dpi = (xdpi , ydpi or xdpi ))
168167 return im .info .get ("dpi" )
@@ -207,7 +206,7 @@ def test_icc(self, tmp_path: Path) -> None:
207206 ImageFile .MAXBLOCK * 4 + 3 , # large block
208207 ),
209208 )
210- def test_icc_big (self , n ) -> None :
209+ def test_icc_big (self , n : int ) -> None :
211210 # Make sure that the "extra" support handles large blocks
212211 # The ICC APP marker can store 65519 bytes per marker, so
213212 # using a 4-byte test code should allow us to detect out of
@@ -433,7 +432,7 @@ def test_smooth(self) -> None:
433432 assert_image (im1 , im2 .mode , im2 .size )
434433
435434 def test_subsampling (self ) -> None :
436- def getsampling (im ):
435+ def getsampling (im : Image . Image ):
437436 layer = im .layer
438437 return layer [0 ][1 :3 ] + layer [1 ][1 :3 ] + layer [2 ][1 :3 ]
439438
@@ -530,7 +529,7 @@ def test_truncated_jpeg_throws_oserror(self) -> None:
530529 pytest .mark .valgrind_known_error , "libjpeg_turbo" , "2.0" , reason = "Known Failing"
531530 )
532531 def test_qtables (self , tmp_path : Path ) -> None :
533- def _n_qtables_helper (n , test_file ) -> None :
532+ def _n_qtables_helper (n : int , test_file : str ) -> None :
534533 with Image .open (test_file ) as im :
535534 f = str (tmp_path / "temp.jpg" )
536535 im .save (f , qtables = [[n ] * 64 ] * n )
@@ -666,7 +665,7 @@ def test_save_low_quality_baseline_qtables(self) -> None:
666665 "blocks, rows, markers" ,
667666 ((0 , 0 , 0 ), (1 , 0 , 15 ), (3 , 0 , 5 ), (8 , 0 , 1 ), (0 , 1 , 3 ), (0 , 2 , 1 )),
668667 )
669- def test_restart_markers (self , blocks , rows , markers ) -> None :
668+ def test_restart_markers (self , blocks : int , rows : int , markers : int ) -> None :
670669 im = Image .new ("RGB" , (32 , 32 )) # 16 MCUs
671670 out = BytesIO ()
672671 im .save (
@@ -724,13 +723,13 @@ def test_bad_mpo_header(self) -> None:
724723 assert im .format == "JPEG"
725724
726725 @pytest .mark .parametrize ("mode" , ("1" , "L" , "RGB" , "RGBX" , "CMYK" , "YCbCr" ))
727- def test_save_correct_modes (self , mode ) -> None :
726+ def test_save_correct_modes (self , mode : str ) -> None :
728727 out = BytesIO ()
729728 img = Image .new (mode , (20 , 20 ))
730729 img .save (out , "JPEG" )
731730
732731 @pytest .mark .parametrize ("mode" , ("LA" , "La" , "RGBA" , "RGBa" , "P" ))
733- def test_save_wrong_modes (self , mode ) -> None :
732+ def test_save_wrong_modes (self , mode : str ) -> None :
734733 # ref https://github.com/python-pillow/Pillow/issues/2005
735734 out = BytesIO ()
736735 img = Image .new (mode , (20 , 20 ))
@@ -982,12 +981,12 @@ def test_eof(self) -> None:
982981 # Even though this decoder never says that it is finished
983982 # the image should still end when there is no new data
984983 class InfiniteMockPyDecoder (ImageFile .PyDecoder ):
985- def decode (self , buffer ) :
984+ def decode (self , buffer : bytes ) -> tuple [ int , int ] :
986985 return 0 , 0
987986
988987 decoder = InfiniteMockPyDecoder (None )
989988
990- def closure (mode , * args ):
989+ def closure (mode : str , * args ) -> InfiniteMockPyDecoder :
991990 decoder .__init__ (mode , * args )
992991 return decoder
993992
0 commit comments